蜘蛛来抓入口頁,走的是 HTTP,就會遇到缓存。缓存本来是為用戶和带宽服務的,但在蜘蛛池里,它會同时影响三件事:蜘蛛每次看到的内容版本、源站要扛多少回源請求,以及你在訪問日誌里判断是否正常的那套依據。入口頁往往改動不多,很多人顺手配一條長缓存,等真要加連結、換指向的时候才發現,蜘蛛看到的還是舊版本。
三层缓存要分開看
把缓存当成一個整体,很容易配错。實际至少有三层:
- 浏览器與客戶端缓存:由 Cache-Control、Expires 控制。搜尋引擎蜘蛛虽然也是客戶端,但通常不會像浏览器那样長期复用本地缓存,這层對蜘蛛影响有限,但對普通訪客和部分抓取工具存在影响。
- CDN 或反向代理缓存:這是蜘蛛池里最容易出問题的一层。蜘蛛請求到的是邊缘节点,节点命中缓存就直接返回,不回到源站。内容更新了但节点没刷新,蜘蛛拿到的就是舊頁面。
- 源站應用层缓存:頁面片段、資料库查询结果、整頁静態化等。它决定回源时生成的内容是不是最新的,属于内部机制,但和 CDN 叠加起来會放大問题。
排查任何内容不更新的問题,都應该按這三层顺序查一遍,而不是先怀疑蜘蛛。
Cache-Control 怎么定比較稳
入口頁和静態资源應该区別對待:
- 入口頁 HTML:不建议设很長的 max-age。比較常见的做法是把 max-age 设得很短,几十秒到几分钟,或者用 no-cache,即允许缓存但每次要回源校驗。真正需要每次都不一样时再用 no-store,但用多了會明顯增加回源压力。
- CSS、JS、图片等静態资源:可以设長缓存,配合文件名里的版本号或哈希。這样蜘蛛抓入口頁时不會因為资源拖慢整体响應。
- 接口和動態片段:一律短缓存或不缓存,避免不同入口頁拿到串味的内容。
關键点是:入口頁本身別做長時間不校驗的缓存。宁可多回几次源,也不要让蜘蛛長期看到舊内容。
ETag 與 Last-Modified:304 是省事,也可能坑人
條件請求的價值在于:内容没變就返回 304,不传正文,省带宽也省源站 CPU。合理使用是好事,但有几個常见坑:
- 内容變了,标识没變:ETag 由文件修改時間或某些内部字段生成,改内容时没同步更新,结果蜘蛛拿着舊标识来校驗,你回 304,蜘蛛就一直認為内容没變。
- 集群节点 ETag 不一致:多台机器生成的 ETag 不同,蜘蛛每次校驗都像遇到新内容,反而可能增加抓取压力。此时不如统一用 Last-Modified,或者干脆關掉 ETag。
- 對 304 的誤讀:日誌里全是 304,不代表蜘蛛没抓,只是没传正文。判断抓取是否正常,要看請求數、狀態分布和内容版本的组合,不能只看正文体积。
内容更新後,怎么让新版本被看到
更新入口頁之後,指望過一會儿蜘蛛自然會看到新版是碰运气。更稳妥的做法是:
- 更新源站内容,確認回源拿到的是新版本。
- 主動刷新 CDN 缓存,或等短 max-age 自然過期。
- 確認 ETag 與 Last-Modified 跟着變了。
- 用外部工具或本地請求驗證邊缘节点返回的是新内容。
- 再观察抓取日誌中该路径的狀態碼和响應大小是否有變化。
几個反复出現的誤区
- 全部 no-store 最安全:确實不容易看到舊内容,但回源压力會明顯上升,蜘蛛集中来訪时容易触發超时和 5xx,反而更糟。
- CDN 缓存越久越省钱:入口頁恰恰是最不该長缓存的部分,省下的带宽可能換来一堆過期的抓取结果。
- 缓存不影响蜘蛛:影响很大,只是它作用在邊缘节点和回源之間,你在源站日誌里看不见。
- 304 多了就是被降權:304 說明内容没變,本身是正常交互,不必過度解讀。
一個简單的检查清單
- 入口頁 HTML:短 max-age 或 no-cache,允许校驗。
- 静態资源:長缓存加版本化文件名。
- ETag 與 Last-Modified:生成規則稳定,多节点一致。
- CDN:入口頁缓存規則單獨配置,更新时有可用的刷新手段。
- 日誌核對:能区分命中缓存、回源、304 三種情况。
缓存本身不會带来抓取,但配置不当會稳定地制造我明明改了的错觉。把它当成抓取鏈路上一個需要定期复核的环节,比事後到處找原因省事得多。