入口页能不能被蜘蛛稳定抓取,很多时候不取决于内容写了什么,而取决于服务器怎么回应蜘蛛的每一次回访。其中最容易忽略的一环,就是 HTTP 缓存相关的响应头,以及由此产生的 304 状态码。
蜘蛛回访不是每次都要读完页面
蜘蛛在第二次、第三次访问同一个 URL 时,通常会带上 If-Modified-Since 或 If-None-Match 请求头,把上次拿到的 Last-Modified 或 ETag 一起送过来。服务器如果判断内容没变,就可以返回 304 Not Modified,不用再传一遍正文。对蜘蛛池这种入口页数量多、单页内容变化不频繁的场景,这个机制直接决定了蜘蛛每次回访要消耗多少带宽和服务器资源。
几个头部各自在表达什么
- Last-Modified:告诉蜘蛛这个页面最后一次变化的时间。它不一定等于文件真实修改时间,很多程序会写成模板渲染时间。
- ETag:内容的指纹。不同类型服务器生成规则不同,有的按内容哈希,有的还带进程、inode 信息。
- Cache-Control:主要给浏览器和中间缓存看,但蜘蛛也会参考。max-age 太长时,蜘蛛可能看到的是缓存层里的旧副本。
- Expires:老式写法,和 Cache-Control 同时存在时容易被忽略,但不建议两边写互相冲突的值。
304 不等于“蜘蛛没来”
很多人在看日志时,看到大量 304 就以为蜘蛛在敷衍、没有真正抓取。实际上 304 说明蜘蛛来了、问了,并且服务器确认内容没变,这是一次正常的交互。真正需要警惕的是另一种情况:内容明明改了,服务器仍然返回 304,蜘蛛拿到的还是旧版本的判断依据,页面更新就一直传不出去。
判断入口页是否被正常回访,最好把 200、304、404 分开统计,再结合响应时间和抓取频次一起看,单看某一类状态码容易得出相反的结论。
蜘蛛池场景里常见的几个坑
- 模板统一生成 Last-Modified:每次请求都返回当前时间,蜘蛛每次都觉得内容变了,于是反复全量抓取,白白消耗抓取预算。
- ETag 跟着进程变化:多台后端、多次重启后 ETag 不一致,缓存判断反复失效,回访时好时坏。
- 缓存层与源站状态码不一致:CDN 或反向代理返回 304,但源站其实已经更新,蜘蛛拿到的是过期副本。
- 对所有入口页设置超长 max-age:内容更新后,蜘蛛在缓存过期前都读不到新版本。
- 用重定向代替 304:为了“省流量”把回访跳到别的地址,反而让蜘蛛对 URL 的稳定性产生困惑。
比较稳妥的配置思路
如果入口页内容会定期更新,建议让 Last-Modified 和实际更新时间保持一致的逻辑,例如由内容的最后编辑时间决定,而不是每次渲染取当前时间。ETag 尽量基于内容生成,不掺入进程或物理路径信息。Cache-Control 可以给一个中等长度的 max-age,同时配合 must-revalidate,让缓存层在内容变化后愿意回源确认。
对于长期不变、只作为链接入口的静态页,则可以给较长的缓存时间和较少的回访频率预期,让蜘蛛把更多抓取次数留给真正需要更新的目标页。具体长度没有统一答案,需要结合入口页的数量、更新节奏和服务器承载能力来调,先小范围观察日志里的 200 与 304 比例,再决定是否放宽。
最后提醒一点:缓存头是服务器与蜘蛛之间的“沟通约定”,它影响的是抓取效率,不决定页面是否会被收录。把它当成资源优化和抓取节奏管理的一部分,比当成提升效果的开关更实际。