先说清楚一件事:搜尋蜘蛛解析入口頁的顺序是“按字符集解碼字节 → 解析 HTML 结构 → 按 URL 規則處理 href 值”。這三步里任何一步出問题,蜘蛛拿到的地址都可能和你预期的不一样,甚至拼不出一個合法 URL。發現环节断在這里,後面抓取、收錄都無從谈起。
第一步:字符集声明决定了 href 里的中文會變成什么
HTML 對蜘蛛来说是一串字节,必须先按某個字符集解碼成字符,才能讀懂 href 的值。這個字符集主要来自三處:HTTP 响應头的 Content-Type 里的 charset 參數、HTML 头部声明的编碼标簽、以及解析器在信息缺失时的自動猜测。
常见故障是這样發生的:文件實际用 UTF-8 儲存,服務端却返回 charset=gbk。蜘蛛按 gbk 解碼,href 里“搜尋”两個字對應的字节被解成另一串字符,再轉成百分号编碼去請求,服務器上根本不存在這個路径,返回 404。反過来,實际是 GBK 却声明 UTF-8,容易出現替換字符,拼出来的地址同样變形。
- 整站统一使用 UTF-8,响應头声明與頁面内声明保持一致。
- 不要指望蜘蛛“猜”對编碼,浏览器容错能力强得多。
- 如果入口頁是脚本批量生成的,检查模板文件本身的儲存编碼,而不是只看浏览器顯示是否正常。
第二步:href 里哪些字符必须處理
即便字符集没問题,href 属性的值本身也有轉义要求。HTML 属性值有定界符,URL 又有自己的保留字符,两套規則叠加起来,坑就多了。
- 空格:直接寫在 href 里會截断地址,後面的内容被当成新属性或纯文本。
- &:HTML 属性中應寫成實体形式,否則解析器可能把它当作實体開头,導致參數丢失或被吞掉。
- #:在 URL 中表示片段标识,不會發送给服務器。想当普通字符传递要用百分号编碼。
- %:本身是编碼引導符,表示字面百分号需要再编碼一次。
- 引号、尖括号:属性值的定界符,出現时要么用實体,要么換一種引号包裹。
- 中文、日文、空格等非 ASCII 字符:建议直接在 href 里寫成 UTF-8 的百分号编碼形式。
蜘蛛池的入口頁大多是程序拼串生成,最容易出問题的就是 ampersand 和空格這两個字符。
第三步:地址合法,但指向了別的地方
還有一種更隐蔽的情况:拼出来的 URL 语法完全合法,蜘蛛也确實抓了,但指向的不是你想推的目标頁。比如一個带两個參數的地址,如果连接符處理不当,服務器實际收到的只有一個參數,頁面能正常打開,内容却對不上。這類問题從日誌里看不出異常,返回碼是 200,但統計时發現目标頁始终没動静。
判断标准很简單:把服務器訪問日誌里蜘蛛請求的原始路径,和你寫在入口頁里的字符串逐字符比一遍,重点看百分号编碼之後的形式。
可以马上做的自查清單
- 用命令行工具或抓取測試功能拉取入口頁原始 HTML,直接看 href 的字节内容,不要看渲染後的效果。
- 在服務器日誌里篩選蜘蛛 UA,核對請求路径是否與预期完全一致,注意中文和參數部分。
- 分別按 UTF-8 和 GBK 解析一遍頁面,對比提取出的連結是否相同,相同才說明声明是自洽的。
- 检查生成連結的代碼有没有做 URL 编碼處理,拼接後是否统一走了编碼函數。
- 能改成 ASCII 路径的就改,用拼音、ID 或短横线替代中文目錄,可以規避掉大部分编碼類問题。
把連結拼對,只是入场券
寫出蜘蛛能正确解析的連結,只能保證它“有机會看到”這個地址。是否抓取、何时抓取、是否收錄,還取决于目标頁自身狀態、内容质量以及站点整体的抓取预算。入口頁能做的,是別在最基础的解析环节丢分——這一步做對了,後面的排查才有意义。