搜索抓取

Last-Modified 与 ETag:蜘蛛回访时怎么判断页面有没有变

蜘蛛回访页面时,条件请求决定了它要不要重新下载整页。Last-Modified 和 ETag 这两个头部如果设置得可靠,可以帮助减少重复传输,把抓取节奏留给真正更新的 URL;如果设置得随意,反而会让蜘蛛反复回访。本文梳理两者的使用要点、常见坑和自查方法。

搜索抓取

Last-Modified 与 ETag:蜘蛛回访时怎么判断页面有没有变

蜘蛛回访一个页面时,并不一定会把整页重新下载一遍。很多爬虫会先发条件请求,问服务器一句:这个页面从上次抓取到现在,有没有变过?服务器如果回答“没变”,蜘蛛就只拿到一个很短的响应,不必重复拉取正文。这个过程依赖两个常见的 HTTP 头部:Last-Modified 和 ETag。

条件请求:蜘蛛先问“变了吗”

第一次抓取时,服务器在响应里给出 Last-Modified 或 ETag。蜘蛛把这组值记下来。下次回访时,它会在请求头里带上 If-Modified-Since 或 If-None-Match,把上次拿到的值回传给服务器。

  • If-Modified-Since 对应 Last-Modified,用时间做比较。
  • If-None-Match 对应 ETag,用标识符做比较。
  • 服务器判断内容没有变化,返回 304 Not Modified,不返回正文。
  • 如果内容变了,返回 200,重新给出完整页面和新的验证值。

对蜘蛛来说,304 的主要意义是省下重复传输,把有限的抓取节奏留给新 URL 和真正更新的旧 URL。它本身不是排名信号,也不代表页面会被收录。

Last-Modified 要真实,不要“永远新鲜”

Last-Modified 最好来自内容真正发生变更的时间。常见问题是动态页面在每次请求时都输出当前时间,蜘蛛每次回访都会看到“刚刚更新”,于是反复抓取同一个没有变化的页面。另一种情况是时间戳来自模板渲染时间或缓存生成时间,和内容实际修改时间对不上,也会让条件请求失去参考价值。

如果站点有发布流程,可以把 Last-Modified 和发布时间、编辑时间绑定,并且在模板层保持稳定。不要因为用户评论数、阅读数这类频繁变动但正文没变的因素,就贸然刷新整个页面的时间戳。

ETag 不要用随机值或进程标识

ETag 可以理解成服务器给某个版本内容贴的标签。强 ETag 要求字节级一致,弱 ETag 允许语义相同但字节略有差异。问题往往出在生成方式上:有些程序默认用进程 ID、内存地址或当前时间拼 ETag,结果每次请求都不一样。蜘蛛带着 If-None-Match 回来,服务器永远匹配不上,只能一直返回 200。

更稳妥的做法是基于内容做哈希,或者干脆只保留 Last-Modified,不输出 ETag。两者同时存在时,蜘蛛会优先使用 ETag。如果 ETag 不可靠,反而会覆盖掉本来可用的时间校验。

304 对抓取节奏的实际影响

  • 减少响应体积,对带宽和源站负载都有帮助。
  • 让蜘蛛用更少的成本确认旧页面状态,腾出节奏去发现新 URL。
  • 不能替代内链结构和 Sitemap,页面如果长期没有入口,条件请求也帮不上忙。
  • 304 仍然要建立连接、等待服务器响应,源站响应慢,蜘蛛一样会被拖住。
304 省的是重复下载,不是抓取动作本身。服务器耗时偏高时,条件请求并不会让抓取节奏自动变快。

中间层可能改写头部

CDN、反向代理、WAF 和安全插件都可能删掉、改写或统一化 Last-Modified 和 ETag。常见表现是:回源请求能看到正确的头部,但边缘节点返回给蜘蛛的是另一套值;或者不同节点返回的 ETag 不一致。蜘蛛在不同时间、不同节点拿到的标识不稳定,条件请求就容易失效。检查时最好分别看回源响应和边缘响应。

怎么自查

  1. 用 curl -I 连续请求同一个 URL,观察 Last-Modified 和 ETag 是否稳定。
  2. 带上 If-None-Match 或 If-Modified-Since 再请求一次,确认是否返回 304。
  3. 在服务器日志里统计 304 与 200 的比例,看回访是否大量重复拉取正文。
  4. 核对内容更新时间与发布流程,确认头部时间不是渲染时间或缓存时间。
  5. 如果使用了 CDN,分别验证回源和边缘的响应头。

小结

Last-Modified 和 ETag 是蜘蛛回访时的重要参考,但它们的价值来自稳定和真实。把这两个头部当作站点运营的一部分,和发布流程、缓存策略一起维护,比频繁调整抓取策略更实际。条件请求做对了,蜘蛛可以把更多精力放在新 URL 和内容确实变化的页面上。