蜘蛛把 URL 抓进索引之后,并不会就此停下。对已经收录的地址,它会按一定节奏回来确认内容是否变化。这个回访过程如果每次都完整下载一遍 HTML,对站点带宽和蜘蛛自身的调度都是负担。HTTP 协议里的条件请求机制,就是为了缓解这件事:蜘蛛带上上次拿到的标识,服务器只需回一个很短的响应,说明“内容没变”。
回访为什么是常态
很多人把抓取理解成一次性的动作,实际上抓取是一个持续核对的过程。首页、栏目页、热门内容页的回访频率通常更高,因为它们的变更概率大。长尾页面回访间隔会拉长,但并不等于放弃。理解这一点之后,就能明白为什么日志里同一个 URL 会出现几十次、上百次记录。
三个头字段的分工
Last-Modified
表示资源最后一次修改的时间。蜘蛛下次回访时会带上 If-Modified-Since,时间与服务器记录一致时,服务器返回 304。它的优点是简单,几乎所有服务器都能自动输出;缺点是精度只到秒,短时间内多次改动可能被合并成一次。
ETag
本质是一段内容指纹,蜘蛛用 If-None-Match 带回来比对。ETag 可以做到内容级判断,比时间戳更准确。但要注意,如果 ETag 是每次请求动态生成的,每次值都不同,条件请求就永远匹配不上,304 也就永远不会出现。
Cache-Control
它更多面向浏览器和 CDN,对搜索蜘蛛的约束力相对有限。不要指望用 Cache-Control 来规定蜘蛛的抓取频率,抓取节奏主要由站点整体表现和蜘蛛自身调度决定。
304 响应到底意味着什么
收到 304,表示服务器确认内容未变,蜘蛛不会重新解析页面,但这次抓取仍会被计入日志。也就是说,304 不等于“这次什么都没发生”,它是把一次完整下载压缩成了一次轻量确认。对站点来说,这是省流量的好事;对运营者来说,看到大量 304 是正常现象,不必紧张。
需要留意的是:304 只说明“没有变化”,不代表这只 URL 的抓取优先级被提升或降低。别把 304 的数量当作健康度指标单独使用。
304 经常失效的常见原因
- ETag 由进程或时间随机生成,每次请求值都不同。
- 页面里嵌入了当前时间、随机数、在线人数等动态片段,导致内容指纹每次都变。
- 中间层代理或 CDN 改写、剥离了 ETag 与 Last-Modified。
- 服务器时间不准,Last-Modified 比实际修改时间还早或还晚。
- 框架为每次请求重新渲染模板,即使数据未变,输出字节也不完全一致。
这几类问题的共同点是:页面对用户看起来没变,但服务器认为它变了。表现出来就是日志里该 URL 全是 200,响应体大小几乎一样,却没有 304。
和 Sitemap 的 lastmod 要对得上
Sitemap 里的 lastmod 是给蜘蛛看的更新提示,而 Last-Modified 是响应头里的更新声明。两者如果长期互相矛盾,比如 Sitemap 天天写当天日期,响应头却几个月没动,会让更新信号的可信度下降。建议让 lastmod 反映真实的内容改动时间,不要为了“催抓”而机械刷新。
核对顺序建议
- 挑几个回访频繁的 URL,用工具或命令行查看响应头,记录 ETag 与 Last-Modified 的具体值。
- 间隔几分钟再请求一次,带上条件头,看是否返回 304;重复两三次,确认 ETag 是否稳定。
- 对照服务器访问日志,统计同一 URL 的 200 与 304 比例。长期全是 200 且体积不变,就值得排查。
- 检查 CDN 或反向代理配置,确认没有剥掉缓存相关头字段。
- 确认 Sitemap 的 lastmod 与响应头时间大致一致,不要出现明显冲突。
别走偏的两个方向
一是为了让蜘蛛“觉得内容更新了”而故意改动 ETag,这种做法只会增加无意义的回访消耗,对内容质量没有帮助。二是把 304 当成抓取成功的证明,实际上它只说明核对通过,与页面是否被收录、是否有排名没有直接关系。
把缓存头当成一项基础设施来维护就够了:让 ETag 稳定、让 Last-Modified 真实、让中间层不干扰。剩下的交给正常的抓取节奏。