搜尋抓取

搜尋蜘蛛抓取:响應体压缩协商與 Content-Length 不一致的排查

抓取異常不一定表現為 5xx,压缩协商偏差常让蜘蛛“收到了却讀不懂”。本文梳理 Content-Encoding、Content-Length、Vary 三個响應头在源站、CDN 之間的常见不一致表現,並给出從直连對比、压缩层級核對到缓存声明补齐的排查步骤,帮助把响應头問题纳入例行巡检。

搜尋抓取

搜尋蜘蛛抓取:响應体压缩协商與 Content-Length 不一致的排查

搜尋蜘蛛在抓取頁面时,拿到的不只是 HTML 文本,還包括一组响應头。其中 Content-EncodingContent-Length 這两個字段,直接决定了蜘蛛能否顺利解出頁面内容。压缩协商一旦出現偏差,表現往往不是明顯的 5xx,而是“抓到了但内容不對”或者“抓一半就断”,排查起来比較绕。

压缩协商的正常流程

請求方在請求头里声明自己支持的压缩方式,例如 Accept-Encoding: gzip, deflate, br。服務器挑其中一種,把响應体压缩後返回,同时在响應头里用 Content-Encoding 說明用了哪種算法,用 Content-Length 說明压缩後的字节數(注意是压缩後的長度,不是原始長度)。中間的 CDN 或反向代理如果不透传這些头,就可能出現声明與實际不一致。

几類典型異常

Content-Encoding 與實际内容不符

服務器声明 gzip,但响應体其實是明文,或者经過了两层压缩(CDN 压了一次、源站又压了一次),蜘蛛按声明解压就會失敗,最终拿到空内容或乱碼。多級代理叠加压缩是常见诱因。

Content-Length 與實际字节數不一致

头部寫的是 20000,實际只传了 8000,蜘蛛按長度等待剩余資料,超时後放弃,表現為抓取中断;反過来,實际传輸超過声明長度,多余部分可能被截断或被视為协议错誤。動態压缩、流式輸出时最容易出現這種偏差。

Vary 缺失導致的缓存串味

如果同一 URL 對不同 Accept-Encoding 返回不同内容,而响應里没有 Vary: Accept-Encoding,CDN 可能把压缩版缓存下来發给不支持该算法的請求方,或者把明文版發给期望压缩的請求方。表現是同一地址时好时坏,很难复現。

排查步骤

  1. 用带 Accept-Encoding 的請求直接拉取目标 URL,對比源站直连與经過 CDN 後的响應头差异。
  2. 检查 Content-Encoding、Content-Length 是否同时存在且自洽,有條件时用原始字节數核對一次。
  3. 確認压缩层級,看源站與 CDN 是否重复啟用压缩,只保留一层。
  4. 检查 Vary 头是否包含 Accept-Encoding,避免缓存串味。
  5. 對比同一 URL 在压缩與非压缩請求下的正文内容,两者應当基本一致。
  6. 查看抓取日誌中该路径的狀態碼與响應体大小,判断問题集中在某類资源還是全站。

調整與驗證

修复方向通常是:關閉重复压缩、补齐 Vary、让 Content-Length 與實际传輸字节嚴格一致,或者對大頁面改用分块传輸並去掉固定的 Content-Length。改完後不要只看一次請求,最好在不同時間段、不同出口各驗證几次,確認头部表現稳定。

压缩协商這類問题不會让頁面彻底無法訪問,人工浏览时几乎無感,但對自動抓取的影响是持續性的。把它纳入服務器响應头的例行巡检,比事後反复猜测某些 URL 為何抓取異常更省事。

小结:抓取鏈路上任何一個环节對响應头的改寫,都可能让蜘蛛“收到了却讀不懂”。把 Content-Encoding、Content-Length、Vary 三者放在一起交叉驗證,通常能較快鎖定問题位置。