3.2 网站图的爬取路径

news2024/11/24 14:44:33

深度优先与广度优先方法都是遍历树的一种方法,但是网站的各个网页 之间的关系未必是树的结构,它们可能组成一个复杂的图形结构,即有回路

如果在前面的网站中每个网页都加一条Home的语句,让每个网页都能回到主界面,那么网站的关系就是一个有回路的图

1. 复杂的 Web网站


  1. books.html

<h3>计算机</h3>
<ul>
    <li><a href="database.html">数据库</a></li>
    <li><a href="program.html">程序设计</a></li>
    <li><a href="network.html">计算机网络</a></li>
</ul>
  1. database.html

<h3>数据库</h3>
<ul>
    <li><a href="mysql.html">MySQL数据库</a></li>
</ul>
<a href="books.html">Home</a>
  1. program.html

<h3>程序设计</h3>
<ul>
    <li><a href="python.html">Python程序设计</a></li>
    <li><a href="java.html">Java程序设计</a></li>
</ul>
<a href="books.html">Home</a>
  1. network.html

<h3>计算机网络</h3>
<a href="books.html">Home</a>
  1. mysql.html

<h3>MySQL数据库</h3>
<a href="books.html">Home</a>
  1. python.html

<h3>Python程序设计</h3>
<a href="books.html">Home</a>
  1. java.html

<h3>Java程序设计</h3>
<a href="books.html">Home</a>

这时,深度优先与广度优先方法要做一点改进可以用一个 python 中的列表 urls ;来记住已经访问过的网站,如果一个网址 url 没有访问过就访问它,并把 url 加到 urls 中保存起来,如果 url 已经访问过就不再访问了,这样就可以避免形成回路,导致无限循环。

2. 改进深度优先客户端程序


假定给定图 G 的初始状态是所有顶点均未曾访问过。在 G 中任选一顶点 v 为初始出发点(圆点),则深度优先遍历可以定义如下:

  • 首先访问出发点v,并将其标记为已访问;

  • 然后依次从 v 触发搜索 v 的每个邻接点 w 。

  • 若 w 未被曾访问过,则以 w 为新的出发点继续进行深度优先遍历,直至图中所有和原点 v 有路径相通的顶点(以称为原点可达的顶点)均已被访问为止。

图的深度优先遍历类似于树的前序遍历。采用的搜索方法的特点是 尽可能先对纵深方向进行搜索。这种搜索方法称为深度优先搜索 (Depth-First Search)。相应地,用此方法遍历图就很自然地称之为图 的深度优先遍历,基本实现思想:

  • 访问顶点v;

  • 从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度 优先遍历;

  • 重复上述两步,直至图中所有和v有路径相通的顶点都被访问到。

使用递归程序

改进客户端程序 client1.py 如下:

# 使用递归的程序
from bs4 import BeautifulSoup
import urllib.request


def spider(url):
    global urls  # 使用列表存储和标记已经访问过的节点
    if url not in urls:  # 未被访问过
        urls.append(url)
        try:
            data = urllib.request.urlopen(url)
            data = data.read()
            data = data.decode()
            soup = BeautifulSoup(data, "lxml")
            print(soup.find("h3").text)
            links = soup.select("a")
            for link in links:
                href = link["href"]
                url = start_url + "/" + href
                spider(url)
        except Exception as err:
            print(err)


start_url = "http://127.0.0.1:5000"
urls = []
spider(start_url)
print("The End")

使用栈的程序

改进客户端程序 client2.py 如下:

# 使用栈的程序
from bs4 import BeautifulSoup
import urllib.request


class Stack:
    def __init__(self):
        self.st = []

    def pop(self):
        return self.st.pop()

    def push(self, obj):
        self.st.append(obj)

    def empty(self):
        return len(self.st) == 0


def spider(url):
    global urls
    stack = Stack()
    stack.push(url)
    while not stack.empty():
        url = stack.pop()
        if url not in urls:
            urls.append(url)
            try:
                data = urllib.request.urlopen(url)
                data = data.read()
                data = data.decode()
                soup = BeautifulSoup(data, "lxml")
                print(soup.find("h3").text)
                links = soup.select("a")
                for i in range(len(links) - 1, -1, -1):
                    href = links[i]["href"]
                    url = start_url + "/" + href
                    stack.push(url)
            except Exception as err:
                print(err)


start_url = "http://127.0.0.1:5000"
urls = []
spider(start_url)
print("The End")

这两个程序结果一样,如下:

3. 改进广度优先客户端程序


图的广度优先遍历BFS算法是一个分层搜索的过程,和树的层序遍历算法类同,它也需要一个队列以保持遍历过的顶点顺序,以便按出队的顺序再去访问这些顶点的邻接顶点。基本实现思想:

