`
zoulc001
  • 浏览: 30471 次
  • 性别: Icon_minigender_1
  • 来自: 成都
文章分类
社区版块
存档分类
最新评论

宽度优先遍历爬虫的python实现

阅读更多

网上很著名的一本爬虫教程《自己手动写网络爬虫》,该书所有源码是用java编写的,

其中提到了宽度优先遍历算法,闲来无事我把他用python实现了一遍。代码量少了将近一半,呵呵。


宽度优先算法介绍

参考:http://book.51cto.com/art/201012/236668.htm

整个的宽度优先爬虫过程就是从一系列的种子节点开始,把这些网页中的"子节点"(也就是超链接)提取出来,放入队列中依次进行抓取。被处理过的链接需要放 入一张表(通常称为Visited表)中。每次新处理一个链接之前,需要查看这个链接是否已经存在于Visited表中。如果存在,证明链接已经处理过, 跳过,不做处理,否则进行下一步处理。

初始的URL地址是爬虫系统中提供的种子URL(一般在系统的配置文件中指定)。当解析这些种子URL所表示的网页时,会产生新的URL(比如从页面中的<a href= "http://www.admin.com "中提取出http://www.admin.com 这个链接)。然后,进行以下工作:

(1) 把解析出的链接和Visited表中的链接进行比较,若Visited表中不存在此链接,表示其未被访问过。

(2) 把链接放入TODO表中。

(3) 处理完毕后,再次从TODO表中取得一条链接,直接放入Visited表中。

(4) 针对这个链接所表示的网页,继续上述过程。如此循环往复。

表1.3显示了对图1.3所示的页面的爬取过程。

表1.3  网络爬取

TODO

Visited

A

BCDEF

A

CDEF

A,B

DEF

A,B,C

续表

TODO

Visited

EF

A,B,C,D

FH

A,B,C,D,E

HG

A,B,C,D,E,F

GI

A,B,C,D,E,F,H

I

A,B,C,D,E,F,H,G

A,B,C,D,E,F,H,G,I

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

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

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

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


宽度优先遍历爬虫的python实现

#encoding=utf-8
from BeautifulSoup import BeautifulSoup
import socket
import urllib2
import re

class MyCrawler:
    def __init__(self,seeds):
        #使用种子初始化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_count):
        #循环条件:待抓取的链接不空且专区的网页不多于crawl_count
        while self.linkQuence.unVisitedUrlsEnmpy() is False and self.linkQuence.getVisitedUrlCount()<=crawl_count:
            #队头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())
            #未访问的url入列
            for link in links:
                self.linkQuence.addUnvisitedUrl(link)
            print "%d unvisited links:"%len(self.linkQuence.getUnvisitedUrl())
            
    #获取源码中得超链接
    def getHyperLinks(self,url):
        links=[]
        data=self.getPageSource(url)
        if data[0]=="200":
            soup=BeautifulSoup(data[1])
            a=soup.findAll("a",{"href":re.compile(".*")})
            for i in a:
                if i["href"].find("http://")!=-1:
                    links.append(i["href"]) 
        return links
    
    #获取网页源码
    def getPageSource(self,url,timeout=100,coding=None):
        try:
            socket.setdefaulttimeout(timeout)
            req = urllib2.Request(url)
            req.add_header('User-agent', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)')
            response = urllib2.urlopen(req)
            if coding is None:
                coding= response.headers.getparam("charset")
            if coding is None:
                page=response.read()
            else:
                page=response.read()
                page=page.decode(coding).encode('utf-8')
            return ["200",page]
        except Exception,e:
            print str(e)
            return [str(e),None]
        
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
    
def main(seeds,crawl_count):
    craw=MyCrawler(seeds)
    craw.crawling(seeds,crawl_count)
if __name__=="__main__":
    main(["http://www.baidu.com","http://www.google.com.hk"],50)
分享到:
评论

相关推荐

    Python爬虫入门教程

    爬虫的抓取策略有六种:深度优先遍历策略、宽度优先遍历策略、反向链接数策略、Partial PageRank策略等等。每种策略都有其优缺,选择哪种策略取决于具体的应用场景。 防爬虫机制是企业常用的防御手段,KS-WAF(网站...

    基于Python的网络爬虫技术研究

    - 宽度优先遍历策略:按照访问的顺序,将新页面中找到的链接立即加入待爬取队列。 - 最佳优先搜索策略:对目标网页的重要性进行评估,优先爬取评价高的页面。 ### 2.3 反爬虫策略采取概述 为了避免被网站封禁或...

    宽度优先搜索策略爬虫源码

    宽度优先搜索(Breadth-First ...总之,宽度优先搜索策略在网络爬虫中有着广泛的应用,通过合理的设计和实现,可以有效地抓取和处理网页数据。理解并掌握BFS的原理和实现方法,对于提升爬虫项目的质量和效率至关重要。

    Crawler:关于Java和Python爬虫那些事儿

    《自己动手写网络爬虫》,并基于Python3和Java实现 为什么采用宽度优先搜索策略? 深度优先遍历可能会在深度上过“深”而陷入“黑洞”; 重要的网页往往距离种子网页比较近,越深的网页的重要性越低; 万维网深度...

    基于Python的网络爬虫技术研究 (1).pdf

    对于爬虫的抓取策略,有深度优先遍历策略、根据反向链接数的策略、宽度优先遍历策略和最佳优先搜索策略等多种。这些策略各有优劣,但最终目的都是为了优先爬取重要网页信息。在实际应用中,根据目标网站和爬取任务的...

    《Python爬虫大数据采集与挖掘》期末考试考题汇总带答案.doc

    图的遍历算法有两种,即深度优先算法 DFS 和宽度优先算法 BFS。 23. 按照链接的形式不同,可以分为绝对链接、相对链接和书签。 24. 按照链接的路径指向不同,可以分为内部链接、锚点链接和外部链接。 25. 按照...

    基于Java和Python的爬虫项目实战源码.zip

    宽度优先遍历有利于多爬虫的合作抓取,多爬虫合作通常先抓取站内链接,抓取的封闭性很强; 解析HTML网页---Jsoup Maven中配置: &lt;dependency&gt; &lt;groupId&gt;org.jsoup&lt;/gorup&gt; &lt;artifactId&gt;jsoup&lt;/artifactId&gt; ...

    python的BFS,DFS,UCS,A星算法

    首先,宽度优先搜索(BFS)是一种遍历或搜索树或图的方法,它从根节点开始,然后扩展最接近根的节点,然后再扩展下一层的节点。BFS通常用于找出两个节点之间的最短路径,尤其是在所有边权重相等的情况下。在Python中...

    浅谈网络爬虫中广度优先算法和代码实现.pdf

    在爬虫技术中,两种常见的遍历策略是深度优先搜索(DFS, Depth-First Search)和广度优先搜索(BFS, Breadth-First Search)。本篇将重点探讨广度优先算法及其在网络爬虫中的应用。 首先,广度优先算法的核心思想是...

    实现深度优先广度优先算法

    深度优先搜索(DFS, Depth-First Search)和广度优先搜索(BFS, Breadth-First Search)是图论中的两种基本搜索策略,用于遍历或搜索树或图。这两种算法在解决各种问题中有着广泛的应用,如路径查找、判断连通性、...

    网络爬虫的相关介绍

    2. **队列管理**:采用宽度优先或深度优先的策略管理待抓取的URL队列,确保爬虫能够高效地探索互联网的结构。 3. **多线程处理**:为了提高效率,爬虫程序通常采用多线程或分布式架构,多个线程并行处理URL队列,...

    数据结构中图的遍历算法

    本文将深入探讨“图的遍历”这一主题,特别是使用广度优先搜索(BFS)算法来实现。 **广度优先搜索(BFS)** 广度优先搜索是一种用于遍历或搜索树或图的算法。它的基本思想是从起始节点开始,首先访问所有相邻节点...

    基于Python的校园网搜索引擎研究.pdf

    常见的爬取策略包括宽度优先策略、深度优先策略等,这些策略通过遍历算法在互联网中下载信息,并根据用户需求对信息进行筛选和格式化。 此外,文章还提及了CAN总线在汽车电子技术中的应用,通过EMS(Engine ...

    基于python技术面向校园网原型搜索引擎设计.pdf

    网络爬虫通过遍历算法下载网络中的信息,遍历算法包括但不限于宽度优先搜索(BFS)和深度优先搜索(DFS)。BFS适用于寻找最短路径问题,而DFS适合于探索未知的或复杂的网络结构。另外,PageRank算法被用于分析网页的...

    Python实现验证码识别

    在Python中实现验证码识别是一项常见的任务,特别是在网络爬虫领域,因为很多网站为了防止机器人自动操作,会使用验证码来验证用户是否为真实的人。本文主要关注的是识图验证码的识别,这种类型的验证码通常包含一些...

    Python自动办公实例-用Python批量往Word文档中指定位置添加图片.zip

    Python作为一个强大的脚本语言,不仅适用于数据分析、网络爬虫和游戏开发,还非常适合进行办公自动化,比如处理大量Word文档。 在本实例中,我们将探讨以下几个核心知识点: 1. **Python与Office文档操作**:...

    Design-of-Data-Capture-Program-Based-on-Web-Crawler-Technology_【彩云小译】_【非对照】.docx

    总的来说,本文通过Python编程实现了一个深度优化的网络爬虫,结合PageRank算法和深度优先策略,提升了数据采集的效率和质量。同时,针对DeepWeb的爬虫算法设计则为获取深层次、更丰富信息提供了可能。这些技术和...

    基于表单爬虫的Web漏洞探测

    通过滑动窗口的方式,爬虫可以在不同深度和宽度之间进行灵活切换,从而避免过度爬行或遗漏重要表单页面。 2. **基于位置特征与复现频率的导航链接发现策略**:该策略主要关注于表单页面的分布特性,即表单通常出现...

Global site tag (gtag.js) - Google Analytics