Scrapy 去重

Scrapy 去重

Scrapy 去重

RFPDupeFilter这个类 set()集合

那么在 scrapy 中是如何来使用这个类的方法的呢?什么时候使用,这个流程是怎样的呢?

这个可以追溯到 scrapy.core.scheduler 中定义的 Scheduler 类来决定。

现在就来看看 Scheduler 类中和过滤重复 url 有关的内容。

在 Scheduler 类中,在调度时,采用了 memory queue 和 disk queue 的存储方法,所以,有一个入队的方法,在入队前,就要对 request 进行检查,检查是否是重复,如果已经重复了,就不入队了。

Scrapy 去重

这里两个条件控制,首先是配置中 dont_filter,如果它是 True,就说明是不筛选的,如果是 False,才是要筛选的。后面的 request_seen() 在默认内置的筛选方法中,就是 RFPDupeFilter() 中的方法,检查 request 是否已经存在。

只有要筛选且没有见过这个 request,才会去筛选 url。

所以这里已经很清晰了,调度器收到了 enqueue_request() 调用时,会检查这个 url 重复的判断开关,如果要筛选,就要检查这个 request 是否已经存在了;这里的检查 if 如果成立,就直接返回了,只有不成立时,才会有后续的存储操作,也就是入队.

下面来看看 scrapy 中是如何判断两个 url 重复的。

关键的函数是 request_fingerprint,这个是判断是否重复的关键实现方(scrapy.utils.request.request_fingerprint())。

默认的调用情况下,计算的内容包括 method、格式化后的 url、请求正文,还有就是 http headers 是可选的。

和通常情况下不一样的是,这里的计算指纹,不是单纯的比较了 url 是否一致。计算的结果是一串 hash 16 进制数字