一个常见现象:URL 已知,内容却迟迟不来
在服务器日志里经常能看到这种情况:某个新 URL 在几小时内就被请求了一次,但返回的 HTML 几乎是空壳,正文全靠 JS 渲染。此后这只 URL 长时间没有第二次请求,收录自然也无从谈起。这不是蜘蛛没发现 URL,而是发现 URL和拿到可用内容被拆成了两步。
发现与渲染是两个独立的队列
抓取大致包含两类动作:一类是爬取原始响应,用于提取链接、判断页面是否值得继续处理;另一类是把页面放进渲染环境,执行脚本后再读取最终 DOM。前者通常较快,后者依赖渲染资源与计算能力,排队时间往往更长。
于是页面在第一次被抓取时,只贡献了链接和少量文本。蜘蛛需要等到渲染队列轮到它,才能看到完整内容。这个间隔没有公开的固定值,短则数小时,长则更久;期间站点如果频繁改动,还可能拿到过渡状态的版本。
哪些页面更容易进入渲染队列
- 首屏内容由前端框架在客户端请求接口后拼装,初始 HTML 里没有正文。
- 正文依赖用户交互才展开,比如点击标签、滚动懒加载。
- 关键内容被脚本按条件插入,例如按 UA 或地区判断后再渲染。
- 页面依赖大量第三方脚本,渲染环境需要反复等待超时。
- 列表页的链接由 JS 生成,初始 HTML 中不包含任何指向详情页的 a 标签。
这几类页面的共同点是:原始 HTML 对蜘蛛的信息量很低,几乎所有判断都被推到了渲染阶段。问题是渲染资源永远比抓取资源紧张,页面越多,平均等待就越长。
把关键内容留在初始响应里
服务端渲染或静态化不是为了讨好蜘蛛,而是让内容在第一轮请求中就可读。做不到全站 SSR 时,可以按优先级处理:
- 先保证详情页的正文、标题、发布时间在初始 HTML 中完整输出。
- 确保分页、列表页和导航里的链接是服务端输出的真实 a 标签,而不是脚本拼接出来的。
- 把影响理解的结构化数据也放进初始 HTML 或独立 JSON-LD。
- 对必须依赖接口的模块,考虑在服务端预取数据后注入首屏。
- 保留一份不依赖 JS 的降级视图,至少让核心内容可读。
验证渲染造成的时滞
判断问题是否出在渲染,可以用几种简单方式对照:
- 关闭 JavaScript 抓取页面,看初始 HTML 里还剩多少正文和链接。
- 比对日志中同一 URL 的多次请求,观察后续请求是否携带渲染特征,例如更长的响应时间、不同的资源请求序列。
- 把服务器日志与站点自身清单对账,找出被抓过却没有后续渲染请求的页面。
- 记录新内容的首次出现时间与内容完整时间,两者的差值就是渲染时滞的粗略下限。
几个容易踩的坑
把渲染当成万能解法,往往会掩盖更基础的问题:链接不可达、HTML 结构混乱、内容必须交互才出现。
- 用脚本生成链接并期待被抓到,等于把 URL 发现也交给了渲染队列。
- 在渲染时才决定 canonical 或 noindex,蜘蛛很可能先看到另一个版本。
- 把重要内容放在异步加载的第二屏,渲染过程也可能不触发。
渲染是补充手段,不是抓取的起点。让初始 HTML 承载尽可能多的信息和链接,渲染队列的压力才会下降,从 URL 被发现到内容被理解之间的空档也会随之缩短。至于最终是否收录、何时收录,仍由搜索引擎自行判断,站点能做的是减少那些本不必要的等待。