搜索抓取

蜘蛛的两趟活:先取 HTML,再排队渲染

蜘蛛处理一个页面通常分两趟:先下载服务器返回的原始 HTML,再把页面放进渲染队列执行 JS。链接只写在 JS 里,URL 的发现就要排队等第二趟。本文说明两趟流程的差别、渲染排队变慢的原因,以及把导航、分页、列表链接放回首屏源码的具体做法与验证方法。

搜索抓取

蜘蛛的两趟活:先取 HTML,再排队渲染

抓取和渲染,在蜘蛛那里是两件事

很多人把「蜘蛛来过」理解成一个动作:请求、下载、看懂页面。实际流程至少能拆成两段。第一段是普通的 HTTP 抓取,服务器返回什么 HTML,蜘蛛就先拿到什么;第二段是把页面丢进渲染队列,用浏览器内核执行 JavaScript,等 DOM 稳定之后再读一遍。两段之间可能只隔几分钟,也可能隔上好几天。

这个时间差直接决定了一件事:如果 URL 只存在于 JS 执行之后的 DOM 里,它被发现的时间就要往后推。

第一趟:原始 HTML 里有什么,就先认什么

第一次请求返回的源码,如果只有一个空容器节点加一段脚本引用,那这一趟能读到的信息就非常有限。蜘蛛不会在这一步替你执行脚本,它只是把源码里现成的线索收走。

能在第一趟被发现的

  • 服务端直接输出在 HTML 里的 a 标签链接;
  • Sitemap 中列出的 URL;
  • RSS、Atom 等订阅文件里的条目;
  • HTTP 响应头中的重定向目标与 Link 信息。

要等第二趟的

  • 由前端路由在浏览器里生成的内链;
  • 点击「加载更多」才会出现的列表项;
  • 依赖接口返回数据拼出来的详情入口。

这里的区别不是「能不能被抓到」,而是「什么时候被抓到」。前者进入常规抓取队列,后者得先过渲染这一关。

渲染队列慢在哪里

渲染比纯抓取贵得多:要起浏览器进程、下载脚本和样式、执行代码、等接口回包。资源有限,站点一多就必然排队。

  • 页面脚本多、体积大,单页渲染耗时更长,队列被占用的时间也长;
  • 渲染失败或超时的页面,通常不会立刻重新排队;
  • 层级深、外部入口少的 URL,排位更靠后,等待更明显。

另外要分清:这里讨论的是发现和获取的节奏,不是收录结果。渲染成功也不等于页面一定会被索引。

让关键链接出现在原始 HTML 里

做法不复杂,核心是别把发现入口全交给 JS。可以按下面的顺序排查和调整:

  1. 栏目页、列表页、详情页之间的互相链接,优先用服务端渲染或静态输出。
  2. 交互可以保留 JS,但基础导航用普通 a 标签兜底。
  3. 分页和「下一页」给出真实 URL,而不是绑定点击事件。
  4. Sitemap 只提交确实需要被发现的 URL,并尽量与站内可见链接保持一致。
  5. 不必整站 SSR,至少把导航、面包屑、列表链接放进首屏源码。

这样做的好处是可预期的:蜘蛛第一趟就能顺着链接往下走,渲染队列只承担补充角色,而不是唯一的入口。

怎么确认自己有没有踩坑

  1. 关闭 JS,或只用源码抓取工具跑一遍,看能顺链接点到第几层。
  2. 对比源码里的链接数量和渲染后 DOM 里的链接数量,差得越多,依赖越重。
  3. 查看抓取日志,看同一批 URL 是否在渲染请求里才出现,是否比首轮抓取晚很多。
  4. 抽查若干深层页,确认它们至少有一条来自原始 HTML 的入口。
蜘蛛并不是看不见 JS 页面,而是它走在两条不同的队列上。把关键链接放回第一趟就能读到的地方,URL 的发现节奏会稳定很多。

最后补一句服务器侧的因素:渲染请求同样要占用连接和带宽。如果源站响应偏慢,渲染阶段的等待会叠加在抓取等待之上,整体节奏更慢。保持响应时间稳定、避免长时间无响应,对两趟流程都有帮助。