蜘蛛第一次抓走入口页之后,很可能还会再来。第二次来的时候,它的请求头里可能多带了两个字段:If-Modified-Since 和 If-None-Match。这是浏览器和爬虫共用的机制——条件请求。服务器判断内容没变,就回一个 304 Not Modified,不用重发整页 HTML。
对蜘蛛池来说,这件事有两个方向的影响:用得好,蜘蛛愿意多来几次、少花流量;用得糙,蜘蛛会因为每次都被告知「没变」而降低对入口页的访问频次,或者反过来,被错误的 304 挡住新内容。
条件请求在蜘蛛池里长什么样
第一次抓取时,服务器在响应里给出两个「指纹」:
- Last-Modified:这个入口页最后一次改动的时间。
- ETag:内容的校验值,通常是文件哈希,也可以是版本号。
蜘蛛下次请求时带上它们,服务器比对:一致就回 304,不一致就回 200 加完整内容。整个过程中,蜘蛛拿到的是「有没有变」这个结论,而不是内容本身。
304 对入口页是好是坏
没有绝对答案,取决于入口页承担的角色。
适合回 304 的情况
- 入口页是长期稳定的跳转页或聚合页,正文几乎不动。
- 页面被大量蜘蛛反复抓取,服务器带宽和 CPU 吃紧。
- 页面由静态文件生成,改动有明显的部署时间点。
不适合硬回 304 的情况
- 入口页上的链接列表会动态更新,靠 304 挡住了蜘蛛,新链接就没机会被发现。
- 时间戳写得过于粗糙,比如整点取整,一小时内多次改动都被算成「没变」。
- 用负载均衡或多台机器时,各机器给出的 ETag 不一致,304 判断来回抖动。
几个常见的坑
- 动态生成的时间戳:每次请求都把 Last-Modified 写成「当前时间」,蜘蛛每次都拿到 200,等于没有缓存协商,白白浪费抓取预算。
- ETag 里带机器名或进程号:集群环境下同一页面有多套 ETag,蜘蛛在不同 IP 上拿到不同值,容易反复重取。
- 内容变了却还回 304:缓存层没清干净,源站内容更新了,边缘节点仍按旧指纹回 304,蜘蛛读到的还是老版本。
- CDN 与源站的 ETag 不一致:CDN 改写了自己的 ETag,回源比对时对不上,源站更新被屏蔽。
- 错误页也参与协商:把 404、503 页面配了长缓存,蜘蛛再来看时收到 304,误以为那个 URL 一直有效。
在蜘蛛池里怎么落地
- 先明确入口页类型:稳定跳转页可以放心用 304,会持续更新链接的页面宁可让它回 200。
- Last-Modified 用真实的内容生成时间,不要用请求时间,精确到秒即可。
- ETag 用内容哈希,去掉机器相关信息;多台源站保持一致。
- 检查缓存层级,确认 CDN 是否改写或丢弃 ETag,必要时在回源请求里保留原值。
- 定期抽查入口页响应,确认改动后第一次抓取拿到的是 200,之后才可能是 304。
用日志验证效果
看蜘蛛日志时,把同一 URL 的访问按时间排开,观察状态码序列。理想情况是「200 → 304 → 304 →(内容更新)→ 200 → 304」。如果一直是 200,说明协商没生效,抓取预算被浪费;如果一直是 304 但页面明明更新过,说明缓存或指纹那一层出了问题。
304 本身不产生收录,也不提升权重,它只是让蜘蛛的重复访问更省事。把它当成一次沟通成本优化,而不是一种优化手段。