先确认一件事:不执行脚本时,页面还剩什么
很多站点用前端框架搭建,页面在浏览器里看起来完整,但服务器返回的初始 HTML 可能只有一个空容器和一堆脚本标签。对访客来说,脚本跑完内容就出现了;对抓取端来说,如果它不执行或只执行一部分脚本,读到的就是空壳。这不是收录与否的保证书,但会让内容进入解析流程之前先多一道门槛。
做站点运营时,可以把它当成结构自查的一部分:不讨论蜘蛛会不会执行脚本,只看关键内容是否出现在初始响应里。如果标题、正文、内链、分页入口都在 HTML 中直接可读,后续的发现和解析会少很多不确定因素。
自查方法:三个角度看页面输出了什么
1. 直接查看网页源代码
在浏览器里按 Ctrl+U 或右键查看源代码,搜索正文里的一句话。如果搜不到,但在页面上能看到,说明这段内容大概率由脚本注入。也可以关掉浏览器 JavaScript 再刷新,看看是否还能读到主要内容。注意,部分站点关闭 JS 后页面样式会乱,但正文仍应存在。
2. 用命令行看原始响应
使用 curl 或类似工具请求页面,把返回内容保存下来,再检查其中有没有目标关键词、链接和结构化信息。这个方法不受浏览器渲染影响,能看到服务器实际发出的东西。重点看:标题、正文首段、栏目链接、分页链接、canonical 地址是否在返回内容中。
3. 对比抓取日志与页面地址
如果站内已有抓取日志,可以挑一些被抓取过的详情页,和它们当前返回的 HTML 做对照。日志显示抓取成功,并不代表内容被完整读到。把日志里的地址手动请求一遍,观察返回内容里是否有实质信息,能帮你判断问题出在渲染还是别处。
常见的“空壳”场景
- 列表页和详情页由同一个前端路由渲染,服务器只返回框架入口文件。
- 正文、价格、库存、评论等数据通过接口异步加载,初始 HTML 不包含这些字段。
- “加载更多”和无限滚动只改前端状态,分页地址没有被写入链接。
- 导航和面包屑用 div 加点击事件实现,没有可跟随的 a 标签地址。
- 页面标题和描述在脚本里动态设置,初始 HTML 里是默认值或空标签。
这些情况不一定都影响抓取,但会增大解析成本。尤其是内链和分页入口,如果它们只存在于脚本里,URL 发现的路径就变窄了。
调整思路:把关键内容放回 HTML
- 优先服务端输出。 用服务端渲染、静态生成或预渲染,让正文、标题、内链在首次响应中就可读。框架通常都有对应方案,选适合现有技术栈的即可。
- 关键字段前置。 如果整站改造周期长,至少把标题、摘要、正文首段、主要栏目链接和分页链接放到服务端模板里。
- 链接用真实地址。 导航、面包屑、卡片、分页都尽量使用 a 标签指向独立 URL,避免只用 JS 跳转。这样既方便访客新开标签,也方便抓取端顺着链接走。
- 异步内容保留降级。 必须异步加载的模块,可以给出静态占位或基础信息,不要求所有内容都实时渲染,但不要让核心信息完全缺失。
- 检查缓存与响应头。 服务端渲染后,确认缓存没有把空壳版本长期存下来,也确认 Content-Type 和编码没有引发解析问题。
渲染方式自查不是追求某种技术路线,而是确认页面在“不跑脚本”的情况下,是否还能把主要内容、层级和入口交代清楚。
内链与分页也要能被直接访问
就算正文已经服务端输出,内链和分页如果仍然依赖脚本,URL 发现还是会变窄。检查栏目页、标签页、上一篇/下一篇、分页按钮,看它们是否对应真实可访问的地址。分页地址最好保持简洁稳定,不要每次渲染都生成带随机参数的链接。站内搜索结果页、筛选页如果由脚本生成,也要确认是否值得让抓取端进入;如果不希望它们被反复发现,可以用合适的规则控制,而不是放任脚本不断产生新地址。
把它放进日常巡检
改版、换框架、上新栏目之后,抽几个代表性页面做一次原始响应检查,成本不高,但能避免“页面上看着正常,服务器返回的却是空壳”这种落差。站点运营不需要把所有页面都改成纯静态,但至少要让重要内容在初始 HTML 中有迹可循。这样做不保证收录或排名,只是减少内容被读到之前的多余损耗。