Bloom Filter替换Scrapy-Redis集合去重

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_1290259791/article/details/82421015

Bloom Filter替换Scrapy-Redis集合去重

Scrapy-Redis源码解析传送门
Scrapy-Redis在dupefilter.py文件中主要使用Redis集合来保存Request的指纹,提供重复过滤。

dupefilter.py文件修改

修改其中的request_seen()方法。

    def request_seen(self, request):
        fp = self.request_fingerprint(request)
        added = self.server.sadd(self.key, fp)
        return added == 0

fp:获取Request的指纹。
added:通过Redis的set来保存fp,added返回添加的结果成功返回1,然后和0进行判断,返回Flase就是成功。

修改后的request_seen()方法。

    def request_seen(self, request):
        fp = self.request_fingerprint(request)
        if self.bf.exists(fp):
            return True
        self.bf.insert(fp)
        return False

fp:获取Request的指纹
再通过BloomFilter的exists方法来判断是否存在,返回True就是存在,不存在的话就调用insert来插入fp返回Flase。

初始化函数

修改之前。

    def __init__(self, server, key, debug=False):
        self.server = server
        self.key = key
        self.debug = debug
        self.logdupes = True

我们首先创建一个bloomfilter.py文件将我们实现的BloomFilter和HashMap导入进去。

from .bloomfilter import BloomFilter
    def __init__(self, server, key, debug, bit, hash_number):
        self.server = server
        self.key = key
        self.debug = debug
        self.bit = bit
        self.hash_number = hash_number
        self.logdupes = True
        self.bf = BloomFilter(server, self.key, bit, hash_number)

主要添加了bit移动的位数和hash_number散列函数的个数,然后就是调用BloomFilter类进行实例化。

from_setting()传递参数

其中bit和hash_number的参数需要使用from_setting()方法来传递。

    @classmethod
    def from_settings(cls, settings):
        server = get_redis_from_settings(settings)
        key = defaults.DUPEFILTER_KEY % {'timestamp': int(time.time())}
        debug = settings.getbool('DUPEFILTER_DEBUG')
        return cls(server, key=key, debug=debug)

首先在defaults.py文件中添加变量。

BLOOMFILTER_HASH_NUMBER = 6
BLOOMFILTER_BIT = 30
DUPEFILTER_DEBUG = False

修改之后的方法的内容。

    @classmethod
    def from_settings(cls, settings):
        server = get_redis_from_settings(settings)
        key = defaults.DUPEFILTER_KEY % {'timestamp': int(time.time())}
        debug = settings.getbool('DUPEFILTER_DEBUG', DUPEFILTER_DEBUG)
        bit = settings.getint('BLOOMFILTER_BIT', BLOOMFILTER_BIT)
        hash_number = settings.getint('BLOOMFILTER_HASH_NUMBER', BLOOMFILTER_HASH_NUMBER)
        return cls(server, key=key, debug=debug, bit=bit, hash_number=hash_number)

然后返回一个类实例。

这样就实现了Bloom Filter和Scrapy-Redis的对接。

使用

我们只修改了存常量参数的文件,修改都是在dupefilter文件中,修改了request_seen方法,还有初始化函数以及from_settings方法。添加了bloomfilter.py文件。
我们在使用的时候和Scrapy-Redis的方法一样都是在Scrapy的setting.py文件中添加配置,以上的修改是在源码中进行的,通过运行可以发现存储的格式是String类型,不是set类型类。

猜你喜欢

转载自blog.csdn.net/qq_1290259791/article/details/82421015