站点运营

站点运营:缓存与最后修改时间自查,别让蜘蛛总抓到旧版本

内容更新后,自己刷新看到的是新版,蜘蛛抓到的却还是旧版,问题往往出在缓存策略和时间戳上。本文梳理浏览器缓存、CDN 缓存与 HTTP 响应头之间的关系,给出 Cache-Control、Last-Modified、ETag、sitemap lastmod 的自查清单,帮你在更新内容后让抓取版本尽快对齐。

站点运营

站点运营:缓存与最后修改时间自查,别让蜘蛛总抓到旧版本

为什么自己看到的是新版,蜘蛛看到的是旧版

更新完一篇文章,后台显示已发布,自己刷新也是新内容,但过几天去看抓取记录,拿到的仍是修改前的版本。这类错位很少是单一原因,多数是缓存策略和时间戳在中间做了手脚。先把链路拆开看,排查会容易很多。

先分清三层缓存

请求一条页面地址,中间至少要经过三层缓存,任何一层没失效,输出的都可能是旧内容:

  • 浏览器缓存:只影响你自己和访客的本地副本。对抓取工具影响有限,但最容易让你误判“已经生效”。
  • CDN 或反向代理缓存:这是最常见的问题源。HTML 被缓存后,抓取工具拿到的可能是几小时甚至几天前的副本。
  • 站点自身缓存:页面缓存、对象缓存、整页静态化,更新后没有主动失效,同样会输出旧内容。

排查顺序建议从外到内:先用带随机参数的地址确认源站已经是新内容,再逐层检查 CDN 和站点缓存。

Cache-Control 怎么设比较稳妥

静态资源和 HTML 的策略应该分开对待,混在一起设很容易出问题。

  • 静态资源:带文件名哈希的 JS、CSS、图片可以设较长缓存时间,更新时换文件名,而不是等缓存自然过期。
  • HTML 页面:缓存时间设短,或让每次请求都回源校验。把 HTML 设成长期缓存,等于给更新加了一道锁。
  • CDN 上的 HTML:内容更新后主动刷新对应路径,而不是等 TTL 到点。
如果 HTML 被设成一年缓存又没有主动刷新机制,对抓取工具来说,这次更新几乎等于没发生。

Last-Modified 与 ETag 的两个极端

这两个响应头决定了抓取工具再次访问时,能否判断页面是否发生变化。实际站点里常见两种反向的坑。

每次都变,等于没变

有些动态页面把 Last-Modified 直接写成当前时间,每次请求都不同。抓取工具会认为页面一直在变,于是提高回访频率,但拿到的内容并没有实质差别,抓取预算被白白消耗。

永远不变,抓取工具就不再回访

另一种是模板里写死了固定时间,正文更新了时间戳也不动。既然响应头说内容没变,条件请求就可能被跳过,新版本要等很久才会有机会被重新获取。

合理做法是让 Last-Modified 跟随真实的正文变更时间,ETag 基于内容特征生成,而不是随机数或当前时间。

sitemap 里的 lastmod 要对得上

站点地图中的 lastmod 常被当成催抓按钮,但它的作用只是声明,不是指令。常见问题包括:

  • 全站页面共用同一个时间,等于没有区分度。
  • 只改了一个标点也把 lastmod 全部刷新,频繁触发回访。
  • lastmod 早于页面实际发布时间,或者格式不规范。

比较稳妥的做法是只在正文有实质修改时更新 lastmod,时间与页面上显示的更新时间保持一致,精确到日通常就够用。

页面上的时间也要自洽

有些站点同时存在三个时间:发布时间、更新时间、结构化数据里的日期。它们互相矛盾时,抓取工具和用户都会困惑。

  • 只是修正错别字或排版,不必改更新时间。
  • 补充了段落、数据或结论,更新时间应当同步调整。
  • 结构化数据里的日期应与页面上可见的时间保持一致。

一份可执行的自查清单

  1. 用 curl 带不同 UA 请求页面,查看响应头里的 Cache-Control、Last-Modified、ETag。
  2. 连续请求两次,确认 Last-Modified 与 ETag 是否稳定,有没有每次都跳。
  3. 更新一篇文章,观察源站、CDN、站点缓存三层是否都已生效。
  4. 检查站点地图中该地址的 lastmod 是否与页面更新时间一致。
  5. 确认 HTML 没有被设成超长缓存,或已配置主动刷新流程。
  6. 对比页面显示时间、结构化数据时间、响应头时间三者是否冲突。

更新内容后的推荐动作

  • 先发布源站,确认直接访问拿到的是最终版本。
  • 再刷新 CDN 对应路径,避免旧副本继续对外输出。
  • 站点地图里只更新真正改动的地址,其余保持不动。
  • 不要为了催抓而反复改动时间戳,这会把原本有效的变化信号稀释掉。

缓存策略和时间戳本身不决定收录结果,但它们直接决定了抓取工具每次来访时看到什么。把这三层缓存和时间戳理清楚,至少能保证一件事:你更新了什么,抓取工具就有机会看到什么。