搜索抓取

源码里的链接和屏幕上的链接:蜘蛛走的是哪一份

在浏览器里点得动的卡片、按钮和分页,源码里可能只是一段脚本。蜘蛛先解析 HTML,再决定要不要渲染,链接不在源码里,URL 发现这条路就断了。这篇梳理链接消失的几种常见写法,以及用服务端渲染、静态内链和 Sitemap 把路径补回来的做法。

搜索抓取

源码里的链接和屏幕上的链接:蜘蛛走的是哪一份

打开开发者工具,页面上是一排排可以点的卡片和分页按钮;查看网页源代码,这些链接却一个都找不到。对用户来说没差别,对蜘蛛来说,这是两条不同的路。

蜘蛛先看源码,再决定要不要渲染

抓取大体分两步:第一步下载 HTML 并解析,第二步在需要时执行脚本、渲染页面。第一步便宜且稳定,第二步更贵,也更不确定。

  • 写在 a 标签 href 属性里的地址,第一步就能进入待抓取队列。
  • 只在脚本执行后才出现的链接,要等渲染完成才可能被发现,而渲染并不是每次都会发生。

所以问题往往不是“蜘蛛不抓 JS 页面”,而是链接从源码里消失了,URL 发现少了一条稳定入口。

链接“消失”的几种常见写法

  • 用脚本跳转代替链接:元素上只绑了点击事件,跳转由脚本里的地址赋值完成。没有 href,第一步就看不到目标地址。
  • 前端路由:单页应用通过 history 接口改写地址栏,源码里的列表项没有 href。
  • 数据来自接口:列表由接口返回的 JSON 渲染,目标地址也写在 JSON 里。
  • 外面套了容器:内容放在 iframe 里,源码中看不到内部链接。
  • 只在交互后加载:点击“展开更多”才把下一批链接插入页面。

这些写法本身没有错,问题在于它们把 URL 发现完全押在渲染这一步上。

让链接回到源码里:几个层级的做法

首选:服务端渲染或静态生成

列表页、详情页、分页导航在服务端就把 a 标签和 href 输出到 HTML 里,蜘蛛第一步就能拿到。分页用真实的下一页链接,而不是一个按钮。这样即使后续脚本出错,抓取路径依然完整。

次选:预渲染与动态渲染

对已知的抓取 UA 返回渲染后的 HTML,是可行但需要持续维护的方案。要留意几点:

  • 渲染后的 HTML 与普通用户看到的应保持一致,不要返回明显不同的内容。
  • 中间若有缓存层,缓存键要能区分不同版本,避免把空壳页缓存给蜘蛛,或把渲染版塞给普通用户。
  • 渲染服务要纳入监控,长时间超时或报错会让蜘蛛拿到不完整的页面。

兜底:Sitemap 与静态内链

如果短期内改不了前端,至少把 URL 清单交给 Sitemap,并在页脚、主导航、面包屑这类静态输出的位置补上通往重要页面的链接。这样即便渲染环节失败,蜘蛛仍有别的入口到达这些地址。

渲染服务不稳时会发生什么

渲染依赖服务端资源,出问题时常见两种表现:

  1. 返回 200,但页面是空壳。蜘蛛拿到一个几乎没有正文和链接的 200 页面,容易影响它对这批 URL 的后续抓取意愿。
  2. 超时或返回 5xx。蜘蛛会稍后重试,短期内这片路径的发现能力下降。

因此,渲染失败率、平均耗时、空内容比例都值得进监控,而不是只盯着首页能不能打开。

抓取路径断掉时,站点通常不会报错,只是新页面迟迟不出现。检查源码,比反复提交 Sitemap 更直接。

怎么自查

  • 用命令行请求页面,看返回的 HTML 里有没有目标链接。
  • 浏览器禁用脚本后再看一遍,确认主导航和列表仍能走通。
  • 在服务器日志里筛蜘蛛的请求路径,看它是否只停在首页和少数入口页。
  • 对比源码版本与渲染版本,确认链接是否只在渲染后才出现。

小结

蜘蛛走的是它拿到的那份 HTML。把关键链接写回源码,是让抓取路径稳定的省事做法;前端渲染并非不能用,但要清楚它把 URL 发现的责任从 HTML 转移到了渲染服务上,而这一步更容易出错。