搜索抓取

HTML 里看不到的内容:蜘蛛的渲染队列与二次抓取

蜘蛛第一次取回的往往是原始 HTML,靠 JavaScript 生成的内容要排队等渲染才可能被看到。渲染资源有限、有超时,懒加载、点击插入、无限滚动这些写法最容易在这一步掉队。本文说明两阶段抓取的过程、常见的漏抓原因,以及把关键内容放回 HTML 的几种做法和自查方式。

搜索抓取

HTML 里看不到的内容:蜘蛛的渲染队列与二次抓取

蜘蛛第一次请求一个 URL 时,拿到的通常是服务器直接返回的原始 HTML,而不是你在浏览器里看到的那个完整页面。如果页面的主要内容是靠 JavaScript 在客户端拼出来的,这段内容就不在这份 HTML 里,它得等下一轮渲染处理,才有机会被看到。理解这一点,能解释很多“页面明明存在,却像没被抓过”的现象。

第一步取 HTML,第二步才是渲染

抓取大致分两段:先是用普通请求把 URL 的响应体取回来,这一步快、成本低、能覆盖的数量大;之后才会把一部分页面放进渲染队列,用接近浏览器的方式执行脚本,拿到渲染后的 DOM。只有走到第二步,JS 生成的内容才可能进入后续判断。

  • 取 HTML 阶段:看的是服务器返回的字节,链接、正文、meta 都在这里被识别。
  • 渲染阶段:执行 JS、加载异步数据,再重新提取内容与链接。
  • 两个阶段的队列是分开的,渲染明显更慢,能处理的数量也少得多。

所以页面的抓取表现,取决于内容出现在哪一段。服务端就输出的内容,在第一段就能被读到;只存在于渲染后的内容,要先排队。

渲染队列不是无限的

渲染要占用计算资源,因此它更像是一种配给:站点权重、页面重要程度、历史抓取表现都会影响一个 URL 能不能进队列、多久轮到一次。排队时间长、单页渲染有超时限制,脚本太慢或者依赖外部接口迟迟不返回,都可能让渲染在半途结束,只留下一份不完整的 DOM。

常见的后果是:链接能发现,但正文抓不到;正文能抓到,但分页链接、图片、价格这些动态部分缺失。它们不是被拒绝,而是没等到渲染完成。

哪些写法最容易在这一步掉队

  • 内容懒加载:图片和正文都要滚动或进入视口才请求,渲染时不一定会触发。
  • 点击后才插入:标签页、折叠面板里的文字,默认状态是空的。
  • 无限滚动:后续内容没有独立 URL,也没有可点击的下一页链接。
  • 依赖登录态或本地存储:未登录访问时脚本直接中断。
  • 关键 JS 被 robots.txt 屏蔽:脚本取不到,页面自然拼不出来。
  • 第三方脚本超时:渲染在等待外部请求时被卡住。

这些问题有一个共同点:把“能不能看到内容”交给了一个不确定的执行环境。

把关键内容放回 HTML

不必把整站改成纯静态,但影响抓取判断的部分最好不依赖渲染。可以按下面的顺序处理:

  1. 正文、标题、主要链接直接由服务端输出,脚本只负责增强交互。
  2. 列表页的分页入口用真实的 a 标签写在后端 HTML 里,不要只用 JS 绑定点击。
  3. 条件允许时用服务端渲染或预渲染,让首屏 HTML 就带上内容。
  4. 动态数据接口尽量同源、响应快,避免渲染时长时间空等。
  5. 确认 JS、CSS 资源本身可以被抓取,不要误屏蔽。
  6. 为无限滚动的列表补上可独立访问的分页 URL。
渲染只是让内容有机会被看到,抓取和渲染都不等于收录,更不等于排名。把内容输出得更稳,减少的是不确定性,不是结果本身。

怎么确认自己有没有这类问题

  • 关掉 JS 抓取一次页面,对比和浏览器里看到的内容差多少。
  • 用工具的“查看渲染后 HTML”功能,看正文是否真的出现在 DOM 里。
  • 翻服务器日志,观察同一 URL 是否出现两类请求:一类只取 HTML,一类会连带请求脚本和接口。
  • 挑几个重要模板页做渲染前后对比,重点看正文首段和列表链接。

如果某个模板在关闭 JS 后几乎空白,那么它的抓取表现就会明显受渲染队列的节奏影响。先把这部分内容搬回 HTML,往往比反复提交 URL 更有效。