蜘蛛再次訪問一個已经抓過的 URL 时,請求头里常常會带上 If-Modified-Since 或 If-None-Match。這两個头的意思很直白:上次我拿到的是這個版本,如果現在還一样,就告诉我一声,不用把整頁传回来。服務器判断内容没變,就會回 304 Not Modified。
304 是抓取過程中很常见的一種响應,但它经常被誤讀。它不是“蜘蛛没来”,也不是“蜘蛛放弃了這個頁面”,只是這一趟没有传輸正文。它节省的是传輸和解析的消耗,頁面在爬虫侧依然是被看過的。
304 發生在哪一步
一次典型的重复抓取大致是這样:
- 蜘蛛請求 URL,带上上次记錄的修改時間或 ETag。
- 服務器拿目前内容去比對這两個值。
- 一致就返回 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 是否正确
- 用命令行工具带條件头請求頁面:先记下一次响應里的 Last-Modified 或 ETag,再用它發起第二次請求,看是否返回 304。
- 改動頁面内容後重复上述請求,確認返回的是 200 而不是 304。
- 在服務器日誌里按狀態碼聚合,看静態资源和 HTML 的 304 比例是否合理。
- 對经過 CDN 的 URL,在源站和 CDN 侧各做一次對比。
小结
304 是抓取過程中的一個效率细节。做對了能减少無谓传輸,做错了可能让蜘蛛長期停留在舊版本上。它替代不了内容更新、内鏈調整和 Sitemap 维護,但当你在排查“蜘蛛為什么没看到新内容”时,它是一個值得優先检查的具体項。