你的SPA网站,百度可能根本看不见
你花两周搭了个炫酷的单页应用,路由跳转丝滑、动画一气呵成,连产品经理都夸“这体验比XX App还顺”。但上线一个月后,你搜自己公司名,首页都排不进前三——不是没做SEO,是百度压根没把你当“有内容的网站”看。
它看到的,很可能就一个空荡荡的 <div id="app">。
为什么爬虫在SPA里就像“瞎子”?
传统网页打开就是HTML:标题、正文、链接,清清楚楚。爬虫扫一眼就走,效率高得像快递员扔完包裹转身就跑。
SPA不是这样。它先扔给你一个几乎啥都没有的HTML壳子,再靠JavaScript一点点把内容“画”出来——加载JS、请求API、拼DOM、触发渲染……整个过程,用户等3秒觉得正常,爬虫等1秒就关页面。
我帮一个做在线题库的团队查过日志:他们首页JS执行要2.7秒,而百度爬虫平均只停留0.8秒。结果呢?上线半年,百度只收录了首页和4个内页,点开全是“数据加载中…”。
百度确实说能执行JS,但实际很保守:超时就放弃、遇到复杂异步就跳过、懒加载图片和文字?基本当不存在。不是它不想看,是你没给它“读得懂”的机会。
3种最常见的“伪收录”陷阱,你踩过几个?
很多人以为“百度搜得到”,就等于被收录了。其实只是幻觉。
第一种:收录了,但点进去是白屏。
你在百度搜 site:yourdomain.com,看到几十个URL。点开一个,页面空白,F12一看,DOM里只有 <div id="app"></div> 和一堆 <script>。这种收录毫无价值——用户进来就走,跳出率直接拉满。
第二种:首页能见,内页全失踪。
首页勉强能抓到,因为路径简单、JS少;但产品页、详情页、用户中心这些,全靠前端路由跳转。爬虫不会点按钮、不会触发 history.pushState,它连“下一页”在哪都不知道。
第三种:收录了,但内容张冠李戴。
有个客户的产品页被收录了,但标题显示的是“关于我们”,描述是一串乱码。查下来发现:路由切换后,<title> 标签根本没更新,爬虫只抓了初始状态。这种错乱比不收录更伤——用户会觉得你网站不可信。
说白了,问题不在爬虫笨,而在我们总把它当“人”用,忘了它本质是个只认静态HTML的文本阅读器。
服务端渲染SSR:最笨但最有效的方法
想让百度真正看懂你的SPA?SSR(服务端渲染)不是最优解,是目前唯一被验证有效的解。
做法很直白:用户或爬虫一请求,服务器先把页面内容渲染成完整HTML,再发出去。爬虫拿到的就是带标题、带正文、带结构的真·网页;浏览器收到后,再“激活”交互逻辑(这个过程叫水合)。
我们帮一家教培机构把Vue SPA迁到Nuxt.js(Vue生态的SSR框架),原来百度收录不到20个页面,两个月后稳定在200+,不少课程长尾词开始出现在搜索结果前两页。
当然,SSR要多扛一部分服务器压力——以前静态资源甩给CDN就行,现在每次访问都要服务端计算。但如果你的流量还没到单日万级,这点开销远不如“没人搜得到”来得痛。
如果项目小、内容更新不频繁,也可以试试预渲染:构建时就把所有路由对应的HTML提前生成好,部署成静态文件。比如用 prerender-spa-plugin,适合官网、介绍页这类场景。
别指望“等百度升级算法”,它现在就能读懂SSR输出的HTML。
动态渲染:给爬虫开“VIP通道”
SSR成本高、周期长?那动态渲染是第二选择:检测来访者是不是爬虫,是——就返回预渲染好的HTML;不是——照常走SPA流程。
相当于在门口装了个识别器:穿工装的是工人,走正门;穿西装的是访客,走VIP通道。
落地方式有两种:
- 自己搭中间件:在Nginx或Node层判断User-Agent,匹配到
Baiduspider就转发给Puppeteer或Rendertron服务,让它实时渲染并返回HTML。 - 用云平台现成能力:阿里云Web应用防火墙、百度云SEO加速,都支持配置动态渲染规则,填个域名、选个模式,几分钟搞定。
真实案例:一家金融资讯站,内容天天更新,但百度收录慢得像蜗牛。上了动态渲染后,新发布的文章平均3天内就被收录,之前要等一两周甚至更久。
注意一个雷区:爬虫看到的HTML,必须和用户最终看到的一模一样。少渲染一段文案、漏掉一个<meta>,百度会判定为“隐藏内容”,轻则降权,重则拒收。
别忘了这些“小细节”,它们能救你的命
大方案再好,细节塌方,照样白干。
第一,路由切换时,必须同步更新 <title> 和 <meta name="description">。
很多SPA只在入口文件写死一个标题,后面所有页面都是“首页 - XXX公司”。百度抓取时就按这个存档,结果上千个页面标题重复,直接被当成垃圾站处理。
第二,别用 #/about 这种hash路由。# 后面的内容,百度基本不解析。它只认 /about、/article/123 这种标准路径。用Vue Router或React Router时,记得开 history 模式,而不是默认的 hash 模式。
第三,sitemap不能交一次就吃老本。
哪怕你是SPA,也得有sitemap。而且得是“活”的:新上一篇博客、新增一个产品页,就得自动加进sitemap.xml,并重新提交到百度站长平台。很多团队上线时提了一次,之后三年没动过。
第四,去百度搜索资源平台翻抓取日志。
不是看“收录量”,是看“哪些URL返回了404/500/超时”。日志里藏着最真实的线索:某个详情页接口挂了,爬虫反复失败;某个路由配置错了,返回空白HTML……80%的人从不点开这页,但问题就藏在这里。
今天就能做的1个操作:用“curl”测试你的页面
别收藏,别“稍后看”,现在就打开终端(Mac/Linux)或 Windows PowerShell,粘贴运行这一行:
curl -H "User-Agent: Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)" https://yourdomain.com/product/abc
把 https://yourdomain.com/product/abc 换成你最想被收录的那个页面地址。
看返回结果:
- 如果里面有真实的标题、正文段落、产品参数——说明爬虫至少能读到内容;
- 如果只有
<div id="app">、<script src="...">、或者“加载中…”——你的SPA对百度来说,就是一张白纸。
如果是后者,今天就打开你的项目,挑一个最核心的页面(比如首页或产品列表页),在构建流程里加上 prerender-spa-plugin,或者在路由守卫里补上 <title> 动态更新逻辑。做完这一步,你已经比多数同行快了一步。