Puppeteer是由Google Chrome 官方团队进行维护的一个Node库,提供了一组高级API, 通过DevTools协议控制无界面Chrome (headless chrome, 也就是无UI界面的chrome)。它允许你从浏览器之外的环境(即命令行)与Chromium进行交互。
本篇文章,我们使用Puppeteer爬取“阮一峰”开源电子书《ECMAScript 6 入门》(电子书地址:es6.ruanyifeng.com/)。
执行结果截图
示例代码的安装、执行
示例代码的仓库地址请点击这里。
在安装依赖、执行示例代码之前,请先安装最新版的Node.js。
# 建议使用cnpm进行安装,puppeteer需要下载Chromium (~170Mb Mac, ~282Mb Linux, ~280Mb Win)
sudo npm install -g cnpm
cnpm install
npm start
代码说明
/**
* 使用Puppeteer爬取“阮一峰”开源电子书《ECMAScript 6 入门》(电子书地址:https://es6.ruanyifeng.com/)。
*/
const puppeteer = require('puppeteer');
(async() => {
// 1、打开 浏览器
const browser = await puppeteer.launch();
// 2、打开 新页面
let page = await browser.newPage();
// 3、网址跳转到 电子书页面
await page.goto('https://es6.ruanyifeng.com', {waitUtil: 'networkidle0'});
await page.waitFor(2000);
// 4、所有文章的链接地址
let aTags = await page.evaluate(() => {
let as = [...document.querySelectorAll('ol li a')];
return as.map((a) =>{
return {
href: a.href.trim(),
name: a.text
};
});
});
// 5、访问所有的文章,然后生成PDF
for(let i = 0; i < aTags.length; i++) {
page = await browser.newPage();
await page.setViewport({width: 1200, height: 800});
let a = aTags[i];
await page.goto(a.href, {waitUtil: 'networkidle0'});
await page.waitFor(5000);
await page.pdf({path: `./docs/${i + '.' + a.name}.pdf`});
await page.close();
}
// 6、关闭浏览器
await browser.close();
})();
我们首先加载puppeteer
模块——require
是Node.js中用于加载模块的关键字。
然后我们将加载好的puppeteer
模块放到名称为puppeteer
的常量中——
const
是ES6中用于定义常量
的关键字。
接下来是一个匿名的立即执行函数
(IIFE,Immediately Invoked Function Expression),里面是我们需要执行的测试代码,
async
是ES7
中用于异步操作的关键字,表示内部是异步操作,返回一个异步操作的结果。
(async() => {
})();
1、打开 浏览器
// 1、打开 浏览器
const browser = await puppeteer.launch();
我们通过puppeteer
模块提供的launch
方法,打开一个浏览器。
在打开浏览器的同时,我们可以提供一些配置项,比如不使用无头浏览器(headless
设置为false
)。
await
是ES7
中用于异步操作的关键字,表示等待异步操作结束、得到返回的结果,await
只能用在异步函数async function
中。
打开浏览器
对Puppeteer
来说是一个异步操作(返回值是Promise
),
Puppeteer的其他API也是类似处理。
我们为了模拟人的输入方式、或者为了查看方便,我们还可以设置slowMo
为true
,这样浏览器会模拟人的输入方式、缓慢地进行输入。
// 1、打开 浏览器
const browser = await puppeteer.launch({headless: true, slowMo: true});
2、打开 新页面
// 2、打开 新页面
const page = await browser.newPage();
3、网址跳转到 电子书页面
// 3、网址跳转到 电子书页面
await page.goto('https://es6.ruanyifeng.com', {waitUtil: 'networkidle0'});
await page.waitFor(2000);
4、抽取所有文章的链接地址
// 4、抽取所有文章的链接地址
let aTags = await page.evaluate(() => {
let as = [...document.querySelectorAll('ol li a')];
return as.map((a) =>{
return {
href: a.href.trim(),
name: a.text
};
});
});
5、访问所有的文章,然后生成PDF
// 5、访问所有的文章,然后生成PDF
for(let i = 0; i < aTags.length; i++) {
page = await browser.newPage();
await page.setViewport({width: 1200, height: 800});
let a = aTags[i];
await page.goto(a.href, {waitUtil: 'networkidle0'});
await page.waitFor(5000);
await page.pdf({path: `./docs/${i + '.' + a.name}.pdf`});
await page.close();
}
6、关闭浏览器
// 6、关闭浏览器
await browser.close();