bigywater.tech
Scrapy · 25

DepthMiddleware:DEPTH_LIMIT 与 DEPTH_PRIORITY

DEPTH_LIMIT 到底从哪里开始数?DEPTH_PRIORITY 为什么能改成广度优先?重定向、起始请求、跨域名的 depth 怎么算?这篇在一个二叉树站点上把层号序列和请求数量都量出来。

63 → 3
DEPTH_LIMIT 从不限到 1,二叉树站点抓取的页面数
011222233333333
DEPTH_PRIORITY = 1 时服务器收到页面的层号序列(默认 011223333223333)
depth_reset
让跨域名的链接从 0 重新数,避免被 DEPTH_LIMIT 误伤的 meta 键

DEPTH_LIMIT

实测 · 本机执行输出
   DEPTH_LIMIT     服务器收到  request_depth_max  各层请求数(层 0、1、2…)
             0        63                  5  [1, 2, 4, 8, 16, 32]
             1         3                  1  [1, 2]
             2         7                  2  [1, 2, 4]
             3        15                  3  [1, 2, 4, 8]
             4        31                  4  [1, 2, 4, 8, 16]
  DEPTH_LIMIT=2 的日志:[scrapy.spidermiddlewares.depth] DEBUG: Ignoring link (depth > 2): http://127.0.0.1:9960/t
  response.meta["depth"] 与页面所在层(DEPTH_LIMIT=2):t0:0, t2:1, t1:1, t6:2, t4:2, t3:2, t5:2 …

DepthMiddleware 给每个从响应产生的请求设置 meta["depth"] = 响应深度 + 1,超过 DEPTH_LIMIT 就丢掉。起始请求深度为 0,所以 DEPTH_LIMIT = N 会抓到第 N 层。

DEPTH_PRIORITY

实测 · 本机执行输出
  默认(DEPTH_PRIORITY = 0)              011223333223333  (共 15 个页面,每个字符是该页面所在层)
  DEPTH_PRIORITY = 1                  011222233333333  (共 15 个页面,每个字符是该页面所在层)
  DEPTH_PRIORITY = 1 + FIFO 队列        011222233333333  (共 15 个页面,每个字符是该页面所在层)
  DEPTH_PRIORITY = -1(深度越深优先级越高)      011223333223333  (共 15 个页面,每个字符是该页面所在层)

请求优先级减去 深度 × DEPTH_PRIORITY。为正数时浅层优先(广度优先),为 0 时按调度器默认顺序(后进先出,深度优先)。

depth 的传递

实测 · 本机执行输出
  leaf    response.meta["depth"] = 1(redirect_reasons=[302])
  t0      response.meta["depth"] = 0
  t1      response.meta["depth"] = 1
  t2      response.meta["depth"] = 0
  t3      response.meta["depth"] = 1
  服务器收到:['/t0', '/t3', '/t2', '/red', '/leaf', '/t1']

重定向沿用原请求的 depth;depth_reset 让请求的深度归零;回调里手动写 meta 的 depth 会被覆盖。

起始请求

实测 · 本机执行输出
  t0: depth = 3
  t1: depth = 4
  同样的代码,DEPTH_LIMIT=3:回调被调用的页面 ['t0'](子请求深度 4 > 3 被丢弃)

start() 里的请求自带 depth 时会保留,子请求从这个值 +1 数起。

跨域名

实测 · 本机执行输出
  不加 depth_reset:回调被调用 [('1', '/t0', 0), ('l', '/t1', 1)](h=127.0.0.1/localhost 首字母)
  跨域链接加 depth_reset:回调被调用 [('1', '/t0', 0), ('l', '/t1', 0), ('l', '/t3', 1)](h=127.0.0.1/localhost 首字母)

depth 不区分域名,要让每个域名自己从 0 数,给跨域链接加 depth_reset。

分步演示

爬取深度
本步的对象

    本文用到的工具与边界

    • 本机 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,数字每次运行会有小幅抖动。二叉树站点:节点 n 的子节点是 2n+1、2n+2;并发 1;DEPTH_STATS_VERBOSE = 1 时 stats 里有 request_depth_count/N
    • 没有验证:重试请求的 depth(应该沿用,没测);DEPTH_STATS_VERBOSE 在真实站点上对 stats 大小的影响;DEPTH_LIMIT 与 CrawlSpider 规则的组合(见后面的文章);depth 与 JOBDIR 恢复;FIFO 队列和 DEPTH_PRIORITY 同层顺序的细节(这里只看了层号序列)
    京ICP备2026067502号-1京公网安备11010502063487号