本文主要介绍基于Puppeteer的Vue,React等单页面应用的SEO通用解决方案。
近期博客系统刚好完成了第一版,无意间得知,百度等一些搜索引擎对于单页面应用不收录,原因很简单,因为百度的爬虫对于js不识别,就导致ajax请求的数据无法抓取到,爬虫爬到的只是一个空壳子单页面seo的方案很多,网上也有不少教材,比如ssr,预渲染等。但是他们都不适合于已经开发完成的程序,或多或少都需要进行修改,因此有了下面的Puppeteer。
Puppeteer是一个Node库,它提供了高级API来通过DevTools协议控制Chrome或Chromium,您可以在浏览器中手动执行的大多数操作都可以使用Puppeteer完成!例如:
- 生成页面的屏幕截图和PDF。
- 抓取SPA(单页应用程序)并生成预渲染的内容(即“ SSR”(服务器端渲染))
- 自动执行表单提交,UI测试,键盘输入等
- 创建最新的自动化测试环境
- 使用最新的JavaScript和浏览器功能,直接在最新版本的Chrome中运行测试
- 捕获站点的时间线跟踪以帮助诊断性能问题
- 测试Chrome扩展程序。
秉着互联网开发共享的学习精神,下面把我折腾4,5天的玩意儿做一个总结,分享给需要做SPA的朋友,话不多说,直接上干货。
一 介绍一下puppeteer实现单页面应用的原理
puppeteer可以操作Googleheadless来进行访问我们的网站,然后返回一个完整的html代码。讲puppeteer之前先说一下UA的一点小内容,已经有所了解的请略过,直接看下面的内容。
#这条是我使用本机mac系统访问的网站日志里面的user-agent
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
#这条是Google爬虫访问我网站时候的user-agent
Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
#搜狗访问user-agent
Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07;
Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07);
#百度的UA
Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html);
普通用户访问我们的网站和爬虫访问我们的网站,user-agent有区别,我拿到服务器上的log,抓取几个对比,可以看出来,搜索引擎的爬虫UA也不同,因此我们可以利用nginx来进行反向代理,如果是爬虫访问我们的网站,我们把它代理到另外一个专门处理渲染爬虫到服务端,也就是puppeteer,交给puppeteer来访问对应的网址,然后返回渲染好的页面给爬虫,看下面这张图即可。
有图可知,我们需要进行2部分操作;1.代理服务器的配置 2.渲染服务器的搭建
二 代理服务器的配置
由于我使用的nginx,所有代理服务器配置我直接上nginx的配置代码
location /{
#if语句里面用于判断UA是否上爬虫
if ($http_user_agent ~* (BaiduSpider|Googlebot|360Spider|Bingbot|Sosospider|Yahoo!\ Slurp\ China|YisouSpider)) {
#如果是爬虫,直接跳转到渲染服务器端 xxx代表,渲染服务器的域名或者ip
proxy_pass http://xxx;
}
#直接返回index
try_files $uri $uri/ /index.html;
}
三 渲染服务端,一下我使用的是kao作为渲染服务
const Koa = require('koa');
const fs = require('fs');
const puppeteer = require('puppeteer');
const browserUrl = fs.readFileSync("chrome.txt","utf8");
const app = new Koa();
const baseUrl = 'http://www.9cka.cn';//这里是真实SPA页面的地址
app.use(async (ctx,next)=>{
let browser = await puppeteer.launch({dumpio:true,args: ['--no-sandbox', '--disable-setuid-sandbox'],timeout: 10000});
const page = await browser.newPage();
try {
let myUrl = baseUrl+ctx.url;
await page.goto(myUrl); //到指定页面的网址.
await page.waitFor(5000);
} catch (err) {
await page.close();
await browser.disconnect();
console.log('出现错误:'+err); // 这里捕捉到错误 `error`
}
let html = await page.content()
/*fs.writeFile("myhtml22.html",html,function (err) {
if (err){
console.log('文件写入出错'+err);
throw err ;
}
console.log("myhtml.html成功"); //文件被保存
}) */
ctx.type = "text/html;charset=utf-8";
ctx.body =html;
await page.close();
await browser.close();
});
app.listen('3388');
console.log('3388端口爬虫代理程序已启动');
四 完成之后部署即可进行测试。
我使用postman进行测试,使用爬虫UA进行测试,返回结果如图,看到获取到了完整的html,包括ajax请求的数据,这样爬虫就可以抓到数据了。
我的个人博客地址:点击跳转