puppeteer實現線上伺服器任意區域截圖
整個九月份由於業務繁重以及玩心頗重,一直沒有機會來寫一篇博文。而且筆者於十月一日將會舉辦人生大事--婚禮,現在家裡籌辦過程中只能抽出零碎的時間來寫這篇文章。
關於服務端截圖,這種使用場景非常少見,大多伺服器不同於PC機器並不提供相關圖形介面以及圖形庫,所以對不同的系統的不同版本的伺服器需要安裝不同的共享庫。同時,截圖依賴的瀏覽器服務也存在很多相容性問題,好在google提供了puppeteer模組依賴於webkit核心,這與大多數業務場景的渲染引擎一致,因此我們可大致忽略引擎渲染的差異(大多數差異在於引擎版本、畫相簿與字型庫導致)。
頁面截圖與元素塊截圖
puppeteer是nodejs社群中的提供API操作Chromium的npm模組,具體的安裝方式可參考Chrome/puppeteer" rel="nofollow,noindex" target="_blank">官方文件 。
進行頁面截圖:
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:
asyncscreenshotDOMElement(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 系統而言:
#依賴庫 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”,即