常见問题

入口頁被 CDN 缓存,改了目标連結後搜尋蜘蛛看到的是哪一版

入口頁上的目标連結改過了,自己用浏览器看是新版,服務器日誌里搜尋蜘蛛抓到的却還是舊 HTML。本文說明搜尋蜘蛛的請求會经過哪些缓存层、怎样用响應头判断它拿到的是哪一版,以及改完連結後刷新缓存和設定缓存策略的常規做法與几個常见誤区。

常见問题

入口頁被 CDN 缓存,改了目标連結後搜尋蜘蛛看到的是哪一版

在蜘蛛池或普通站点的运营里,经常出現這样的情况:入口頁上的目标連結已经改過,自己用浏览器打開也確認是新的,但過一两天去看服務器日誌,搜尋蜘蛛抓到的還是舊版本 HTML,里面指向的是老 URL。多數时候這不代表蜘蛛「记性差」,而是它拿到的根本就是缓存副本。

搜尋蜘蛛請求时,中間隔了哪些缓存层

搜尋蜘蛛發起的是一次普通的 HTTP 請求,它经過的鏈路和你用 curl 請求时基本一致:

  • CDN 邊缘节点缓存
  • 反向代理缓存(Nginx proxy_cache、Varnish 等)
  • 應用层頁面缓存(部分 CMS、缓存插件生成的静態 HTML)
  • 對象存储或静態托管服務的預設缓存

只要其中一层存着舊副本並且還在有效期内,蜘蛛讀到的就是舊 HTML,頁面里能被解析出来的目标 URL 自然也是舊的。改文件、清應用缓存,但没清 CDN,是很常见的一種漏項。

蜘蛛本身並不绕過缓存

有一種誤解是:搜尋蜘蛛是「特殊訪客」,缓存對它不生效。實际上蜘蛛只是被動接收响應,它並不會主動跳過 CDN 邊缘节点去回源,也不會像浏览器那样讀取本地磁盘缓存後再校驗。它的行為更接近一個不带 Cookie、不带本地缓存的命令行請求:谁先應答,它就拿到谁给的内容。

唯一需要注意的是,部分 CDN 會按 User-Agent 或 IP 段做分流,例如把已知爬虫直接放行回源,或给爬虫單獨一條缓存策略。這會让「浏览器看到舊版、蜘蛛看到新版」或反過来都可能發生,所以最好實测而不是凭经驗猜。

怎么確認蜘蛛拿到的是哪一版

  1. 用 curl -I 看响應头,重点看 Age、X-Cache、CF-Cache-Status、X-Cache-Hits 這類字段。Age 值很大,說明命中的是邊缘节点上的舊副本。
  2. 连續請求两次,對比两次返回的 HTML 是否完全一致。如果两次都相同却和源站文件不同,基本可以确定中間有缓存。
  3. 把 User-Agent 換成搜尋蜘蛛的 UA 再請求一次,观察返回内容或响應头是否變化。
  4. 在服務器日誌里對比蜘蛛抓取时返回的字节數,和你目前頁面文件大小是否一致,差异明顯时通常是缓存或压缩层在起作用。
  5. 如果入口頁連結由 JavaScript 注入,抓取工具拿到的 HTML 里本来就不含目标 URL,這时候要先排查渲染問题,而不是缓存問题。

改了連結之後可以做什么

  • 主動刷新缓存。主流 CDN 都提供刷新或预热接口,按 URL 或目錄提交即可。刷新是异步的,节点多的时候需要等几分钟到更久。
  • 给 HTML 設定較短的缓存時間。图片、CSS 這類静態资源可以長缓存,但入口頁這種連結经常變動的頁面,用較短的 max-age,或者用 no-cache 让节点每次回源校驗,會更省心。
  • 让缓存键跟着内容變化。改連結时顺带調整路径或查询參數,等于換了一個新缓存键,舊副本自然不會命中。
  • 通過站点地图或提交入口告知更新。這只是一種通知方式,不能替代缓存刷新。
刷新缓存解决的是「蜘蛛看到舊連結」的問题,它不會让蜘蛛立刻回来,也不代表目标 URL 會被收錄。抓取和收錄是两件互相獨立的事。

几個容易踩的坑

第一個坑是只清了一半。源站清了、反向代理清了一部分、CDN 没清,结果蜘蛛抓到的仍是舊版。排查时最好從最外层往里一层层驗證响應头。

第二個坑是把刷新缓存当成日常手段,一改連結就全站刷新。频繁刷新會让邊缘节点反复回源,源站压力上升,也可能让蜘蛛在短時間内抓到多個版本的同一頁面。比較稳妥的做法是把缓存時間设短一点,让版本更替自然發生。

第三個坑是忽略了响應头的隐藏信息。有些托管服務預設给 HTML 加上了較長的 Cache-Control,部署时看不见,出問题时也想不到。上线前用一次 curl 看一眼响應头,比事後翻日誌省事得多。

最後,缓存只是影响 URL 發現的一环。蜘蛛能不能發現入口頁里的目标連結,還取决于入口頁本身是否被抓、頁面能否被正常解析、連結是否在可達的 HTML 里。逐項確認比反复改動缓存策略更有效。