大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

人生苦短 我用Python

扩大
缩小

Scrapy 增量式爬虫

Scrapy 增量式爬虫

https://blog.csdn.net/mygodit/article/details/83931009

https://blog.csdn.net/mygodit/article/details/83896412

https://blog.csdn.net/qq_39965716/article/details/81073015

一、定义

二、原理

  spider构造的第一个Request请求经由引擎交给了Scheduler,Scheduler中构造一个request对象,并将这个对象存入一个Scheduler的队列中,入队之前会生成一个对应的,唯一的指纹,下一个request对象入队之前,会先比对指纹是否已经存在,以此来达到request对象去重的目的。

  Scheduler中Request对象的初始化属性,其中dont_filter表示不去重,默认是False。所以scrapy框架默认是去重的。

1 class Request(object_ref):
2     def __init__(self, url, callback=None, method='GET', headers=None, body=None,
3                  cookies=None, meta=None, encoding='utf-8', priority=0,
4                  dont_filter=False, errback=None, flags=None):
Rquest

爬虫组件Spider中,负责构造request对象是 start_requests(self) 函数。Spider构造的request对象修改了dont_filter属性。

源码如下:

def start_requests(self):
cls = self.__class__
if method_is_overridden(cls, Spider, 'make_requests_from_url'):
warnings.warn(
"Spider.make_requests_from_url method is deprecated; it "
"won't be called in future Scrapy releases. Please "
"override Spider.start_requests method instead (see %s.%s)." % (
cls.__module__, cls.__name__
),
)
for url in self.start_urls:
yield self.make_requests_from_url(url)
else:
for url in self.start_urls:
yield Request(url, dont_filter=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Scrapy去重的原理
Scrapy去重原理是通过sha1()加密request对象的url,method,body属性生成一个十六进制的40位随机字符串,称为指纹。将每个request对象对应的唯一指纹保存到Scheduler队列中,下次请求时,通过对比指纹,来达到request对象去重的目的。
生成指纹集合的源码如下:

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 or b'')
if include_headers:
for hdr in include_headers:
if hdr in request.headers:
fp.update(hdr)
for v in request.headers.getlist(hdr):
fp.update(v)
cache[include_headers] = fp.hexdigest()
return cache[include_headers]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
存储在Scheduler中的reqeust队列,是放在内存上的,如果服务器关闭,或者重启,内存中的缓存就会清空,下次请求就会继续访问原来发送过的请求。

增量式爬虫的意义就是将reques队列持久化存储,以此来达到永久性的缓存。

对此需要用到scrapy_redis(需要pip install scarpy_redis),将request对象的队列和指纹集合存储的位置替换成redis。如下图所示:

 

只需要在settings.py文件中添加一些配置,就能实现持久化去重的效果:

 1 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
 2 SCHEDULER = "scrapy_redis.scheduler.Scheduler"
 3 SCHEDULER_PERSIST = True
 4 
 5 # 添加redis链接
 6 REDIS_URL = "redis://127.0.0.1:6379"
 7 
 8 # 或者使用下面的方式
 9 # REDIS_HOST = "127.0.0.1"
10 # REDIS_PORT = 6379
11 
12 # 在pipeline中添加存储信息的scrapy_redis管道
13 ITEM_PIPELINES = {
14     'scrapy_redis.pipelines.RedisPipeline': 400,
15 }

 

posted on 2019-04-30 11:09  GuoZeping  阅读(176)  评论(0编辑  收藏  举报

导航