蜘蛛請求一個 URL,服務器先返回狀態行和响應头,然後才是正文。抓取異常里有一部分跟正文没關系,問题出在头部:内容類型不對、字符编碼冲突、或者一條本不该存在的 noindex。正文寫得再規整,蜘蛛也可能在解析之前就停下了。
Content-Type 不對,頁面可能不算網頁
正常網頁應该返回 text/html,並带上 charset。常见問题有几類:静態服務器對某些路径返回 application/octet-stream;模板渲染时輸出 text/plain;反向代理或 CDN 回源时把头部改寫或丢掉。结果是蜘蛛拿到一段二進制或纯文本,正文里的連結也提不出来,URL 發現鏈條就断在這里。
排查方式很直接:用 curl -I 看第一級响應头,再對比浏览器開發者工具里的實际响應。如果通過 CDN 訪問和直接訪問源站的头部不一致,問题多半在缓存或回源配置。
编碼声明冲突,正文會變成乱碼
编碼可能出現在两個地方:响應头的 charset,以及 HTML 里的 meta charset。两者不一致时,解析通常更依赖头部声明,正文里的中文會變成乱碼,锚文本和連結也可能被拆错。乱碼頁面本身能被抓,但内容無法理解,連結提取质量下降,後續路径同样受影响。
比較稳的做法是全站统一 UTF-8:服務器、資料库、模板、响應头都對齐。歷史頁面如果還在用 GBK,至少保證头部声明和實际字节一致。
X-Robots-Tag:比 meta robots 更早生效
meta robots 寫在正文里,蜘蛛要先下载並解析 HTML 才能看到;X-Robots-Tag 寫在响應头里,讀到头部就生效。它的好處是不改頁面就能控制索引行為,但也很容易誤伤:某次為了压測試环境,在 CDN 或 Nginx 上加了全局 noindex;图片、PDF 目錄被加了 nofollow,内鏈的传递路径就在這些资源處断掉。
更隐蔽的是分环境加头:測試环境加了,配置跟着發布同步到了线上。建议把 X-Robots-Tag 当作和 robots.txt 同級的出口配置,改動时走一次线上驗證。
缓存與压缩相關的头
- Vary:寫了 Vary: User-Agent 而缓存层按 UA 分版本时,蜘蛛拿到的可能是為其他訪問者准备的版本,甚至是一個空壳頁。
- Content-Encoding:gzip 或 brotli 声明與實际编碼對不上,正文解压失敗,蜘蛛看到的是空响應。
- Cache-Control 與過期缓存:頁面已经改版,缓存里還是舊版,蜘蛛顺着舊連結繼續走,抓到的是已经不存在的路径。
一份自查清單
- 對首頁、栏目頁、詳情頁各取一個样本,用 curl -I 看头部,不要只看浏览器。
- 確認 Content-Type 是 text/html,charset 與 meta 声明一致。
- 检查是否存在全局或目錄級的 X-Robots-Tag。
- 對比 CDN 與源站返回的头部差异,重点看 Vary 和缓存策略。
- 在服務器日誌里交叉驗證:狀態碼、响應字节數、蜘蛛 UA。
抓取路径的第一环,是服務器答應给什么,而不是頁面里寫了什么。头部是這份答應的一部分,值得在翻正文之前先看一眼。