最近公司需要对网页进行seo优化,奈何项目为vue的spa应用,没那么方便改造,所以记录一下优化经历

一、非SSR项目进行seo优化有以下五种方案:

  1. ssr服务端渲染:项目所使用的的微前端框架需要使用window对象,无法实现

  2. 使用puppeteer,slimerjs搭建nodejs服务,通过nginx判断请求头是否为爬虫,是则指向通过puppeteer拉取html并返回html的地址,否则指向正常页面
    在这里插入图片描述

  3. 通过php或jsp开发简易网站,只包含需要进行seo优化的内容的,通过nginx判断请求头是否为爬虫,是则指向seo页面,否则指向正常页面

  4. 预渲染,只能生成静态文件,对于有动态加载数据的页面不支持,不采用

  5. nuxt,和ssr方案一样,不适合
    所以将采用puppeteer这种方案

二、文件编写

ssr文件:

const puppeteer = require('puppeteer');
const Cacheman = require('cacheman');
const md5 = require('md5');
let browserWSEndpoint = null;
const FilecCache = new Cacheman('htmls', {
  // 缓存3个小时
  ttl: 60 * 60 * 3,
  engine: 'file',
});

async function ssr (url) {
  let browser = null;
  let urlMd5 = md5(url);
  // 是否命中缓存
  var hitByCache = await FilecCache.get(urlMd5);
  if (hitByCache) {
    console.log(hitByCache)
    return hitByCache;
  }
  if (browserWSEndpoint) {
    try {
      browser = await puppeteer.connect({browserWSEndpoint});
    } catch (e) {
      browserWSEndpoint = null;
      browser = null;
    }
  }
  if (!browserWSEndpoint) {
    browser = await puppeteer.launch({
      headless: true,
      ignoreHTTPSErrors: true,
      args: [
        // Required for Docker version of Puppeteer
        '--no-sandbox',
        '--disable-setuid-sandbox',
      ]
    });
    browserWSEndpoint = await browser.wsEndpoint();
  }
  const start = Date.now();
  const page = await browser.newPage();
  // 1. 监听网络请求
  await page.setRequestInterception(true);
  page.on('request', req => {
    // 2. 忽略不必要的请求,如图片,视频样式等等
    const whitelist = ['document', 'script', 'xhr', 'fetch'];
    if (!whitelist.includes(req.resourceType())) {
      return req.abort();
    }

    // 3. 其它请求正常继续
    req.continue();
  });
  try {
    // networkidle0 等待直到500ms内没有请求了
    await page.goto(url, {waitUntil: 'networkidle0'});
  } catch (err) {
    console.error(err);
    throw new Error('page.goto/waitForSelector timed out.');
  }

  const html = await page.content(); // 获取HTML结构
  // 写入缓存
  await FilecCache.set(urlMd5, html.results);
  await browser.close();

  const ttRenderMs = Date.now() - start;
  console.info(`Headless rendered page in: ${ttRenderMs}ms`);
  return {html, ttRenderMs};
}

module.exports = {ssr}

server.js文件:

var express = require('express');
var {createProxyMiddleware} = require('http-proxy-middleware');
var app = express();
var server = require('http').createServer(app);
var history = require('connect-history-api-fallback');
var {ssr} = require('./ssr.js');
var listenPort = 3000;
// const proxy = {
//     '/static/assets': {
//         target: 'https://www.ccyunchina.com',
//         changeOrigin: true
//     },
// };
//
// for (let key in proxy) {
//     app.use(key, createProxyMiddleware(proxy[key]));
// }
const staticFileMiddleware = express.static('dist');
app.use(function (req, res, next) {
    var UA = req.headers['user-agent'];
    var isStaticDir = false;
    // 判断是否是爬虫, 排除资源目录的请求
    if (UA && !isStaticDir) {
        // 生成本地访问链接
        var requestUrl = req.protocol + '://' + req.hostname + req.originalUrl;
        (async () => {
            try {
                var results = await ssr(requestUrl);
                res.send(results.html);
            } catch (e) {
                console.log('ssr failed', e);
                res.status(500).send('Server error');
            }
        })();
        return;
    }
    next();
});


// 先
app.use(staticFileMiddleware);

// 如果资源没命中会继续、经过history rewirte后
app.use(history({
    disableDotRule: true,
    verbose: true
}));

// 再次处理
app.use(staticFileMiddleware);
server.listen(listenPort, function () {
    console.log('Spider app listening on port 3000!');
});

三、arm环境中nodejs环境搭建

  1. uname -a查看服务器是否是64位的
  2. 64位的安装v8版本,32位的安装v7版本
    在这里插入图片描述
    wget https://npm.taobao.org/mirrors/node/v14.9.0/node-v14.9.0-linux-arm64.tar.xz
  3. 下载下来后运行xz -d /usr/local/node-v14.10.0-linux-arm64.xztar -xvf /usr/local/node-v14.10.0-linux-arm64.tar进行解压和编译
  4. 修改 ~/.bashrc。在文末加入一句 export PATH=/usr/local/node-v14.10.0-linux-arm64/bin:$PATH改变环境变量或网上的文章是用软链接的方式,将bin文件的node、npm加入的原本的环境变量的文件夹里面去
  5. node -v测试一下

四、arm环境下安装谷歌或火狐浏览器

注意puppeteer是使用的谷歌内核,如果要使用火狐内核,需要改用puppeteer-firefox,参考链接

yum -y install firefox火狐安装
谷歌arm64版本可以参考网址下载(https://fedora.pkgs.org/32/fedora-aarch64/chromium-80.0.3987.163-1.fc32.aarch64.rpm.html

五、nginx配置

设置map

map $http_user_agent $is_bot {
  default 0;
  ~*bot 1;
  ~*spider 1;
  'Yahoo! Slurp China' 1;
  'Mediapartners-Google' 1;
  'YisouSpider' 1;
}

修改location

location / {
   error_page 418 =200 @bots;
    if ($is_bot) {
        return 418;
    }
    add_header Cache-Control no-store;
    root dist/;
    index index.html;
    #proxy_pass   http://127.0.0.1:3000;
    try_files $uri $uri/ /index.html;
}
location @bots {
    rewrite ^/(.*) http://$server_name:3000 permanent;
}

这里自己的爬虫服务用nodejs启动的是3000端口

六、用pm2管理nodejs服务

pm2得到使用可以参考这边文章https://www.jianshu.com/p/e15fd72727fe

七、专门针对seo生成网页

可以使用beetle搭建一个简陋的网页,页面只返回需要给爬虫爬取的数据,不需要任何样式或逻辑,通过第五步设置的nginx转发在配置相同的路由即可

Logo

前往低代码交流专区

更多推荐