实测 gRPC 的 max_concurrent_streams:服务端在 SETTINGS 帧里公布,客户端自己排队而不是被拒绝;排队时间算在 deadline 里;限制是每条连接的;长流会占满名额让普通调用无限期排队。
在 Scrapy 2.19.0 本机实测并发限制:默认 asyncio reactor 下 CONCURRENT_REQUESTS_PER_DOMAIN 没有生效(单域名 48 个请求峰值始终 48,SelectReactor 下峰值等于设置值);全局 CONCURRENT_REQUESTS 和 DOWNLOAD_DELAY 有效;PER_IP 和 DOWNLOAD_SLOTS 同样失效;无 reactor 模式的限制来自 aiohttp 连接器。
实测 2.19 的下载延迟:DOWNLOAD_DELAY = 0.2 且默认 ±50% 抖动时,实际平均间隔是 243 ms 而不是 200 ms(总耗时 24.2 s 对 20.1 s);延迟按“发出到发出”计算,慢响应只会让在途请求变多;每个域名独立计时;DOWNLOAD_SLOTS 可以单独设 delay;RANDOMIZE_DOWNLOAD_DELAY 与 download_delay 属性已弃用。
实测下载槽:槽名默认是小写主机名(忽略端口和协议),CONCURRENT_REQUESTS_PER_IP 下变成解析后的 IP,meta["download_slot"] 优先;把两个主机名合并成一个槽总耗时从 4.0 s 变 7.9 s,把一个主机拆成两个槽从 7.9 s 变 3.8 s;DOWNLOAD_SLOTS 可按槽名设 delay;空闲的槽在 60~120 秒后被回收。
实测 AutoThrottle:延迟每次向 latency ÷ 目标并发 走一半,约 8 个响应收敛;变慢时一步跳升、变快时折半下降;非 200 响应不会让延迟下降(404 后 delay 保持 506 ms,200 后降到 25 ms);DOWNLOAD_DELAY 是下限、MAX_DELAY 是上限;它只调延迟,实际并发峰值会超过目标。
实测 RetryMiddleware:默认 RETRY_TIMES = 2(共 3 次请求);8 个状态码(500、502、503、504、522、524、408、429)和连接被拒/超时/断开/DNS 失败都会重试,404/403/400 不重试;重试之间只隔 1 ms 没有退避;重试请求优先级 -1 排到所有正常请求之后;meta 的 dont_retry、max_retry_times 可逐请求控制;get_retry_request 可在回调里手动重试。
实测重定向中间件:301/302/303 的 POST 变 GET 丢请求体、307/308 保持 POST;meta 记录 redirect_urls/reasons/times/ttl;REDIRECT_MAX_TIMES = 20 时服务器收到 21 次请求后丢弃(errback 拿到 IgnoreRequest),跳回同一 URL 会被去重;跨主机删除 Cookie/Authorization;meta refresh 秒数 < 100 就立即跳转。
实测 Scrapy 2.19 的 HTTP 缓存:默认关闭,打开后第二次运行 3 个请求全部命中、服务器 0 个请求;每个请求在磁盘上 7 个文件;DummyPolicy 连 no-store 和 404/500 都缓存;RFC2616Policy 尊重 no-store、max-age、ETag/Last-Modified(304 用缓存正文);EXPIRATION_SECS 过期;服务器关闭时用旧缓存兜底。
实测 CookiesMiddleware:Set-Cookie 自动存进 jar 并带到后续请求;headers 里的 Cookie 会被覆盖,要用 cookies 参数;meta["cookiejar"] 隔离多个会话,但必须自己一路传下去;Path、Secure、Domain、Max-Age 都按规则生效;COOKIES_DEBUG 的日志;dont_merge_cookies。
实测 RobotsTxtMiddleware:内置默认 ROBOTSTXT_OBEY = False 而项目模板写 True;被禁请求抛 IgnoreRequest 且不发出,robots.txt 每个 netloc 只下载一次并排在前面;默认 UA 匹配 User-agent: Scrapy 组;robots.txt 404/500/超时/乱码一律放行;Crawl-delay 被忽略。
用原始套接字服务器看 Scrapy 2.19 发出的请求字节:默认头顺序是 Accept、Accept-Language、User-Agent、Accept-Encoding(gzip, deflate, br, zstd)、Host;请求自己的头 > DEFAULT_REQUEST_HEADERS > USER_AGENT 设置;USER_AGENT 设空串就不发 UA;头名规范成 Title-Case,列表值拆成多行;Request 的 POST 不带 Content-Type,FormRequest 才带。
在二叉树站点上实测 DepthMiddleware:DEPTH_LIMIT = 1/2/3/4 分别抓 3/7/15/31 个页面;DEPTH_PRIORITY = 1 把层号序列从 011223333223333(深度优先)变成 011222233333333(广度优先);重定向沿用 depth,depth_reset 归零,手动 meta depth 会被覆盖。