2019.2.23 更新:
其实第一种方法,在写完这篇博文后没几天我就给实现了。本来想过几天就专门写一篇博文对实现方法、代码作介绍的,但我懒啊,就一直拖到现在还没写。。。先把实现的地址放上吧,相关博文有空了再说(一般来说,有空了再搞 等于 不搞了?=。=)。
项目 github:scrapy_redis_expiredupefilter
地址:https://github.com/AaronJny/scrapy_redis_expiredupefilter
emmm,名字起得有点low。毕竟起名苦手= =!
PS:这篇博文主要讨论思路、方法,有细节伪代码,但没有完整实现代码。如果有时间,后面会专门写一篇实现的博文,附上完整代码。
转载请注明出处:https://blog.csdn.net/aaronjny/article/details/84899262
scrapy应该算是当下最流行、也最受欢迎的python爬虫框架了。利用scrapy,爬虫工程师可以快速开发高效的爬虫程序。
scrapy默认是单机模式,但可以借助scrapy_redis,通过简单的配置,实现单机scrapy程序到分布式爬虫程序的转化。其内在原理可以简单理解为:借助公用的redis数据库,实现请求队列和去重集合的共享,进而使各主机上分布式部署的爬虫程序协调工作。
这里就不深入讨论了,网上相关的资料有很多,这也不是本文讨论的重点,不再多做赘述。
当分布式爬虫开发完成后,有一个问题就被摆在我们面前:如何让请求指纹在指定时间后自动过期?
如果不是很理解这个问题的话,我们举个例子。
假设,我们接到一个需求,需要采集某网站的博文信息。具体的需求是这样的:
- 1.网站有一个博文列表的入口,可以翻页,我们的爬虫定时运行,每次采集前30页的数据。需要注意的是,这个列表的排序不是按照发布时间排列的,并且博文的更新或者点赞等其他操作都有可能使博文的排序提升。
- 2.一个博文在一个月内只采集一次,当月再次遇到它时不会二次采集,一个月后再碰到会进行采集。
在scrapy中,当一个请求被spider发起时,它会先经过去重器校验,校验的过程大致如下:
- 1.对发起的请求的相关信息,通过特定的算法,生成一个请求指纹
- 2.判断这个指纹是否存在于指纹集合中
- 3.如果在指纹集合,则表示此请求曾经执行过,舍弃它
- 4.如果不在,则表示此为第一次执行,将指纹加入到指纹集合中,并将请求加入到请求队列中,等待调度
我们可以在scrapy中找到对应源码,我加上了注释:
def request_seen(self, request):
# 计算request的指纹
fp = self.request_fingerprint(request)
# 判断指纹是否已经存在
if fp in self.fingerprints:
# 已存在
return True
# 不存在,加入到指纹集合中
self.fingerprints.add(fp)
但scrapy的去重集合是单机的,所以scrapy_redis为了实现分布式,重写了去重器,这是其中一部分代码:
def request_seen(self, request):
"""Returns True if request was already seen.
Parameters
----------
request : scrapy.http.Request
Returns