蜘蛛第一次抓走入口頁之後,很可能還會再来。第二次来的时候,它的請求头里可能多带了两個字段:If-Modified-Since 和 If-None-Match。這是浏览器和爬虫共用的机制——條件請求。服務器判断内容没變,就回一個 304 Not Modified,不用重發整頁 HTML。
對蜘蛛池来说,這件事有两個方向的影响:用得好,蜘蛛愿意多来几次、少花流量;用得糙,蜘蛛會因為每次都被告知「没變」而降低對入口頁的訪問频次,或者反過来,被错誤的 304 挡住新内容。
條件請求在蜘蛛池里長什么样
第一次抓取时,服務器在响應里给出两個「指纹」:
- Last-Modified:這個入口頁最後一次改動的時間。
- ETag:内容的校驗值,通常是文件哈希,也可以是版本号。
蜘蛛下次請求时带上它們,服務器比對:一致就回 304,不一致就回 200 加完整内容。整個過程中,蜘蛛拿到的是「有没有變」這個结论,而不是内容本身。
304 對入口頁是好是坏
没有绝對答案,取决于入口頁承担的角色。
适合回 304 的情况
- 入口頁是長期稳定的跳轉頁或聚合頁,正文几乎不動。
- 頁面被大量蜘蛛反复抓取,服務器带宽和 CPU 吃紧。
- 頁面由静態文件生成,改動有明顯的部署時間点。
不适合硬回 304 的情况
- 入口頁上的連結列表會動態更新,靠 304 挡住了蜘蛛,新連結就没机會被發現。
- 時間戳寫得過于粗糙,比如整点取整,一小时内多次改動都被算成「没變」。
- 用负载均衡或多台机器时,各机器给出的 ETag 不一致,304 判断来回抖動。
几個常见的坑
- 動態生成的時間戳:每次請求都把 Last-Modified 寫成「目前時間」,蜘蛛每次都拿到 200,等于没有缓存协商,白白浪費抓取预算。
- ETag 里带机器名或進程号:集群环境下同一頁面有多套 ETag,蜘蛛在不同 IP 上拿到不同值,容易反复重取。
- 内容變了却還回 304:缓存层没清干净,源站内容更新了,邊缘节点仍按舊指纹回 304,蜘蛛讀到的還是老版本。
- CDN 與源站的 ETag 不一致:CDN 改寫了自己的 ETag,回源比對时對不上,源站更新被屏蔽。
- 错誤頁也參與协商:把 404、503 頁面配了長缓存,蜘蛛再来看时收到 304,誤以為那個 URL 一直有效。
在蜘蛛池里怎么落地
- 先明确入口頁類型:稳定跳轉頁可以放心用 304,會持續更新連結的頁面宁可让它回 200。
- Last-Modified 用真實的内容生成時間,不要用請求時間,精确到秒即可。
- ETag 用内容哈希,去掉机器相關信息;多台源站保持一致。
- 检查缓存层級,確認 CDN 是否改寫或丢弃 ETag,必要时在回源請求里保留原值。
- 定期抽查入口頁响應,確認改動後第一次抓取拿到的是 200,之後才可能是 304。
用日誌驗證效果
看蜘蛛日誌时,把同一 URL 的訪問按時間排開,观察狀態碼序列。理想情况是「200 → 304 → 304 →(内容更新)→ 200 → 304」。如果一直是 200,說明协商没生效,抓取预算被浪費;如果一直是 304 但頁面明明更新過,說明缓存或指纹那一层出了問题。
304 本身不产生收錄,也不提升權重,它只是让蜘蛛的重复訪問更省事。把它当成一次沟通成本優化,而不是一種優化手段。