先给结论:

核心结论: 不是没用 Redis Scheduler,而是 dont_filter=True 跳过了去重器,所以 Redis 里不会创建 dupefilter 这个 Key。

问题背景

在 scrapy-redis 爬虫中,如果不重写 start_requests(),而是使用父类默认方法,会发现 Redis 里没有 xxx:dupefilter 这个 Set。


调度流程

Spider → Engine → Scheduler → DupeFilter(去重器)

是否触发去重,取决于 request.dont_filter 的值。


父类 start_requests() 做了什么?

scrapy_redis.spiders.RedisSpider 默认实现大致如下:

yield Request(url, dont_filter=True)

关键就在 dont_filter=True


调度器内部逻辑

Scheduler.enqueue_request() 中有如下判断:

if not request.dont_filter:
    if self.df.request_seen(request):
        return False

逻辑链路:

  1. dont_filter=True → 跳过去重逻辑
  2. 不调用 request_seen()
  3. 不执行 SADD top250:dupefilter fingerprint
  4. Redis 里不创建 dupefilter Key

对比验证

场景方式Redis dupefilter
使用父类默认 start_requests()dont_filter=True❌ 不创建
自己重写,使用默认 Requestdont_filter=False(默认)✅ 创建

自己重写示例:

def start_requests(self):
    yield scrapy.Request(url)  # dont_filter 默认为 False,会触发去重

dont_filter=True 的影响范围

dont_filter=True 只影响

  • 是否调用去重器(DupeFilter)

不影响

  • 是否使用 Redis Scheduler
  • 是否使用 Redis 队列

为什么 scrapy-redis 这样设计?

RedisSpider 作为分布式爬虫入口,URL 是从 Redis 队列 lpush 进来的,设计假设是:

  • 入口 URL 由外部控制,不需要在 start_requests 阶段去重
  • 若默认开启去重,多个节点并发启动时,start URL 可能被直接拦截

所以默认 dont_filter=True,跳过去重。


总结

问题答案
是否使用 Redis Scheduler?
为什么没有 dupefilter?因为 dont_filter=True,跳过了去重
是不是没用 Redis?不是
去重什么时候发生?dont_filter=False

本质理解:dont_filter 控制的是单个 Request 是否走去重流程,与使用哪个 Scheduler 无关。

标签: none

添加新评论