知其然,知其所以然
Scrapy 内部原理 2026-10-12

JOBDIR:暂停和恢复时磁盘上存了什么

实测 JOBDIR:Ctrl-C 后留下 requests.queue/ 磁盘队列、active.json、requests.seen(41 × 22 字节)、spider.state;续跑 22 个页面零重复,self.state 累加(18 + 22 = 40);自己写的 start() 起始请求在续跑时被去重,默认 start_urls 会重发;kill -9 会丢掉 requests.seen 内容,恢复等于重头抓(重叠 22 个);meta 里放不能 pickle 的对象会让 24 个请求在中断时永久丢失。

Scrapy JOBDIR 暂停恢复 requests.queue requests.seen spider.state 真实验证 动画演示
Scrapy 内部原理 2026-10-12

scraper 的背压:SCRAPER_SLOT_MAX_ACTIVE_SIZE 与慢 pipeline

实测 scraper 的背压:待处理响应的字节数超过 SCRAPER_SLOT_MAX_ACTIVE_SIZE(默认 5,000,000)引擎就不再取新请求;400 个 100 KB 页面、慢回调下,上限 1 MB → 100 MB 让 RSS 从 99.5 涨到 239.4 MiB、耗时从 11.1 s 降到 0.9 s;快回调没有堆积;小响应按 1024 字节算。

Scrapy 背压 SCRAPER_SLOT_MAX_ACTIVE_SIZE scraper 内存 真实验证 动画演示
Scrapy 内部原理 2026-10-12

async def 回调:协程怎么接入 Twisted

实测 async def 回调:return 单个/列表、yield、异步生成器都被接受;异步生成器边产出边处理(136 ms / 1138 ms);20 个 await 0.3 s 的回调总耗时 0.33 s,同步 sleep 要 6.25 s;直接 await Deferred 抛 RuntimeError,要用 maybe_deferred_to_future;回调里可以用 aiohttp;async errback 可以 yield item。

Scrapy asyncio async def 回调 Deferred 异步生成器 真实验证 动画演示
Scrapy 内部原理 2026-10-12

DropItem、IgnoreRequest、CloseSpider:异常在引擎里怎么处理

实测 Scrapy 的控制异常:中间件里抛 IgnoreRequest 走 errback、回调里抛则是普通错误;CloseSpider 只在回调和 start() 里生效,在 pipeline、下载器中间件、信号处理函数里抛只记 ERROR 不关爬虫;NotConfigured 悄悄(或带 WARNING)禁用组件;不支持的协议抛 NotSupported 且不重试。

Scrapy 异常 IgnoreRequest CloseSpider NotConfigured NotSupported 真实验证 动画演示
Scrapy 内部原理 2026-10-12

errback 与 Failure:下载失败时拿到什么

用能制造各种故障的服务器看 errback 拿到的 Failure:500/404 是 HttpError(带 response),连接被拒、DNS 失败、超时、数据截断、超过 DOWNLOAD_MAXSIZE 各有自己的 scrapy.exceptions 类,TLS 或解析错误统一包成 DownloadFailedError;failure.check 可分支;errback 返回 None 吞掉、返回 Request 重调度、不定义则记 ERROR。

Scrapy errback Failure 异常类型 DownloadFailedError HttpError 真实验证 动画演示
Scrapy 内部原理 2026-10-12

request.meta 里的特殊键

从 Scrapy 2.19 源码 grep 出 45 个 request.meta 键(公开 40、内部 5;输入键 24、输出键 10)并实测前面没讲过的:download_timeout、download_maxsize、handle_httpstatus_*、bindaddress、referrer_policy;请求级 Basic 认证 http_user / http_pass,以及 HTTPAUTH_DOMAIN 因匹配 netloc(含端口)而对带端口的 URL 失效的坑。

Scrapy request.meta 特殊键 download_timeout referrer_policy http_user 真实验证 动画演示
Scrapy 内部原理 2026-10-12

下载处理器:http、https、file 的分派

实测 Scrapy 2.19 的下载处理器:协议到处理器的映射;file:// 与 data: 返回的响应类;自己写 BaseDownloadHandler 注册新协议、把 ftp 设成 None 禁用;换成实验性的 AiohttpDownloadHandler 后每域名并发限制真的生效(峰值 4 对 48),但 bindaddress 被忽略。

Scrapy 下载处理器 DOWNLOAD_HANDLERS file data URI aiohttp 真实验证 动画演示
Scrapy 内部原理 2026-10-12

HTTP/2 下载处理器

用 nginx(HTTPS + HTTP/2)实测 H2DownloadHandler:41 个请求只用 1 条连接(默认处理器 20 条),response.protocol = h2;DOWNLOAD_VERIFY_CERTIFICATES 默认 False,自签名证书能连、设 True 就失败;服务器的最大并发流 4 把总耗时从 0.66 s 拉到 3.12 s;不支持代理。

Scrapy HTTP/2 H2DownloadHandler 多路复用 TLS 真实验证 动画演示
Scrapy 内部原理 2026-10-12

FilesPipeline:文件下载与去重

实测 FilesPipeline:file_urls 下载到 full/<SHA1(URL)><扩展名>,checksum 是内容 md5,重复 URL 只请求一次;失败的 404/302 没有结果也不缓存;第二次运行 3 个文件变 uptodate 不再请求,FILES_EXPIRES=0 全部重下;MEDIA_ALLOW_REDIRECTS 默认不跟 302;重写 file_path 自定义文件名。

Scrapy FilesPipeline 文件下载 FILES_STORE uptodate 真实验证 动画演示
Scrapy 内部原理 2026-10-12

spider 参数:-a 传参与 custom_settings

实测 spider 参数:-a 的值总是字符串并写成实例属性(覆盖同名类属性);__init__ 漏了 **kwargs 会 TypeError;-a start_urls=字符串 被按字符遍历,抛 Missing scheme 却退出码为 0;-a 没有 = 退出码 2;CrawlerProcess.crawl(S, page=3) 保留类型,与设置互相独立。

Scrapy spider参数 -a start_urls __init__ 真实验证 动画演示
Scrapy 内部原理 2026-10-12

Item 类型:dict、Item、dataclass 与 ItemAdapter

实测四种 item 类型:ItemAdapter 给 dict/scrapy.Item/dataclass/attrs 同一套接口;scrapy.Item 赋值未声明字段抛 KeyError,dataclass 不检查类型;导出 jsonlines/csv 都能写,Item 的 serializer 生效,csv 表头取第一个 item;创建 10 万个 3 字段 item:dict 1.3 ms/万次,scrapy.Item 17.8 ms/万次(13.5 倍),dataclass 3.0 ms,内存 192 / 436 / 104 字节。

Scrapy Item dataclass attrs ItemAdapter 真实验证 动画演示
gRPC 2026-10-12

负载均衡:pick_first 与 round_robin 的区别

实测 gRPC 负载均衡的两个内置策略:pick_first 只用第一个后端,加入新后端不会被用上;round_robin 平均分配,新后端立即生效;停掉后端的切换行为;慢后端对两种策略的影响。

gRPC 负载均衡 pick_first round_robin 故障切换 shuffleAddressList Go 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号