• 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即可

  • 相关阅读:
    赛况激烈!2022 OceanBase数据库大赛50强诞生
    思科的简易配置
    【Leetcode】1052. Grumpy Bookstore Owner
    [附源码]计算机毕业设计基于Springboot三星小区车辆登记系统
    antd Carousel 重写dot样式
    gitlab Activating and deactivating users
    mEngine.hasImplicitBatchDimension
    unresolved external symbol OPENSSL_UplinkTable
    Orillusion引擎正式开源!AIGC时代下的WebGPU轻量级3D渲染引擎!
    Win11dll文件缺失怎么修复?Win11系统dll文件丢失的解决方法
  • 原文地址:https://blog.csdn.net/Qwertyuiop2016/article/details/127103954