搜尋抓取

304 與條件請求:让蜘蛛少下一遍已经拿過的頁面

蜘蛛重訪頁面时會带上 If-None-Match 和 If-Modified-Since,服務器回 304 就能省下一次完整下载。本文說明這两组字段怎么配對、304 對抓取效率的實际影响,以及 ETag 抖動、Last-Modified 恒為目前時間、中間层改寫头部這三類常见失效配置的排查方法。

搜尋抓取

304 與條件請求:让蜘蛛少下一遍已经拿過的頁面

蜘蛛第二次訪問同一地址时,往往不需要把完整 HTML 再下载一遍。它會在請求头里带上几個字段,相当于告诉服務器:我上次来過,手里存着当时的版本,你確認一下有没有變。如果内容没動,服務器回一個空的 304,這次交互就結束了。單個頁面省下的量很小,但铺到全站几萬、几十萬個地址上,就是抓取效率的差別。

蜘蛛重訪时會带哪些头

條件請求依赖两组配對字段,缺一组就會退化成全量下载。

  • If-None-Match 配 ETag:服務器给每個版本一個标识,蜘蛛下次带回来比對,标识一致就回 304。
  • If-Modified-Since 配 Last-Modified:按時間比對,蜘蛛带上次收到的最後修改時間。
  • 两组都没有,或者服務器不認,蜘蛛就只能把頁面完整再拉一次。

304 省下来的不只是带宽

很多人只把它当成省流量的手段,其實對抓取這件事,影响更直接的是另外几层:

  • 响應体积從几十 KB 降到几百字节,同样的抓取配額能覆盖更多 URL。
  • 後端渲染和資料库查询可以被跳過,服務器在抓取高峰时更從容。
  • 响應更快,蜘蛛在單位時間内的抓取节奏更平稳,不容易触發限速。
  • 日誌里能清楚看出哪些頁面确實没變,排查抓取異常时更省事。

常见的三種失效配置

ETag 每次請求都變

有的框架預設用進程 ID、時間戳或随机串拼 ETag,同一個頁面每次返回的标识都不同。蜘蛛带回来的值和服務器目前值永遠對不上,只能一直回 200 全量下载。這種情况在日誌里表現為:同一 URL 高频重复抓取,且响應体积没有下降。

Last-Modified 恒等于目前時間

部分 CMS 或模板在輸出时直接寫上目前時間,頁面其實没改,時間却在走。蜘蛛看到的是頁面一直在更新,就會更频繁地回来確認,實际拿到的東西一模一样。這類配置比 ETag 出错更隐蔽,因為它看起来像是内容活跃。

中間层把头部丢掉或改寫

CDN、反向代理、WAF 有时會重寫或剥离 ETag、Last-Modified,也可能在邊缘缓存後返回自己的标识。节点之間标识不一致时,蜘蛛今天從這個节点拿到的 ETag,明天從另一個节点去比對,结果自然對不上。

自查方法

  1. 用命令行连續請求同一個地址两次,對比两次响應头里的 ETag 和 Last-Modified 是否一致。
  2. 把第一次拿到的 ETag 手動放進 If-None-Match 再請求一次,看是否返回 304。返回 200 說明條件請求没生效。
  3. 換成站点實际使用的 CDN 域名再测一遍,確認邊缘层没有引入新的标识。
  4. 抓一周日誌,統計同一 URL 的重复抓取次數和平均响應体积,看有没有下降趋势。

几個容易走偏的地方

  • 304 不代表内容會被重新评估。它只是告诉蜘蛛没變,不构成任何更新信号,別指望靠它推動重抓。
  • 内容真的改了就必须回 200。為了省资源把變更後的頁面也回 304,會让蜘蛛長期拿到舊版本。
  • 不要按 UA 区別對待。對搜尋蜘蛛一套條件請求策略,對普通訪客另一套,容易被判定為伪装,風險高于收益。
  • 它不能替代其他手段。304 優化的是重复抓取的成本,URL 發現仍然要靠内鏈和 Sitemap,抓取深度仍然取决于站点结构。
把條件請求的配對字段做對,是抓取效率里性價比很高的一項:改動小、覆盖范围大,但前提是标识稳定且中間层不捣乱。先测,再改。