scrapy使用布隆过滤器实现增量爬取

1,941 阅读1分钟

scrapy使用布隆过滤器实现增量爬取

之前看了很多关于scrapy-redis使用bloomfilter进行持久化存储进行url去重的例子,可是发现没有一种适用于scrapy,于是萌生了基于现有scrapy-redis-bloomfilter库进行改写的想法。

经过修改,此脚本可以做一个初步的文本内容去重

言归正传,直接上代码:

settings.py

# 散列函数的个数,默认为6,可以自行修改
BLOOMFILTER_HASH_NUMBER_URL = 6
# Bloom Filter的bit参数,默认30,占用128MB空间,去重量级1亿
BLOOMFILTER_BIT_URL = 30
# redis连接方式
REDIS_URL = 'redis://user:password@host:port/0'

spiders.py

#code by Kirinshy
import scrapy
from gne import GeneralNewsExtractor
from scrapy.utils.project import get_project_settings
from redis import Redis
from scrapy_redis_bloomfilter.bloomfilter import BloomFilter

class CrawlerSpider(scrapy.Spider):
    name = 'crawler'
    settings = get_project_settings()
    server = Redis.from_url(settings.get("REDIS_URL"))

    def start_requests(self):
        url_list = []
        for url in url_list:
        	#使用布隆过滤器进行去重
            if not self.dul_url_bf(url,'url_finger'):
                yield scrapy.Request(url,callback=self.parse_detail)

    def parse_detail(self,response):
        content = response.xpath().extract_first()
        #使用布隆过滤器进行去重
        if not self.dul_url_bf(content,'content_finger'):
            print(content)
        
    #此处传入url,或者文本正文,key可以传递指纹名称
    def dul_url_bf(self, url , key):
        '''
        url去重,如果url已经存在返回True,反之把url写入bloomfilter,并返回False(bf组件的exist()存在的时候返回1, 不存在返回false)
        :param url:
        :return: 如果存在返回True,不存在返回False
        '''
        bf = BloomFilter(server=self.server, key= key,
                         hash_number=self.settings.get("BLOOMFILTER_HASH_NUMBER_URL"),
                         bit=self.settings.get("BLOOMFILTER_BIT_URL"))
        if bf.exists(url):
            print(f'dupeurl:{url}')
            return True
        else:
            bf.insert(url)
            return False

以上便是需要修改的代码,另感谢崔大之前发布的scrapy-redis-bloomfilter包,确实让我能够偷懒不少!~

如需转载,请注明出处!~谢谢配合!