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

  • 相关阅读:
    Android APN开关原理
    HTC Wildfire 闪光灯手电筒的实现方式
    Android Stagefright MPEG4Extractor分析
    Ubuntu 10.10 64bit下使用Android NDK r6编译FFmpeg 0.8.1
    开始IMS学习相关名词和术语(持续更新)
    Ubuntu 下安装代码格式化程序 astyle
    Ubuntu 10.10 x64 安装 ffmpeg tutorial 相关支持库
    关于GradientDrawable的angle属性
    判断SIM卡所属的运营商
    最小生成树算法
  • 原文地址:https://www.cnblogs.com/lovema1210/p/13372590.html
Copyright © 2011-2022 走看看