搜尋抓取

304 與條件請求:蜘蛛重訪时省下的那一趟抓取

蜘蛛重訪頁面时會带上 If-Modified-Since 或 If-None-Match,服務器回 304 還是 200,直接影响這一趟抓取的開销。本文說明條件請求在抓取路径里的作用、几種把 304 用坏的做法,以及怎样用响應头和日誌自查。

搜尋抓取

304 與條件請求:蜘蛛重訪时省下的那一趟抓取

蜘蛛第一次抓取某個頁面之後,再回来时通常不會從零開始。請求头里往往會带上 If-Modified-Since 或 If-None-Match,含义是「我上次拿到的是這個版本,如果内容没變,就別再發一遍正文」。服務器怎么回答,既决定這一趟抓取的開销,也影响蜘蛛把時間花在哪里。

蜘蛛重訪时带的两個头

  • If-Modified-Since:值来自上一次响應的 Last-Modified,服務器把頁面目前的修改時間和它比一比。
  • If-None-Match:值来自上一次响應的 ETag,相当于给内容算的一個版本标识,服務器比對标识是否一致。

两個头可能同时出現,服務器只要判断「没變」,就可以返回 304,不带正文。返回 304 並不是拒绝抓取,而是告诉蜘蛛:你手上那份還能用。

304 省下的是哪一段成本

對蜘蛛来说,抓到 304 意味着這一次不需要重新下载和解析整頁内容,原有的正文、連結和索引信息可以繼續沿用,只是把頁面的「最近一次確認時間」往後推。對服務器来说,省下的是正文传輸和带宽,而不是請求本身——請求還是来了。

当站内大量頁面長期不變时,條件請求命中得越准,蜘蛛就越容易把有限的抓取額度挪到真正有新内容的路径上。反過来,如果每個頁面都老老實實回 200 全量重传,抓取額度里就會多出一批重复劳動。這不會直接带来惩罚,但會让新 URL 和更新頁排得更靠後。

几種把 304 用坏的做法

  • 修改時間造假:每次請求都把 Last-Modified 设成目前時間,蜘蛛每次都得重新下载,條件請求形同虚设。
  • 内容變了却回 304:頁面明明已经改過,服務器仍按舊時間戳或舊 ETag 判断,蜘蛛會繼續沿用過期内容,改動迟迟不生效。
  • ETag 随机生成:每次請求算出来都不一样,蜘蛛每次都拿到 200,還多消耗一轮解析。
  • 模板里的時間字段:頁面底部嵌了「目前時間」之類的動態輸出,導致整頁指纹天天變,長效頁面變成天天更新。

CDN 與多节点下的一致性問题

站点用了 CDN 或多台後端时,同一個 URL 從不同节点返回的 ETag 可能不一样。蜘蛛這次從 A 节点拿到一個标识,下次落到 B 节点,标识對不上,只能再取一遍全文。更麻烦的是邊缘缓存與源站内容不同步:缓存里還是舊頁面,源站已更新,回 304 的依據就成了舊版本。

處理思路不复杂:让 ETag 由内容本身决定,而不是由机器、進程或時間决定;源站更新时主動清一次缓存;必要时把 Last-Modified 也统一下来,別让不同节点各说各话。

用响應头自查

  1. 對同一 URL 连續請求两次,第二次带上 If-Modified-Since 或 If-None-Match,看狀態碼是不是 304。
  2. 換一台机器、換一個出口 IP 再试一次,確認不同节点返回的 ETag 是否一致。
  3. 改一次頁面正文,再用舊标识請求,正常情况應返回 200 而不是 304。
  4. 在服務器日誌里看 304 與 200 的比例,以及哪些路径几乎全是 200,那批頁面往往就是條件請求没配好。
304 是省流量的手段,不是省抓取的手段。刻意堆 304 換来一個好看的比例,並不會让蜘蛛對站点更有兴趣;把 Last-Modified、ETag 和 Sitemap 里的 lastmod 對齐成同一套事實,才更容易让重抓节奏和實际更新對上。