蜘蛛抓一個頁面,並不是每次都從头到尾把内容重新下载一遍。對已经抓過的 URL,它更常见的做法是先带上几個驗證头,問服務器一句:這份内容還是我上次拿到的版本吗?服務器回答“是”,流程就到此為止;回答“不是”,才重新传一遍。這條往返鏈路就是條件請求,也是抓取效率里常被忽略的一环。
第一次抓取留下的两样東西
第一次抓取时,服務器通常會在响應头里给出两個标识:Last-Modified 和 ETag。前者是内容最後修改的時間,精度到秒;後者是服務器生成的一串字符,代表這個版本的指纹。蜘蛛會把這两样東西随 URL 一起记下来,下次再抓這個地址时,把它們分別放進 If-Modified-Since 和 If-None-Match 請求头里带回来。
304 是怎么發生的
- 蜘蛛請求 /page-a,並带上 If-None-Match: "abc123"。
- 服務器比對目前内容的 ETag,如果仍是 "abc123",直接返回 304 Not Modified,不带正文。
- 蜘蛛確認頁面没變,沿用上次解析出的内容與連結,不再重复解析。
- 如果 ETag 變了,服務器返回 200 和新正文,蜘蛛按新内容處理。
整個過程省下的是正文传輸和後續解析。對体量大的站点,這部分节省並不小;對蜘蛛来说,它可以用同样的時間確認更多 URL 的狀態。
Last-Modified 與 ETag 各管什么
两者不是二選一的關系。Last-Modified 更接近“内容什么时候動過”,方便蜘蛛判断頁面的更新节奏;ETag 更接近“内容是不是同一個版本”,對動態生成的頁面更可靠。有些服務器只给其中一個,蜘蛛也能工作,但两個都给,判断會更准。
容易被忽略的几種配置
- ETag 每次都變:部分框架會把進程 ID、時間戳塞進 ETag,導致同一個頁面每次响應的指纹都不同。蜘蛛每次都收到 200 和完整正文,條件請求形同虚设。
- Last-Modified 長期不動:頁面内容其實更新了,但時間戳停留在建站那天。蜘蛛可能因此降低回訪频率,新内容迟迟等不到確認。
- 把 304 当成缓存专属:304 是给所有支持條件請求的客戶端用的,蜘蛛同样會發這些头,不需要特殊配置,也不能靠它去“引導”蜘蛛。
- Cache-Control 與抓取混為一谈:CDN 缓存時間長短影响的是回源次數,和蜘蛛是否重新抓取並不等價。两者都需要,但解决的是不同問题。
對站点运营意味着什么
條件請求的價值主要在两头。一头是服務器:大量 304 响應比大量 200 响應轻得多,抓取高峰时压力更可控。另一头是蜘蛛:它花更少時間在没變化的頁面上,就有余力去看看新發布或刚改過的 URL。
如果站点每天的更新集中在少數栏目,可以观察這些栏目的 Last-Modified 是否正常推進。更新了却不動,往往說明是模板或發布時間字段的問题,不是蜘蛛的問题。
需要說明的是,304 只影响蜘蛛是否需要重新获取内容,不代表它會因此加快抓取,也不构成任何收錄上的保證。它更像是把一次抓取的成本压低,让有限的時間用在更有價值的地方。真正决定抓取结果的,仍然是内容本身、站点结构和可訪問性。
實践上可以這样自查:用一個正常的 HTTP 客戶端模拟带 If-None-Match 的請求,看服務器是否正确返回 304;再對比頁面實际更新時間和响應头里的時間戳是否一致。這两步做過之後,再去看日誌里的抓取频次,判断會更清楚。