vue3使用puppeteer做SEO(二)-部署puppeteer脚本和配置nginx

作者
2024-09-18阅读 1091

参考文章: https://blog.csdn.net/wuyuanshun/article/details/127737603

1、创建文件夹mysite

mkdir /app/puppeteer/project/mysite
cd /app/puppeteer/project/mysite

2、puppeteer-pool.js 性能优化,去除不必要的功能,提高性能。

const puppeteer = require('/app/puppeteer/core/node_modules/puppeteer');//由于目录不一致,所以使用的是绝对路径
const MAX_WSE = 2; //启动几个浏览器 
let WSE_LIST = []; //存储browserWSEndpoint列表
//负载均衡
(async () => {
	for (var i = 0; i < MAX_WSE; i++) {
		const browser = await puppeteer.launch({
            //无头模式
			headless: true,
            //参数
			args: [
				'--disable-gpu',
				'--disable-dev-shm-usage',
				'--disable-setuid-sandbox',
				'--no-first-run',
				'--no-sandbox',
				'--no-zygote',
				'--single-process'
			]
		});
		browserWSEndpoint = await browser.wsEndpoint();
		WSE_LIST.push(browserWSEndpoint);
	}
})();

module.exports = WSE_LIST

3、spider.js渲染请求的页面

const puppeteer = require('/app/puppeteer/core/node_modules/puppeteer');//由于目录不一致,所以使用的是绝对路径
const WSE_LIST = require('./puppeteer-pool.js') //这里注意文件的路径和文件名
const spider = async (url) => {
	
	let tmp = Math.floor(Math.random() * WSE_LIST.length);
	//随机获取浏览器
	let browserWSEndpoint = WSE_LIST[tmp];
	//连接
	const browser = await puppeteer.connect({
		browserWSEndpoint
	});
	//打开一个标签页
	var page = await browser.newPage();
	//打开网页
	await page.goto(url, {
		timeout: 0, //连接超时时间,单位ms
		waitUntil: 'networkidle0' //网络空闲说明已加载完毕
	})
	//获取渲染好的页面源码。不建议使用await page.content();获取页面,因为在我测试中发现,页面还没有完全加载。就获取到了。页面源码不完整。也就是动态路由没有加载。vue路由也配置了history模式
	var html = await page.evaluate(() => {
		return document.getElementsByTagName('html')[0].outerHTML;
	});

	await page.close();

	return html;
}

module.exports = spider;

4、server.js,通过express 开启一个服务器。接受转发的请求

首先需要安装express。这里我是回到了/app/puppeteer/core这个目录。

这里由于下载速度问题,我还是用的cnpm

cd /app/puppeteer/core
cnpm install express --save
cnpm install html-minifier --save

null

然后是server.js的代码

const express = require('/app/puppeteer/core/node_modules/express');//由于目录不一致,所以使用的是绝对路径
var app = express();
var spider = require("./spider.js")
var minify = require('/app/puppeteer/core/node_modules/html-minifier').minify;//由于目录不一致,所以使用的是绝对路径
app.get('*', async (req, res, next) => {
	// 部署到服务器的完整URL
	 var url = req.protocol + '://'+ req.hostname + req.originalUrl;
	console.log('请求的完整URL:' + url);
	var content = await spider(url).catch((error) => {
		console.log(error);
		res.send('获取html内容失败');
		return;
	});
    //由于是直接获取的源码,下面通过minify库压缩代码,也不知道是不是多余的。
	content=minify(content,{removeComments: true,collapseWhitespace: true,minifyJS:true, minifyCSS:true});
	res.send(content);
});
//监听4000端口
app.listen(4000, () => {
	console.log('预渲染服务已启动!');
});


尝试启动

node server.js

null

这样表示服务启动成功了。

这里用的端口号是4000(可以根据自己的服务器情况更换端口号)。后续nginx的时候要用到

5、接下来开始配置nginx

整体的部署说明一下

(1)用的域名,端口是80。

(2)因为是vue的应用,所以location /中配置了alias来访问前端

(3)而我们的这个也是要监听所有的应用,也就是也要放在location /中

整体的访问结构图

简单说明:

一个请求过来,首先是判断是否是爬虫,如果是爬虫的话,就将其抓到puppeteer上,然后puppeteer会根据url抓取到最终的完整页面返给爬虫,从而达到我们SEO的目的。如果不是爬虫,则直接访问前端即可,这样的场景就是普通的请求,直接放行即可(不需要再经过puppeteer了,因为这样其实是慢的)。

null

附上我的nginx的配置。

location / {
    #爬虫的转发配置 start
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    if ($http_user_agent ~* "Sogou Pic Spider|Baiduspider|Baiduspider-render|YisouSpider|Sogou web spider|Bytespider|360Spider|Googlebot|YodaoBot") {
        proxy_pass http://localhost:4000;
    }
    #爬虫的转发配置 end
    #vue前端的文件夹 start
    alias /app/mysite-front/dist/;
    gzip_static on; #查找静态文件
    #vue前端的文件夹 end
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
}

6、做了个启动脚本文件

文件名:startup.sh

内容:

nohup node /app/puppeteer/project/mysite/server.js &

7、启动

/app/puppeteer/project/mysite/startup.sh

8、测试

我用postman测试的

header中的user-agent设置成:Baiduspider

然后看返回值即可,如果是比较完成的页面,则表示没问题了

null



全部评论