很多站長给入口頁開了缓存校驗(Last-Modified / ETag)之後,發現日誌里入口頁的狀態碼變成了 304,于是产生疑問:蜘蛛這次到底有没有讀到頁面内容?里面的目标連結還會不會被發現?要回答這個問题,先要弄清 304 是怎么来的。
304 是怎么产生的
304 Not Modified 不是服務器主動返回的,而是對條件請求的回應。搜尋蜘蛛第二次、第三次訪問同一個 URL 时,通常會在請求头里带上 If-Modified-Since 或 If-None-Match,把上次拿到的 Last-Modified 時間或 ETag 值回传。
- 服務器比對後認為文件没變,返回 304,响應体為空(0 字节)。
- 服務器認為變了,返回 200,重新下發完整 HTML。
- 服務器不支持條件請求,忽略請求头,直接返回 200。
所以 304 代表的是“和上次一样”,而不是“這次没抓”。
蜘蛛遇到 304 时通常怎么處理
從抓取調度的角度看,304 是一個正常且成本很低的结果。多數搜尋引擎會把這次訪問計入抓取統計(日誌里确實有一次請求),並沿用上一次缓存下来的頁面内容與連結關系。也就是说:
- 頁面里的連結大概率不會被重新完整解析一遍,因為内容被認為和上次是同一份。
- 该 URL 的抓取频率可能维持甚至略微下降,服務器说没變化,調度上就少了重抓的理由。
- 如果入口頁的連結是按時間轮換、由脚本動態插入的,那么“内容没變”的判定本身就可能出错。
關键差別在于:入口頁的作用是持續暴露新的目标 URL,而 304 的前提是“内容没變”。這两者天然有点冲突。所以問题不在于 304 是否被處理,而在于你的入口頁到底有没有真的發生變化。
什么样的入口頁容易被 304 卡住
頁面内容确實長期不變
入口頁寫好後几個月不動,連結列表固定,這时返回 304 是合理的,連結發現也早已完成,不构成問题。
内容會變,但校驗逻辑没有跟着變
常见几種情况:按天生成缓存但文件時間戳忘了更新;ETag 由前端模板 ID 生成,改了連結列表 ETag 却没變;反向代理或 CDN 把舊的校驗值原样透传回来。此时爬虫看到的一直是“没變”,新的目标連結就迟迟暴露不出去。
怎么判断入口頁有没有被真正重讀
- 看服務器日誌里 200 與 304 的比例。如果入口頁長期几乎全是 304,而你每周都在換連結,那就不正常。
- 看响應体大小。304 的响應体是 0 字节,200 才會带上 HTML 体积,日誌里同时记錄這两列,問题會一目了然。
- 看 User-Agent 與訪問時間分布,確認是搜尋蜘蛛而不是自己的缓存探针触發的 304。
- 小范围驗證:手動改一條連結再观察,如果依然是 304,說明校驗值没有跟着内容更新。
處理建议
- 不要為了“让蜘蛛多来”就强行關掉缓存校驗。每次都返回 200 會消耗更多带宽,也可能把抓取预算花在没必要的地方。
- 让校驗值跟着内容走。ETag 或 Last-Modified 應基于頁面真實内容生成,而不是固定值或模板版本号。
- 入口頁更新要改到能被檢測到的程度。連結的增删與顺序調整都算變化,只改不可见的注释不算。
- 新的目标 URL 優先單獨提交。入口頁负责長期暴露,提交负责快速發現,两者是互补關系。
- 适当分散入口頁。不要把大量連結挤在一個長期不變的頁面上,否則 304 一旦卡住,影响面會很大。
304 本身不是错誤,也不會直接導致目标 URL 不被抓取。真正需要關注的是:入口頁的内容變化,有没有被服務器的校驗逻辑如實反映出来。
最後提醒一句,抓取和收錄是两件事。入口頁被正常重讀、目标 URL 被成功抓取,都不等于一定會收錄,最终還是取决于目标頁面自身的质量和站点整体表現。