Scrapy-Redis去重失效的四大原因:DUPEFILTER_CLASS路径错误、Redis连接失败、JOBDIR配置冲突、请求指纹未归一化,均会导致静默降级为内存去重。

DUPEFILTER_CLASS 配置没生效或写错路径
Scrapy 默认用 scrapy.dupefilter.RFPDupeFilter,但 Scrapy-Redis 的去重必须显式启用 scrapy_redis.dupefilter.RFPDupeFilter。漏掉引号、大小写错(比如写成 RfpDupeFilter)、路径少个下划线,都会导致配置静默失败,回退到内存去重。
检查 settings.py 中这行是否完整且无拼写错误:
DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'
常见错误包括:
- 写成
scrapy_redis.dupefilter.RfpDupeFilter(首字母小写) - 漏掉引号,变成
DUPEFILTER_CLASS = scrapy_redis.dupefilter.RFPDupeFilter - 路径写成
scrapy_redis.RFPDupeFilter(少了dupefilter.)
Redis 连接失败导致自动 fallback 到本地去重
只要 REDIS_URL 不通,RFPDupeFilter 就无法写入/查询 Redis 的 SET,它会悄悄退化为内存去重——此时所有节点各自维护独立集合,自然无法跨机器去重。
立即学习“Python免费学习笔记(深入)”;
验证方式很简单:
- 运行
redis-cli -u redis://localhost:6379 ping,必须返回PONG - 检查日志里有没有
Connected to Redis类似提示;没有?大概率连不上 - 注意:连接失败时通常不报错,只在首次调用
request_seen时静默降级
JOBDIR 配置干扰了 Redis 去重
JOBDIR 是 Scrapy 本地持久化去重记录的路径,一旦设置,它会优先接管去重逻辑,直接绕过 RFPDupeFilter 和 Redis。
如果你同时写了:
DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'<br>JOBDIR = './jobdir'
那去重实际走的是 JOBDIR/requests.seen 文件,和 Redis 完全无关。解决方法只有两个:
- 删掉
JOBDIR配置(推荐,分布式场景不该依赖本地文件) - 或者确认你真需要本地断点续爬,且接受它与 Redis 去重互斥
请求指纹被意外改变,导致“同一 URL”算作不同请求
RFPDupeFilter 的去重依据是 request_fingerprint(),它对 URL、HTTP 方法、body、headers、cookies 全部敏感。哪怕只是 headers 多了个 User-Agent 或 query 参数带了个随机 ts=1725285840,指纹就变了。
典型场景:
- 手动构造 Request 时加了动态
headers或meta - 用了
response.follow(url, dont_filter=False)但没清理掉原响应带过来的随机参数 - 目标页要求带时间戳才能访问,但你没在去重前标准化 URL(比如正则去掉
&r=\d+\.\d+)
这时得自定义 dupefilter,重写 request_seen 方法,在计算指纹前先归一化 URL 或 body。
最容易被忽略的是:去重是否生效,根本没法靠“看日志有没有报错”来判断。它不报错、不警告,只默默失效——所以每次改完配置,务必用 redis-cli 查 SMEMBERS myspider:dupefilter 确认指纹真存进去了。


















