成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

使用 Puppeteer 導(dǎo)出聲享 PPT

Codeing_ls / 3508人閱讀

摘要:而打印所用的頁面需要用到用戶信息,所以我們登錄了一個超管帳號來執(zhí)行打印操作。在訪問頁面的時候通過參數(shù)校驗判斷是否是打印而打開的頁面,如果是則登錄超管帳號。

現(xiàn)狀

聲享是一個基于 ThinkJS 開發(fā)的在線制作 PPT 平臺。聲享制作的 PPT 支持代碼高亮、圖片上傳、神奇效果等功能,同時你可以在聲享收藏自己喜歡的 PPT 、對自己的 PPT 進(jìn)行分類管理。其中有一個 PDF 導(dǎo)出的功能,可以將自己制作的 PPT 導(dǎo)出成 PDF 保存到本地。

功能實現(xiàn)比較簡單,只是提供了一個頁面,用戶需要手動去打印成 PDF。這個方案存在一些問題:

由于使用了 iframe 懶加載導(dǎo)致未加載的 iframe 無法正常顯示。

該種方案只能打印所有頁面的初始狀態(tài)。如果頁面中存在切換動畫,可能會丟失部分 PPT 信息。

需要用戶手動操作,提高了使用難度。

如果是前端來生成 PDF,這些問題基本可以得到解決,但是開發(fā)量比較大而且存在一個效率問題。如果 PPT 頁面存在多個 iframe,PDF 的生成時間過長會讓用戶長時間等待,明顯不太合適。最終還是決定服務(wù)端來生成 PDF,才有了后來 Puppeteer 的嘗試。

Puppeteer

什么是Puppeteer呢?官方給的解釋是:

Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.

簡而言之,這貨是一個提供高級 API 的 node 庫,能夠通過 devtool 控制 headless 模式的 Chrome 或者 Chromium,它可以在 headless 模式下模擬任何的人為操作。通過它我們可以實現(xiàn):

生成頁面的截圖或者 PDF。

抓取 SPA(單頁應(yīng)用)并生成預(yù)渲染內(nèi)容(即“SSR”(服務(wù)器端渲染))。

自動提交表單,進(jìn)行 UI 測試,鍵盤輸入等。
...

通過 Puppeteer,我們可以直接使用 Chrome 把我們需要的內(nèi)容導(dǎo)出為 PDF。對比以前的實現(xiàn)方式有以下優(yōu)點:

不需要用戶手動操作,服務(wù)端生成 PDF 后直接以郵件的方式發(fā)送給用戶。

PPT 中的動畫可以模擬用戶翻頁的動作觸發(fā),然后以初始、結(jié)束兩張 PDF 的方式展示,不會丟失 PPT 內(nèi)容。

不需要考慮圖片/ iframe 跨域等問題。

可以說 Puppeteer 完美的解決來我們一期 PDF 導(dǎo)出存在的問題。

解決方案

我們基本的實現(xiàn)思路是:

打開一個正常的 PPT 播放頁,獲取需要打印的 DOM 元素并翻頁 。

重復(fù)第一步操作直至到最后一頁 。

清空頁面內(nèi)容并將前兩步獲得的頁面內(nèi)容依次填充到當(dāng)前頁面(為什么要依次填充會在后面解釋)。

對應(yīng)上述方案實現(xiàn)的部分代碼如下:

通過 Puppeteer 打開指定的頁面。

// 測試時建議headless設(shè)置為false,以便可以直觀看到頁面效果
this.browser = await puppeteer.launch({headless: this.isDebug});
this.page = await this.browser.newPage();
await this.page.goto("https://xxxxx.com", { waitUntil:"networkidle2" });

打開頁面后可以通過 Puppeteer 模擬用戶翻頁操作,每次翻頁后緩存需要打印的 DOM 元素字符串。

let canNext;
let i = 0;
const content = {};
do {
    canNext = await this.page.$(".navigate-right.enabled");
    const iframes = await this.page.$$(".PluginPage.present iframe").length;
    content[i++] = {
        iframe: iframes,
        domStr: await this.page.$eval(".RevealViewPort", el => el.outerHTML)
    }
    if (canNext) {
        await this.page.click(".navigate-right");
        // 等待翻頁動畫
        await this.page.waitFor(1000);
    }
} while (canNext);

獲取到要打印的所有頁面 DOM 后,替換掉原來的頁面內(nèi)容。因為 $evaluate 方法中不支持調(diào)用外部變量所以只能以傳參的方式使用。

this.page.evaluate(domStr => document.body.innerHTML = domStr, content);

調(diào)用生成 PDF 的 API。

this.page.pdf({
    path: path.join(think.ROOT_PATH, "runtime/xxx.pdf"),
    format: "A4",
    landscape: true,
    printBackground: true //如果要顯示背景,此屬性要設(shè)置為true
})

使用 nodemailer 發(fā)送郵件給用戶。這一步如果想使用本地的 SMTP 服務(wù)請用 nodemailer 的 2.7.5 的版本,此版本后這項功能被刪除了。

let transporter = nodemailer.createTransport({
    host: "smtp.ym.163.com",
    port: 994,
    secure: true,
    auth: {
        user: "xxx@xxx.com",
        pass: "xxx"
    }
});
transporter.sendMail({
    from: "xxx@xxx.com",
    to: "xxx@xxx.com",,
    subject: "【聲享】xxx",
    attachments: [{
        filename: "xxx.pdf",
        path: path.join(think.ROOT_PATH, "runtime/xxx.pdf"),
        contentType: "application/pdf"
    }]
})
開發(fā)中需要注意的問題

用戶登錄

使用 Puppeteer 打開頁面相當(dāng)于你新啟動了一個瀏覽器實例,頁面中的 seession 和 cookie 是空的。而打印所用的頁面需要用到用戶信息,所以我們登錄了一個超管帳號來執(zhí)行打印操作。在 ThinkJS 中可以通過中間件來實現(xiàn)這項功能。在訪問頁面的時候通過參數(shù)校驗判斷是否是打印而打開的頁面,如果是則登錄超管帳號。

// 打開指定頁面時通過校驗后面參數(shù)判斷是否以超管登錄
module.exports = options => {
    return async (ctx, next) => {
        const { token, ctime } = ctx.query;
        const md5Str = tockenGenerator();
        if (md5Str === token) {
            await ctx.session("userInfo", adminUser);
        }
        return next();
    };
};

Puppeteer 啟動

如果服務(wù)端是運(yùn)行在 root 權(quán)限下,在啟動 Puppeteer 時要添加 --no-sandbox 參數(shù),否則 Chrome/Chromium 會啟動失敗。詳情見 Running as root without — no-sandbox is not supported。這個權(quán)限問題在linux以root用戶使用 Chrome 的時候同樣適用。

this.browser = await puppeteer.launch({args:["--no-sandbox"]});

iframe 無法加載

聲享支持頁面內(nèi)嵌入 iframe,在打印的時候碰到一個問題。如果同時在頁面上插入 iframe 過多,后面的 iframe 會直接卡住不再加載。所以 iframe 最好分批插入或者一個一個插入,同時設(shè)定10秒來加載iframe。 如果想精確控制 iframe 也可以使用 API 等待 iframe 完全加載再執(zhí)行后續(xù)操作。

for (let i = 0; i < pages.length; i++) {
    const page = pages[i];
    await this.page.$evaluate(content => {
        const divDom = document.createElement("div");
        divDom.innerHTML = content;
        document.body.appendChild(divDom.childNodes[0])
    }, page.domStr);
    if (page.iframe) await this.page.waitFor(10000 * page.iframe);
}

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/102645.html

