为什么自己看到的是新版,蜘蛛看到的是旧版
更新完一篇文章,后台显示已发布,自己刷新也是新内容,但过几天去看抓取记录,拿到的仍是修改前的版本。这类错位很少是单一原因,多数是缓存策略和时间戳在中间做了手脚。先把链路拆开看,排查会容易很多。
先分清三层缓存
请求一条页面地址,中间至少要经过三层缓存,任何一层没失效,输出的都可能是旧内容:
- 浏览器缓存:只影响你自己和访客的本地副本。对抓取工具影响有限,但最容易让你误判“已经生效”。
- 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,时间与页面上显示的更新时间保持一致,精确到日通常就够用。
页面上的时间也要自洽
有些站点同时存在三个时间:发布时间、更新时间、结构化数据里的日期。它们互相矛盾时,抓取工具和用户都会困惑。
- 只是修正错别字或排版,不必改更新时间。
- 补充了段落、数据或结论,更新时间应当同步调整。
- 结构化数据里的日期应与页面上可见的时间保持一致。
一份可执行的自查清单
- 用 curl 带不同 UA 请求页面,查看响应头里的 Cache-Control、Last-Modified、ETag。
- 连续请求两次,确认 Last-Modified 与 ETag 是否稳定,有没有每次都跳。
- 更新一篇文章,观察源站、CDN、站点缓存三层是否都已生效。
- 检查站点地图中该地址的 lastmod 是否与页面更新时间一致。
- 确认 HTML 没有被设成超长缓存,或已配置主动刷新流程。
- 对比页面显示时间、结构化数据时间、响应头时间三者是否冲突。
更新内容后的推荐动作
- 先发布源站,确认直接访问拿到的是最终版本。
- 再刷新 CDN 对应路径,避免旧副本继续对外输出。
- 站点地图里只更新真正改动的地址,其余保持不动。
- 不要为了催抓而反复改动时间戳,这会把原本有效的变化信号稀释掉。
缓存策略和时间戳本身不决定收录结果,但它们直接决定了抓取工具每次来访时看到什么。把这三层缓存和时间戳理清楚,至少能保证一件事:你更新了什么,抓取工具就有机会看到什么。