為什么自己看到的是新版,蜘蛛看到的是舊版
更新完一篇文章,後台顯示已發布,自己刷新也是新内容,但過几天去看抓取记錄,拿到的仍是修改前的版本。這類错位很少是單一原因,多數是缓存策略和時間戳在中間做了手脚。先把鏈路拆開看,排查會容易很多。
先分清三层缓存
請求一條頁面地址,中間至少要经過三层缓存,任何一层没失效,輸出的都可能是舊内容:
- 浏览器缓存:只影响你自己和訪客的本地副本。對抓取工具影响有限,但最容易让你誤判“已经生效”。
- 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 對應路径,避免舊副本繼續對外輸出。
- 站点地图里只更新真正改動的地址,其余保持不動。
- 不要為了催抓而反复改動時間戳,這會把原本有效的變化信号稀释掉。
缓存策略和時間戳本身不决定收錄结果,但它們直接决定了抓取工具每次来訪时看到什么。把這三层缓存和時間戳理清楚,至少能保證一件事:你更新了什么,抓取工具就有机會看到什么。