搜尋抓取

HTTP 缓存头與重复抓取:ETag、Last-Modified 與 304 的核對

蜘蛛對已收錄 URL 的回訪是常態,條件請求能让重复抓取更省资源。本文說明 Last-Modified、ETag 與 304 响應在抓取流程中的實际作用,梳理 304 经常失效的原因,並给出日誌與响應头的核對顺序,帮助站長判断回訪行為是否正常。

搜尋抓取

HTTP 缓存头與重复抓取:ETag、Last-Modified 與 304 的核對

蜘蛛把 URL 抓進索引之後,並不會就此停下。對已经收錄的地址,它會按一定节奏回来確認内容是否變化。這個回訪過程如果每次都完整下载一遍 HTML,對站点带宽和蜘蛛自身的調度都是负担。HTTP 协议里的條件請求机制,就是為了缓解這件事:蜘蛛带上上次拿到的标识,服務器只需回一個很短的响應,說明“内容没變”。

回訪為什么是常態

很多人把抓取理解成一次性的動作,實际上抓取是一個持續核對的過程。首頁、栏目頁、热门内容頁的回訪频率通常更高,因為它們的變更概率大。長尾頁面回訪間隔會拉長,但並不等于放弃。理解這一点之後,就能明白為什么日誌里同一個 URL 會出現几十次、上百次记錄。

三個头字段的分工

Last-Modified

表示资源最後一次修改的時間。蜘蛛下次回訪时會带上 If-Modified-Since,時間與服務器记錄一致时,服務器返回 304。它的優点是简單,几乎所有服務器都能自動輸出;缺点是精度只到秒,短時間内多次改動可能被合並成一次。

ETag

本质是一段内容指纹,蜘蛛用 If-None-Match 带回来比對。ETag 可以做到内容級判断,比時間戳更准确。但要注意,如果 ETag 是每次請求動態生成的,每次值都不同,條件請求就永遠匹配不上,304 也就永遠不會出現。

Cache-Control

它更多面向浏览器和 CDN,對搜尋蜘蛛的约束力相對有限。不要指望用 Cache-Control 来規定蜘蛛的抓取频率,抓取节奏主要由站点整体表現和蜘蛛自身調度决定。

304 响應到底意味着什么

收到 304,表示服務器確認内容未變,蜘蛛不會重新解析頁面,但這次抓取仍會被計入日誌。也就是说,304 不等于“這次什么都没發生”,它是把一次完整下载压缩成了一次轻量確認。對站点来说,這是省流量的好事;對运营者来说,看到大量 304 是正常現象,不必紧張。

需要留意的是:304 只說明“没有變化”,不代表這只 URL 的抓取優先級被提升或降低。別把 304 的數量当作健康度指标單獨使用。

304 经常失效的常见原因

  • ETag 由進程或時間随机生成,每次請求值都不同。
  • 頁面里嵌入了目前時間、随机數、在线人數等動態片段,導致内容指纹每次都變。
  • 中間层代理或 CDN 改寫、剥离了 ETag 與 Last-Modified。
  • 服務器時間不准,Last-Modified 比實际修改時間還早或還晚。
  • 框架為每次請求重新渲染模板,即使資料未變,輸出字节也不完全一致。

這几類問题的共同点是:頁面對用戶看起来没變,但服務器認為它變了。表現出来就是日誌里该 URL 全是 200,响應体大小几乎一样,却没有 304。

和 Sitemap 的 lastmod 要對得上

Sitemap 里的 lastmod 是给蜘蛛看的更新提示,而 Last-Modified 是响應头里的更新声明。两者如果長期互相矛盾,比如 Sitemap 天天寫当天日期,响應头却几個月没動,會让更新信号的可信度下降。建议让 lastmod 反映真實的内容改動時間,不要為了“催抓”而机械刷新。

核對顺序建议

  1. 挑几個回訪频繁的 URL,用工具或命令行查看响應头,记錄 ETag 與 Last-Modified 的具体值。
  2. 間隔几分钟再請求一次,带上條件头,看是否返回 304;重复两三次,確認 ETag 是否稳定。
  3. 對照服務器訪問日誌,統計同一 URL 的 200 與 304 比例。長期全是 200 且体积不變,就值得排查。
  4. 检查 CDN 或反向代理配置,確認没有剥掉缓存相關头字段。
  5. 確認 Sitemap 的 lastmod 與响應头時間大致一致,不要出現明顯冲突。

別走偏的两個方向

一是為了让蜘蛛“觉得内容更新了”而故意改動 ETag,這種做法只會增加無意义的回訪消耗,對内容质量没有帮助。二是把 304 当成抓取成功的證明,實际上它只說明核對通過,與頁面是否被收錄、是否有排名没有直接關系。

把缓存头当成一項基础设施来维護就够了:让 ETag 稳定、让 Last-Modified 真實、让中間层不干扰。剩下的交给正常的抓取节奏。