分布式爬虫及Bloom fileter去重

分布式爬虫介绍

1.使用redis:

虽然scrapy帮我们将爬虫程序处理成了多线程加异步(默认100个线程),但是我们只能在一台主机上运行,所以爬取速率还是很有限的,分布式爬虫将多台主机组合起来,共同完成一个爬虫任务,这将大大提高爬虫效率。

2.维护爬虫队列

我们要做的就是在多台主机上同时运行爬虫任务协同爬取,而协同爬取的前提就是共享爬虫队列,这样主机就不需要各自维护爬虫队列,而是从共享爬取队列中存取Request。
而维护爬虫队列最好的选择之一大概就是Redis了,因为redis采取的是先进先出的模式,我们就可以通过它来实现先进先出式爬取队列,另外redis中的集合的元素师无序且不重复的,我们可以很方便的实现随机排序且不重复的爬取队列。

3.去重

Scrapy中自带了去重机制,原理是使用了Python中的集合,这个集合记录了Scrapy中每个Request的指纹(也就是字符串),这个指纹实际上就是Request的散列值,Scrapy通过识别Request的指纹来判断这个请求是否已经存在。
对于分布式爬虫来说,我们肯定不能再用每个爬虫各自的集合来去重了,因为这样还是每个主机单独维护自己的队列,不能做到共享。

我们可以使用redis的集合作为指纹集合来共享爬取队列,每台主机新生成Request之后,把该Request的指纹与集合对比来判断是否要爬取该Request。

4.防止中断

在Scrapy中,爬虫运行时的Request队列放在内存中。爬虫中断后,这个队列的空间就被释放了,此队列就被销毁了。所以一旦爬虫再次运行,爬虫就相当于全新的爬取过程。
要做到中断后继续爬取,我们可以将队列的Request保存起来,下次爬取直接读取保存数据即可获取上次爬取的队列。我们在Scrapy中指定一个爬取队列的存储路径即可,这个路径使用JOB_DIR变量来标识,我们可以用如下命令来实现:
scrapy crawl spider -s JOB_DIR=crawl/spider
在分布式爬虫中我们完全不需要担心这个问题,因为爬取队列本身就保存在数据库中,即使爬虫中断了,数据库中的Request还是存在的,下次启动时会接着上次中断的地方继续爬取。
所以当redis为空时,爬虫会继续爬取,爬虫会重新爬取,当redis不为空时,爬虫会接着上次中断之处继续爬取。

实现分布式爬虫

我们要做一个分布式爬虫,首先实现一个共享的爬取队列,还要实现去重的功能。另外,重写一个调度器的实现,使之可以从共享的爬取队列存取Request。不过前人已经帮我们造好了轮子,这就是Scrapy-Redis。它为我们提供了Scrapy分布式的队列、调度器、去重等功能,Github地址

配置分布式爬虫

配置分布式爬虫非常简单。在settings.py加上以下几段代码即可:


REDIS_URL = 'redis://:xxx@xxx:xxx' #连接redis(master的配置)
#REDIS_PARAMS  = {"password":'xxz199439',}#slave的配置
#REDIS_HOST = "112.74.60.22"
3REDIS_PORT = 1994

SCHEDULER = "scrapy_redis.scheduler.Scheduler"
#调度器

DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

#配置每次爬虫完成后,任务队列不清空
SCHEDULER_PERSIST = True

redis和scrapy一样采取了指纹机制,每个指纹的长度为40,且每个字符都是一个16进制数。每个16进制的占用空间为4b,一个指纹就占用了20B,一亿个指纹就需要2G的存储空间,而这仅是指纹的占用数,还不包括爬取队列,所以当爬取量上亿后,Scrapy-Redis提供的集合去重已经不能满足我们的要求了。所以这里推荐一种更加节省内存的去重算法Bloom Filter(布隆过滤器)。

Bloom Filter

布隆过滤器的原理是,当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。
优点:
运行快速,内存占用小。一般方法是将集合中所有元素保存起来,然后通过比较确定。链表、树、哈希表等数据结构都是这种思路。但是随着集合中元素的增加,我们需要的存储空间越来越大。同时检索速度也越来越慢。
缺点:

  1. 随着存入的元素数量增加,误算率随之增加。但是如果元素数量太少,则使用散列表足矣。
配置Bloom Filter

和配置scrapy-redis一样,在views.py中加入下面的一段代码:

REDIS_URL = 'redis://:xxzx@x:xxx' #master的配置
REDIS_PARAMS  = {"password":'xxz199439',}#slave的配置
REDIS_HOST = "112.74.60.22"
REDIS_PORT = 1994
#
SCHEDULER = "scrapy_redis_bloomfilter.scheduler.Scheduler"
# # 调度器
DUPEFILTER_CLASS = "scrapy_redis_bloomfilter.dupefilter.RFPDupeFilter"
#
BLOOMFILTER_HASH_NUMBER = 6
BLOOMFILTER_BIT = 30

# REDIS_START_URLS_AS_SET = True

#配置每次爬虫完成后,任务队列不清空
SCHEDULER_PERSIST = True
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值