基于nodejs与puppeteer库实现网页截图服务应用

初始化应用

1
2
3
mkdir app
cd app
npm init

安装依赖

1
2
3
4
npm install --save express@3.0.0
npm install --save fs-extra@8.0.1
npm install --save puppeteer@1.9.0
npm install --save puppeteer-cluster@0.16.0

创建app.js

const express = require('express');
const app = express();

(async () => {
    // setup server
    app.get('/', async function (req, res) {
        console.log('req');
    });

    app.listen(3000, function () {
        console.log('Screenshot server listening on port 3000.');
    });
})();

完整实现案例

const express = require('express');
const app = express();
const { Cluster } = require('puppeteer-cluster');
const path = require('path');
const fs = require('fs-extra');
const basedir="/data/";
const now_time = new Date().toLocaleString();
(async () => {

    const cluster = await Cluster.launch({
        concurrency: Cluster.CONCURRENCY_CONTEXT,
        puppeteerOptions: {
            headless: true,
            ignoreHTTPSErrors: true,
            args: [
                '--disable-gpu',
                '--disable-dev-shm-usage',
                '--disable-setuid-sandbox',
                '--no-first-run',
                '--no-sandbox',
                '--no-zygote'
            ]
        },
        maxConcurrency: 2,
    });

    // setup server
    app.get('/', async function (req, res) {
        var action = req.query.action||"screenshot";
        var url = req.query.url||"";
        var imgpath = req.query.imgpath||"pic/1.jpg";
        var real_imgpath = basedir+imgpath;
        var try_execute = async function(url,real_imgpath,num){
            try {
                const result = await cluster.execute({url,real_imgpath},async ({ page, data: params}) => {

                        console.log(params)

                        await page.goto(params.url,{
                            timeout: 15000,
                            waitUntil: ['networkidle0']
                        });

                        await page.waitFor(2000);

                        // 自定义截屏参数
                        await page.screenshot({
                            path: params.real_imgpath,
                            clip:{
                                    x:0,
                                    y:0,
                                    width:2480,
                                    height:3508
                                }
                        });

                        await page.close();

                        return "success";
                    });
                console.log("result: "+result)
            } catch (err) {
                // catch error
                console.log('Error: ' + err.message);
                num--;
                if(num>0){
                    console.log('retry: ' + num);
                    await try_execute(url,real_imgpath,num);
                }
            }
        }
        if(action=="screenshot"){
            var imgdir = path.dirname(real_imgpath);
            if (!fs.existsSync(imgdir)) {
              fs.ensureDirSync(imgdir);
            }
            if (!req.query.url) {
                return res.end('error');
            }

            await try_execute(url,real_imgpath,5);

            res.end("success");
        }else{
            console.log(now_time+" not exists action");
            res.writeHead(404);
            res.end('404 Not Found');
        }
    });

    app.listen(3000, function () {
        console.log('Screenshot server listening on port 3000.');
    });
})();

运行

1
node app.js

访问

1
curl http://localhost:3000/?url=https%3a%2f%2fwww.baidu.com%2f&imgpath=pic/1.jpg

Dockerfile案例

指定安装字体

FROM node:8

RUN apt-get -y update
# for https
RUN apt-get install -yyq ca-certificates
# install libraries
RUN apt-get install -yyq libappindicator1 libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6
# tools
RUN apt-get install -yyq gconf-service lsb-release wget xdg-utils
# and fonts
RUN apt-get install -yyq fonts-liberation

RUN mkdir /app
WORKDIR /app
COPY package.json /app/
RUN npm install

COPY fonts/*.ttf /usr/share/fonts/TTF/
RUN cd /usr/share/fonts/TTF/ && fc-cache -fv

RUN mkdir -p /usr/share/fonts/truetype/custom/
COPY fonts/ /usr/share/fonts/truetype/custom/
RUN cd /usr/share/fonts/truetype/custom/ && fc-cache -fv

COPY app.js /app/

EXPOSE 3000

CMD ["node" ,"/app/app.js"]