针对SPA网站的SEO方式探索-2
nano71.com
2024/4/25 18:07:59
0 comments
61 views
前言
针对SPA网站,本文将使用Nginx+Express+Puppeteer实现一个高效的SEO工具,大致的实现思路为:Nginx判断UA再进行代理转发,Express负责监听转发的请求,Puppeteer接到Express命令后启动一个无用户界面的Chrome对目标页面进行访问,等待目标SPA页面加载完成后,再返回完整的HTML给爬虫
配置Nginx
使用map指令配合正则匹配多种爬虫UA,下面的正则覆盖了Google和Bing的爬虫,以及其它的HTTP客户端请求
map $http_user_agent $bot {
default 0;
"~*Wget|PowerShell|bingbot|Googlebot|Googlebot-Image|Googlebot-Mobile|Googlebot-News|Googlebot-Video|Google-InspectionTool|Headless|python|curl|java|wget|httpclient|okhttp" 1;
}
location块内判断是否为爬虫访问,为爬虫访问则代理转发
if ($bot) {
proxy_pass http://localhost:9001;
}
配置完成记得重新加载Nginx配置文件,将刚才的修改生效
nginx -s reload
配置Express路由
实例化和启动之类的代码就不贴了哈,直接使用get("*")处理所有的代理转发
app.get('*', async (request, response) => {
const userAgent = request.useragent;
const url = request.url
// 一般的SPA路由都不包括后缀,这里的判断排除各种资源文件的url
if (!url.includes(".")) {
let html = await fetchHTML(url, userAgent) // 该函数在后面会提到
response.contentType("text/html")
response.send(html)
closeBrowser()
} else {
response.status(400).send("Bad Request")
}
});
值得一提的是,防止爬虫爬取资源文件从而浪费性能,我们可以使用express-robots-txt库来模拟生成一个robots.txt文件
app.use(robots([
{
UserAgent: "*",
Disallow: ["/*.css$", "/*.js$", "/*.gif$"], // 根据自己的网站按需修改
Sitemap: []
}
]));
app.use(useragent.express())
编写Puppeteer任务
对于Puppeteer这个库的用法我就不在本文中概述了,有兴趣去Puppeteer官网看看各种功能的具体用法
async function fetchHTML(url, ua) {
// 如果browser在后台有运行,则重新连接上,否则创建新的实例
if (browserWSEndpoint) {
browser = await puppeteer.connect({
browserWSEndpoint
})
} else {
browser = await puppeteer.launch({
headless: true // 无头模式
});
browserWSEndpoint = browser.wsEndpoint()
}
const page = await browser.newPage();
await page.setRequestInterception(true);
await page.setUserAgent(ua)
page.setDefaultTimeout(60000)
page.on('request', (request) => {
const path = new URL(request.url()).pathname;
// 加快页面加载速度,拦截掉无用的静态资源请求,如图像和字体等
if (path.includes(".") && !path.endsWith(".js")) {
request.abort();
} else {
request.continue();
}
});
// 记得定义targetHost变量,就是你SPA网站的host
await page.goto(targetHost + url, {
waitUntil: 'networkidle0' // networkidle0是等待页面加载完成
});
let html = await page.content(); // 获取当前页面的HTML文本
await page.close()
return html
}
考虑到频繁的browser启动和关闭会有一定的延迟,以及一直保持browser活跃会占用一定的内存,我们可以对其进行一点点优化:如果页面只剩下默认的空白页,则5秒后关闭browser,防止占用内存
function closeBrowser() {
clearTimeout(timer)
timer = setTimeout(async () => {
if ((await browser.pages()).length === 1) {
browserWSEndpoint = undefined
await browser.close();
}
}, 5000)
}
以上就是一个对SPA的SEO工具实现思路,完整的实现代码已在GitHub中共享:仓库地址,有需要的可以去看看😀
nano71.com
2024/4/25 18:07:59
0 comments
61 views





