• puppeteer实现线上服务器任意区域截图


    整个九月份由于业务繁重以及玩心颇重,一直没有机会来写一篇博文。而且笔者于十月一日将会举办人生大事--婚礼,现在家里筹办过程中只能抽出零碎的时间来写这篇文章。

    关于服务端截图,这种使用场景非常少见,大多服务器不同于PC机器并不提供相关图形界面以及图形库,所以对不同的系统的不同版本的服务器需要安装不同的共享库。同时,截图依赖的浏览器服务也存在很多兼容性问题,好在google提供了puppeteer模块依赖于webkit内核,这与大多数业务场景的渲染引擎一致,因此我们可大致忽略引擎渲染的差异(大多数差异在于引擎版本、画图库与字体库导致)。

    页面截图与元素块截图

    puppeteer是nodejs社区中的提供API操作Chromium的npm模块,具体的安装方式可参考官方文档

    进行页面截图:

    const puppeteer = require('puppeteer');
    
    (async () => {
      const browser = await puppeteer.launch();
      const page = await browser.newPage();
      await page.goto('https://example.com',{
                waitUntil: 'networkidle2'
            });
      await page.screenshot({path: 'example.png'});
    
      await browser.close();
    })();
    

    puppeteer自带全局截图,文档中也提供了相关示例。

    可大多数场景是针对页面的某个DOM元素区域进行局部截图,这就需要依赖puppeteer提供的在当前页面执行js的功能,通过定位DOM元素计算该元素的位置和盒子模型的信息,计算出DOM元素的坐标值,进行裁剪。

    局部截图

    通过evaluate接口在页面上下文执行js:

    async  screenshotDOMElement(page, selector, path, padding = 0) {
        const rect = await page.evaluate(selector => {
            try{
                const element = document.querySelector(selector);
                const {x, y, width, height} = element.getBoundingClientRect();
                if(width * height != 0){
                    return {left: x, top: y, width, height, id: element.id};
                }else{
                    return null;
                }
            }catch(e){
                return null;
            }
        }, selector);
        
        return await page.screenshot({
            path: path,
            clip: rect ? {
            x: rect.left - padding,
            y: rect.top - padding,
             rect.width + padding * 2,
            height: rect.height + padding * 2
            } : null
        });
    }
    
    let puppeteer = require('puppeteer');
    const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']});
    const page = await browser.newPage();
    page.setViewport({ 1580, height: 1024, deviceScaleFactor: 2});
    // 使用管理员的cookie
    var cookie = {
        name: "vdian-fe-l-u",
        value: "eyJpZCI6InlhbmdIm5hbWUiOiLmnajldsafds",
        domain: ip.trim(),
        path: "/",
        expires: Date.now() + 3600 * 1000
    };
    await page.setCookie(cookie); // 设置cookie
    await page.goto(pageUrl, {
        waitUntil: 'networkidle2'
    });
    await screenshotDOMElement(page,"[data-share-wrapper]",savedPath);
    await browser.close();
    

    服务器依赖配置

    目前社区内部对于Centos6的系统没有提供相关依赖解决方案,笔者也针对Centos6做了1天的尝试,确实无法正常运行,主要是缺少了几个共享库导致,并且无法在Centos6上正确安装。

    因此下文的依赖安装仅仅针对 Centos7 系统而言:

    #依赖库
    yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 nss.x86_64 -y
    
    #字体
    yum install ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc -y
    

    同时,在机器中安装puppeteer执行如下命令:

    npm install puppeteer --unsafe-perm=true
    

    设置unsafe-perm为true,则是为了避免npm在执行puppeteer包的脚本的时候随意切换UID/GID,如果使用默认的unsafe-perm=false,则会以非root身份安装puppeteer导致出错。

    中文编码乱码问题

    • 服务器安装中文字体,关于中文字体安装,请参考 给CentOS安装中文字体
    • 页面编码为“utf-8”,即<meta charset="utf-8" />
  • 相关阅读:
    MVC入门学习笔记(五)
    IIS搭配Serveru构建企业空间服务(一)
    HTMLTextBox基于WebBrowser的HTML编辑控件
    MVC入门学习笔记(一)
    MVC入门学习笔记(七)
    MVC入门学习笔记(十)
    关注以下.NET技术
    Notification状态栏通知
    Activity设置横屏显示
    通过xml文件与代码去除通知栏和标题全屏显示
  • 原文地址:https://www.cnblogs.com/accordion/p/9716817.html
Copyright © 2020-2023  润新知