(1)顶点v入队列。
(2)当队列非空时则继续执行,否则算法结束。
(3)出队列取得队头顶点v;访问顶点v并标记顶点v已被访问。
(4)查找顶点v的第一个邻接顶点col。
(5)若v的邻接顶点col未被访问过的,则col入队列。
(6)继续查找顶点v的另一个新的邻接顶点col,转到步骤(5)。直到 顶点v的所有未被访问过的邻接点处理完。转到步骤(2)。

广度优先遍历图是以顶点v为起始点,由近至远,依次访问和v有路径相通 而且路径长度为1,2,……的顶点。为了使“先被访问顶点的邻接点”先 于“后被访问顶点的邻接点”被访问,需设置队列存储访问的顶点。

使用队列的程序

改进客户端程序 client3.py 如下:

# 使用队列的程序
from bs4 import BeautifulSoup
import urllib.request


class Queue:
    def __init__(self):
        self.st = []

    def fetch(self):
        return self.st.pop(0)  # 出队列,弹出列表头的元素

    def enter(self, obj):  # 入队
        self.st.append(obj)

    def empty(self):
        return len(self.st) == 0


def spider(url):
    global urls
    queue = Queue()
    queue.enter(url)
    while not queue.empty():
        url = queue.fetch()
        if url not in urls:
            try:
                urls.append(url)
                data = urllib.request.urlopen(url)
                data = data.read()
                data = data.decode()
                soup = BeautifulSoup(data, "lxml")
                print(soup.find("h3").text)
                links = soup.select("a")
                for link in links:
                    href = link["href"]
                    url = start_url + "/" + href
                    if url not in urls:
                        queue.enter(url)
            except Exception as err:
                print(err)


start_url = "http://127.0.0.1:5000"
urls = []
spider(start_url)
print("The End")

程序运行结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/373892.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

windows服务器实用(4)——使用IIS部署网站

windows服务器实用——IIS部署网站 如果把windows服务器作为web服务器使用&#xff0c;那么在这个服务器上部署网站是必须要做的事。在windows服务器上&#xff0c;我们一般使用IIS部署。 假设此时前端给你一个已经完成的网站让你部署在服务器上&#xff0c;别人可以在浏览器…

【Linux】-- 基于阻塞队列的生产者消费者模型

目录 前言 总结&#xff1a; 第一个问题的解决 基于BlockingQueue的生产者消费者模型 第二个问题的解决 wait的唤醒漏洞 深度理解生产者消费者模型 代码体现 锁的设计 总结&#xff1a; 前言 在多线程的条件变量遗留到此的问题。 #问&#xff1a;条件满足时&#xff0…

linux 防火墙管理-firewalld

什么是Firewalld 当前很多linux系统中都默认使用 firewalld&#xff08;Dynamic Firewall Manager of Linux systems&#xff0c;Linux系统的动态防火墙管理器&#xff09;服务作为防火墙配置管理工具。 “firewalld”是firewall daemon。它提供了一个动态管理的防火墙&#x…

Java知识复习(五)JVM虚拟机

1、虚拟机的自动内存管理和C/C的区别 C/C开发程序时需要为每一个new操作去写对应的delete/free操作&#xff0c;不容易出现内存泄漏和溢出问题。而Java程序将内存控制权交给了Java虚拟机 2、JVM的运行机制 1、Java程序的具体运行过程如下&#xff1a; Java源文件被编译器编…

c盘爆满--如何清理电脑C盘

问题 c盘饱满很多天了&#xff0c;今天终于忍无可忍&#xff0c;开始展开对c盘的处理 c盘的基本处理有两步&#xff0c; 第一步&#xff0c;电脑系统清理 1,c盘右键属性&#xff0c;有个磁盘清理&#xff0c;好像是系统更新的一些缓存资源&#xff0c;可以直接清理 当然这只…

Hadoop MapReduce

目录1.1 MapReduce介绍1.2 MapReduce优缺点MapReduce实例进程阶段组成1.3 Hadoop MapReduce官方示例案例&#xff1a;评估圆周率π&#xff08;PI&#xff09;的值案例&#xff1a;wordcount单词词频统计1.4 Map阶段执行流程1.5 Reduce阶段执行流程1.6 Shuffle机制1.1 MapReduc…

BigScience bloom模型

简介项目叫 BigScience,模型叫 BLOOM,BLOOM 的英文全名代表着大科学、大型、开放科学、开源的多语言语言模型。拥有 1760 亿个参数的模型.BLOOM 是去年由 1000 多名志愿研究人员,学者 在一个名为“大科学 BigScience”的项目中创建的.BLOOM 和今天其他可用大型语言模型存在的一…

信号的FFT变换与加窗

1. fft 傅里叶变换 1.1 傅里叶变换的本质 数学上有一种公式叫做 泰勒展开&#xff1a; 泰勒公式&#xff1a; 其表达的思想&#xff0c;是任意一函数可以有多个指数函数构成 当指数函数的个数趋近于无穷多个&#xff0c;那么组合出来的函数将会逼近原函数&#xff1b; …

