scrapy使用布隆过滤器

前言

搜一下scrapy布隆过滤器其实已经有现成的了,看了下代码发现还有能优化的地方,就在上面做了点优化

ScrapyRedisBloomFilter: https://github.com/Python3WebSpider/ScrapyRedisBloomFilter

优化点

代码里的去重逻辑主要是scrapy_redis_bloomfilter.dupefilter 这个文件,去重关键代码如下:
在这里插入图片描述
self.bf是一个布隆过滤器的实例。每执行一次bf.exists就会使用6个不同的hash函数计算出值,然后执行6次redis的getbit操作,判断相应的bit位。也就是说,bf.exists会和redis服务器进行6次交互操作,bf.insert也是6次,只是变成了setbit。(这里的6个指的是hash函数的个数,也就是设置的BLOOMFILTER_HASH_NUMBER 的默认值)

这就导致了去重一个url最少要和redis服务器交互6次(存在),最多是12次(不存在的情况)。如果网络差点或者数据量很大,那么去重所带来的网络开销会很大,同时也会卡住scrapy的异步逻辑,让scrapy变的很慢。

优化方式

redis其实已经实现了布隆过滤器,直接拿到用就行了,官方的优化肯定比咱们做的好。更重要的是,使用redis的布隆过滤器,只需要传一个url给redis服务端,服务端告诉你这个url存不存在,这样去重只需要和服务端进行一次交互就能完成。

python使用redis布隆过滤器
import redis

redis_url = "redis://127.0.0.1:6379"
server = redis.StrictRedis.from_url(redis_url, decode_responses=True)

bf = server.bf()
# redis key
key = "test"
# 错误率
errorRate = 0.001
# 去重数据量
capacity = 10000
if not server.exists(key):
    print(bf.create(key, errorRate, capacity))

for i in range(10):
    print(i, bf.add(key, f"http://www.httpbin.org/get?a={
      
      i}"))
for i in range(20):
    print(i, bf.add(key, f"http://www.httpbin.org/get?a={
      
      i}"))
for i in range(10):
    print(i, bf.exists(key, f"http://www.httpbin.org/get?a={
      
      i}"))

基本操作大概就是add和exists了,更多的命令看官方文档:https://redis.io/commands/?group=module。另外,python的接口和官方文档可能有点不一样,比如创建布隆过滤器,命令是BF.RESERVE,在python里的方法则是bf.create

要在redis中使用布隆过滤器,需要先加载一个插件,或者直接运行带布隆过滤器的docker版redis,这个可以参考:docker启动带布隆过滤器的redis

我是直接使用docker,如果要在docker设置redis的密码,启动命令如下:

docker run -d -p 6379:6379 --name redisbloom redislabs/rebloom:latest \
/usr/local/bin/redis-server \
--appendonly yes \
--requirepass "123456" \
--loadmodule "/usr/lib/redis/modules/redisbloom.so"

--requirepass 后面跟的就是密码

代码

改动的地方比较少,用上面的bf替换掉代码的bf即可

完整代码请看:https://github.com/kanadeblisst/scrapy_redis_bf

使用

安装

pip install scrapy-redis-bf

使用

将如下设置加入到scrapy项目的settings.py文件中

SCHEDULER = "scrapy_redis_bf.scheduler.Scheduler"

DUPEFILTER_CLASS = "scrapy_redis_bf.dupefilter.RFPDupeFilter"

REDIS_URL = 'redis://localhost:6379'

# 错误率
BLOOMFILTER_ERRORRATE = 0.001
# 去重量
BLOOMFILTER_CAPACITY = 10000
测试

GitHub项目的tests文件夹有个测试的scrapy项目,修改里面的REDIS_URL运行scrapy crawl test即可

猜你喜欢

转载自blog.csdn.net/Qwertyuiop2016/article/details/127103954
今日推荐