使用Puppeteer爬取《ECMAScript 6 入门》

228 阅读1分钟

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模块——requireNode.js中用于加载模块的关键字。

然后我们将加载好的puppeteer模块放到名称为puppeteer的常量中—— constES6中用于定义常量的关键字。

接下来是一个匿名的立即执行函数(IIFE,Immediately Invoked Function Expression),里面是我们需要执行的测试代码, asyncES7中用于异步操作的关键字,表示内部是异步操作,返回一个异步操作的结果。

(async() => {

})();

1、打开 浏览器

// 1、打开 浏览器
const browser = await puppeteer.launch();

我们通过puppeteer模块提供的launch方法,打开一个浏览器。

在打开浏览器的同时,我们可以提供一些配置项,比如不使用无头浏览器(headless设置为false)。

awaitES7中用于异步操作的关键字,表示等待异步操作结束、得到返回的结果,await只能用在异步函数async function中。

打开浏览器Puppeteer来说是一个异步操作(返回值是Promise), Puppeteer的其他API也是类似处理。

我们为了模拟人的输入方式、或者为了查看方便,我们还可以设置slowMotrue,这样浏览器会模拟人的输入方式、缓慢地进行输入。

// 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();