单页面网站,好比vue、recat框架的网站,通常都是直接从服务器推送index.html,再根据自身路由经过js在客户端浏览器渲染出完整的html页面。css
可是搜索引擎的爬虫可没有这么智能(实际上google就有这么智能,拿到js文件自动帮你渲染好,但身在CN,将就下百度这个阿斗吧),为了SEO,要想爬虫爬到你的网站的内容,就得先由服务器把页面渲染好后再发送给爬虫,这就尴尬了,传统的服务器渲染是多页面的,一个请求对应一个页面,但SPA不是啊,原本就一个单页面,你叫我写各类路由对应渲染好了再给你??固然也不是不能够,如下就是几种方案:html
react自带的renderToStringvue
react自带的renderToString 和 renderToStaticMarkup 就能够用来将组件(Virtual DOM)输出成 HTML 字符串,看起来不错,可是要本身配参数啊,webpack不会怎么办,本来路由写在一块儿怎么办,redux要改动怎么办,若是这些你都ok的话,react自带的方案也是一种不错的选择,这里就很少说了,网上相关帖子不少。node
nextjsreact
还有一种方案,就更尴尬了,叫nextjs框架(nextjs是react的,vue的叫nuxtjs),这种框架写出来直接就是多页面的,也就是用react的语法和规则,写出多页面网站来,每一个页面的入口名字就是路由名字,服务器也是nextjs自带的,短短几行就能把单个网页渲染好并推送出去,是否是看起来棒棒的?!linux
那为啥说尴尬呢?就是由于他虽然说跟react很像,但仍是一个新框架,你不得不花时间学一下nextjs;他的路由对应页面文件,这种路由看似简单明了,可是一点都不自由;nextjs是多页面的,好不容易进化到单页面,你让我再回到中世纪?原罪啊!因此若是你已经写好了一个单页面网站,要改为nextjs框架的话,我只能说呵呵了,这返工返的……webpack
rendertrongit
咱们的主角要出场了!rendertron的由来我很少说了,当初诞生就是为了作SEO的。先说说原理,听完你就知道是个好东西了。github
Rendertron是nodejs框架下的产物,是google-chrome旗下的的配套产品。首先,服务器上装有个google-chrome,rendertron把他打开,而后在服务器(官方推荐express)中增长中间件,先判断UA(user-agent)里面有没有带有相似Baiduspider(百度爬虫)等字样,若是没有,就像正常的单页面服务器那样,把原始html推送出去,由客户端浏览器完成js、css渲染的工做;若是带有指定UA头字样,就先把网页推送给本地服务器那个google-chrome,等他渲染好对应页面后,把渲染好的html结果推送出去。不就是为了SEO么,你爬虫来了我再渲染给你总行了吧,其他的我仍是作个人单页面,呵呵哒。web
下面上一张图,说明原理。(原理跟rendora的差很少,下图的rendora你把他换成rendertron就行了)
好了,如今讲讲怎么用,官网有用法,我给个连接rendertron官网。可是这里我讲一下具体怎么用的一种无脑方案,你照作就能够了,另外官网demo还有很多的坑和bug,我也挑出来和你们分享一下。
安装Chromeheadless
先在你的服务器上安装Chromeheadless,这是服务器上的无头chrome浏览器,若是你的服务器上已经有这个,那恭喜你了,由于安装过程的坑实在是太多太多了。网上关于安装Chromeheadless的教学贴不少,在此我贴几个。
先在你的服务器上安装Chromeheadless,这是服务器上的无头chrome浏览器,若是你的服务器上已经有这个,那恭喜你了,由于安装过程的坑实在是太多太多了。网上关于安装Chromeheadless的教学贴不少,在此我贴几个:
安装过程当中你会遇到不少坑,不过没关系,把error复制粘贴一下放百度,仍是有不少解决方案的,毕竟Chromeheadless不是什么小众的东西
安装rendertron
直接命令行输入
npm install -g rendertron
回车,就装好了。就这么简单?呵呵,有greatWall,安装过程当中必需的某个东东下载不了,这时候要用代理,会的同窗固然ok,可是不会的同窗就没办法了,我本身一台大陆一台海外,大陆的装不了就改海外服务器了。
还有一个方案,也是官方给出的:
git clone https://github.com/GoogleChrome/rendertron.git cd rendertron npm install npm run build
运行:
npm run start
能用第一种安装方案的推荐用第一种。
在你的express服务器程序中引入中间件rendertron-middleware
进入项目目录,命令行输入并回车
npm install --save express rendertron-middleware
在你的express服务器程序的代码中加入几行:
const express = require('express');const rendertron = require('rendertron-middleware'); const app = express(); app.use(rendertron.makeMiddleware({ proxyUrl: 'http://localhost:3000/render',})); app.use(express.static('files'));app.listen(8080);
重点是插入的
app.use(rendertron.makeMiddleware({ proxyUrl: 'http://localhost:3000/render',}));
其中rendertron.makeMiddleware有好几个参数,github上说有
proxyUrl、userAgentPattern、excludeUrlPattern、injectShadyDom、timeout,也就是有相似如下的设置。 app.use(rendertron.makeMiddleware({ proxyUrl: 'http://localhost:3000/render', userAgentPattern:****, excludeUrlPattern:****, injectShadyDom:true or false, //这个参数通常不用设,用的时候这行删掉就行了 timeout:11000,//这个timeout超时参数亲测已经无效了,尴尬,用的时候也去掉这行就好}));
下面重点讲讲以上的userAgentPattern和excludeUrlPattern参数的含义和怎么设置。
userAgentPattern是用来写清楚哪些UA头须要服务器渲染,除此以外的请求都直接单页面推送。好比说:
const botUserAgents = [ 'Baiduspider', 'bingbot', 'Embedly', 'facebookexternalhit', 'LinkedInBot', 'outbrain', 'pinterest', 'quora link preview', 'rogerbot', 'showyoubot', 'Slackbot', 'TelegramBot', 'Twitterbot', 'vkShare', 'W3C_Validator', 'WhatsApp',];//略n行代码app.use(rendertron.makeMiddleware({ //其余参数 userAgentPattern: new RegExp(botUserAgents.join('|'), 'i'),}));
把你要的爬虫UA头都写到一个数组里,而后用new RegExp()正则一下
excludeUrlPattern是指哪些文件格式须要在chromeheadless中被彻底加载,用法以下
const staticFileExtensions = [ 'ai', 'avi', 'css', 'dat', 'dmg', 'doc', 'doc', 'exe', 'flv', 'gif', 'ico', 'iso', 'jpeg', 'jpg', 'js', 'less', 'm4a', 'm4v', 'mov', 'mp3', 'mp4', 'mpeg', 'mpg', 'pdf', 'png', 'ppt', 'psd', 'rar', 'rss', 'svg', 'swf', 'tif', 'torrent', 'ttf', 'txt', 'wav', 'wmv', 'woff', 'xls', 'xml', 'zip',];//略n行代码app.use(rendertron.makeMiddleware({ //其余参数 userAgentPattern: new RegExp(`\\.(${staticFileExtensions.join('|')})$`, 'i'),}));
把你须要加载的文件后缀都写到一个数组里,而后用new RegExp()正则一下
至于proxyUrl
参数的用法,若是rendertron+chromeheadless在本地服务器,那就写'http://localhost:3000/render'
(rendertron启动后默认开启3000端口),若是是在别的服务器,那就写http://www.xxxx.com/render或...://106.xx.xx.xxx:xxxx/render。
proxyUrl
参数设置的就是遇到爬虫UA头后、转到rendertron用本地服务器上的chromeheadless浏览器渲染的地址。
好了,express服务器改写好后,正常启动他,而后再启动rendertron,方法也很简单,直接命令行输入rendertron
就好了。
下面测试一下,命令行输入curl -A “baiduspider” http://你须要测试的网址(就是访问你的server程序对应的那个网址,即改写前的那个原来的网址)
,而后就能看到经过chromeheadless渲染好的html代码,大功告成!
rendertron的改进
有没有发现你每次curl之后都须要10s左右后才能返回数据,这种响应时间怎么可能用在SEO上呢??!!因此要改进一下咯。
在rendertron的github上有写到,能够在rendertron的根目录写一个config.json
,里面能够设置datastoreCache(是否适用缓存,默认false),timeout(渲染超时,过了这个时间尚未渲染结束就硬性返回已渲染好的html,默认10000ms,即10s),port(端口,默认3000),width和height(渲染用的浏览器屏幕宽高,默认1000,这个在rendertron的另外一个功能‘截图’上能够用到)。
而后你很天真的设置了config.json文件,把timeout改为3000ms——这差很少已是搜索引擎认为你是优质网站所要求的响应时间的上限了。再一次curl,什么!!仍是10s!!这个怎么搞哦!!
又一次大写的尴尬!下面来公布答案吧~rendertron的码源里面已经没有引用config.json里面的timeout参数了,这个参数无法经过外部设置,呵呵哒,坑。
好了,下面说解决方法。找到rendertron
根目录,里面有个build
文件夹,里面有个renderer.js
文件,打开后,搜索timeout,一共有两处,后面都跟了10000这个值,把它改为你须要的2000或者之类的(单位ms),而后再次从新启动rendertron,在命令行输入
curl -A “baiduspider” http://你须要测试的网址(就是访问你的server程序对应的那个网址,即改写前的那个原来的网址)
能够发现只须要2s就有html代码返回了,搞定!
注:以上问题是针对
npm install -g rendertron
方式安装的rendertron,其余方式安装后是否有以上问题不必定。
若是你的渲染程序会崩,那就pm2 start rendertron
。pm2真的挺好用,不熟悉的同窗百度下就行了,满满的资料。