重复抓取並不等于浪費
站点日誌里经常能看到同一個地址被反复抓取。多數人第一反應是蜘蛛在浪費预算,但實际情况是:蜘蛛需要確認頁面有没有發生變化。如果每次都要把整個 HTML 重新传一遍,對站点带宽和蜘蛛的處理资源都是消耗。HTTP 协议里本来就有一套机制用来回答“這個资源變了吗”,條件請求就是其中之一。
條件請求:蜘蛛先問一句“變了吗”
当蜘蛛之前抓過某個頁面,它可能记住两個信息:响應里的 ETag 和 Last-Modified。下次再来同一個地址时,請求头里會带上 If-None-Match 或 If-Modified-Since。
- 内容没變:服務器返回 304 Not Modified,不带正文,蜘蛛只需更新一下“我確認過”的记錄。
- 内容變了:返回 200 和完整正文,蜘蛛重新抓取、重新處理。
從抓取效率上看,304 是省成本的;但從“發現新内容”的角度看,304 意味着這次訪問没有带来新信息。两者並不矛盾:稳定的頁面用 304 回應是正常的,频繁變更的頁面每次返回 200 也是正常的。
站点侧容易被忽略的几点
- ETag 生成方式:如果 ETag 里混入了請求時間、進程 ID 之類每次都變的字段,等于每次都是“新版本”,蜘蛛永遠拿不到 304。
- Last-Modified 的准确性:文件時間被部署脚本整体刷新,會让所有頁面看起来刚刚更新過。
- 動態拼接的頁面:广告位、推荐位、随机排序的内容如果直接寫進 HTML,頁面每次都不一样,條件請求會持續失效。
- CDN 與源站的头不一致:邊缘节点回源後改寫或丢弃 ETag,也會让缓存协商失效。
- 304 响應不要带正文:有些中間层會给 304 硬塞一段内容,容易让蜘蛛判断混乱。
304 多了是不是不好
不必然。一個内容稳定的文档頁,長期返回 304 是健康的,說明服務器在正确地告诉蜘蛛“不用重新下载”。真正需要在意的是该變的頁面没變:比如列表頁新增了文章,但返回的仍是上次的 ETag,蜘蛛就會繼續用舊版本,新 URL 需要靠内鏈、Sitemap 等其他通路才能被發現。
判断标准不是 304 的數量,而是 304 是否與頁面的真實更新节奏一致。
和抓取预算之間的關系
條件請求省下的是传輸和解析的成本,不一定會减少蜘蛛訪問的次數。蜘蛛依然會按自己的节律回訪,只是每次拿到的資料量小一些。所以不要把“让蜘蛛少来”当目标,而是让每次訪問都尽量是有效信息:该更新的頁面能被识別為更新,没變的頁面不重复传輸。
可以落地的检查清單
- 抓几個不同類型頁面(首頁、列表頁、詳情頁),用 curl 带條件头模拟一次請求,看是否返回 304。
- 检查 ETag 是否稳定:同一頁面连續两次請求,ETag 應保持一致。
- 確認 Last-Modified 反映的是内容真實修改時間,而不是部署時間。
- 對比源站與 CDN 返回的头,確認没有被改寫。
- 對高频更新的頁面,接受它返回 200;對稳定頁面,保留正确的协商头。
這些细节不顯眼,但會持續影响蜘蛛每次来訪拿到的東西。把條件請求理顺,属于成本不高、方向明确的基础工作。