做蜘蛛池或站点运营时,入口页上的链接经常不是写死的绝对地址,而是相对路径。多数情况下这没问题,但如果页面里出现过 base 标签,解析基准就被改掉了,搜索蜘蛛最终请求的地址可能落在一个你根本没打算推广的域名上。日志里出现陌生的抓取路径,很多时候原因就在这里。
现象:日志里抓到的 URL 不是你以为的那个
典型表现是:入口页地址是 https://a.com/dir/list.html,你希望蜘蛛去抓 a.com 下的目标页,结果日志里出现的却是 b.com 上的路径,或者一批 404、一批指向测试环境的请求。这时候先别怀疑蜘蛛池效果,先确认链接的解析基准对不对。
相对链接的解析基准是什么
HTML 里相对 URL 会基于“文档基准 URL”展开。没有额外声明时,基准就是当前文档自身的地址。例如入口页是 https://a.com/dir/list.html:
- 链接写 target/1.html,解析结果是 https://a.com/dir/target/1.html
- 链接写 /target/1.html,解析结果是 https://a.com/target/1.html
- 链接写 ../target/1.html,会先退一级再拼接
也就是说,路径写法本身就决定了层级,斜杠位置和层级符号写错,解析结果就会偏。
base 标签会改写整个基准
只要页面里出现 base href,页面上所有相对链接都会以它为基准,而不是以当前页面地址为基准。举例:入口页在 https://a.com/dir/list.html,页面里声明 base href="https://b.com/",链接写 x/1.html,最终解析成 https://b.com/x/1.html。搜索蜘蛛如果解析并跟进了这个链接,抓的就是 b.com。
base 常见的几种写错方式
- 写了 base href="/",但站点部署在二级目录,链接全部跑到根目录
- base 里的域名漏了结尾斜杠,拼接结果变成 b.comx/1.html 这类错误地址
- 页面是 https,base 里却写成 http,出现混合内容
- base 的值来自模板变量,多域名、多语言站点上输出了别的域名
- 页面由前端拼接或嵌在 iframe 中,base 的实际取值与预期不一致
按这几步排查
- 用抓取工具或命令行拉取入口页的原始 HTML,不要用浏览器渲染后的 DOM,因为渲染过程可能额外插入基准
- 在源码里搜索 base,确认它的值以及出现的位置和次数
- 手工取一条相对链接,按 base 的值拼一次,得到实际会请求的完整地址
- 拿这个地址去服务器日志里比对,按搜索蜘蛛的 UA 筛选,看它请求的路径是否与你拼接的一致
- 如果解析到了其他域名,检查那个域名是否可达、是否返回正常状态码、内容是否为你要推的目标页
- 修正后(改 base 或改链接写法)再观察一段时间日志,确认抓取路径回到预期范围
要不要干脆全部用绝对路径
对入口页和站点导航来说,把链接统一写成 https:// 开头的绝对地址,能省掉大部分解析歧义,排查时也一眼能看懂。代价是以后换域名或调整目录结构时改动量大。折中做法是保留相对路径,但保证 base 只出现一次、值固定且正确,并在每次部署后抽查几条链接的解析结果。
相对路径本身不是问题,基准不对才是问题。排查时先确认基准,再看链接本身,顺序反了会白忙。
几个容易忽略的细节
- base 标签只认第一个,后面再出现的会被忽略,模板叠加时容易踩
- base 的 target 属性只影响打开方式,不影响 URL 解析,别把两者混在一起看
- 协议相对链接 //example.com/x 会跟随当前页面的协议,站点同时支持 http 和 https 时要留意
- 路径大小写和结尾斜杠在拼接时会影响结果,有的服务器会当成两个地址
- 入口页返回 200,不代表解析出来的那个域名也能正常返回,两边都要单独验证
如果确认解析没问题、目标 URL 也能稳定返回,剩下的就是抓取节奏和收录进度的事,不必因为一时没动静就反复改动入口页结构——改动越频繁,日志越难比对,排查成本反而更高。