浏览器能容忍的,蜘蛛不一定能
同一個地址,你在浏览器里看着正常,蜘蛛拿到的却可能是空白、乱碼或者半截内容。原因往往不在 HTML 本身,而在传輸和编碼這两层:响應头怎么说、内容實际怎么压、字符集怎么声明。浏览器有大量容错和猜测机制,蜘蛛的解析流程更依赖声明,一旦声明和實际對不上,它就按自己的規則處理,结果通常不是你想要的。
Content-Encoding 與實际内容對不上
用 gzip 或 Brotli 压缩頁面是常規操作,但前提是声明和實际一致。常见的三類問题:
- 响應头寫了 Content-Encoding: gzip,返回的却是未压缩内容,或者反過来。解压失敗會被记成一次抓取错誤。
- 源站和 CDN 各压一次,形成双重压缩。蜘蛛只解一层,拿到的是压缩資料的二進制流,頁面自然是乱碼。
- 压缩後的長度與 Content-Length 不一致,连接被提前截断,正文只到一半。
這几類問题在浏览器里往往感觉不到,因為浏览器會尝试多種解碼方式;蜘蛛按声明解碼失敗後,一般不會反复试探。
怎么快速確認
用命令行看头部最直接:curl -sI 加上地址,观察 Content-Type、Content-Encoding、Content-Length 三項是否互相矛盾。再用 curl --compressed 取一次完整响應,對比压缩前後的字节數。如果解压後的大小異常小,基本可以定位問题出在压缩鏈路。
字符集:三條声明渠道,只有一條说了算
一個頁面的字符集可能出現在三個地方:HTTP 响應头的 Content-Type、HTML 里的 meta charset、以及文件自身的實际编碼。它們的優先級通常是响應头最高,meta 次之,文件實际编碼只是事實。
- 响應头声明 charset=utf-8,實际文件是 GBK,蜘蛛按 utf-8 解碼,中文整段變成乱碼。
- 响應头没寫 charset,meta 声明 utf-8,但文件带 BOM 或是 GBK,解碼同样可能出错。
- 两邊都没寫,蜘蛛只能靠統計猜测,長頁面里中文比例高时猜错的概率並不低。
乱碼之後會發生什么
很多人以為只是顯示不好看,實际上影响會一路传導下去:
- 連結解析:href 里带中文參數或中文路径时,解碼错誤會把連結指向不存在的地址,蜘蛛顺着走下去就是一片 404。
- 正文提取:正文變成乱碼或空白,頁面质量判断會明顯偏低。
- 元信息:title、description 错乱,展示结果和你的预期完全不同。
- 整頁判定:解碼失敗嚴重时,蜘蛛可能直接把這頁当成空内容,反复抓取也拿不到有效信息。
BOM 和不可见字符
文件開头多出的 BOM、編輯器留下的零宽字符、模板拼接时混入的控制字符,都會占用正文開头的位置。有些程序在處理时把它們当正文輸出,頁面開头于是出現奇怪符号,進一步干扰解析。
一份可落地的排查清單
- 检查响應头:curl -sI 看 Content-Type、Content-Encoding、Content-Length 三項是否自洽。
- 检查實际编碼:把响應正文儲存成文件,用编碼檢測工具確認是不是声明的那個字符集。
- 检查压缩鏈路:临时關掉 CDN 压缩,只留源站压缩,观察抓取是否恢复正常。
- 检查声明一致性:响應头、meta、文件编碼三者统一,避免任何一條成為例外。
- 检查日誌:抓取失敗率、空内容頁面數量是否集中在某几個模板或某次發布之後。
把問题挡在蜘蛛進来之前
传輸和编碼是抓取鏈路里最底层的一环,出错时上层的内鏈優化、Sitemap 提交都無從發挥。把响應头、压缩方式、字符集三件事固定成上线检查的一部分,比事後從日誌里逐個找原因省事得多。對蜘蛛来说,一份能正确解压、按声明解碼的响應,是後面所有工作的前提。
提醒一句:编碼問题不會因為你看不到就消失,它只是換了一種形式出現在抓取日誌里。