如何实现网址池URL Pool(云服务器、云主机、高防IP、高防服务器、香港服务器、美国服务器,编程语言)

时间:2024-05-05 04:11:55 作者 : 石家庄SEO 分类 : 编程语言
  • TAG :

    %E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E7%BD%91%E5%9D%80%E6%B1%A0URL+Pool

对于比较大型的爬虫来说,URL管理的管理是个核心问题,管理不好,就可能重复下载,也可能遗漏下载。这里,我们设计一个URL池来管理URL。
这个URL池就是一个生产者 - 消费者模式:

如何实现网址池URL Pool

生产者 - 消费者流程图

依葫芦画瓢,URLPool就是这样的

如何实现网址池URL Pool

设计的网络爬虫URLPool

我们从网址池的使用目的出发来设计网址池的接口,它应该具有以下功能:

往池子里面添加URL;

从池子里面取URL以下载;

池子内部要管理URL状态;

前面我提到的网址的状态有以下4中:

已经下载成功

下载多次失败无需再下载

正在下载

下载失败要再次尝试

前两个是永久状态,也就是已经下载成功的不再下载,多次尝试后仍失败的也就不再下载,它们需要永久存储起来,以便爬虫重启后,这种永久状态记录不会消失,已经成功下载的网址不再被重复下载永久存储的方法有很多种:

比如,直接写入文本文件,但它不利于查找某个URL是否已经存在文本中;
比如,直接写入的MySQL等关系型数据库,它利用查找,但是速度又比较慢,
比如,使用键值数据库,查找和速度都符合要求,是不错的选择!

我们这个URL池选用LevelDB来作为URL状态的永久存储.LevelDB是谷歌开源的一个键值数据库,速度非常快,同时自动压缩数据。我们用它先来实现一个UrlDB作为永久存储数据库。

UrlDB将被UrlPool使用,主要有三个方法被使用:

has(url)查看是否已经存在某url

set_success(url)存储url状态为成功

set_failure(url)存储url状态为失败

而正在下载和下载失败次数这两个URL的状态只需暂时保存在内容即可,我们把它们放到UrlPool这个类中进行管理接着我们来实现网址池:

UrlPool的实现有些复杂,且听我一一分解。

先看看它的主要成员及其用途:

self.db是一个UrlDB的示例,用来永久存储url的永久状态

self.pool是用来存放url的,它是一个字典(dict)结构,key是url的主机,值是一个用来存储这个主机的所有url的集合(set)。

self.pending用来管理正在下载的url状态。它是一个字典结构,key是url,value是它被pop的时间戳。当一个url被pop()时,就是它被下载的开始。当该url被set_status()时,就是下载结束的时刻。如果一个url被添加()入池时,发现它已经被套的时间超过pending_threshold时,就可以再次入库等待被下载。否则,暂不入池。

self.failue是一个字典,key是url,value是识别的次数,超过failure_threshold就会被永久记录为失败,不再尝试下载。

hub_pool是一个用来存储hub page面的字典,key是hub url,value是上次刷新该hub页面的时间。

以上成员就构成了我们这个网址池的数据结构,再通过以下成员方法对这个网址池进行操作:

1. load_cache()和dump_cache()对网址池进行缓存
load_cache()在init()中调用,创建池的时候,尝试去加载上次退出时缓存的URL池;
dump_cache()在del()中调用,也就是在网址池销毁前(比如爬虫意外退出),把内存中的URL pool缓存到硬盘。
这里使用了pickle模块,这是一个把内存数据序列化到硬盘的工具。

** 2. set_hubs()方法设置hub URL **
hub网页就是像百度新闻那样的页面,整个页面都是新闻的标题和链接,是我们真正需要的新闻的聚合页面,并且这样的页面会不断更新,把最新的新闻聚合到这样的页面,我们称它们为hub页面,其URL就是hub url。在新闻爬虫中添加大量的这样的url,有助于爬虫及时发现并抓取最新的新闻。
该方法就是将这样的hub url列表传给网址池,在爬虫从池中取URL时,根据时间间隔(self.hub_refresh_span)来取集枢纽网址。

** 3. add(),addmany(),push_to_pool()对网址池进行入池操作**
把url放入网址池时,先检查内存中的self.pending是否存在该url,即是否正在下载该。网址如果正在下载就不入池;如果正下载或已经超时,就进行到下一步;
接着检查该网址是否已经在性LevelDB中存在,存在就表明之前已经成功下载或彻底失败,不再下载了也不入池。如果没有则进行到下一步;
最后通过push_to_pool()把url放入self.pool中。存放的规则是,按照url的主机进行分类,相同主机的url放到一起,在取出时 -个主取一个url,尽量保证每次取出的一批url都是指向不同的服务器的,这样做的目的也是为了尽量减少对抓取目标服务器的请求压力。力争做一个服务器友好的爬虫O(∩∩ _∩)O

4. pop()对网址池进行出池操作
爬虫通过该方法,从网址池中获取一批url去下载。取出url分两步:
第一步,先从self.hub_pool中获得,方法是遍历hub_pool,检查每个集线器-URL距上次被弹出的时间间隔是否超过毂页面刷新间隔(self.hub_refresh_span),来决定毂-URL是否应该被弹出。
第二步,从self.pool中获取。前面push_to_pool中,介绍了流行的原则,就是每次取出的一批URL都是指向不同服务器的,有了self.pool的特殊数据结构,安装这个原则获取网址就简单了,按主机(自我.pool的键)遍历self.pool即可。

5. set_status()方法设置网址池中url的状态
其参数status_code是http响应的状态码。爬虫在下载完URL后进行url状态设置。
首先,把该url成self.pending中删除,已经下载完毕,不再是未决状态;
接着,根据STATUS_CODE来设置URL状态,200和404的直接设置为永久状态;其它状态就记录失败次数,并再次入池进行后续下载尝试。

通过以上成员变量和方法,我们把这个网址池(UrlPool)解析的清清楚楚。小猿们可以毫不客气的收藏起来,今后在写爬虫时可以用它方便的管理URL,并且这个实现只有一个PY文件,方便加入到任何项目中。

1.网址的管理
网址的管理,其目的就是为了:不重抓,不漏抓。

2. pickle模块
把内存数据保存到硬盘,再把硬盘数据重新加载到内存,这是很多程序停止和启动的必要步骤.pickle就是实现数据在内存和硬盘之间转移的模块。

3. leveldb模块
这是一个经典且强大的硬盘型key-value数据库,非常适合url-status这种结构的存储。

4. urllib.parse
解析网址的模块,在处理url时首先想到的模块就应该是它。

本文:如何实现网址池URL Pool的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:J-Hi快速开发平台到快在哪呢下一篇:

3 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18