1.去重的应用场景:
如果你只是做一些简单的爬虫,可能不会遇到这种问题,可是如果你正在做一个大型的全站爬虫,或是一个持久化的爬虫,那你一定会遇到这样的问题:刚开始爬虫速度还可以,随着待爬取的队列达到数亿级甚至更多的时候,爬虫会变得非常慢,为什么会出现这样的问题呢? 我们以scrapy为例来说明并解决这个问题。
2.scrapy去重原理
Scrapy 有自动去重功能,它的去重使用了 Python 中的集合。这个集合记录了 Scrapy 中每个 Request 的指纹,这个指纹实际上就是 Request 的散列值。
在scrapy中发出一个请求时,会有一个参数dont_filter,而scrapy会根据这个参数来判断是否去重。
scrapy 对 request 不做去重很简单,只需要在 request 对象中设置dont_filter为 True。默认是False, 默认是去重,改为True就不去重了。比如说:
yield scrapy.Request(url, callback=self.get_response, dont_filter=True)
那么,scrapy是怎么去重的呢,让我们从源码角度来分析一下scrapy是怎么去重的。我们可以看看 Scrapy 的源代码,如下所示:
核心源代码如下:
import hashlib
def request_fingerprint(request, include_headers=None):
if include_headers:
include_headers = tuple(to_bytes(h.lower())
for h in sorted(include_headers))
cache = _fingerprint_cache.setdefault(request, {
})
if include_headers not in cache:
fp = hashlib.sha1()
fp.update(to_bytes(request.method))
fp.update(to_bytes(canonicalize_url(request.url)))
fp.update(request.body