适用场景
- 已经用vue,完成了项目开发,但想增强SEO能力的场景
使用约束
- 该方案仅适用于针对特定爬虫程序的SEO增强。
- 因为是基于puppeteer,而puppeteer实际内部使用的是Chromium,所以,资源占用会比较多,要注意防止,被大规模访问时的相关问题
vue项目为什么seo能力不行?
因为vue项目所有用户看到的界面元素都是在浏览器渲染之后才有的。而爬虫程序,如果只是对网页源码进行收录,那将毫无意义,因为没有通过浏览器渲染的html源码,毫无价值。
原理
简单测试下puppeteer
import puppeteer from "puppeteer";
(async () => {
// 禁止发出请求的资源类型
const disabled_resource_type_arr = [
"stylesheet",
"image",
"font",
"fetch",
"media",
];
const browser = await puppeteer.launch({
args: [
"--disable-gpu",
"--disable-dev-shm-usage",
"--disable-setuid-sandbox",
"--no-first-run",
"--no-sandbox",
"--no-zygote",
"--single-process",
"--blink-settings=imagesEnabled=false",
],
});
const page = await browser.newPage();
// 这里是将web控制台的信息打印到终端(可用于调试)
// page.on("console", (msg) => console.log("PAGE LOG:", msg.text));
// 启用拦截器,仅加载html和js即可
await page.setRequestInterception(true);
page.on("request", (interceptedRequest) => {
// console.log(
// interceptedRequest.resourceType(),
// interceptedRequest.isInterceptResolutionHandled(),
// interceptedRequest.url()
// );
if (interceptedRequest.isInterceptResolutionHandled()) return;
// 禁止所有:图片/css/字体/视频/音频的加载
if (
disabled_resource_type_arr.indexOf(interceptedRequest.resourceType()) >= 0
)
interceptedRequest.abort();
else interceptedRequest.continue();
});
// 从浏览器查看源码对比这里获取到的html内容,看看有什么区别
await page.goto("https://free_pan.gitee.io/archetype-backend-template", {
// 关于 waitUtil 官方说明: https://pptr.nodejs.cn/api/puppeteer.puppeteerlifecycleevent
// 等到页内网络请求少于等于2个,且至少持续500ms时,则认为页面加载完毕
waitUtil: "networkidle2",
});
// 生成网页截图,可用于判断拦截器是否生效效果
await page.screenshot({ path: "screenshot-12138.png", fullPage: false });
// 获取网页的完整html字符串
const htmlContent = await page.content();
// console.log(htmlContent);
await browser.close();
})();
完整puppeteer服务代码
free pan/puppeteer-seo-service (gitee.com)
nginx配置
有了puppeteer服务之后,还需要nginx协助,所有请求在经过nginx时, nginx判断该请求是否爬虫发出的请求,如果是,则转发到puppeteer服务, 否则,按正常方式处理
以下配置方式任选一种即可,作用是通过UserAgent判断,当前请求是否为爬虫程序发出
配置方式一
location / {
proxy_set_header Host $host:$proxy_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if ($http_user_agent ~* "Baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator|bingbot|Sosospider|Sogou Pic Spider|Googlebot|360Spider") {
# 当浏览器的 UserAgent 包含如上的部分内容时,则认为是爬虫程序,因此将请求转发给`puppeteer`服务
proxy_pass http://192.168.1.111:3000;
}
# 非爬虫程序,走正常方式
alias /usr/share/nginx/html/;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
配置方式二
http {
map $http_user_agent $is_bot {
default 0;
~*bot 1;
~*spider 1;
~*crawl 1;
~*Googlebot 1;
}
server {
listen 80;
server_name your-domain.com;
location / {
if ($is_bot) {
proxy_pass http://127.0.0.1:4000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
try_files $uri $uri/ /index.html;
}
}
}
配置方式三
server {
listen 80;
server_name localhost;
location / {
root /usr/local/etc/nginx/html;
index index.html index.htm;
set $prerender 0;
if ($http_user_agent ~* "googlebot|bingbot|yandex|baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest/0.|pinterestbot|slackbot|vkShare|W3C_Validator") {
set $prerender 1;
}
if ($args ~ "_escaped_fragment_") {
set $prerender 1;
}
if ($http_user_agent ~ "Prerender") {
set $prerender 0;
}
if ($uri ~* ".(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff|svg|eot)") {
set $prerender 0;
}
if ($prerender = 1) {
set $prerender "0.0.0.0:10001";
rewrite .* /$scheme://$host$request_uri? break;
proxy_pass http://$prerender;
}
}
}
配置完成之后,记得先测试是否配置正确nginx -t, 配置正确之后,再重启 nginx -s reload
给了爬虫不同的页面,会不会被认为是网页作弊行为呢?
google认为,只要与原始网页差异不大,就不算作弊
动态渲染作为解决方法 |Google 搜索中心 |文档 |面向开发者的 Google
Google Web Search 的垃圾邮件政策 |Google 搜索中心 |文档 |面向开发者的 Google
参考资料
SPA 的 SEO 方案对比、最终实践 - 掘金 (juejin.cn)
Vue3+Vite使用Puppeteer进行SEO优化(SSR+Meta)_vue3怎么解决seo引擎-CSDN博客
巧用Puppeteer解决SEO问题 - 掘金 (juejin.cn)
puppeteer调试方法 - 掘金 (juejin.cn)
Prerender(JavaScript 网站静态化) - 知乎 (zhihu.com)
Vue3+Vite使用Puppeteer进行SEO优化(SSR+Meta)_vue3怎么解决seo引擎-CSDN博客
Puppeteer 截图及相关问题 - 刘哇勇 - 博客园 (cnblogs.com)
Gitee 极速下载/prerender - 码云 - 开源中国
Centos7 yum安装Chrome浏览器 - ianduin - 博客园 (cnblogs.com)
javascript - 在node中import from引入的文件要跟.js后缀,但是webapck不用? - SegmentFault 思否
巧用Puppeteer解决SEO问题 - 掘金 (juejin.cn)