很多人排查蜘蛛池入口页的抓取问题时,注意力都放在状态码、页面内容和跳转上,很少去看响应头。实际上,蜘蛛拿到一个 URL 之后,最先解析的就是响应行和响应头,页面正文要等这一步之后才会被处理。响应头里写错了东西,页面本身再正常也可能白搭。
状态码之外,响应头决定了蜘蛛怎么理解这个页面
200 只表示请求成功,它不说明返回的是什么类型的内容、能不能索引、要不要缓存,这些信息都在响应头里。入口页通常是程序批量生成的,如果程序模板里带了某些默认头,几百上千个页面就会一起带上,问题也会被一起放大。
几类值得逐项检查的响应头
Content-Type 与字符集
Content-Type 应该明确写成 text/html 并带上字符集,例如 text/html; charset=utf-8。如果服务器返回 text/plain 或者干脆不写,蜘蛛可能不按 HTML 去解析,页面里的链接也就无法被提取出来。字符集写错则会让中文变成乱码,正文解析出一堆无意义的字符。
X-Robots-Tag
这是放在 HTTP 头里的指令,作用和页面里的 meta robots 类似,但优先级更高。常见的误用是:入口页本身想被蜘蛛抓取,却因为服务器统一加了 X-Robots-Tag: noindex,导致页面抓得到却不会进入索引。
抓取和收录是两件事。noindex 不影响蜘蛛来抓,但会阻止页面进入索引。如果你本来就只希望入口页承担“被爬到、再顺着链接走到目标页”的作用,那么 noindex 本身未必是错,但要清楚自己在做什么,而不是全局一刀切。
Server 与版本信息
Server 头会暴露服务器软件和版本号,比如 nginx/1.18.0。这不是抓取层面的问题,但从运维角度看,公开精确版本号没有什么好处,可以简化成 nginx 一类,或者用配置去掉。顺带检查有没有暴露内部转发信息,比如上游地址、内网 IP。
Location 与跳转
如果入口页需要跳转到目标页,用的是 301 或 302,那么 Location 里的地址必须是完整的绝对 URL,且不能跳到自己、不能形成循环。相对地址、带空格未编码的地址、跳转链条过长,都会让蜘蛛在中间放弃。
缓存与校验类头
Cache-Control、ETag、Last-Modified、Expires 这几项会影响蜘蛛重复访问时的行为。入口页内容长期不变,可以让蜘蛛用 If-Modified-Since 只拿到 304,省下带宽;但如果你希望蜘蛛每次重新解析页面上的链接,缓存时间就不要设得太长。这类设置没有统一答案,取决于入口页是静态展示还是频繁更新。
Content-Length 与实际内容
这个头如果和实际字节数对不上,通常意味着程序在中途出错,或者用了压缩但没有正确处理。蜘蛛可能读到半截内容就断开,表现出来就是抓取不完整、页面大小异常。
几个常见的配置坑
- 只在部分页面上写了正确的 Content-Type,其余走服务器默认值,而默认值并不是 HTML。
- 用反向代理或 CDN 回源时把源站头部改写掉,或者叠加出两个 Content-Type。
- 为了防采集加了一堆自定义头,其中某个与蜘蛛的解析逻辑冲突。
- 跳转配置写在应用层,但响应头里的 Location 指向了测试环境地址。
- 页面引用了 http 资源,却没有意识到混合内容对抓取和渲染的影响。
怎么查:curl 加日志两步
最直接的方式是用 curl 看响应头,把 UA 换成你关心的爬虫,多测几个不同路径的入口页,看看头部是否一致。如果服务器对爬虫和普通用户返回不同的头,这一步就能看出来。
第二步是看访问日志。日志里记录的状态码、返回字节数和响应时间,可以和 curl 的结果互相印证。如果某个入口页在日志里反复出现 200 但字节数为 0 或极小,多半不是内容问题,而是响应头或程序输出有问题。
小结
响应头不需要天天盯,但在入口页上线之前、以及抓取表现异常的时候,值得花十几分钟逐项过一遍。它属于那种平时不出声、出问题很难查的配置,提前把模板规范好,比事后一个个补要省事得多。