蜘蛛对 JavaScript 的处理不是统一的
不同搜索引擎的蜘蛛对 JS 的执行能力差别很大。有的蜘蛛只抓取初始 HTML,不执行脚本;有的虽然能渲染,但会排入单独的渲染队列,时间上滞后很多。这就意味着,如果你的入口页把关键链接和内容都交给 JS 生成,蜘蛛可能只看到一个空框架。
所以讨论入口页的 JS 渲染,核心问题不是“能不能用 JS”,而是“哪些信息必须让蜘蛛在第一次抓取时就拿到”。
蜘蛛渲染和普通抓取不是一回事
即使蜘蛛具备渲染能力,很多搜索引擎也会把渲染放在独立的队列里。初始抓取和渲染之间可能间隔一段时间,入口页数量一多,这个延迟会被放大。如果你的入口页主要作用是传递链接权重和引导 URL 发现,等待渲染队列显然不划算。
另外,渲染会消耗更多资源。搜索引擎不会对每个页面都投入同样的渲染预算,入口页越薄、越模板化,被跳过渲染的概率越高。
这些内容建议放在初始 HTML 里
- 可抓取的链接:指向目标页的 a 标签最好直接出现在 HTML 中,而不是等 JS 插入。蜘蛛顺着链接发现新 URL,依赖的就是这些初始的 href。
- 页面主题相关的主标题和正文摘要:至少让蜘蛛读到入口页在讲什么,有助于判断是否继续抓取。
- canonical 和 meta robots:这些声明如果由 JS 后置写入,蜘蛛可能来不及看到,规范化和屏蔽指令就会失效。
- 状态码和跳转:服务端能返回的,不要改用前端路由或 JS 跳转代替。HTTP 层面的信号更明确。
预渲染与动态渲染的取舍
如果入口页确实需要 JS 才能展示完整内容,可以考虑预渲染或动态渲染,但要注意成本和一致性。
预渲染
在构建或缓存阶段就把页面渲染成静态 HTML,蜘蛛和用户拿到的是同一份内容。这种方式稳定,但内容更新后需要重新生成,适合入口页结构相对固定的场景。
动态渲染
根据 User-Agent 判断是否返回渲染后的 HTML。实现时要小心:蜘蛛 UA 会变化,伪装 UA 的爬虫也不少。如果只对特定 UA 返回不同内容,容易造成内容不一致,也可能被判定为作弊。更稳妥的做法是服务端渲染或同构渲染,让所有访问者拿到基本一致的 HTML。
几个容易踩的坑
- 把链接做成 onclick 事件,或者用 javascript:void(0) 这类空地址,蜘蛛拿不到真实目标。
- 首屏内容由接口异步加载,初始 HTML 里只有 loading 提示。
- 用前端路由处理分页,URL 变了但 HTML 不变,蜘蛛容易把不同页看成同一页。
- 依赖 JS 写入 meta 标签,比如 noindex 或 canonical,实际抓取时可能根本没生效。
怎么确认蜘蛛看到了什么
最直接的办法是看服务端日志里的请求。如果蜘蛛只请求了 HTML,没有请求 JS 和接口,那它大概率没有执行渲染,或者渲染在另一个阶段进行。也可以对比“源代码”和“渲染后 DOM”的差异,差异越大,风险越高。
如果日志显示蜘蛛抓取了 JS 文件,但入口页的链接仍然没有出现在后续抓取中,需要检查链接是否在初始 HTML 里,以及是否被 JS 条件隐藏。
一个简单的检查顺序
- 查看页面源代码,而不是开发者工具里的渲染后 DOM。源代码里有没有链接、标题和正文?
- 禁用浏览器 JavaScript,看页面还剩多少可读内容。
- 用抓取工具模拟蜘蛛,只拿初始 HTML,确认关键元素是否出现。
- 检查 canonical、meta robots 和主要链接是否都在服务端输出。
- 如果必须用 JS,评估预渲染或 SSR 的成本,别只靠动态渲染兜底。
入口页的 JS 策略,本质上是在“开发方便”和“蜘蛛可读”之间做取舍。能服务端输出的,尽量别留给客户端。