相關(guān)文章

  • Node.js定時導(dǎo)出Highchart圖表

    摘要:一背景需求因為數(shù)據(jù)包含機(jī)密信息,所以得自己搭建圖表導(dǎo)出服務(wù)器在后臺生成對應(yīng)圖表以圖片的形式導(dǎo)出保存。圖表個性化程度較高,如一些圖列是沒有的,但在前端可以利用實現(xiàn)。每周定時執(zhí)行上述生成圖表的任務(wù),保存到指定位置。 一、背景需求 1、因為數(shù)據(jù)包含機(jī)密信息,所以得自己搭建圖表導(dǎo)出服務(wù)器;在后臺生成對應(yīng)Highcharts圖表、以圖片的形式導(dǎo)出保存。2、圖表個性化程度較高,如一些圖列是High...

    miguel.jiang 評論0 收藏0
  • 用純 DOM 的方式結(jié)合 Puppeteer 自動生成網(wǎng)頁骨架屏

    摘要:可以通過的提供的直接控制模擬大部分用戶操作來進(jìn)行或者作為爬蟲訪問頁面來收集數(shù)據(jù)。 ??骨架屏是在頁面數(shù)據(jù)尚未加載完成前先給用戶展示出頁面的大致結(jié)構(gòu),直到請求數(shù)據(jù)返回后再顯示真正的頁面內(nèi)容;隨著單頁應(yīng)用( SPA )的越來越流行,單頁應(yīng)用的用戶體驗也越來越得到前端開發(fā)者的關(guān)注;為了優(yōu)化用戶體驗,在數(shù)據(jù)到達(dá)用戶之前,往往會在頁面上加上 loading 的效果,而現(xiàn)在,越來越多的場景傾向于使...

    BlackHole1 評論0 收藏0
  • 手把手教你如何用Crawlab構(gòu)建技術(shù)文章聚合平臺(一)

    摘要:本文將介紹如何使用和抓取主流的技術(shù)博客文章,然后用搭建一個小型的技術(shù)文章聚合平臺。是谷歌開源的基于和的自動化測試工具,可以很方便的讓程序模擬用戶的操作,對瀏覽器進(jìn)行程序化控制。相對于,是新的開源項目,而且是谷歌開發(fā),可以使用很多新的特性。 背景 說到爬蟲,大多數(shù)程序員想到的是scrapy這樣受人歡迎的框架。scrapy的確不錯,而且有很強(qiáng)大的生態(tài)圈,有g(shù)erapy等優(yōu)秀的可視化界面。但...

    LinkedME2016 評論0 收藏0
  • 手把手教你如何用Crawlab構(gòu)建技術(shù)文章聚合平臺(一)

    摘要:本文將介紹如何使用和抓取主流的技術(shù)博客文章,然后用搭建一個小型的技術(shù)文章聚合平臺。是谷歌開源的基于和的自動化測試工具,可以很方便的讓程序模擬用戶的操作,對瀏覽器進(jìn)行程序化控制。相對于,是新的開源項目,而且是谷歌開發(fā),可以使用很多新的特性。 背景 說到爬蟲,大多數(shù)程序員想到的是scrapy這樣受人歡迎的框架。scrapy的確不錯,而且有很強(qiáng)大的生態(tài)圈,有g(shù)erapy等優(yōu)秀的可視化界面。但...

    Jeffrrey 評論0 收藏0
  • Puppeteer 初探

    摘要:獲取獲取上下文句柄執(zhí)行計算銷毀句柄除此之外,還可以使用意為在瀏覽器環(huán)境執(zhí)行腳本,可傳入第二個參數(shù)作為句柄,而則針對選中的一個元素執(zhí)行操作。 我們?nèi)粘J褂脼g覽器或者說是有頭瀏覽器時的步驟為:啟動瀏覽器、打開一個網(wǎng)頁、進(jìn)行交互。 無頭瀏覽器指的是我們使用腳本來執(zhí)行以上過程的瀏覽器,能模擬真實的瀏覽器使用場景。 有了無頭瀏覽器,我們就能做包括但不限于以下事情: 對網(wǎng)頁進(jìn)行截圖保存為圖片或 ...

    appetizerio 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<