Article details

针对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
Welcome to myBlog-site
Recent
Category
Guestbook
2026/3/10 16:11:31

解决 Dify 数据库插件连接 SQL Server 2008/2012 报错 DB-Lib error message 20002, severity 9

(pymssql.exceptions.OperationalError) (20002, b'DB-Lib error message 20002, severity 9:\nAdaptive Server connection failed (192.168.0.223)\nDB-Lib error message 20002, severity 9:\nAdaptive Server connection failed (192.168.0.223)\n') (Background on this error at: https://sqlalche.me/e/20/e3q8)

view
coverImage
2025/8/21 15:53:02

代码还原 Pinia 官网上的那个可以互动的小菠萝

眨眼 眼球跟随鼠标 一定时间鼠标不移动眼球归位

view
coverImage
2025/5/20 13:58:34

JDBC速成

JDBC(Java Database Connectivity)是 Java 官方提供的一套 API,集成在 java.sql 和 javax.sql 包中 JDBC 允许 Java 程序连接和操作各种关系型数据库,如 MySQL、Oracle、PostgreSQL、SQL Server 等

view
coverImage
2024/11/25 13:34:21

Node.js实现一个数据缓存服务器

需求场景 公司的数据服务器每次更新部署时,会有一个服务不可用的时间以及服务重新启动的时间,但如果恰巧这段时间有用户进行访问。。。当然,这只适应于非即时性的数据

view
coverImage
2024/7/18 19:30:34

Go的高并发实现:多协程和任务队列设计

前言 随着大学生活的结束,我入职了浙江的一家属于电气制造业的公司,岗位是数据分析,我算是暂时脱离了互联网这一行业,以后可能就很少接触Web开发了;把曾经对Web电子邮件系统中的性能优化的一部分抽出来记录下,也算在表达我对Web后端开发的一种敬意了

view
coverImage
2024/4/25 18:07:59

针对SPA网站的SEO方式探索-2

前言 针对SPA网站,本文将使用Nginx+Express+Puppeteer实现一个高效的SEO工具,大致的实现思路为:Nginx判断UA再进行代理转发,Express负责监听转发的请求,Puppeteer接到Express命令后启动一个无用户界面的Chrome对目标页面进行访问,等待目标SPA页面加载完成后,再返回完整的HTML给爬虫

view
coverImage
loading-GIF