抓取诊断时,大部分人先看状态码:200 就放心,404 就去修,5xx 就去查服务器。但蜘蛛在一次请求里拿到的不只是一个数字,还有一整组响应头。这些头信息决定了它怎么解析内容、要不要重新下载、下一次什么时候再来。状态码正确、响应头写错,同样会让抓取结果打折扣。
Content-Type 与字符集:决定蜘蛛怎么读这段内容
响应头里的类型声明,是蜘蛛判断「这是不是一篇网页」的第一依据。
- charset 缺失或与页面声明不一致:HTML 里写 UTF-8,响应头写别的编码,蜘蛛按响应头解析,正文可能变成乱码,影响内容提取。
- 类型写成 application/octet-stream 或 text/plain:页面路径返回下载类型,蜘蛛可能当成文件处理,而不是当作可解析的 HTML 页面。
- 接口返回 JSON 却挂在可索引路径下:内容本来不是给用户看的页面,却占用了抓取配额。
这几类问题的共同点是:用户在浏览器里看不出异常,因为浏览器容错强;而蜘蛛按声明解析,出错就直接体现在正文质量上。
压缩与传输方式:体积小不等于传输完整
支持 gzip 或 brotli 能让同样的 HTML 少传不少字节,对蜘蛛和用户都是好事。需要注意的是压缩之后不能出现截断,传输中途断开会让蜘蛛拿到不完整的文档。用分块传输、没有 Content-Length 通常没有问题,但如果前面的代理对分块处理出错,蜘蛛也可能读到残缺内容。日志里同一 URL 反复抓取、单次抓取体积明显偏小,就值得往这个方向查。
缓存相关的头:让回访更省,但别让更新迟到
ETag 和 Last-Modified 的作用是让蜘蛛回访时能带上校验条件询问,内容没变就返回 304,省掉一次完整下载。这对抓取预算是正向的。但要注意,304 只表示「内容没变」,并不代表蜘蛛会因此调整已有索引;反过来,如果页面更新后缓存标记没有跟着变化,蜘蛛可能一直收到 304,始终看不到新内容。
另一个方向是给 HTML 设置很长的 Cache-Control: max-age 或 immutable。用户端可能被 CDN 缓存住,蜘蛛回访时也拿到旧版本,更新被推迟。静态资源适合长期缓存,页面本身通常不适合。
Location:跳转链要收敛到落地页
Location 是另一处容易出问题的地方。单次跳转属于正常的路径调整,但跳转链太长时,每次抓取都要多花几次请求,还容易在中途丢失参数。更稳妥的做法是让所有变体都直接指向最终落地页,而不是 A 跳到 B、B 再跳到 C。
X-Robots-Tag:藏在头里的索引指令
有些站点不方便改 HTML,就用响应头里的 X-Robots-Tag 控制索引状态。它确实有效,但也容易被忽略:某个中间层、CDN 规则或历史配置给整站加上了这个字段,页面却照常返回 200,从表面看一切正常。排查「抓取正常但迟迟没有进入索引」这类情况时,值得专门看一眼响应头里有没有这个字段。
Retry-After:过载时的礼貌,不是常规限流手段
服务器压力大时返回 503 并带上 Retry-After,比直接连接超时更友好,等于告诉蜘蛛多久之后再来。但不要长期拿它当挡箭牌:持续返回 503 会打乱抓取节奏,恢复之后也需要一段时间才能回到原来的访问频率。
Vary 与 Set-Cookie:缓存层面的连带影响
Vary: User-Agent 的含义是不同 UA 给不同版本。如果 CDN 真的按 UA 分版本缓存,蜘蛛拿到的可能是移动版或精简版 HTML,与你想让它抓的版本不一致。另外,静态资源上带着 Set-Cookie,会降低缓存命中效率,这类配置遗留同样会影响抓取时的响应表现。
一份可以照着走的排查清单
- 用抓取工具查看响应头,确认 Content-Type 与 charset 和实际内容一致。
- 检查是否误挂了 X-Robots-Tag,尤其留意全站级别与中间层配置。
- 确认压缩传输没有截断,对比同一 URL 多次抓取的体积是否稳定。
- 看跳转链长度,把多跳收敛成一跳直达落地页。
- 确认 HTML 的缓存策略不会让它长期返回 304 旧版本。
- 503 与 Retry-After 只在真实过载时使用,不当作日常限流开关。
状态码告诉你「这次请求成没成」,响应头告诉你「蜘蛛读到了什么、下次还会不会来」。两者一起看,抓取问题才容易定位到具体的那一层配置。