内链如果由 JavaScript 动态生成,蜘蛛第一次请求拿到的 HTML 里可能只有一段脚本和占位容器,看不到任何可跟随的链接。这不等于页面抓不到,但 URL 进入发现路径的时间点会往后挪,节奏也不再由你的内链结构决定。
渲染前后是两份不同的内容
搜索蜘蛛通常先抓取原始 HTML,再决定是否把页面放进渲染队列。原始 HTML 是未执行脚本的版本,渲染后的 DOM 才是用户看到的结构。两者的链接集合经常不一致:导航、卡片列表、相关推荐、筛选标签,只要靠脚本插入,就只存在于第二份内容里。
差别带来的直接后果是:原始 HTML 里的链接会被立刻提取并排队,渲染后才出现的链接要额外等一个环节。这个环节的排队长度站点无法直接控制,能做的是减少对它的依赖。
容易被推后的几类链接
- 无限滚动与懒加载列表:后续条目在滚动时才请求数据,渲染也未必一次执行到底。
- 前端路由生成的地址:链接由脚本按规则拼接,原始 HTML 中不存在对应节点。
- 点击才出现的入口:折叠菜单、标签切换、查看更多按钮背后的链接,需要交互才会渲染。
- 接口返回的关联内容:相关文章、作者页、标签页由后台接口填充,首屏 HTML 为空。
这几类的共同点是把链接的产出放在了脚本执行阶段。数量少时影响有限,如果站点的核心入口都落在这一类,URL 的发现速度就会受制于渲染队列。
自查:把两版内容摊开对照
- 关闭 JavaScript 抓取页面源码,保存为版本 A。
- 在浏览器打开同一 URL,等页面稳定后复制渲染后的 DOM 结构,保存为版本 B。
- 分别提取两版中的链接,做成两张清单并求差集,差集就是只在渲染后存在的链接。
- 对差集里的 URL 分类:属于装饰性的分享按钮、辅助导航,还是需要被抓取的正文与栏目入口。
- 抽样打开其中几个 URL,确认服务器直接返回的内容与渲染后展示的内容是否一致。
这组对照不需要复杂工具,重点在于持续做,而不是上线新版本时只做一次。
把关键入口放回原始 HTML
服务端渲染或预渲染
让首屏 HTML 就带上真实链接是最直接的做法。整站改造代价高时,可以只覆盖核心栏目页与文章详情页的导航和推荐模块。
静态兜底链接
在列表容器外补一组普通链接,指向最新的若干条目或主要分类。它不承担展示职责,但确实存在于 HTML 中,蜘蛛可以正常提取并继续深入。
Sitemap 作为备用入口
Sitemap 不解决页面之间的传递关系,但能保证 URL 有一条不依赖渲染的提交通道。对渲染内容较多的站点,把它当作兜底比当作唯一手段更稳妥。
渲染环节能提高抓取成功率,但它不是免费的。把全部希望压在渲染上,等于把发现时机交给别人的排队策略。
改完之后的观察节奏
比较一段时间内的抓取日志:之前只在渲染后才出现的 URL,是否开始出现在原始 HTML 请求的记录里;同一批 URL 的首次抓取与再次抓取之间的间隔有没有变化。如果没有起色,先确认渲染依赖是否仍然存在,再考虑其他原因,不必急着加大链接投放量。