繁体   English   中英

Scrapy-Redis中的Dupefilter无法正常工作

[英]Dupefilter in Scrapy-Redis not working as expected

我对使用Scrapy-RedisRedis中存储刮擦的物品感兴趣。 特别是, 基于Redis的请求重复过滤器似乎是一个有用的功能。

首先,我在https://doc.scrapy.org/en/latest/intro/tutorial.html#extracting-data-in-our-spider中修改了蜘蛛,如下所示:

import scrapy
from tutorial.items import QuoteItem

class QuotesSpider(scrapy.Spider):
    name = "quotes"
    start_urls = [
        'http://quotes.toscrape.com/page/1/',
        'http://quotes.toscrape.com/page/2/',
    ]

    custom_settings = {'SCHEDULER': 'scrapy_redis.scheduler.Scheduler',
                       'DUPEFILTER_CLASS': 'scrapy_redis.dupefilter.RFPDupeFilter',
                       'ITEM_PIPELINES': {'scrapy_redis.pipelines.RedisPipeline': 300}}

    def parse(self, response):
        for quote in response.css('div.quote'):
            item = QuoteItem()
            item['text'] = quote.css('span.text::text').extract_first()
            item['author'] = quote.css('small.author::text').extract_first()
            item['tags'] = quote.css('div.tags a.tag::text').extract()
            yield item

其中I产生的项目中使用scrapy startproject tutorial在命令行和定义QuoteItemitems.py

import scrapy

class QuoteItem(scrapy.Item):
    text = scrapy.Field()
    author = scrapy.Field()
    tags = scrapy.Field()

基本上,我的自述中的“用法”一节中实现的设置, 每个蜘蛛设置,并取得了蜘蛛yieldItem对象,而不是一个常规的Python字典。 (我认为这对于触发Item Pipeline是必要的)。

现在,如果我使用命令行中的scrapy crawl quotesscrapy crawl quotes ,然后执行redis-cli ,则会看到一个quotes:items键:

127.0.0.1:6379> keys *
1) "quotes:items"

这是长度为20的列表:

127.0.0.1:6379> llen quotes:items
(integer) 20

如果我再次运行scrapy crawl quotes ,则列表的长度将增加一倍,达到40:

127.0.0.1:6379> llen quotes:items
(integer) 40

但是,我希望quotes:items的长度仍为20,因为我只是重新刮了相同的页面。 我在这里做错什么了吗?

Scrapy-redis不会自动过滤重复项。

(请求)dupefilter与爬网中的请求有关。 您想要的东西似乎类似于deltafetch中间件: https : //github.com/scrapy-plugins/scrapy-deltafetch

您可能需要修改deltafetch才能与分布式存储一起使用,也许redis的位图功能将适合这种情况。

这是我最后解决问题的方法。 首先,正如在另一个问题中向我指出的, 如何在Scrapy中实现自定义dupefilter? ,使用start_urls类变量可实现start_requests的实现,其中产生的Request对象具有dont_filter=True 要禁用此功能并使用默认的dont_filter=False ,我直接实现了start_requests

import scrapy
from tutorial.items import QuoteItem

class QuotesSpider(scrapy.Spider):
    name = "quotes"

    custom_settings = {
                       'SCHEDULER': 'scrapy_redis.scheduler.Scheduler',
                       'DUPEFILTER_CLASS': 'tutorial.dupefilter.RedisDupeFilter',
                       'ITEM_PIPELINES': {'scrapy_redis.pipelines.RedisPipeline': 300}
                       }

    def start_requests(self):
        urls = [
            'http://quotes.toscrape.com/page/1/',
            'http://quotes.toscrape.com/page/2/',
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):
        for quote in response.css('div.quote'):
            item = QuoteItem()
            item['text'] = quote.css('span.text::text').extract_first()
            item['author'] = quote.css('small.author::text').extract_first()
            item['tags'] = quote.css('div.tags a.tag::text').extract()
            yield item

其次,正如Rolando所指出的,默认情况下,指纹不会在不同的爬网中持久存在。 为了实现这一点,我将Scrapy-Redis的RFPDupeFilter类子类化:

import scrapy_redis.dupefilter
from scrapy_redis.connection import get_redis_from_settings


class RedisDupeFilter(scrapy_redis.dupefilter.RFPDupeFilter):
    @classmethod
    def from_settings(cls, settings):
        server = get_redis_from_settings(settings)
        key = "URLs_seen"                               # Use a fixed key instead of one containing a timestamp
        debug = settings.getbool('DUPEFILTER_DEBUG')
        return cls(server=server, key=key, debug=debug)

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

    def clear(self):
        pass                                            # Don't delete the key from Redis

主要区别在于(1)将key设置为固定值(不包含时间戳),以及(2)有效禁用了clear方法,该方法在Scrapy-Redis的实现中从Redis删除key

现在,当我第二次运行scrapy crawl quotes时,我看到了预期的日志输出

2017-05-05 15:13:46 [scrapy_redis.dupefilter] DEBUG: Filtered duplicate request <GET http://quotes.toscrape.com/page/1/> - no more duplicates will be shown (see DUPEFILTER_DEBUG to show all duplicates)

而且没有任何物品被刮掉。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM