利用NODEJS+Puppeteer實現服務器保存網頁爲圖片和PDF

本文適用於對docker,node有必定了解的童鞋node

Puppeteer簡介

今年5月在github上建立的項目,屬於比較新的chromium無頭瀏覽器類庫。git

Puppeteer在項目中的實際使用

基礎安裝

選用Puppeteer的主要緣由有兩點,github

  • 1:GOOGLE官方維護,活躍度很高,我的以爲前途光明。
  • 2:咱們的產品在chrome上適配最好。目前最新版本是0.13.0,咱們採用0.12.0版本,因0.13.0版本API作了一些變化沒法知足咱們的需求。咱們截圖時有以下兩個必須解決的場景
    • 網站須要等待當前儀表盤全部查詢都完成才能夠進行截圖操做
    • 咱們並不知道全部儀表盤發起的查詢會查詢多久結束

npm安裝puppeteer時會從google一個網站上下載chromium,由於牆的緣由會下載失敗。咱們採用的方式先設置環境變量chrome

set PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
複製代碼

阻止install的時候自動下載,而後手工下載chromium後經過docker build打包成一個基礎鏡像。咱們在Dockerfile中From此鏡像,而後再作後續操做。docker

npm instal puppeteer@0.12.0 --save
複製代碼

如今可經過docker很快速的進行打包。最終打包後的image裏/usr/src/node/包含node代碼及chromium目錄npm

基本操做

調用puppeteer

咱們手動指定chromium目錄來運行。api

const browser = await puppteer.launch({
        args: ['--no-sandbox', '--disable-setuid-sandbox'],  // docker中運行須要加上這兩個args
        executablePath: 'chromium/chrome', // 基礎鏡像已將chromium複製到/usr/src/node/chromium目錄下
   });
複製代碼

保存圖片

經過URL打開網站瀏覽器

await page.goto(fullUrl, {
       waitUntil: 'networkidle',
       networkIdleTimeout: 15000,
       timeout: 240000
   });
複製代碼

networkIdleTimeout: 15000參數表明當前頁面網絡處於idle狀態至少15秒時導航完畢,避免導出的截圖數據不全。
若是直接保存整個頁面爲圖片或PDF是很簡單的,有現成的API直接調用。但此次咱們只將某一區域保存爲圖片,網絡

let rect = await page.evaluate(() => {
        const element = document.querySelector(
            '.class1'
        );  // 選擇包含指定class屬性的dom節點
        const { x, y, width, height } = element.getBoundingClientRect();
        return {
            left: x,
            top: y,
            width,
            height,
        };
    });
    await page.screenshot({
        path: imagePath,
        clip: {
            x: rect.x,
            y: rect.y,
            width: actualWidth,
            height: actualHeight
        }
    });
複製代碼

能夠在page.evaluate中操做頁面元素,因此能夠獲取指定區域的長寬等信息。這樣咱們只需截取那一區域便可。完整的API地址仍是請參閱github官方API文檔dom

保存PDF

如上節所說,若是保存整個頁面爲PDF很簡單,由於咱們只保存某一區域,然而保存pdf的API中沒有相似page.screenshot中clip參數,個人處理方式就是將上一步保存的圖片轉爲PDF便可。轉換方式不少,我採用pdfkit類庫實現。代碼就不贅述,能夠參考不少DEMO。

總結

由於咱們經過docker+CICD+devops打包部署node服務,puppeteer在docker中也有一些坑,好在官方給出了一系列解決方案。我在實際使用中仍是偶爾發生頁面加載失敗的狀況,指望在將來版本會變得更增強大和穩定。

相關文章
相關標籤/搜索