搜尋蜘蛛回訪已收錄的 URL 时,通常會在請求头里带上 If-None-Match 或 If-Modified-Since。服務端如果判定内容没變並返回 304,蜘蛛就不必下载正文、解析頁面、再和索引里的版本比對;如果每次都是 200 加完整正文,站長從浏览器里看不出任何異常,但抓取预算會被反复花在同一批頁面上。
304 协商省下的是什么
- 传輸体积:正文不必回传,對图片多、正文長的詳情頁更明顯。
- 蜘蛛端開销:拿到 304 後可直接跳過解析與比對环节。
- 高峰带宽占用:抓取密集时段,重复传輸减少對源站更友好。
需要分清的是,304 只表示“自上次校驗头所代表的狀態以来没有變化”,它不代表這個 URL 一定被收錄,也不代表内容永遠不會更新。
常见的 304 失效原因
- ETag 每次請求都變,比如由進程号、時間戳或随机串拼成。
- Last-Modified 取的是目前渲染時間,而不是内容的最後更新時間。
- 反向代理或 CDN 回源後重寫头部,把源站返回的 ETag 換掉。
- 缓存层剥掉了 If-None-Match,源站收不到校驗头,只能返回 200。
- 頁面里寫入随机數、AB 測試标记或毫秒級時間戳,内容哈希每次都不同。
- 多台源服務器各自生成 ETag,蜘蛛命中的机器不同,校驗值自然對不上。
一條可执行的排查顺序
- 先用命令行取一次响應,记下 ETag 與 Last-Modified,再带上同样的值請求同一個 URL,观察狀態碼是否為 304。
- 分別對源站 IP 直连和经過 CDN 的域名各测一次,確認差异出現在哪一层。
- 连續請求两次相同 URL,比較两次 ETag 是否一致;不一致說明生成逻辑带入了易變因子。
- 检查 Vary、Cache-Control、Age 是否符合预期。Vary 里带上 Cookie 之類的字段,會使缓存與协商几乎不命中。
- 翻服務器日誌,統計带 If-None-Match 的請求數與返回 304 的數量,算出整体命中水平,再按目錄分類看哪類頁面最差。
- 先從更新频率低、數量大的列表頁與歷史詳情頁入手,這類頁面修正後的收益最直接。
別用 304 去“省抓取”
304 的含义是资源未修改。内容其實已经更新却仍返回 304,蜘蛛會繼續沿用舊版本,頁面更新可能長期滞後。想控制抓取频次,應该靠合理的更新节奏與入口收敛,而不是靠错誤的校驗头。
還要注意,把 200 改成 301 或返回空正文,都不是 304 的替代方案。301 會改變入口指向,空正文會让蜘蛛認為頁面内容缺失,两者的副作用都比“多传几次正文”大得多。
與抓取预算的關系
單頁省下几 KB 看起来有限,但一個几萬頁的站点,如果每次回訪都全量返回,累积的传輸與解析開销並不小。把校驗头做對属于成本低、可長期受益的優化。它不能提高收錄,也無法保證排名,只是让蜘蛛把有限的抓取次數花在更值得的地方。
小结
- 先確認校驗头能否稳定复現,再区分是源站問题還是中間层改寫。
- ETag 要基于内容本身生成,避免带入時間戳、進程号、随机串。
- Last-Modified 用真實的内容更新時間,不要用渲染时刻。
- 日誌里的 304 命中率是長期观测指标,值得定期复查。