现在不少站点依赖 JavaScript 渲染:列表由接口拉取,正文由前端拼装,导航由组件生成。对访客来说页面是完整的,对抓取工具来说却可能只是一个加载中的骨架。前端渲染内容自查,就是确认人看到的内容和抓取工具拿到的内容,是不是同一份。
为什么会只剩空壳
常见的原因有这几种:
- 首屏内容完全由脚本异步请求后插入,HTML 源码里只有一个挂载点;
- 关键信息放在点击后才出现的折叠区、标签页或弹窗里;
- 分页、筛选依赖接口,地址不变或变化没有规律;
- 图片地址和正文链接由脚本动态写入,源码中对应位置是空的。
抓取工具通常先取 HTML,再决定是否执行脚本。执行脚本需要额外资源,也可能因为超时、资源被屏蔽而中断,于是最终拿到的是一个空壳。
自查怎么做
1. 关掉脚本看一遍
用浏览器禁用 JavaScript 打开页面,或直接抓取 HTML 源码。如果正文、导航、主要链接都不见了,说明关键内容依赖脚本。
2. 对比两份快照
把原始 HTML 和渲染后的 DOM 各存一份,逐项对照:标题、正文、图片替代文字、内链、分页地址。差异越大,需要处理的地方越多。
3. 检查入口和链接
站内链接如果是脚本事件绑定的按钮,抓取工具通常不会去点。链接应该是真正的 a 标签,带上可以访问的 href。
4. 看资源是否被挡
脚本、接口如果写在 robots.txt 的禁止项里,抓取工具就无法取到数据来完成渲染。需要在别让接口被大量抓取和内容能被渲染之间做个取舍。
可以考虑的处理方式
- 服务端渲染:在服务端把 HTML 拼好再返回,首屏内容直接出现在源码里,改动相对集中。
- 静态化或预渲染:对更新不频繁的栏目页、详情页,在发布时生成静态 HTML,既能被直接读取,也减轻数据库压力。
- 同构渲染:同一套代码在服务端和客户端运行,首屏由服务端输出,后续交互由客户端接管。
- 动态渲染:识别到抓取工具时返回预渲染版本,普通访客仍走原来的前端流程。实现较简单,但要保证两版内容一致,避免出现差异。
- 内容分层:把标题、摘要、正文主体、主要内链放进首屏 HTML,评论、推荐、点赞之类的交给脚本。
容易忽略的几个细节
- 分页和筛选的地址应该可以独立打开,而不是只有点击才触发;
- 懒加载图片要保留可读的地址或占位,别让图片信息只存在于脚本里;
- 发布时间、作者、面包屑等字段尽量用静态标签写出来;
- 如果站点有站点地图,确认清单里的地址都能返回带内容的 HTML。
提醒:渲染方式的调整会影响页面加载表现和服务器负载,改完之后记得观察一段时间的响应时间和错误率,别只看抓取结果。
小结
前端渲染本身不是问题,问题在于关键内容只存在于脚本运行之后。把正文、链接、分页这些需要被读到的部分放进 HTML,其余交互仍然可以交给前端。这样访客体验不变,抓取工具也能拿到相对完整的页面。