返回介绍

17.6 去重优化

发布于 2024-01-26 22:39:51 字数 2367 浏览 0 评论 0 收藏 0

最后在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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文