抓取和渲染,在蜘蛛那里是两件事
很多人把「蜘蛛来过」理解成一个动作:请求、下载、看懂页面。实际流程至少能拆成两段。第一段是普通的 HTTP 抓取,服务器返回什么 HTML,蜘蛛就先拿到什么;第二段是把页面丢进渲染队列,用浏览器内核执行 JavaScript,等 DOM 稳定之后再读一遍。两段之间可能只隔几分钟,也可能隔上好几天。
这个时间差直接决定了一件事:如果 URL 只存在于 JS 执行之后的 DOM 里,它被发现的时间就要往后推。
第一趟:原始 HTML 里有什么,就先认什么
第一次请求返回的源码,如果只有一个空容器节点加一段脚本引用,那这一趟能读到的信息就非常有限。蜘蛛不会在这一步替你执行脚本,它只是把源码里现成的线索收走。
能在第一趟被发现的
- 服务端直接输出在 HTML 里的 a 标签链接;
- Sitemap 中列出的 URL;
- RSS、Atom 等订阅文件里的条目;
- HTTP 响应头中的重定向目标与 Link 信息。
要等第二趟的
- 由前端路由在浏览器里生成的内链;
- 点击「加载更多」才会出现的列表项;
- 依赖接口返回数据拼出来的详情入口。
这里的区别不是「能不能被抓到」,而是「什么时候被抓到」。前者进入常规抓取队列,后者得先过渲染这一关。
渲染队列慢在哪里
渲染比纯抓取贵得多:要起浏览器进程、下载脚本和样式、执行代码、等接口回包。资源有限,站点一多就必然排队。
- 页面脚本多、体积大,单页渲染耗时更长,队列被占用的时间也长;
- 渲染失败或超时的页面,通常不会立刻重新排队;
- 层级深、外部入口少的 URL,排位更靠后,等待更明显。
另外要分清:这里讨论的是发现和获取的节奏,不是收录结果。渲染成功也不等于页面一定会被索引。
让关键链接出现在原始 HTML 里
做法不复杂,核心是别把发现入口全交给 JS。可以按下面的顺序排查和调整:
- 栏目页、列表页、详情页之间的互相链接,优先用服务端渲染或静态输出。
- 交互可以保留 JS,但基础导航用普通 a 标签兜底。
- 分页和「下一页」给出真实 URL,而不是绑定点击事件。
- Sitemap 只提交确实需要被发现的 URL,并尽量与站内可见链接保持一致。
- 不必整站 SSR,至少把导航、面包屑、列表链接放进首屏源码。
这样做的好处是可预期的:蜘蛛第一趟就能顺着链接往下走,渲染队列只承担补充角色,而不是唯一的入口。
怎么确认自己有没有踩坑
- 关闭 JS,或只用源码抓取工具跑一遍,看能顺链接点到第几层。
- 对比源码里的链接数量和渲染后 DOM 里的链接数量,差得越多,依赖越重。
- 查看抓取日志,看同一批 URL 是否在渲染请求里才出现,是否比首轮抓取晚很多。
- 抽查若干深层页,确认它们至少有一条来自原始 HTML 的入口。
蜘蛛并不是看不见 JS 页面,而是它走在两条不同的队列上。把关键链接放回第一趟就能读到的地方,URL 的发现节奏会稳定很多。
最后补一句服务器侧的因素:渲染请求同样要占用连接和带宽。如果源站响应偏慢,渲染阶段的等待会叠加在抓取等待之上,整体节奏更慢。保持响应时间稳定、避免长时间无响应,对两趟流程都有帮助。