网络爬虫(一)深度优先爬虫与广度优先爬虫

news/2024/7/8 2:06:39 标签: 爬虫, python

1. 深度优先爬虫:深度优先爬虫是一种以深度为优先的爬虫算法。它从一个起始点开始,先访问一个链接,然后再访问该链接下的链接,一直深入地访问直到无法再继续深入为止。然后回溯到上一个链接,再继续深入访问下一个未被访问的链接。这种算法的优点是可以快速深入到网站的深层页面,但可能会陷入无限循环或者遗漏一些链接。

2. 广度优先爬虫:广度优先爬虫是一种以广度为优先的爬虫算法。它从一个起始点开始,首先访问该链接下的所有链接,然后再逐个访问这些链接下的链接。这种算法的优点是可以较好地保证网站的全面爬取,并避免陷入无限循环。但缺点是可能会花费较长的时间,因为需要逐层遍历所有链接。

        

这两种爬虫算法适用于不同的应用场景,深度优先爬虫适用于需要尽快深入到网站的深层页面进行数据抓取的场景,而广度优先爬虫适用于需要全面爬取整个网站的场景。

对应地,我们可以联系数据结构的树来进行理解。

树是一种数据结构,它是由节点和边组成的集合。树的节点之间有一对一的关系,其中一个节点是根节点,其他节点可以分为多个子节点,每个子节点可以再分为更多的子节点,以此类推。树的模型在计算机科学中被广泛应用,包括文件系统、数据库索引、图形界面等。

树的根节点是最顶层的节点,没有父节点。每个节点可以有零个或多个子节点。节点之间的边表示节点之间的关系,其中每个边连接一个父节点和一个子节点。

树的一些常见的特殊情况包括二叉树、二叉搜索树、平衡二叉树等。二叉树是一种特殊的树,其中每个节点最多有两个子节点。二叉搜索树是一种有序的二叉树,其中对于每个节点,其左子树的所有节点的值都小于它的值,右子树的所有节点的值都大于它的值。平衡二叉树是一种特殊的二叉搜索树,其中任意节点的左子树和右子树的高度差不大于1。

树的模型可以用来表示层次化的数据,如组织结构、目录结构等。在编程中,可以使用树来实现递归算法、搜索算法、排序算法等。树的模型也可以用图形方式表示,通过节点和边的可视化,更直观地展示树结构。

from bs4 import BeautifulSoup
import requests
import re
#自定义队列类
class linkQuence:
    def __init__(self):
        # 已访问的url集合
        self.visted = []
        # 待访问的url集合
        self.unVisited = []
    # 获取访问过的url队列
    def getVisitedUrl(self):
        return self.visted
    # 获取未访问的url队列
    def getUnvisitedUrl(self):
        return self.unVisited
    # 添加到访问过得url队列中
    def addVisitedUrl(self, url):
        self.visted.append(url)
    # 移除访问过得url
    def removeVisitedUrl(self, url):
        self.visted.remove(url)
    # 未访问过得url出队列
    def unVisitedUrlDeQuence(self):
        try:
            return self.unVisited.pop()
        except:
            return None
    # 保证每个url只被访问一次
    def addUnvisitedUrl(self, url):
        if url != "" and url not in self.visted and url not in self.unVisited:
            self.unVisited.insert(0, url)
    # 获得已访问的url数目
    def getVisitedUrlCount(self):
        return len(self.visted)
    # 获得未访问的url数目
    def getUnvistedUrlCount(self):
        return len(self.unVisited)
    # 判断未访问的url队列是否为空
    def unVisitedUrlsEnmpy(self):
        return len(self.unVisited) == 0
