搜索蜘蛛回访已收录的 URL 时,通常会在请求头里带上 If-None-Match 或 If-Modified-Since。服务端如果判定内容没变并返回 304,蜘蛛就不必下载正文、解析页面、再和索引里的版本比对;如果每次都是 200 加完整正文,站长从浏览器里看不出任何异常,但抓取预算会被反复花在同一批页面上。
304 协商省下的是什么
- 传输体积:正文不必回传,对图片多、正文长的详情页更明显。
- 蜘蛛端开销:拿到 304 后可直接跳过解析与比对环节。
- 高峰带宽占用:抓取密集时段,重复传输减少对源站更友好。
需要分清的是,304 只表示“自上次校验头所代表的状态以来没有变化”,它不代表这个 URL 一定被收录,也不代表内容永远不会更新。
常见的 304 失效原因
- ETag 每次请求都变,比如由进程号、时间戳或随机串拼成。
- Last-Modified 取的是当前渲染时间,而不是内容的最后更新时间。
- 反向代理或 CDN 回源后重写头部,把源站返回的 ETag 换掉。
- 缓存层剥掉了 If-None-Match,源站收不到校验头,只能返回 200。
- 页面里写入随机数、AB 测试标记或毫秒级时间戳,内容哈希每次都不同。
- 多台源服务器各自生成 ETag,蜘蛛命中的机器不同,校验值自然对不上。
一条可执行的排查顺序
- 先用命令行取一次响应,记下 ETag 与 Last-Modified,再带上同样的值请求同一个 URL,观察状态码是否为 304。
- 分别对源站 IP 直连和经过 CDN 的域名各测一次,确认差异出现在哪一层。
- 连续请求两次相同 URL,比较两次 ETag 是否一致;不一致说明生成逻辑带入了易变因子。
- 检查 Vary、Cache-Control、Age 是否符合预期。Vary 里带上 Cookie 之类的字段,会使缓存与协商几乎不命中。
- 翻服务器日志,统计带 If-None-Match 的请求数与返回 304 的数量,算出整体命中水平,再按目录分类看哪类页面最差。
- 先从更新频率低、数量大的列表页与历史详情页入手,这类页面修正后的收益最直接。
别用 304 去“省抓取”
304 的含义是资源未修改。内容其实已经更新却仍返回 304,蜘蛛会继续沿用旧版本,页面更新可能长期滞后。想控制抓取频次,应该靠合理的更新节奏与入口收敛,而不是靠错误的校验头。
还要注意,把 200 改成 301 或返回空正文,都不是 304 的替代方案。301 会改变入口指向,空正文会让蜘蛛认为页面内容缺失,两者的副作用都比“多传几次正文”大得多。
与抓取预算的关系
单页省下几 KB 看起来有限,但一个几万页的站点,如果每次回访都全量返回,累积的传输与解析开销并不小。把校验头做对属于成本低、可长期受益的优化。它不能提高收录,也无法保证排名,只是让蜘蛛把有限的抓取次数花在更值得的地方。
小结
- 先确认校验头能否稳定复现,再区分是源站问题还是中间层改写。
- ETag 要基于内容本身生成,避免带入时间戳、进程号、随机串。
- Last-Modified 用真实的内容更新时间,不要用渲染时刻。
- 日志里的 304 命中率是长期观测指标,值得定期复查。