很多站点的链接并不是写在 HTML 里,而是页面加载后由 JavaScript 拼出来的。对用户来说,点开就看到了;对搜索蜘蛛来说,这件事要分两步看。第一轮请求拿到的往往只是一段初始 HTML,脚本还没执行,链接自然也不存在。这就是“页面上明明有入口,蜘蛛却像没看见”的常见原因。
第一轮抓取,蜘蛛先拿到什么
蜘蛛发出的第一次请求和普通的抓取请求很接近:它拿到服务器返回的 HTML,解析里面的 a 标签、link 标签、图片地址等。如果这份 HTML 里没有目标 URL,这一轮就发现不了它,后面的路径也就无从谈起。
蜘蛛确实具备渲染能力,但渲染成本更高,通常不是首轮就做,而是把需要渲染的 URL 放进队列,稍后再用另一轮请求以渲染方式访问。也就是说,脚本生成的链接不是不能被抓,而是要等,而且不保证等到。
渲染队列带来的时间差
- 链接出现在渲染之后,不等于出现在首轮抓取路径里;
- 排队意味着延迟,越靠后、越不被重视的页面等得越久;
- 数据依赖接口返回,接口拒绝了蜘蛛的请求,链接就直接消失;
- 需要滚动、点击、登录才出现的链接,大概率永远进不了队列。
所以真正的问题不是“渲染会不会被处理”,而是“你愿不愿意把关键入口押在第二轮上”。更新频繁的列表页、商品页、文章页,等一轮队列的代价很明显;而登录后、后台类页面本来也不需要被抓,延迟甚至抓不到都无所谓。
把结构性链接放回初始 HTML
最省事的做法是先分清楚哪些链接属于结构性入口——主导航、分类页、分页、上一页下一页、面包屑、相关推荐。这些应该由服务端直接输出成可点击的 a 标签,而不是留给脚本补上。
- 列表页与详情页的静态部分优先做服务端渲染或预渲染;
- 分页使用真实 URL,例如 ?page=2 或 /list/2,不要只在脚本里追加数据;
- 筛选、排序这类交互,至少保证有一个可抓取的默认版本;
- 跳转写成带 href 的链接,避免用 onclick 或 div 模拟。
判断标准很简单:把浏览器 JS 关掉再刷新页面,如果关键入口还在,蜘蛛第一轮大概率也能看到。
几项可以自己做的自查
- 用抓取工具分别查看禁用 JS 与启用 JS 两种状态下的链接列表,对比差异;
- 在服务器日志里观察同一个 URL 是否被多次访问,以及两次访问之间隔了多久;
- 抽查 URL 检查类工具返回的原始 HTML 与渲染后 HTML,确认目标链接出现在哪一份里。
容易被忽略的连带影响
渲染后的页面还可能改变地址本身:脚本里带 hash、附加追踪参数、动态拼接路径,都会让同一份内容变成多个 URL,抓取路径随之走偏。渲染前和渲染后如果 canonical、标题、内链不一致,蜘蛛两次看到的就不是同一页,之前建立起来的路径判断也会被推翻。
结论并不复杂:渲染可以当作补充,但不适合当成发现 URL 的主通道。把结构性链接放回初始 HTML 和 Sitemap,让首轮抓取就能顺着走;剩下的交互再交给脚本处理,这样路径才稳定。