Pandas数据查询

Pandas数据查询 Pandas查询数据的几种方法 df.loc方法&#xff0c;根据行、列的标签值查询 df.iloc方法&#xff0c;根据行、列的数字位置查询 df.where方法 df.query方法 .loc既能查询&#xff0c;又能覆盖写入&#xff0c;强烈推荐&#xff01; Pandas使用df.loc查询数据…

深度学习基础(二)-学习是怎么个回事

深度学习基础(一) 引入了一个 helloworld&#xff0c;提出了神经网络的简单关系&#xff0c;也就是一个基础公式 a(L) Sigmoid( a(L-1)*W(L) b(L)) a(L): 第L层神经元被激活之后 进行Sigmoid函数收敛 得到的值 b(L): 第L层神经元被激活阈值 W(L): 第L层神经元 与 第L-1层…

Android安卓中jni封装代码打包为aar

前文【Android安卓中jni与Java之间传递复杂的自定义数据结构】已经介绍jni编译c++代码且已经成功封装成java,但是c++是以源代码形式继承在app中,本文介绍如何将前述jni c++代码以隐藏源代码封装成aar的形式。 1、aar打包 1.1、新建module 按照流程 File -> New Module …

学习周报2.26

文章目录前言文献阅读摘要方法结果深度学习Encoder-Decoder&#xff08;编码-解码&#xff09;信息丢失的问题Attention机制总结前言 This week,I read an article about daily streamflow prediction.This study shows the results of an in-depth comparison between two di…

Oracle-RAC集群主机重启问题分析

问题背景: 在对一套两节点Oracle RAC19.18集群进行部署时&#xff0c;出现启动数据库实例就会出现主机出现重启的情况&#xff0c;检查发现主机重启是由于节点集群被驱逐导致​。 问题: 两节点Oracle RAC19.18集群,启动数据库实例会导致主机出现重启。 问题分析: 主机多次出现…

2023年第八周总周结 | 开学倒数第一周

为什么要做周总结&#xff1f; 1.避免跳相似的坑 2.客观了解上周学习进度并反思&#xff0c;制定可完成的下周规划 一、上周存在问题 发现自己反复犯同样问题&#xff0c;不想反思就不会意识到。总想以面带点的学习&#xff0c;实际上却在原地踏步。问题导向使用ChatGPT&#…

目标检测:DETR详解

1. 概述 DETR: End-to-End Object Detection with Transformers, DETR 是 Facebook 团队于 2020 年提出的基于 Transformer 的端到端目标检测,是Transformer在目标检测的开山之作 – DEtection TRansformer。 相比于传统的Faster-rcnn,yolo系列,DETR有以下几个优点:1).无需…

微信实时音视频通话数据流分析

一、实时音视频的架构 实时音视频通信架构主要包括P2P、SFU、MCU三种方式&#xff0c;其中点对点通信通常以P2P优先&#xff0c;P2P走不通的场景再借助于SFU/MCU。 P2P方式&#xff0c;终端之间点对点的相互收发数据流&#xff0c;音视频流不经过服务器&#xff1b; SFU是端侧…

scrapy下载图片

&#x1f431; 个人主页&#xff1a;莎萌玩家&#x1f64b;‍♂️ 作者简介&#xff1a;全栈领域新星创作者、专注于全栈各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01;&#x1f4ab;系列专栏&#xff1a;网络爬虫、WEB全栈开发&#x1f4e2; 资料…

二叉树的后序遍历-java递归+非递归-力扣145双百方案

一、题目描述给你一棵二叉树的根节点 root &#xff0c;返回其节点值的 后序遍历 。示例 1&#xff1a;输入&#xff1a;root [1,null,2,3]输出&#xff1a;[3,2,1]示例 2&#xff1a;输入&#xff1a;root []输出&#xff1a;[]示例 3&#xff1a;输入&#xff1a;root [1]…

使用jenkins实现自动化部署springboot应用

1. 前置准备 这里代码仓库使用gitlab。在介绍如何通过gitlab和jenkins进行自动化部署之前&#xff0c;需要先安装完成gitlab以及jenkins。两种程序的安装方式以及相关配置可以参看以下内容&#xff1a; linux中安装gitlab&#xff1a;linux安装极狐gitlab linux中安装jenki…

Objective-C description 自定义对象的打印格式/输出的字符串 类似于Java 中的 toString 方法

总目录 iOS开发笔记目录 从一无所知到入门 文章目录IntroNSObject 源码测试类截图测试代码输出Intro 在 Java 中&#xff0c;对于自定义类一般会重写集成自Object类的toString方法&#xff0c;这样在打印该类的对象时&#xff0c;打印出的字符串就是我们在 toString() 方法中返…