搜尋抓取

服務器回 304 之後,蜘蛛這一趟抓到了什么

蜘蛛再次抓取同一個 URL 时,請求头里常带着條件請求标记,服務器如果回 304,這一趟就不會传正文。本文說明 304 的判断依據、動態頁面與 CDN 常见的實現偏差,以及怎么用條件請求和日誌驗證自己的配置是否准确。

搜尋抓取

服務器回 304 之後,蜘蛛這一趟抓到了什么

蜘蛛再次訪問一個已经抓過的 URL 时,請求头里常常會带上 If-Modified-Since 或 If-None-Match。這两個头的意思很直白:上次我拿到的是這個版本,如果現在還一样,就告诉我一声,不用把整頁传回来。服務器判断内容没變,就會回 304 Not Modified。

304 是抓取過程中很常见的一種响應,但它经常被誤讀。它不是“蜘蛛没来”,也不是“蜘蛛放弃了這個頁面”,只是這一趟没有传輸正文。它节省的是传輸和解析的消耗,頁面在爬虫侧依然是被看過的。

304 發生在哪一步

一次典型的重复抓取大致是這样:

  1. 蜘蛛請求 URL,带上上次记錄的修改時間或 ETag。
  2. 服務器拿目前内容去比對這两個值。
  3. 一致就返回 304,响應体為空;不一致就返回 200,重新传一遍完整頁面。

所以 304 只代表“和上次相比没變化”,並不能說明頁面质量、排名或者抓取频次有什么结论。

正确實現 304 需要什么

要让 304 判断准确,前提是服務器能分清“變了”和“没變”。常见做法有两種:

  • Last-Modified / If-Modified-Since:基于最後修改時間。静態頁面、图片、CSS 這類直接映射到文件的资源比較容易做准。
  • ETag / If-None-Match:基于内容生成的标识,通常更精确,但要求同一份内容稳定生成同一個 ETag。

麻烦多半出在動態頁面上。如果模板里嵌了目前時間、随机數、會话 ID,或者每次都算出不一样的 ETag,蜘蛛每次都會拿到 200,條件請求形同虚设。反過来,如果内容已经改了,但程序逻辑没有更新 Last-Modified,服務器仍然會回 304,蜘蛛就繼續拿着舊版本。

304 的前提是服務器说真话。判断逻辑一旦有偏差,省下的那点带宽換来的可能是蜘蛛長期看不到更新。

几個容易被忽略的地方

反向代理與 CDN 這一层

如果 CDN 或反向代理缓存了 ETag,而源站内容已经更新,缓存层可能仍按舊标识回 304。排查這類問题,要分別看源站直连和经過 CDN 的响應头是否一致,單看一侧容易得出错誤结论。

304 和抓取频率没有直接關系

有些运营者想通過频繁返回 304 来“减少蜘蛛訪問”。實际效果有限,因為蜘蛛是否再来、間隔多長,取决于站点整体更新情况、連結變化、抓取预算等多個因素。把 304 当成频率開關,通常達不到预期。

空响應不代表可以忽略狀態碼

304 的响應体是空的。如果日誌里只統計字节數或内容長度,很容易把這類請求当成異常。統計时應單獨看狀態碼分布,区分 200、304、301、404 各自的比例。

怎么驗證自己站点的 304 是否正确

  1. 用命令行工具带條件头請求頁面:先记下一次响應里的 Last-Modified 或 ETag,再用它發起第二次請求,看是否返回 304。
  2. 改動頁面内容後重复上述請求,確認返回的是 200 而不是 304。
  3. 在服務器日誌里按狀態碼聚合,看静態资源和 HTML 的 304 比例是否合理。
  4. 對经過 CDN 的 URL,在源站和 CDN 侧各做一次對比。

小结

304 是抓取過程中的一個效率细节。做對了能减少無谓传輸,做错了可能让蜘蛛長期停留在舊版本上。它替代不了内容更新、内鏈調整和 Sitemap 维護,但当你在排查“蜘蛛為什么没看到新内容”时,它是一個值得優先检查的具体項。