先说清楚一件事:搜索蜘蛛解析入口页的顺序是“按字符集解码字节 → 解析 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 或短横线替代中文目录,可以规避掉大部分编码类问题。
把链接拼对,只是入场券
写出蜘蛛能正确解析的链接,只能保证它“有机会看到”这个地址。是否抓取、何时抓取、是否收录,还取决于目标页自身状态、内容质量以及站点整体的抓取预算。入口页能做的,是别在最基础的解析环节丢分——这一步做对了,后面的排查才有意义。