先说清楚:304 是“内容没變”的確認信号
当搜尋蜘蛛再次請求一個入口頁时,通常會带上 If-Modified-Since 或 If-None-Match 請求头。服務器判断頁面和上次一样,就返回 304 Not Modified,不返回正文。
對蜘蛛来说,這等于確認“還是我上次拿到的那個版本”。它會繼續沿用本地缓存里的那一次抓取结果,包括当时頁面里發現的目标連結。
所以 304 本身不會让已经發現過的目标 URL “失效”,也不會因為這次請求而重新解析一遍新連結——因為根本没有新正文可解析。
那 304 什么时候會變成麻烦
關键不在狀態碼本身,而在于頁面真的變了,服務器却说没變。常见场景有這几種:
- 入口頁的連結列表會定期轮換,但頁面 mtime 没動,或用的是统一的發布時間。
- ETag 被中間层寫成了固定值,或者由几個字段拼出来、内容變化时它却不變。
- CDN 或反向代理自己缓存了 HTML,並按自己的規則返回 304,源站更新没透传。
- 入口頁由模板渲染,模板改了但文件時間戳没變,條件請求判断失效。
一旦出現這種情况,蜘蛛拿到的永遠是舊版本連結列表,新加進去的目标 URL 就一直等不到第一次被發現的机會。
日誌里怎么判断是“正常 304”還是“卡住了”
- 按入口頁 URL 聚合狀態碼,看它是不是長期只有 304、几乎没有新的 200。
- 抽查請求头,確認蜘蛛是否带上 If-Modified-Since / If-None-Match,以及服務器返回的 Last-Modified / ETag 是否和内容更新同步。
- 手動改一次入口頁内容,然後带同样的條件請求头發一次請求。如果仍然返回 304,說明條件判断有問题。
- 對比目标 URL 的首次被抓時間與入口頁最後一次 200 的時間。若目标 URL 首次抓取時間明顯晚于連結上线時間,基本可以確認入口頁在“假 304”。
几個實际的調整方向
- 入口頁内容變化时,让 Last-Modified 或 ETag 真實變化,不要用硬编碼時間或固定字符串。
- HTML 類的入口頁,缓存 TTL 別设太長;連結列表更新频繁时更要注意。
- 確認 CDN 是否忽略了源站的缓存校驗头,必要时让入口頁回源校驗。
- 304 虽然不传正文,但仍會消耗一次請求。入口頁數量多的时候,無意义的條件請求同样占用抓取预算,不要靠它来“省抓取”。
- 如果你确實希望蜘蛛尽快看到新連結,让入口頁在更新後正常返回 200,是最直接的做法。
顺带一提:304 和“新連結發現”是两件事
連結發現依赖的是蜘蛛真正拿到並解析過一次的頁面正文。它能复用缓存,但不會凭空知道缓存里不存在的東西。把“蜘蛛来過”当成“連結已经被發現”,是這類問题里最常见的誤判。
304 说的是“和上次一样”,不是“再抓一次”。入口頁的連結列表在變,就不要再让它一直回 304。