bigywater.tech
Scrapy · 10

dont_filter:什么时候该绕过去重

dont_filter=True 能让请求绕过去重。什么情形必须用,什么情形用了会出事?这篇用有环的站点、重试、重定向和轮询四个场景实测:什么时候少了它会丢请求,什么时候多了它会停不下来。

799 个
有环站点全部 dont_filter=True,1 秒内发出的请求数(去重时只要 3 个)
0 次
重定向到已抓过的 URL 时 /go 回调被调用的次数(dont_filter 默认 False)
True
重试请求的 dont_filter 值

绕过去重的代价

实测 · 本机执行输出
  默认(去重):服务器收到 3 个请求;finish_reason=finished;dupefilter/filtered=3;request_depth_max=2
  dont_filter=True,CLOSESPIDER_PAGECOUNT=50:服务器收到 50 个请求;finish_reason=closespider_pagecount;dupefilter/filtered=0;request_depth_max=26
  dont_filter=True,DEPTH_LIMIT=4:服务器收到 19 个请求;finish_reason=finished;dupefilter/filtered=0;request_depth_max=4
  dont_filter=True,CLOSESPIDER_TIMEOUT=1:服务器收到 799 个请求;finish_reason=closespider_timeout;dupefilter/filtered=0;request_depth_max=400

去重是防止爬虫在环里打转的第一道防线;对所有请求关掉它,就必须有 DEPTH_LIMIT、CLOSESPIDER_PAGECOUNT 或 CLOSESPIDER_TIMEOUT 之类的刹车。

Scrapy 内部请求

实测 · 本机执行输出
  请求            dont_filter   已重试次数   重定向产生的
  /robots.txt   False         0         False
  /flaky        False         0         False
  /go           False         0         False
  /target       False         0         True
  /flaky        True          1         False
  /flaky        True          2         False

重试请求会被设成 dont_filter=True,所以不会被去重吃掉;重定向沿用原请求的值;robots.txt 请求是 False。

重定向的坑

实测 · 本机执行输出
  /go 的请求 dont_filter=False(默认):服务器收到 ['/target', '/go'];/go 的回调没有被调用;dupefilter/filtered=1;finish_reason=finished
  /go 的请求 dont_filter=True:服务器收到 ['/target', '/go', '/target'];/go 的回调被调用;dupefilter/filtered=0;finish_reason=finished

重定向产生的请求同样经过去重。如果重定向目标之前已经抓过,默认会被过滤,回调不会被调用。想要这个响应就给原请求设 dont_filter=True。

轮询

实测 · 本机执行输出
  不加 dont_filter:1 个请求(想轮询 5 次),dupefilter/filtered=1
  dont_filter=True:5 个请求,dupefilter/filtered=0

反复请求同一个 URL 想拿最新数据时,每次都要 dont_filter=True,否则第二次起就被过滤。

分步演示

dont_filter
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.8 / Scrapy 2.19.0 / Twisted 26.4.0 / lxml 6.1.3 / parsel 1.12.1(临时虚拟环境);所有请求只发给本机自己起的测试服务器(127.0.0.1,端口 9960 以上,不访问任何真实网站);服务器可以按实验需要制造延迟、重定向、压缩、断连等行为,并记录收到的原始请求;每个实验在临时目录里新建 Scrapy 项目或单文件 spider,命令输出来自真实的 scrapy 进程;计时用 time.perf_counter,数字每次运行会有小幅抖动。有环站点是三个页面互相链接;重定向用 302;重试用前两次返回 503 的路径;刹车开关用 CLOSESPIDER_PAGECOUNT=50、DEPTH_LIMIT=4、CLOSESPIDER_TIMEOUT=1;并发均为 1
    • 没有验证:dont_filter 请求在 HTTP 缓存里的表现;自定义 dupefilter 里对 dont_filter 的处理;redirect 中间件里 meta 的 dont_redirect 与 dont_filter 的组合;CLOSESPIDER_TIMEOUT 下“799”这个数字随机器速度变化(只作量级参考)
    京ICP备2026067502号-1京公网安备11010502063487号