Scrapy-Redis的dupefilter未去重主因是DUPEFILTER_CLASS配置失效或Redis连接失败导致回退内存去重;需显式配置scrapy_redis.dupefilter.RFPDupeFilter并确保REDIS_URL连通。

Scrapy-Redis 的 dupefilter 为什么没去重?
根本原因通常是 DUPEFILTER_CLASS 配置没生效,或者 Redis 连接失败导致去重逻辑退化为内存去重。Scrapy 默认用 RFPDupeFilter,但 Scrapy-Redis 要求显式指定为 scrapy_redis.dupefilter.RFPDupeFilter。
- 检查
settings.py是否写了DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter',漏掉引号或路径错一个字母都会静默回退到本地去重 - 确认
REDIS_URL可连通:redis-cli -u redis://localhost:6379 ping返回PONG才算数;连接失败时日志里通常没报错,但dupefilter会自动 fallback - 注意:
RFPDupeFilter依赖request_fingerprint,如果自定义了make_requests_from_url或改了Request的meta/headers,指纹可能变,导致误判为新请求
多个爬虫共用同一个 redis_key 会怎样?
所有爬虫实例会从同一个队列取任务,但彼此之间不协调,容易重复抓同一 URL,尤其在起始请求多、响应快的场景下。这不是 bug,是设计使然——Scrapy-Redis 本身不负责“任务分片”,只提供共享队列能力。
- 不同爬虫必须用不同
redis_key,比如myproject:start_urls和myproject:detail_urls,否则调度完全混乱 - 如果真要协同消费(如 A 爬列表页,B 爬详情页),得靠业务逻辑约定 key 命名 + 自定义
next_requests,而不是指望框架自动分流 -
redis_key在RedisSpider里默认是spider.name + ':start_urls',别直接改类属性,应在实例化时传参或重写start_urls属性
RedisSpider 启动后没拉取任何 URL?
最常见的是 Redis 队列为空,或爬虫没识别到队列变化。Scrapy-Redis 不监听 Redis 的 pub/sub,而是轮询(默认每 5 秒一次),所以往队列塞数据后不会立刻触发。
- 手动推入测试 URL:
redis-cli -u redis://localhost:6379 lpush myproject:start_urls '{"url": "https://example.com", "callback": "parse"}'—— 注意必须是 JSON 字符串,且字段名严格匹配Request构造参数 - 检查
REDIS_START_URLS_KEY和爬虫name是否一致;RedisSpider默认读spider.name + ':start_urls',如果改过name但没同步改 key,就找不到队列 - 日志里搜
Reading start URLs from redis key,没这句说明根本没走到队列读取逻辑,大概率是继承错了类(用了Spider而非RedisSpider)或start_requests方法被意外重写了
并发量上不去,CPU/Redis 都很闲?
瓶颈往往卡在 Scrapy 自身的并发控制层,而非 Redis。Scrapy-Redis 只管队列读写,真正发请求还是走 Scrapy 的 CONCURRENT_REQUESTS 和 DOWNLOAD_DELAY。
立即学习“Python免费学习笔记(深入)”;
-
CONCURRENT_REQUESTS默认是 16,但 Redis 读取频率SCHEDULER_IDLE_BEFORE_CLOSE(默认 0)和SCHEDULER_QUEUE_REFRESH_MS(默认 5000)会拖慢任务获取节奏 - 把
SCHEDULER_QUEUE_REFRESH_MS改小(比如 100),能加快从 Redis 拿新请求的速度,但别设成 0,否则空轮询打爆 Redis - 确认没开着
AUTOTHROTTLE_ENABLED = True,它会动态压低并发,和CONCURRENT_REQUESTS冲突,调试阶段建议关掉
Redis 本身不是瓶颈,除非你单机跑几十个爬虫实例还用默认配置;真正要注意的是 start_urls 队列里有没有足够多的初始 URL——没料,再快的引擎也转不起来。


