class MyCrawler:
    def __init__(self, seeds):
        # 初始化当前抓取的深度
        self.current_deepth = 1
        # 使用种子初始化url队列
        self.linkQuence = linkQuence()
        if isinstance(seeds, str):
            self.linkQuence.addUnvisitedUrl(seeds)
        if isinstance(seeds, list):
            for i in seeds:
                self.linkQuence.addUnvisitedUrl(i)
        print("Add the seeds url %s to the unvisited url list" % str(self.linkQuence.unVisited))
        # 抓取过程主函数
    def crawling(self, seeds, crawl_deepth):
        # ********** Begin **********#
        # 循环条件:抓取深度不超过crawl_deepth
        while self.current_deepth <= crawl_deepth:
            # 循环条件:待抓取的链接不空
            while not self.linkQuence.unVisitedUrlsEnmpy():
                # 队头url出队列
                visitUrl = self.linkQuence.unVisitedUrlDeQuence()
                print("Pop out one url \"%s\" from unvisited url list" % visitUrl)
                if visitUrl is None or visitUrl == "":
                    continue
                # 获取超链接
                links = self.getHyperLinks(visitUrl)
                print("Get %d new links" % len(links))
                # 将url放入已访问的url中
                self.linkQuence.addVisitedUrl(visitUrl)
                print("Visited url count: " + str(self.linkQuence.getVisitedUrlCount()))
                print("Visited deepth: " + str(self.current_deepth))
            # 未访问的url入列
            for link in links:
                self.linkQuence.addUnvisitedUrl(link)
            print("%d unvisited links:" % len(self.linkQuence.getUnvisitedUrl()))
            self.current_deepth += 1
        # ********** End **********#
    # 获取源码中得超链接
    def getHyperLinks(self, url):
        # ********** Begin **********#
        links = []
        data = self.getPageSource(url)
        soup = BeautifulSoup(data,'html.parser')
        a = soup.findAll("a", {"href": re.compile('^http|^/')})
        for i in a:
            if i["href"].find("http://") != -1:
                links.append(i["href"])
        return links
        # ********** End **********#
    # 获取网页源码
    def getPageSource(self, url):
        # ********** Begin **********#
        try:
            r = requests.get(url)
            r.raise_for_status()
            r.encoding = 'utf-8'
            return r.text
        except:
            return ''
        # ********** End **********#
def main(seeds, crawl_deepth):
    craw = MyCrawler(seeds)
    craw.crawling(seeds, crawl_deepth)
if __name__ == '__main__':
    main("http://www.baidu.com", 3)


http://www.niftyadmin.cn/n/5535905.html

相关文章

【笔试记录】华为 | 20230823 | cpp

获取连通的相邻节点列表 题目描述 在网元内&#xff0c;存在了 N 个转发节点&#xff0c;每个转发节点有自己唯一的标识 TB 且每个节点有 M 个端口&#xff0c;节点间通过端口进行报文通讯。出于业务隔离的需求&#xff0c;服务器内的端口被划分为多个通讯平面(用 VLAN 隔离&…

HandlerMethodArgumentResolver :深入spring mvc参数解析机制

❃博主首页 &#xff1a; <码到三十五> ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a; 搬的每块砖&#xff0c;皆为峰峦之基&#xff1b;公众号搜索(码到三十…

go Channel原理 (三)

Channel 设计原理 不要通过共享内存的方式进行通信&#xff0c;而是应该通过通信的方式共享内存。 在主流编程语言中&#xff0c;多个线程传递数据的方式一般都是共享内存。 Go 可以使用共享内存加互斥锁进行通信&#xff0c;同时也提供了一种不同的并发模型&#xff0c;即通…

【你真的了解double和float吗】

&#x1f308;个人主页&#xff1a;努力学编程’ ⛅个人推荐&#xff1a;基于java提供的ArrayList实现的扑克牌游戏 |C贪吃蛇详解 ⚡学好数据结构&#xff0c;刷题刻不容缓&#xff1a;点击一起刷题 &#x1f319;心灵鸡汤&#xff1a;总有人要赢&#xff0c;为什么不能是我呢 …

C++ :lambda表达式

目录 lambda表达式书写格式&#xff1a; lambda表达式各部分说明&#xff1a; lambda的使用示范&#xff1a; 注意事项&#xff1a; 返回值类型可以省略&#xff0c;参数也可也省略&#xff1a; sort内部也可以直接写lambda表达式&#xff1a; 排序时利用lambda进行排序…

VPN是什么?

VPN&#xff0c;全称Virtual Private Network&#xff0c;即“虚拟私人网络”&#xff0c;是一种在公共网络&#xff08;如互联网&#xff09;上建立加密、安全的连接通道的技术。简单来说&#xff0c;VPN就像是一条在公共道路上铺设的“秘密隧道”&#xff0c;通过这条隧道传输…

通过SimU-Net进行同时深度学习体素分类的纵向CECT扫描肝病灶变化分析| 文献速递-深度学习自动化疾病检查

Title 题目 Liver lesion changes analysis in longitudinal CECT scans by simultaneous deep learning voxel classification with SimU-Net 通过SimU-Net进行同时深度学习体素分类的纵向CECT扫描肝病灶变化分析 01 文献速递介绍 影像学随访是对影像学研究的解读&#x…

VBA打开其他Excel文件

前言 本节会介绍通过VBA实现打开其他excel文件&#xff0c;包括模糊匹配文件名称、循环同时打开多个文件&#xff0c;并获取工作表及工作簿进行数据操作后&#xff0c;对打开的文件进行保存并关闭操作。 一、打开固定文件名称的文件 场景说明&#xff1a; 1.新建一个宏文件VBA…