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

DepthMiddleware:DEPTH_LIMIT 与 DEPTH_PRIORITY

在二叉树站点上实测 DepthMiddleware:DEPTH_LIMIT = 1/2/3/4 分别抓 3/7/15/31 个页面;DEPTH_PRIORITY = 1 把层号序列从 011223333223333(深度优先)变成 011222233333333(广度优先);重定向沿用 depth,depth_reset 归零,手动 meta depth 会被覆盖。

Scrapy DepthMiddleware DEPTH_LIMIT DEPTH_PRIORITY depth_reset 真实验证 动画演示
Scrapy 内部原理 2026-10-12

OffsiteMiddleware:allowed_domains 的匹配规则

实测 allowed_domains 与 OffsiteMiddleware:正则 ^(.*\.)?(域名)$ 只比主机名,子域名自动放行,写成带端口或带协议的值一个都匹配不上且没有警告;被过滤请求静默丢弃(无回调、无 errback),stats offsite/filtered、offsite/domains,日志每个域名只记一条;allow_offsite / dont_filter 可绕过;start_urls 默认不被过滤。

Scrapy OffsiteMiddleware allowed_domains allow_offsite 真实验证 动画演示
Scrapy 内部原理 2026-10-12

HttpCompressionMiddleware:压缩响应的解压

实测 HttpCompressionMiddleware:gzip、x-gzip、deflate(含裸 deflate)、br、zstd 和叠加编码都能解回 12,026 字节原文;不支持的 compress 原样保留并警告,假 gzip 抛 BadGzipFile,截断的 gzip 返回已解出的部分;DOWNLOAD_MAXSIZE 拦住 20 KB 解成 20 MiB 的炸弹,DOWNLOAD_WARNSIZE 只警告。

Scrapy HttpCompressionMiddleware gzip brotli zstd 解压炸弹 真实验证 动画演示
Scrapy 内部原理 2026-10-12

HttpProxyMiddleware:环境变量代理与 request.meta 里的 proxy

用假代理实测 HttpProxyMiddleware:meta["proxy"] 让请求行变成绝对 URI,URL 里的凭据变成 Proxy-Authorization: Basic;启动时读取 http_proxy/https_proxy/no_proxy(大小写都行),meta["proxy"] = None 可逐个请求关掉;HTTPPROXY_ENABLED = 0 只关环境变量;https 先发 CONNECT;407 是 HttpError。

Scrapy HttpProxyMiddleware 代理 Proxy-Authorization CONNECT 真实验证 动画演示
Scrapy 内部原理 2026-10-12

Selector:xpath、css 与 re 的底层是什么

实测 Selector 的底层:parsel 1.12.1 + lxml 6.1.3(libxml2 2.14.6),css 先被 cssselect 翻译成 XPath;::text 与 //text()、string() 取文本的差别;libxml2 对坏 HTML 的修复;XML 命名空间要 remove_namespaces;1 MB 文档上 xpath 取 href 28.9 ms、等价 css 178.0 ms、css :nth-child(100) 1203.4 ms。

Scrapy Selector parsel xpath css lxml 真实验证 动画演示
Scrapy 内部原理 2026-10-12

LinkExtractor:链接是怎么被找到并过滤的

在一个含 base href、重复、pdf、mailto、nofollow 的页面上实测 LinkExtractor:默认 13 个链接;allow/deny 是完整 URL 上的正则;restrict_css、restrict_text 限定链接文字;tags="*" 通配;canonicalize 合并参数顺序不同的链接;91 个默认过滤的扩展名;nofollow 链接照常提取。

Scrapy LinkExtractor 链接提取 allow restrict_css canonicalize 真实验证 动画演示
Scrapy 内部原理 2026-10-12

CrawlSpider 的 Rule:follow 与 callback 的组合

实测 CrawlSpider 的 Rule:没有 callback 时 follow=True、有 callback 时 follow=False(11 个页面 vs 4 个);同一链接被多条规则命中只归第一条;meta 里有 rule 和 link_text;process_links / process_request 可过滤和丢弃;自己定义 parse 不破坏规则;XML 响应里的链接不被跟踪。

Scrapy CrawlSpider Rule follow process_links process_request 真实验证 动画演示
Scrapy 内部原理 2026-10-12

SitemapSpider:sitemap 索引的递归抓取

实测 SitemapSpider:从 robots.txt 的 Sitemap: 行出发递归索引、解开 .xml.gz 与即时 gzip;sitemap_rules 取第一个匹配并丢弃不匹配的 URL;sitemap_follow 过滤子 sitemap;sitemap_filter 按 lastmod 过滤;sitemap_alternate_links 把 3 个页面变 6 个;Content-Type 是 text/plain 的合法 sitemap 会被当作无效而忽略。

Scrapy SitemapSpider sitemap robots.txt sitemap_rules 真实验证 动画演示
Scrapy 内部原理 2026-10-12

FormRequest.from_response:表单字段是怎么拼出来的

实测 FormRequest.from_response:2.19 里已弃用(推荐 form2request);默认收集隐藏字段、选中的 checkbox/radio/select、textarea,连 disabled 字段也会带上;clickdata 的 nr 是 form.inputs 里的序号;formdata 里 None 删字段、列表变多个同名参数;GET 表单字段进查询串;enctype multipart 被忽略。

Scrapy FormRequest from_response 表单 clickdata 真实验证 动画演示
Scrapy 内部原理 2026-10-12

Feed 导出:FEEDS 的格式、批次与存储

实测 FEEDS:同一批 item 写 json/jsonlines/csv/xml/pickle/marshal(422/415/141/669/432/354 字节);json 默认转义中文,csv 默认 UTF-8;fields 选列;本地文件默认追加,json 追加会得到不合法的 JSON;batch_item_count 把 25 个 item 拆成 3 个文件;item_classes、gzip 后处理、stdout:、store_empty。

Scrapy Feed导出 FEEDS json csv batch_item_count 真实验证 动画演示
Scrapy 内部原理 2026-10-12

统计信息:stats 里每个数字怎么来的

逐项对账 Scrapy 的 stats:5 个请求里 response_count 5 而 response_received_count 4(302 被中间件消费);response_bytes 与线上字节完全相等(92 / 20,077),request_bytes 比线上少 5 字节(Host 里的端口);自定义 inc_value/max_value;DummyStatsCollector 与 STATS_DUMP=0;结束日志 25 项而 spider.closed() 里 20 项。

Scrapy 统计信息 stats StatsCollector request_bytes 真实验证 动画演示
Scrapy 内部原理 2026-10-12

扩展:CloseSpider 与 MemoryUsage

实测 CloseSpider 与 MemoryUsage:PAGECOUNT = 10 实际收到 24 个响应、ITEMCOUNT = 10 实际 32 个 item(都因在途请求而超出);ERRORCOUNT 只数回调异常、不数 404;TIMEOUT、TIMEOUT_NO_ITEM、PAGECOUNT_NO_ITEM 的关闭原因;内存读数是峰值 RSS 且默认 60 秒才更新一次,超过 MEMUSAGE_LIMIT_MB 以 memusage_exceeded 关闭。

Scrapy CloseSpider MemoryUsage CLOSESPIDER_PAGECOUNT MEMUSAGE_LIMIT_MB 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号