deltafetch 是 scrapy 第三方中间件插件,能跳过已抓取的页面:它在请求发出前基于 url 等指纹判断是否已存在记录,若匹配则直接丢弃请求,避免重复 http 调用,但无法识别内容更新,仅解决完全重复请求问题。

DeltaFetch 是什么,它真能跳过已抓取的页面?
DeltaFetch 不是 Scrapy 内置功能,而是一个第三方中间件插件,它的核心作用是在请求发出前检查该 URL 是否已被成功抓取过——如果已存在对应 item 或 response 的指纹记录,就直接丢弃该请求。它不依赖数据库去查“内容是否重复”,而是靠请求指纹(默认是 URL + 可选参数)做快速判断,因此不能识别内容更新后的重新抓取,只解决“完全重复请求”的问题。
常见错误现象:DeltaFetch 启用后抓取量没减少,或日志里仍显示大量 Filtered duplicate request 但实际没生效——大概率是没正确配置指纹字段,或没启用 DUPEFILTER_CLASS 配合。
- 必须同时设置
DELTAFETCH_ENABLED = True和DUPEFILTER_CLASS = 'scrapy.dupefilters.RFPDupeFilter'(Scrapy 默认即此值,但显式写上更稳妥) - 默认指纹只基于 URL,若目标页通过
?page=1、?t=1712345678等参数区分版本,需用deltafetch_key显式指定去重字段,例如在Request中传入:Request(url, meta={'deltafetch_key': url.split('?')[0]}) - 它不自动清理历史指纹,长期运行需定期清空
deltafetch.json文件(默认路径),否则文件会越来越大,影响性能
如何安装并启用 DeltaFetch?
它不是 pip install scrapy-deltafetch 就完事——这个包名早已失效。当前唯一可用版本是社区维护的 scrapy-deltafetch(注意无横线),但仅支持 Python 3.7+ 和 Scrapy 2.0+;旧项目若用 Scrapy 1.x,则只能降级使用 fork 分支或改用 scrapy-redis 自建去重逻辑。
实操建议:
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
- 执行:
pip install scrapy-deltafetch(确认安装后pip show scrapy-deltafetch输出版本 ≥ 2.0.0) - 在
settings.py中添加:DELTAFETCH_ENABLED = True DELTAFETCH_FILE = 'deltafetch.json' # 可选,指定存储路径 DELTAFETCH_RESET = False # 设为 True 每次启动清空历史,调试用
- 在
DOWNLOADER_MIDDLEWARES中启用中间件:'scrapy_deltafetch.DeltaFetch': 100(数值需低于RetryMiddleware,否则重试请求可能绕过 DeltaFetch)
为什么抓取结果没变,但 DeltaFetch 日志显示“filtered”?
这是最常被误解的一点:DeltaFetch 的 “filtered” 仅表示该请求被跳过,不代表对应页面内容没变化。它不会比对 HTML 内容、标题、时间戳等字段,只认指纹。所以即使页面实际已更新,只要 URL 和 deltafetch_key 没变,就会被过滤。
典型场景:
- 新闻列表页分页链接不变(如
/news?page=2),但后台数据刷新了 → DeltaFetch 会跳过,导致漏抓新条目 - 商品详情页 URL 固定,但价格/库存字段每天更新 → 同样会被跳过,除非你主动修改
deltafetch_key加入时间戳或版本号 - 使用
scrapy.FormRequestPOST 提交时,默认指纹不含 body,需手动设置:meta={'deltafetch_key': f"{url}_{hashlib.md5(formdata.encode()).hexdigest()}"}
DeltaFetch 和自带 DUPEFILTER 有什么区别?
Scrapy 原生 RFPDupeFilter 在 Scheduler 阶段去重,而 DeltaFetch 是 Downloader Middleware,在请求真正发出前拦截。这意味着:
- DeltaFetch 能节省 HTTP 请求开销(不发请求),原生去重只是不入队列,但若请求已进队列再被滤掉,仍可能占用调度资源
- DeltaFetch 支持持久化存储(JSON 文件),重启后仍有效;原生去重默认只在内存中,除非你配了
JOBDIR - 二者可共存,但 DeltaFetch 的判断优先级更高——它先拦,拦不住才交给 DUPEFILTER
- 注意:若同时启用
JOBDIR和 DeltaFetch,需确保两者指纹逻辑一致,否则可能漏抓或误判
真正要实现“内容变更检测”,得配合 scrapy-redis-bloom 或自己在 parse 里计算 HTML MD5 存 DB,DeltaFetch 只负责最轻量的请求级跳过——这点容易被高估,也最容易被忽略。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










