蜘蛛不是只来一次
站点运营常把抓取理解成一次性的:URL 被发现、抓取、收录,然后就结束了。实际蜘蛛对多数页面是反复回访的,回访频率受内容更新节奏、页面重要程度和服务器响应影响。回访时,蜘蛛会带上条件请求头,服务器如果判断内容没变,返回 304。这一来一回看起来只是省流量,实际上决定了蜘蛛手里拿着的是哪一版页面,也就间接影响了下一步会沿着哪些链接走。
条件请求的两种配对方式
- If-Modified-Since 配合响应头 Last-Modified,按时间判断。
- If-None-Match 配合响应头 ETag,按内容标识判断。
- 服务器判定未修改,返回 304,不带正文。
- 判定已修改,返回 200,重新下发完整 HTML。
蜘蛛拿到 304 后,通常会沿用上一次抓取到的正文来解析链接。304 决定的是用哪一版页面,而不是路径本身。如果缓存里的那一版已经过时,蜘蛛就会继续沿着旧链接走。
常见几种写错的缓存头
Last-Modified 写成当前时间
动态生成的页面里,不少框架直接把请求时间输出成 Last-Modified。这样每次条件请求都会被判定为已修改,蜘蛛每次都要重新下载完整页面。带宽和抓取额度被白白消耗,长列表页、筛选页尤其明显。
ETag 用时间戳或进程信息生成
用文件 inode、进程 ID、毫秒时间戳生成 ETag,多台服务器之间不一致,同一个 URL 每次返回的 ETag 都不同,条件请求永远无法命中,回访等于全新抓取。反过来,把全站模板统一塞一个固定 ETag 也有问题:蜘蛛认为所有页面永远没变,标题和正文改了也不会重新抓。
Vary 与 Cookie 把缓存切碎
如果 Vary 头按 User-Agent 或 Cookie 分缓存,蜘蛛拿到的可能是一个只有它自己见过的版本,里面的链接和其他用户看到的并不一样。运营侧可以用固定 UA 请求一次,对比正文里的链接来验证。
改版和 URL 迁移时最容易出问题
页面正文没动,但模板变了:导航加了新栏目、换了一批内链、URL 结构调整并做了 301。如果服务器仍按老逻辑返回 304,蜘蛛手里还是旧版 HTML,里面是旧链接。这时候通常会出现两种情况:
- 蜘蛛继续沿旧路径走,反复请求已经 301 的地址。
- 新页面虽然进了 Sitemap,但没有任何内链指向它,被发现的速度被拖慢。
处理办法并不复杂:改版后主动让 ETag 或 Last-Modified 变化,比如把资源版本号写进 ETag,让下一次条件请求返回 200。等蜘蛛拿到新版本,缓存自然会刷新。
CDN 与中间层要一并确认
不少站点前面有 CDN 或缓存代理,需要确认它对带条件头的请求是怎么处理的:有的会把 304 转成 200 再补正文,有的会把不同来源的 ETag 合并成一个。这类行为在源站层面看不出问题,只能通过直接请求 CDN 节点来验证。
运营侧可以自查的清单
- 抽样几条重要 URL,带 If-Modified-Since 和 If-None-Match 请求,看返回码和 ETag 是否稳定。
- 看服务器日志里 304 的比例。比例过低说明缓存头没生效;比例过高而内容明明在更新,就要查 ETag 是不是写死了。
- 重点关注列表页、栏目页和导航接口,这些页面的缓存版本决定了蜘蛛下一步能走到哪里。
- 把缓存刷新写进发布流程,改版、换模板、调 URL 时都执行一遍。
304 的含义是内容没变、不用重传,不是蜘蛛不用来。路径的更新要落在正文和链接上,别指望缓存头替你做这件事。