使用puppeteer之全网页截图-修订版

免责声明:本人博客所有文章纯属学习之用,不涉及商业利益。不合适引用,自当删除!

内容简介:

  1. 接上一篇的内容之前,简单介绍一下puppeteer环境的快速搭建;
  2. 修订版目的;
  3. 修订版具体实现,代码展示。

1、puppeteer运行环境快速搭建

以下是个人从无到有的搭建过程,linux、windows系统搭建,大同小异:

1.1、首先是node.js的安装

1.1.1、官网下载安装包,node-v11.3.0-linux-x64.tar.xz

1.1.2、复制至/usr/local下

1.1.3、解压:tar -xvf node-v11.3.0-linux-x64.tar.xz

1.1.4、配置/etc/profile

export NODEJS_HOME=/usr/local/nodejs

export PATH=$NODEJS_HOME/bin:$PATH

1.1.5、执行source /etc/profile,查看node.js安装情况:node -v,查看npm安装情况:npm -v

[master@master nodejs]$ node -v
v11.3.0
[master@master nodejs]$ npm -v
6.4.1

1.2、安装puppeteer

如果是项目,则cd至项目路径下,如果是执行js文件,则安装在与js文件的同级目录下,因为实际场景中会有项目运行,以及一些单独运行的小项目存在,根据不同场景自行选择。

1.2.1、安装cnpm,直接通过npm安装puppeteer,容易失败,使用阿里淘宝的源

npm install -g cnpm --registry=https://registry.npm.taobao.org

-g参数,说明是全局安装。

1.2.2、查看cnpm版本

[master@master nodejs]$ cnpm -v
[email protected] (/usr/local/nodejs/lib/node_modules/cnpm/lib/parse_argv.js)
[email protected] (/usr/local/nodejs/lib/node_modules/cnpm/node_modules/npm/lib/npm.js)
[email protected] (/usr/local/nodejs/bin/node)
[email protected] (/usr/local/nodejs/lib/node_modules/cnpm/node_modules/npminstall/lib/index.js)
prefix=/usr/local/nodejs 
linux x64 3.10.0-693.el7.x86_64 
registry=https://registry.npm.taobao.org

1.2.3、安装puppeteer

cnpm install puppeteer

等待完成,到这里环境的基本搭建就完成了。如果是有node.js的其他安装包,先运行npm install,再运行puppeteer,因为经常更新环境,发现单独对puppeteer进行升级,会导致node_modules下的软链接文件夹被删除。

2、修订版目的

理由:第一个版本太丑陋了。

3、修订版实现

其实已经写完很久了,一直疏于整理。主要针对第一个版本中的滚屏进行修改,看过第一版知道,其实现滚屏的方式是修改html页面中scrollTop的值。

document.scrollingElement.scrollTop = scrollTop + scrollStep;

实际上可以使用window对象的相关函数。

上代码:

// puppeteer测试DEMO
var puppeteer = require('puppeteer');

(async() => {

    let timeoutMillSeconds = 10000;
    let waitUntilStr = 'domcontentloaded';

    let headlessFlag = false;
    const system_warn = 1002; // 系统提示/告警

    let args = [
        '--no-sandbox',
        '--disable-infobars ', // don't show information bar
        '--window-size=1920,1080', // resize window view port size
        '--lang=zh-CN',
        '--disable-dev-shm-usage'
    ];
    const browser = await puppeteer.launch({
        defaultViewport: {width: 1920, height: 1080},
        ignoreHTTPSErrors: true,
        headless:headlessFlag,
        args: args
    });
    const page = await browser.newPage();
    let request_url = 'https://blog.csdn.net/ASAS1314/article/details/81633423';
    await page.goto(request_url, {timeout:timeoutMillSeconds, waitUntil: waitUntilStr}).catch(err => {
    });

    let height_limit = false;
    let scroll_times = 0;
    let mValues = {'scrollEnable': true, 'height_limit': height_limit, 'times': 10};
    let result_map = new Map();

    try {
        await page.waitFor(5000);


        while (mValues.scrollEnable) {
            mValues = await page.evaluate((max_height_px,
                                           page_screentshot_height_limit,
                                           height_limit,
                                           result_map,
                                           system_warn,
                                           request_url,
                                           scroll_times
                                           ) => {

                let times = 1;
                let scrollEnable = true;
                if (undefined !== document.body && null != document.body) {
                    window.scrollBy(0, window.innerHeight);
                    times = parseInt(document.body.clientHeight / 1080);

                    // 超出图片的限制高度, 生成PDF
                    if (document.body.clientHeight > page_screentshot_height_limit) {
                        height_limit = true;
                    }
                    // 超出网页的限制高度, 不再滚动
                    if (document.body.clientHeight > max_height_px && scroll_times > 40) {
                        result_map['resultCode'] = system_warn;
                        result_map['warning'] = '网页加载高度过长, 易造成数据获取失败。';
                        scrollEnable = false;
                    }
                } else {
                    scrollEnable = false;
                }

                times = times + 1;
                return {
                    'scrollEnable': scrollEnable,
                    'height_limit': height_limit,
                    'times': times,
                    'title':document.title
                };

            }, 60000, 60000, height_limit, result_map, system_warn, request_url, scroll_times);

            // 等待随机时间
            let randomMillSecond = randomNum(600, 2000);
            await sleep(randomMillSecond);
            scroll_times++;
            console.log(request_url + ' 需要滚动 : ' + mValues.times + '次 , 滚动第[' + scroll_times + ']次');
            if (scroll_times > mValues.times) {
                console.log(request_url + ' 结束');
                mValues.scrollEnable = false;
            }
        }

        console.log(mValues);
        await page.screenshot({path: 'example.png', fullPage: true});

    } catch (e) {
        console.log(e);
        console.log('执行异常');
    } finally {
        await browser.close();
    }

})();

// 随机数
function randomNum(minNum, maxNum) {
    switch (arguments.length) {
        case 1:
            return parseInt(Math.random() * minNum + 1, 10);
        case 2:
            return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
        default:
            return 0;
    }
}

// 延时函数
function sleep(delay) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            try {
                resolve(1)
            } catch (e) {
                reject(0)
            }
        }, delay)
    })
}

真实线上的代码比这个来的复杂得多,这是被我阉割后的简易版本。

优化点:滚动优化,实时计算滚动次数,因为现在的页面大部分是动态加载。

上结果:

你可能感兴趣的:(javascript,puppeteer)