很多站点用前端框架重构之後會遇到同一類問题:頁面在浏览器里打開是完整的,标题、正文、内鏈都在,但在收錄上却明顯變慢,甚至長期停在“已發現”或“已抓取,未编入索引”。這时候先別急着改内容,多數情况下問题出在一個更靠前的环节——搜尋引擎拿到的頁面版本,和你用浏览器看到的版本不是同一份東西。
為什么 JS 渲染的頁面容易卡在入口
传统頁面把内容寫在 HTML 里,抓取程序拿到响應就能直接讀到全文。而 JS 渲染的頁面,初始 HTML 往往只有一個容器和几個脚本文件,真正的文字、連結是浏览器执行脚本之後才出現的。搜尋引擎要讀到這些内容,需要額外走一步渲染,而渲染本身有成本:要排队、要执行脚本、要等接口返回。不同引擎的渲染能力和調度策略不同,出現延迟、部分渲染甚至跳過渲染,都属于正常范围内的波動。
结果就是:頁面對人没問题,對抓取程序却像一張空壳。空壳頁面很难被判断為有價值内容,收錄节奏自然就慢。
先確認三件事,再動手改
1. 查看源代碼,而不是開發者工具里的元素面板
開發者工具的元素面板顯示的是渲染後的 DOM,容易造成“内容明明在頁面上”的错觉。要看的是右键“查看網頁源代碼”得到的那份 HTML。如果里面搜不到正文關鍵詞、搜不到主要連結,說明内容依赖脚本生成。
2. 检查 JS 和 CSS 有没有被 robots.txt 拦住
有些人為了“减少抓取消耗”,在 robots.txt 里屏蔽了 js、css 目錄。對渲染型頁面来说,這几乎等于把内容一起屏蔽了:脚本拿不到,渲染出来還是空壳。這類誤封很隐蔽,因為頁面在浏览器里完全正常,控制台也不會报错。
3. 渲染後的内容里,連結是不是真的連結
導航和列表項應该是带 href 的 a 标簽;如果只是给 div 绑了点击事件、点了才跳轉,抓取程序没有“点击”這個動作,站内入口等于不存在,頁面之間的發現路径也就断了。
常见的几類“渲染不出来”
- hash 路由:地址中 # 後面的部分不會發给服務器,多個路由在抓取程序看来是同一個 URL。
- 内容依赖接口且需要登入態或特殊請求头:渲染程序拿不到資料,頁面就是空的。
- 無限滚動:只加载首屏,後面的内容必须滚動才出現。
- 点击展開、悬停顯示:正文藏在交互之後,初始狀態不可见。
- 渲染超时:脚本体积太大、接口太慢,渲染任務在拿到内容前就結束了。
- 文字画在 canvas 或图片里:人能看到,但机器讀不到文本内容。
改動顺序:從低成本到高成本
- 先把關键内容直出:标题、正文主体、面包屑、主要内鏈尽量寫進初始 HTML,交互效果在直出基础上做增强。
- 清理渲染阻塞項:robots.txt 是否拦截脚本、接口是否需要鉴權、首屏請求數量是否過多、脚本能否再压缩。
- 如果整站都是客戶端渲染,考虑對内容型頁面做服務端渲染或静態生成,至少覆盖栏目頁和文章頁。
- 暂时改不動架构的,可以對重点 URL 做预渲染,把渲染後的完整 HTML 返回出去。
顺序上不要反過来:先保證 HTML 里讀得到内容,再谈提交和加速。
一份快速自查清單
- 查看源代碼时,能否搜到本頁的核心關鍵詞。
- robots.txt 是否拦截了 js、css 或資料接口路径。
- 主要導航是否為 a 标簽,href 是否指向可直接訪問的地址。
- 頁面是否需要登入、点击、滚動才能看到正文。
- 渲染所依赖的接口是否稳定,是否有限流或超时。
抓取和收錄是两件事:抓取只說明程序来過,能不能進入索引,還要看它到底讀到了什么。JS 渲染带来的問题,多數不是内容质量不够,而是内容没有被完整交付。