站点运营

站点运营:缓存與最後修改時間自查,別让蜘蛛總抓到舊版本

内容更新後,自己刷新看到的是新版,蜘蛛抓到的却還是舊版,問题往往出在缓存策略和時間戳上。本文梳理浏览器缓存、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 對應路径,避免舊副本繼續對外輸出。
  • 站点地图里只更新真正改動的地址,其余保持不動。
  • 不要為了催抓而反复改動時間戳,這會把原本有效的變化信号稀释掉。

缓存策略和時間戳本身不决定收錄结果,但它們直接决定了抓取工具每次来訪时看到什么。把這三层缓存和時間戳理清楚,至少能保證一件事:你更新了什么,抓取工具就有机會看到什么。