蜘蛛打开一个入口页,第一件事不是读正文,而是读响应头。正文写得再规整,头信息里某个字段设错,蜘蛛对页面的判断就可能完全变样。下面这几个字段,在蜘蛛池的日常维护里最容易被忽略,也最容易出问题。
Content-Type 与字符集:读得懂,还是读成乱码
响应头里的 Content-Type: text/html; charset=utf-8 决定了蜘蛛用什么编码去解码字节流。如果页面实际是 UTF-8,服务器却声明 gbk,蜘蛛按声明的编码解码,抓到的就是一堆问号和方块。虽然 HTML 里的 meta charset 也能声明编码,但多数实现中响应头的优先级更高,两边打架时以头为准。
维护建议很简单:让响应头和页面里的 meta 声明保持一致,别一个 utf-8 一个 gbk 各说各话。改过服务器配置或换过 CDN 之后,这种情况尤其容易出现,值得定期核对一次。
Last-Modified 与 ETag:蜘蛛判断“变没变”的依据
蜘蛛再次来访时,通常会带上 If-Modified-Since 或 If-None-Match,问服务器一句:内容变了没有?服务器回 304,蜘蛛就知道不用重新解析正文,节省双方的时间。
- 每次都输出当前时间:程序图省事,把 Last-Modified 写成请求发生的时刻。蜘蛛每次来都看到“刚刚更新过”,会认为页面频繁变动,反复抓取,却拿不到实质新内容。
- 永远返回一个很早的固定时间:蜘蛛认为页面长期没动,重抓的意愿下降,新加的内容迟迟不被重新读取。
- ETag 被中间层重写:部分 CDN 或反代会把 ETag 换成自己生成的值,导致同一份内容在不同节点上 ETag 不一致,条件请求失效,等于每次都全量抓。
动态生成的入口页,最好让 Last-Modified 跟随实际内容的时间戳,而不是跟随请求时间。
Cache-Control 与 Age:蜘蛛拿到的是不是最新版
Cache-Control 里的 max-age 设得很长,又叠了 CDN 缓存,蜘蛛抓到的可能是一份几小时甚至几天前的副本。响应头中的 Age 字段能直接告诉你:这份内容在缓存里已经放了多久。如果 Age 明显偏大,而站点内容更新频繁,就要考虑对 HTML 类请求缩短缓存时间,或者做主动刷新。
X-Robots-Tag:藏在头里的指令
除了页面里的 meta robots,HTTP 头里也能下发爬虫指令,写法是 X-Robots-Tag,可以针对单个 URL、整个目录,甚至某类文件类型生效。
它的麻烦之处在于隐蔽:网页源码里什么都看不出来,只有抓响应头才能发现。常见的坑是配置里给某个目录批量加了 noindex,后来页面挪了用途,指令还留着,于是入口页内容正常、链接正常,却长期不进索引。
排查“内容没问题却不被索引”这类现象时,先看响应头,往往比翻正文更快找到答案。
Vary 与缓存分片:同一个 URL 的不同版本
如果响应头里写了 Vary: User-Agent,缓存系统会按不同的 UA 分开存副本。对蜘蛛和普通访客返回不同版本的站点,就会出现两边看到的内容不一致的情况。有些站为了给爬虫减负,对爬虫返回精简页面,本意是好的,但一旦精简版丢掉了主要链接或正文,效果就反过来了。建议至少做一次对照:用普通 UA 和蜘蛛 UA 各抓一次,比对正文和链接是否一致。
怎么快速自查
- 用命令行工具只取响应头,不要下载整个页面,逐条看状态码、Content-Type、Last-Modified、ETag、Cache-Control、X-Robots-Tag。
- 换一个 UA 再抓一次,比对两次的头信息和正文长度是否一致。
- 隔一段时间重复抓同一 URL,观察 Last-Modified 与 ETag 是否稳定,304 是否按预期返回。
- 把结论记进站点维护清单,尤其是目录级的 X-Robots-Tag 和缓存策略,交接时最容易漏。
响应头不是玄学,它只是蜘蛛进入页面的第一道门。把这道门上的几个字段理顺,很多看起来莫名其妙的抓取异常,其实都会自己消失。