搜索抓取

蜘蛛的两次到访:先取 HTML,再排队渲染

蜘蛛抓取一个 URL 常常不是一次动作,而是先下载 HTML 源码,再进入渲染队列执行 JavaScript。源码里没有的链接,URL 发现就会被推迟甚至中断。本文说明两条管线的差别,以及哪些前端写法会拖慢链接发现,并给出让抓取更省事的做法。

搜索抓取

蜘蛛的两次到访:先取 HTML,再排队渲染

很多人以为蜘蛛抓一个 URL 就是一次动作:来、下载、走。实际情况更接近两次到访——第一次只拿走 HTML 源码,第二次才在另一条管线里执行 JavaScript。分不清这两步,就很容易把链接放在蜘蛛第一次看不到的地方。

第一次到访:拿到的只是源码

蜘蛛发起请求时,服务器返回的 HTML 响应体就是它第一眼看到的东西。这一刻,页面还没有"运行":由 JS 注入的导航、列表、分页链接、正文内容,全都不在里面。

这带来一个直接的后果:如果站内链接是脚本生成的,URL 的发现就被推迟到渲染阶段。而渲染不是每个 URL 都会做,也不是立刻做。有些页面等到了,有些页面一直没等到。

第二次到访:渲染队列是另一条管线

渲染管线会执行页面上的脚本、发起额外请求、构建最终的 DOM,再从里面提取链接和内容。它比单纯抓 HTML 贵得多:占资源、要排队、有超时,通常只对一部分页面触发。

  • 渲染有等待上限,第三方接口慢,页面就可能渲染不全;
  • 渲染通常在无头环境里跑,滚动、点击、登录态这类交互不会发生;
  • 渲染产出会进缓存,但缓存什么时候刷新、是否刷新,站点无法直接控制。

换句话说,渲染是"补救",不是"默认"。把关键链接和内容押在渲染上,等于把抓取节奏交给了一条你不能直接调的队列。

哪些写法会拖慢链接发现

  • 用 div 或 span 加 onclick 跳转,没有真正的 a 标签和 href;
  • 前端路由切换后,地址栏变了,但页面里没有可爬的链接指向那些 URL;
  • 无限滚动:内容靠滚动触发加载,渲染环境下不会滚;
  • 分页是按钮,实际 URL 不可直接访问;
  • 链接依赖第三方接口返回后才渲染出来。

这些做法对用户体验未必有问题,但对第一次到访的蜘蛛来说,页面里确实什么都没有。

让两条管线都省事的做法

  1. 导航、栏目、分页、文章列表用真实 a 标签,href 指向可访问的 URL;
  2. 首屏关键内容和链接尽量由服务端输出,SSR、SSG 或预渲染都可以;
  3. 分页给出稳定的 URL 结构,让每个页码都能被直接请求;
  4. 必须用 JS 渲染的部分,也留一条 HTML 兜底路径,例如 noscript 中的链接或静态列表页;
  5. 把重要 URL 同时放进 Sitemap,作为发现渠道的补充。

怎么验证自己的站点

抓取工具里关闭 JavaScript,看剩下多少链接和内容;再打开 JavaScript 对比一次。两次差异越大,说明站点对渲染管线的依赖越重。服务器日志里,如果出现大量 CSS、JS 等静态资源的请求,往往就是渲染管线的访问痕迹,可以和纯抓取请求分开观察。

链接发现靠的是源码可见性,渲染只是第二道保险。第一眼看不到的链接,抓取节奏就只能听天由命。

顺着这条思路检查一遍站点,通常能发现几处"只有渲染后才存在"的链接。把它们挪回 HTML 源码,URL 发现的节奏会立刻稳定不少。