很多人盯着抓取次數,却忽略了一個更细的消耗:蜘蛛每次来都要把整個頁面重新下载一遍,即使這一頁從上周到現在一個字都没改。條件請求就是用来解决這種浪費的——它让服務器有机會告诉蜘蛛“内容没變,別下了”,只回一個 304 狀態碼。
條件請求在做什么
蜘蛛第一次抓取某個 URL 时,服務器除了返回頁面,還會带上一两個版本标记:Last-Modified(最後修改時間)和 ETag(内容指纹)。下次蜘蛛再来,會在請求头里带上這两個字段對應的條件:
- If-Modified-Since:如果頁面在這個時間之後没改過,就別返回正文。
- If-None-Match:如果 ETag 還對得上,同样別返回正文。
服務器判断之後,若内容确實没變,就回一個 304 Not Modified,不带正文。蜘蛛由此知道:頁面還在,内容没變,不需要重新解析和走索引流程。
它能省什么,不能省什么
先把邊界说清楚,避免期待错位:
- 省的是传輸和解析:少下几十到几百 KB 的 HTML,少一次 DOM 解析,服務器带宽和响應耗时也轻一点。
- 不省請求本身:蜘蛛仍然會訪問這個 URL,304 只是让這一次訪問少传内容。所以它替代不了“减少無價值 URL”那部分工作。
304 是降本,不是节流。真正吃掉抓取机會的,是那些本来就不值得抓的 URL,而不是“值得抓但没變”的 URL。
常见的配置坑
一、時間戳每次都變
有些 CMS 每次渲染頁面都把 Last-Modified 设成目前時間。蜘蛛下次带着這個時間再来問,服務器自然判定“已修改”,又返回 200 和完整正文,條件請求等于失效。
二、ETag 算法不稳定
如果 ETag 按服務节点、按請求時間或按随机值生成,同一個頁面在不同机器、不同請求下拿到的 ETag 各不相同,比對永遠不匹配。多机房、多實例的站点尤其容易踩這個坑。
三、正文變了却回 304
這比配置失效更麻烦。内容更新了但版本标记没更新,蜘蛛會以為頁面還是老样子,新内容可能很久才被重新處理。更新頁面时要确保 Last-Modified 和 ETag 一並刷新,做不到就干脆別做條件請求。
四、缓存层改寫了响應
CDN 或反向代理可能自行處理條件請求头,也可能把源站的 304 轉成 200。排查时最好分別看源站和 CDN 返回的狀態碼與响應头,不要只盯着浏览器里看到的结果。
和 Sitemap 的 lastmod 對不上怎么办
Sitemap 里的 lastmod 和 HTTP 头里的 Last-Modified 是两套東西,但它們讲的是同一個故事。如果 Sitemap 说今天更新過,實际响應头却顯示两個月前,蜘蛛對這两個信号的信任都會打折。合理做法是让两者由同一份資料源生成:内容真正被編輯时才更新字段,不要用發布時間、上线時間或自動任務時間凑數。
哪些頁面值得配
- 内容型頁面,單頁体积大、更新频率低,收益最明顯。
- 列表頁和分類頁,只要排序規則和内容稳定,也可以做。
- 频繁變動、每次請求都不同的頁面(實时資料、個性化推荐),不适合靠條件請求省流量,重点應放在是否值得让蜘蛛抓。
一次简單的自查驗證
- 用同样的請求头连續請求同一個 URL 两次,第二次带上第一次返回的 ETag 或 Last-Modified。
- 看第二次的狀態碼是不是 304,正文是不是空的。
- 改一段正文再請求一次,確認狀態碼回到 200,並且版本标记随之變化。
這三步能覆盖大部分配置問题。做完之後,蜘蛛再訪問這些稳定頁面时,消耗的带宽和解析成本會降下来,更完整的抓取能力就能留给真正在變的頁面。