zoukankan      html  css  js  c++  java
  • 广度优先搜索与网络爬虫

    1.网页搜索与爬虫简介

          为了对互联网中的有效信息进行高效获取,可以依托例如“阅读更多”链接对文章建立有向图,其中的点代表文章,有向边是文章之间的链接关系,从而不断深入获取文章的相关文章簇。之后就可以对图进行遍历获取文章。

      广度优先搜索策略爬虫现在是使用最多的搜索策略。它的工作原理是,数据获取模块的爬虫在抓取文章页时,优先抓取当前层次范围的“阅读更多”,完成本层遍历后再抓取“阅读更多”数据,直到满足条件时结束抓取。

      深度优先搜索策略爬虫是指从某篇文章为起点,根据文章提供的“阅读更多”,并沿着URL继续向下搜索并抓取,不断执行直到完整的执行完本条URL 线路后返回抓取源头处,开始新的一轮线路搜索和抓取任务。

      深度优先遍历的优点是设计简单,但是这种遍历的最大缺陷是:由于顶层文章价值最高,往下逐渐减弱。无限制的深度挖取,挖取的文章的价值不会太大。

    2.广度优先搜索进行网络爬虫

    广度优先搜索是爬虫中使用最广泛的一种策略,主要原因有以下三点:

    (1)重要的网页往往离种子比较近,例如我们打开新闻网站时首先看到的往往是最热门的新闻,随着不算的深入冲浪,所看到的的网页(新闻)的重要性越来越低。

    (2)万维网的实际深度最多能达到17层,但到达某个网页总存在一条很短的路径。而广度优先搜索会以最快的速度到达这个网页。

    (3)广度优先有利于多爬虫的合作抓取,多爬虫合作通常先抓取站内链接,抓取的封闭性很强。

    例子:爬取新浪微博的链接,一级一级展开

    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):
                # 循环条件:抓取深度不超过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)   #获取visiturl中的所有超链接
                        print("Get %d new links" % len(links))
    
                        # 将visitUrl放入已访问的url中
                        self.linkQuence.addVisitedUrl(visitUrl)
                        print("Visited url count: " + str(self.linkQuence.getVisitedUrlCount()))
    
                        print("Visited deepth: " + str(self.current_deepth))
    
                    # 未访问的url入列   也就是visiturl网页中的所有超链接links
                    for link in links:
                        self.linkQuence.addUnvisitedUrl(link)
                    print("%d unvisited links:" % len(self.linkQuence.getUnvisitedUrl()))
    
                    self.current_deepth += 1
    
        # 获取源码中得超链接
        def getHyperLinks(self, url):
            links = []
            data = self.getPageSource(url)  #获取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
    
        # 获取网页源码
        def getPageSource(self, url):
            try:
                r = requests.get(url)
                r.raise_for_status()
                r.encoding = 'utf-8'
                return r.text
            except:
                return ''
    
    def main(seeds, crawl_deepth):
        craw = MyCrawler(seeds)
        craw.crawling(seeds, crawl_deepth)
    
    
    #爬取新浪微博超链接,深度为3
    if __name__ == '__main__':
        main("http://www.sina.com.cn", 3)

    参考https://blog.csdn.net/weixin_34613450/article/details/72810595

  • 相关阅读:
    素数路径Prime Path POJ3126 素数,BFS
    Fliptile POJ3279 DFS
    Find the Multiple POJ1426
    洗牌Shuffle'm Up POJ3087 模拟
    棋盘问题 POJ1321 DFS
    抓住那只牛!Catch That Cow POJ3278 BFS
    Dungeon Master POJ2251 三维BFS
    Splitting into digits CodeForce#1104A
    Ubuntu下手动安装Nvidia显卡驱动
    最大连续子序列和
  • 原文地址:https://www.cnblogs.com/lovema1210/p/13372590.html
Copyright © 2011-2022 走看看