免责声明:本人博客所有文章纯属学习之用,不涉及商业利益。不合适引用,自当删除!
内容简介:
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)
})
}
真实线上的代码比这个来的复杂得多,这是被我阉割后的简易版本。
优化点:滚动优化,实时计算滚动次数,因为现在的页面大部分是动态加载。
上结果: