蜘蛛第二次访问同一地址时,往往不需要把完整 HTML 再下载一遍。它会在请求头里带上几个字段,相当于告诉服务器:我上次来过,手里存着当时的版本,你确认一下有没有变。如果内容没动,服务器回一个空的 304,这次交互就结束了。单个页面省下的量很小,但铺到全站几万、几十万个地址上,就是抓取效率的差别。
蜘蛛重访时会带哪些头
条件请求依赖两组配对字段,缺一组就会退化成全量下载。
- If-None-Match 配 ETag:服务器给每个版本一个标识,蜘蛛下次带回来比对,标识一致就回 304。
- If-Modified-Since 配 Last-Modified:按时间比对,蜘蛛带上次收到的最后修改时间。
- 两组都没有,或者服务器不认,蜘蛛就只能把页面完整再拉一次。
304 省下来的不只是带宽
很多人只把它当成省流量的手段,其实对抓取这件事,影响更直接的是另外几层:
- 响应体积从几十 KB 降到几百字节,同样的抓取配额能覆盖更多 URL。
- 后端渲染和数据库查询可以被跳过,服务器在抓取高峰时更从容。
- 响应更快,蜘蛛在单位时间内的抓取节奏更平稳,不容易触发限速。
- 日志里能清楚看出哪些页面确实没变,排查抓取异常时更省事。
常见的三种失效配置
ETag 每次请求都变
有的框架默认用进程 ID、时间戳或随机串拼 ETag,同一个页面每次返回的标识都不同。蜘蛛带回来的值和服务器当前值永远对不上,只能一直回 200 全量下载。这种情况在日志里表现为:同一 URL 高频重复抓取,且响应体积没有下降。
Last-Modified 恒等于当前时间
部分 CMS 或模板在输出时直接写上当前时间,页面其实没改,时间却在走。蜘蛛看到的是页面一直在更新,就会更频繁地回来确认,实际拿到的东西一模一样。这类配置比 ETag 出错更隐蔽,因为它看起来像是内容活跃。
中间层把头部丢掉或改写
CDN、反向代理、WAF 有时会重写或剥离 ETag、Last-Modified,也可能在边缘缓存后返回自己的标识。节点之间标识不一致时,蜘蛛今天从这个节点拿到的 ETag,明天从另一个节点去比对,结果自然对不上。
自查方法
- 用命令行连续请求同一个地址两次,对比两次响应头里的 ETag 和 Last-Modified 是否一致。
- 把第一次拿到的 ETag 手动放进 If-None-Match 再请求一次,看是否返回 304。返回 200 说明条件请求没生效。
- 换成站点实际使用的 CDN 域名再测一遍,确认边缘层没有引入新的标识。
- 抓一周日志,统计同一 URL 的重复抓取次数和平均响应体积,看有没有下降趋势。
几个容易走偏的地方
- 304 不代表内容会被重新评估。它只是告诉蜘蛛没变,不构成任何更新信号,别指望靠它推动重抓。
- 内容真的改了就必须回 200。为了省资源把变更后的页面也回 304,会让蜘蛛长期拿到旧版本。
- 不要按 UA 区别对待。对搜索蜘蛛一套条件请求策略,对普通访客另一套,容易被判定为伪装,风险高于收益。
- 它不能替代其他手段。304 优化的是重复抓取的成本,URL 发现仍然要靠内链和 Sitemap,抓取深度仍然取决于站点结构。
把条件请求的配对字段做对,是抓取效率里性价比很高的一项:改动小、覆盖范围大,但前提是标识稳定且中间层不捣乱。先测,再改。