入口頁一旦被搜尋蜘蛛抓過几次,服務器往往會開始收到带條件的請求,返回 304 Not Modified。這时日誌里看不到 200,也看不到完整 HTML,很多做蜘蛛池的人就會担心:既然没返回正文,頁面里的目标連結是不是也没被讀到?
先说结论:304 本身不是問题,缓存對不上才是
304 的含义是“内容没變,用你上次那份”。搜尋蜘蛛在抓取過一個 URL 之後,本地會保留一份快照和連結關系。再次抓取时它會带上 If-Modified-Since 或 If-None-Match,服務器確認内容未變就回 304,蜘蛛直接用本地缓存版本繼續處理。
所以,只要首次抓取是正常的 200,且頁面里当时就有那些目标連結,後續的 304 一般不會让連結凭空消失。真正容易出問题的是另一種情况:頁面明明改了,服務器却回了 304。
304 是怎么产生的
- 服務器根據 Last-Modified 判断:請求头里的時間不早于文件修改時間,就回 304。
- 服務器根據 ETag 判断:請求头里的 ETag 與目前一致,就回 304。
- 中間的 CDN、反向代理、Nginx 缓存层自己做了判断,直接把缓存的 304 或 200 吐出来,源站甚至没收到請求。
這三種情况里,前两種通常是准确的;第三種最容易出現“源站内容變了,蜘蛛拿到的還是舊版本”的偏差。
哪些寫法會让新增的目标連結被延後發現
1. 内容變了但 ETag、Last-Modified 没變
有些程序會给入口頁寫死一個固定的 Last-Modified,或者 ETag 只按 URL 生成、不按内容生成。结果就是你在頁面里新增了一批目标連結,蜘蛛下次来還是拿到 304,缓存版本里自然没有新連結。這種延迟可能持續到缓存過期或被强制刷新為止。
2. CDN 把入口頁当成長期静態资源缓存
入口頁本质是動態列表頁,如果被 Cache-Control 设成很長的 max-age,或者被 CDN 的“全部缓存”規則命中,蜘蛛拿到的就是舊快照。新增連結、刪除連結都不會及时体現。
3. 不同 UA 命中不同缓存
有些配置按 User-Agent 分缓存,但没有正确設定 Vary,導致搜尋蜘蛛拿到的是给普通用戶看的版本,或者反過来拿到一個空壳版本。表現上看是 200,實际正文里没有目标連結。
4. 首抓失敗後又一直回 304
如果第一次抓取时頁面超时、返回 5xx,蜘蛛没有建立有效快照,後續服務器再回 304,它手上没有可用版本,這次抓取基本等于作废。所以入口頁的稳定性比“省不省流量”重要得多。
自查清單
- 翻日誌,看入口頁的狀態碼分布:200 與 304 各占多少,是否出現異常比例的 304。
- 连續两次手動請求同一個入口頁,對比 Last-Modified、ETag 是否随内容更新而變化。
- 在入口頁新增一條測試連結,然後不带條件請求一次,確認返回 200 且 HTML 里能看到新連結。
- 检查 CDN 與反代規則,確認入口頁没有被長期强缓存,或者缓存時間在可接受范围内。
- 確認没有把搜尋蜘蛛的 UA 單獨導向一個内容不同的版本。
比較稳妥的做法
- 入口頁不做過度缓存,缓存時間控制在几分钟到十几分钟量級,内容更新能較快反映。
- 让 Last-Modified 和 ETag 真實反映内容變化,不要寫死。
- 新增或刪除目标連結时,确保頁面 HTML 有實际變化,這样條件請求自然會返回 200。
- 入口頁保持轻量、可稳定訪問,避免首抓就失敗。
需要提醒的是,304 只影响“這次抓取要不要重新传正文”,它不决定目标 URL 最终會不會被索引。搜尋蜘蛛是否顺着連結繼續訪問、目标頁是否被收錄,還取决于目标頁本身能否正常打開、内容是否有價值。入口頁能做的是把發現這一步做顺,後面的结果不是它能單方面决定的。