- 前言
- 基础篇
- 第1章 回顾 Python 编程
- 第2章 Web前端基础
- 第3章 初识网络爬虫
- 第4章 HTML 解析大法
- 第5章 数据存储(无数据库版)
- 第6章 实战项目:基础爬虫
- 第7章 实战项目:简单分布式爬虫
- 中级篇
- 第8章 数据存储(数据库版)
- 第9章 动态网站抓取
- 第10章 Web 端协议分析
- 第11章 终端协议分析
- 第12章 初窥 Scrapy 爬虫框架
- 第13章 深入 Scrapy 爬虫框架
- 第14章 实战项目:Scrapy 爬虫
- 深入篇
- 第15章 增量式爬虫
- 第16章 分布式爬虫与 Scrapy
- 第17章 实战项目:Scrapy 分布式爬虫
- 第18章 人性化 PySpider 爬虫框架
17.6 去重优化
最后在settings中配置scrapy_redis,代码如下:
# 使用scrapy_redis的调度器 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 在redis中保持scrapy-redis用到的各个队列,从而允许暂停和暂停后恢复 SCHEDULER_PERSIST = True # 使用scrapy_redis的去重方式 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" REDIS_HOST = '127.0.0.1' REDIS_PORT = 6379
经过以上步骤,一个分布式爬虫就搭建起来了,如果你想在远程服务器上使用,直接将IP和端口进行修改即可。
下面需要讲解一下去重优化的问题,我们看一下scrapy_redis中是如何实现的RFPDupeFilter。关键代码如下:
def request_seen(self, request): fp = request_fingerprint(request) added = self.server.sadd(self.key, fp) return not added
scrapy_redis是将生成的fingerprint放到Redis的set数据结构中进行去重的。接着看一下fingerprint是如何产生的,进入request_fingerprint方法中。
def request_fingerprint(request, include_headers=None): if include_headers: include_headers = tuple([h.lower() for h in sorted(include_headers)]) cache = _fingerprint_cache.setdefault(request, {}) if include_headers not in cache: fp = hashlib.sha1() fp.update(request.method) fp.update(canonicalize_url(request.url)) fp.update(request.body or '') 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]
从代码中看到依然调用的是scrapy自带的去重方式,只不过将fingerprint的存储换了个位置。之前我们提到过这是一种比较低效的去重方式,更好的方式是将Redis和BloomFilter结合起来。
推荐一个开源项目:https://github.com/qiyeboy/Scrapy_Redis_Bloomfilter ,它是在scrapy-redis的基础上加入了BloomFilter的功能。使用方法如下:
git clone https:// github.com/qiyeboy/Scrapy_Redis_Bloomfilter
将源码包clone到本地,并将BloomfilterOnRedis_Demo目录下的scrapy_redis文件夹拷贝到Scrapy项目中settings.py的同级文件夹,以yunqiCrawl项目为例,在settings.py中增加如下几个字段:
·FILTER_URL=None
·FILTER_HOST='localhost'
·FILTER_PORT=6379
·FILTER_DB=0
·SCHEDULER_QUEUE_CLASS='yunqiCrawl.scrapy_redis.queue.SpiderPriorityQueue'
将之前使用的官方SCHEDULER替换为本地目录的SCHEDULER:
SCHEDULER = "yunqiCrawl.scrapy_redis.scheduler.Scheduler"
最后将DUPEFILTER_CLASS=“scrapy_redis.dupefilter.RFPDupeFilter”删除即可。
到此为止实战项目全部完成,最终的抓取效果如图17-4所示。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论