puppeteer實現線上服務器任意區域截圖

整個九月份因爲業務繁重以及玩心頗重,一直沒有機會來寫一篇博文。並且筆者於十月一日將會舉辦人生大事--婚禮,如今家裏籌辦過程當中只能抽出零碎的時間來寫這篇文章。node

關於服務端截圖,這種使用場景很是少見,大多服務器不一樣於PC機器並不提供相關圖形界面以及圖形庫,因此對不一樣的系統的不一樣版本的服務器須要安裝不一樣的共享庫。同時,截圖依賴的瀏覽器服務也存在不少兼容性問題,好在google提供了puppeteer模塊依賴於webkit內核,這與大多數業務場景的渲染引擎一致,所以咱們可大體忽略引擎渲染的差別(大多數差別在於引擎版本、畫圖庫與字體庫致使)。git

頁面截圖與元素塊截圖

puppeteer是nodejs社區中的提供API操做Chromium的npm模塊,具體的安裝方式可參考官方文檔github

進行頁面截圖:web

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自帶全局截圖,文檔中也提供了相關示例。npm

可大多數場景是針對頁面的某個DOM元素區域進行局部截圖,這就須要依賴puppeteer提供的在當前頁面執行js的功能,經過定位DOM元素計算該元素的位置和盒子模型的信息,計算出DOM元素的座標值,進行裁剪。centos

局部截圖

經過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,
        width: 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({width: 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 系統而言:cookie

#依賴庫
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執行以下命令:app

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" />
相關文章
相關標籤/搜索