搜索抓取

前端路由与 URL 发现:单页应用里的链接蜘蛛能不能抓到

单页应用把渲染交给浏览器,蜘蛛第一次请求拿到的常常只是一份空壳 HTML。本文梳理 history、hash、查询参数三种路由在发现难度上的差别,说明为什么链接要写回 a 标签的 href、服务端渲染与预渲染各自付出什么代价,并给出几个可落地的自查动作。

搜索抓取

前端路由与 URL 发现:单页应用里的链接蜘蛛能不能抓到

蜘蛛第一次拿到的往往是空壳

单页应用把渲染工作交给了浏览器:一次请求返回的 HTML 通常只有固定的头部、一个空的挂载节点和几段打包脚本,正文和链接都要等 JavaScript 执行、接口返回之后才出现。蜘蛛抓取的第一份内容就是这份外壳,里面既没有可读文本,也没有指向路由的 a 标签,路由背后的 URL 自然也就没被登记进来。

三种路由写法,被发现的难度不同

  • history 模式:地址看起来是正常的路径,例如 /list/2,本身具备被抓取的形式,难点在于页面里要先有指向它的链接。
  • hash 模式:地址里带 #,片段部分通常不作为独立 URL 处理,路由再多也可能只对应一个抓取入口。
  • 查询参数路由:形如 ?page=3 的写法容易被抓取,但参数一旦叠加,容易生出大量近似地址。

写法本身没有绝对的好坏,关键在于能否在 HTML 层面暴露足够多、指向明确的链接。

把链接写回 href

很多 SPA 的导航是可点击的,但对蜘蛛来说不可读:点击事件挂在 div 上,地址靠脚本 push 进去,HTML 里什么也没留下。要改变这一点,思路其实很朴素——让每个需要被发现的路由,都有一个真实的链接地址。

  • 导航与列表项用 a 标签承载 href,而不是给 div 绑定点击事件。
  • href 写真实路径,避免 javascript:void(0) 或只做页内锚点跳转。
  • 滚动加载之外,给出可访问的分页地址,让靠后的内容有独立入口。
  • 路由切换时同步更新 title 与主要内容区域,不要只替换一小块组件。

渲染成本的另一面

服务端渲染或预渲染能把首屏 HTML 直接吐出来,蜘蛛不必执行脚本就能读到内容和链接,这是最省事的一条路。但它也有代价:每个需要跑脚本的页面都会占用额外的抓取资源,接口响应慢时还会把整体抓取时间拉长。因此常见的做法是分层处理——首页、栏目页、详情页这类需要被发现的内容走服务端输出,交互密集的个人中心、购物车之类留在客户端渲染。

渲染不是免费的:让每个 URL 都跑一遍脚本,等于把发现成本转嫁给抓取资源,能静态输出的路径尽量静态输出。

几个自查动作

  1. 临时关闭 JavaScript 打开页面,看看还剩多少可读文本和可点链接。
  2. 查看页面源码,确认关键链接出现在源码里,而不是运行时才注入。
  3. 翻服务器日志,看蜘蛛抓到的是各个路由路径,还是反复访问同一个外壳地址。
  4. 把重要路由写进 Sitemap,作为内链之外的一条补充发现通道。

SPA 的抓取问题,说到底不是技术选型的问题,而是链接有没有以蜘蛛读得到的形式出现。把发现路径铺好,后面的抓取节奏才有讨论的基础。