排查“入口頁被爬了、目标 URL 却没被發現”這類問题时,多數人會先看 robots.txt、nofollow、JS 渲染,却容易忽略一個更底层的東西:頁面声明的字符编碼和 HTTP 响應头里的 Content-Type。這两處寫错,頁面在浏览器里可能只是乱碼,但在抓取端,可能直接導致解析提前断開,後半頁的連結讀不到。
编碼声明為什么會直接影响連結解析
抓取程序拿到的是一串字节流,要先确定用什么编碼解碼,才能识別出頁面里的連結标簽和 href 值。如果声明與實际字节不一致,解碼過程會出現替換字符,标簽名、属性名、引号都可能被讀错。常见的结果是:前半部分連結正常,後半部分丢失;或者連結地址被截断成無效 URL;嚴重时整頁被判定為無法解析。
需要說明的是,這不等于“改了编碼就會被收錄”,它只影响連結有没有机會被正确讀到。真正决定收錄的還有後續的抓取、判断和索引环节。
几種常见的错誤寫法
- 頁面實际是 UTF-8,meta 里却寫 charset=gb2312,或者服務器响應头里寫 charset=gbk。
- meta charset 與 HTTP 头里的 charset 不一致,两者冲突时通常以头部為准,文字和連結都可能错位。
- meta charset 放在 head 偏後的位置,甚至在大量内容之後才出現,解析器在讀到它之前已按預設编碼處理了前面部分。
- 頁面里混入了從別處複製来的、编碼不同的片段,出現局部非法字节。
- 模板輸出时被二次轉碼,或压缩輸出與编碼声明不匹配。
自查顺序
- 用 curl 或浏览器開發者工具查看响應头中的 Content-Type,確認它声明的 charset 是什么。
- 用文本編輯器或無头浏览器確認文件真實编碼,與声明做對比。
- 把 meta charset 尽量放在 head 最前面,保證它在任何可见内容之前出現。
- 翻訪問日誌,如果抓取次數正常但识別到的連結數長期為 0 或異常少,可優先怀疑编碼問题。
- 修正後重新抓一次,對比前後能被识別出的連結數量,而不是只看頁面是否顯示正常。
不要和其他“抓不到”的原因混在一起
编碼只是众多环节之一。抓取频率、robots 規則、nofollow、JS 渲染、入口頁响應速度都會影响連結是否被發現。区分的方法是看現象:如果頁面内容能被正常抓取、只是連結數量異常少,编碼的優先級較高;如果整頁都抓不到,先看訪問日誌、响應狀態碼和 robots 規則更有效率。把這两類問题混着改,很容易改完也不知道是哪一步起了作用。
處理时的几個注意点
- 统一為 UTF-8,並让 HTTP 头和 meta 保持一致,避免同一個頁面出現两種说法。
- 改编碼属于结构性調整,尽量一次性改完,不要一部分頁面 UTF-8、一部分 gb2312 混着跑。
- 改完後不要立刻下结论,抓取和解析都有延迟,看一段時間的日誌趋势比看單次结果更有意义。
- 如果入口頁是批量生成的,检查生成程序里是否對编碼做了重复轉碼。
编碼检查是基础項,不是優化手段。它解决的是“連結能不能被讀到”,而不是“讀到之後會不會被收錄”。
简單说,入口頁的编碼和 Content-Type 属于那種平时不起眼、出問题却影响面很大的配置。把它放進入口頁上线前的固定检查清單,能省掉不少“明明被抓了却什么都没發生”的排查時間。