很多抓取问题里,页面本身能返回 200,内容也正常,但蜘蛛拿到的那批链接却指向了错误的主机或路径。这类情况通常不是服务器配置引起的,而是 HTML 中相对链接与 base 标签的解析结果,和运营的预期不一致。
蜘蛛如何把链接变成绝对地址
解析 HTML 时,蜘蛛会按标准 URI 引用规则,把 href 里的相对引用与「基准 URL」拼接。基准 URL 默认是当前文档地址;一旦文档里出现 base 标签,就会改用 base 指定的地址。常见几种形态:
- 绝对链接(https://example.com/a)不受基准影响;
- 根相对链接(/a)会替换基准的路径部分;
- 路径相对链接(a 或 ../a)基于基准的目录拼接;
- 协议相对链接(//example.com/a)沿用当前页面的协议。
也就是说,基准 URL 一变,页面上所有相对链接的落点都会跟着变。
base 标签的常见误用
全站模板里统一写死 base
有些站点为了兼容旧系统,在模板 head 里放了一条固定的 base,例如指向测试域名或另一个子域。蜘蛛从正式域名抓到的页面里,相对链接会被整体拼到那个域名下,正式站的内链结构在抓取视角里等于断裂。
base 带路径却漏了结尾斜杠
base href="https://example.com/blog" 与 base href="https://example.com/blog/" 的结果完全不同。前者会把页面里的 a 拼成 https://example.com/a,后者才是 https://example.com/blog/a。这类偏差在目录型站点里很隐蔽,因为浏览器地址栏看不出异常。
多个 base 或位置靠后
规范要求只取文档中第一个 base 的 href。有些页面在公共模板和组件里各写了一条,实际生效的未必是运营以为的那条。另外,如果 base 出现在 head 之后,不同解析器对已读内容的处理并不完全一致。
其他容易造成落点偏差的写法
- 相对链接写在 JS 拼接的字符串里,静态 HTML 中拿不到,也就形不成入口;
- 链接写成 //example.com/a,页面在 http 与 https 之间切换时,落点协议会跟着变;
- href 前后夹带空格、换行或不可见字符,部分解析器会直接丢弃;
- 用 <a href="#"> 配合 onclick 跳转,蜘蛛只会看到一个指向当前页的锚点。
怎么排查
- 从日志里挑出被抓取频繁的页面,把 HTML 原样保存下来;
- 用标准解析库(如 Python 的 urljoin 配合解析器)重新计算页面里每个 href 的绝对地址;
- 把结果与 Sitemap、内链清单交叉比对,看是否存在落到非目标域名或集中 404 的路径;
- 同时检查服务器日志里,是否有蜘蛛在请求一个你并不打算公开的域名或目录。
如果日志里出现集中请求某个测试域名的情况,基本可以判断是基准 URL 出了问题,而不是网络抖动或封禁。
修复与长期维护
- 能用绝对链接的地方尽量用绝对链接,尤其是导航、面包屑、页脚这类模板区域;
- 确实需要 base 时,统一在 head 最前面写一条,路径结尾带上斜杠,并在发布前做一次回归检查;
- 把 base 标签、站点主域名、Sitemap 中的域名纳入同一份上线检查清单;
- 站点改版或迁移域名后,重新跑一遍比对流程,避免旧 base 跟着模板被留下来。
相对链接本身没有问题,问题在于基准 URL 是否和你的运营意图一致。基准错了,页面内容再完整,蜘蛛拿到的仍然是一张指错方向的链接图。