首页 > 解决方案 > 如何在没有 shell 访问权限的情况下安装 puppeteer 依赖项?

问题描述

我使用无头 Chrome 创建了一个网页抓取脚本。这是代码:

const puppeteer = require('puppeteer'),
    PDFDocument = require('pdfkit'),
    express = require('express');

app = express();
app.listen();
app.get('/', (req, res) => {
    if (!req.query.url) {
        res.send("URL not provided");
        return;
    }

    work(req.query.url).then(data => {
        if (data.status === 'ok') {
            res.setHeader('Content-Type', 'application/pdf');
            res.setHeader('Content-Disposition', `attachment; filename=${data.file_name}`);
            data.pdf.pipe(res);
            data.pdf.end();
            return;
        } else {
            res.send(data.message);
        }
    });
});

async function work(url) {
    const browser = await puppeteer.launch({
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
        ],
    });
    const page = await browser.newPage();
    await page.setViewport({
        width: 1920,
        height: 1080
    });
    const nav = await page.goto(url);
    if (nav._status === 404) return { status: 'error', message: 'Page not found' };

    const total_height = await page.evaluate(() => {
        element = document.querySelector('.document_scroller');
        let height = element.scrollHeight;
        element.scrollTop = height;
        return height;
    });
    await page.setViewport({
        width: 1920,
        height: total_height
    });
    const num_pages = await page.evaluate(() => {
        return document.querySelectorAll(".outer_page.only_ie6_border").length;
    });

    //Get JSON data
    const json = await page.evaluate(() => {
        script_tags = document.getElementsByTagName("script");
        for (let script of script_tags) {
            json_index = script.innerText.indexOf("new Scribd.EmbedsShow(");
            if (json_index !== -1) return script.innerText.substring(json_index).match(/\{.*\}/)[0];
        }
    });
    const data = JSON.parse(json);
    const name = `${data.document.title}.pdf`;

    const doc = new PDFDocument({ autoFirstPage: false });
    for (let i = 1; i <= num_pages; i++) {
        await page.waitForSelector(`#outer_page_${i} img`);
        await page.waitForFunction(`document.querySelector("#outer_page_${i} img").hasAttribute("src")`);
        await page.waitForFunction(`document.querySelector("#outer_page_${i} img").complete`);
        const slide = await page.$(`#outer_page_${i}`);
        const image = await slide.screenshot({ encoding: "base64" });

        const dimensions = await slide.boundingBox();
        doc.addPage({
            size: [dimensions.width, dimensions.height],
            margins: { top: 0, bottom: 0, left: 0, right: 0 }
        });
        doc.image("data:image/png;base64," + image);
    }
    await browser.close();

    return { status: 'ok', pdf: doc, file_name: name };
}

它在本地运行良好。另外,我已经使用 puppeteer buildpack 在 Heroku 上对此进行了测试,它工作正常。

现在我想使用带有 CPanel 而不是 Heroku 的共享主机。我在 CPanel 中创建了一个 NodeJS 应用程序并设置了所有内容。我已经测试过该脚本可以运行。
但是,在实际测试期间它失败了,我在 CPanel 的日志中收到了这个错误消息:

App 171986 output: /home/myapp/nodevenv/node/12/lib/node_modules/puppeteer/.local-chromium/linux-901912/chrome-linux/chrome: error while loading shared libraries: libatk-bridge-2.0.so.0: cannot open shared object file: No such file or directory

很明显,缺少一些 Chrome 依赖项。我的问题是,在没有 shell 或 root 访问权限的情况下,我应该如何以及在哪里安装 CPanel 中缺少的依赖项?

标签: node.jspuppeteergoogle-chrome-headless

解决方案


推荐阅读