前端爬虫Puppeteer(二)

335 阅读1分钟

前面写了一篇关于 Puppeteer 的 基础知识. ,接下来的篇内容将通过爬取微博热门文章来增强对 Puppeteer 的学习。

一、安装

Puppeteer 至少需要 Node v6.4.0,下面的示例使用 async / await,它们仅在 Node v7.6.0 或更高版本中被支持。

npm i puppeteer

二、使用

创建一个 Browser 实例

//使用 puppeteer.launch 启动 Chrome
const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({
        headless: false, //有浏览器界面启动
        slowMo: 100, //放慢浏览器执行速度,方便测试观察
        args: [] //启动 Chrome 的参数
            
    });
    //设置浏览器视口大小
    await page.setViewport({
        width: 1200,
        height: 600,
    })
    const page = await browser.newPage();
    await page.goto('https://www.weibo.com');
    // 
})();

执行 puppeteer.launch() 每次都启动一个 Chrome 实例,传一个对象参数设置浏览器相关配置后,调用 newPage() 生成一个新页面,并且打开微博首页

模拟用户登录

    //...续上
    //找到用户名输入框并输入账号
    await (await page.waitForSelector('.W_unlogin_v4 .W_login_form .username .input_wrap .W_input')).type('*********', {
        delay: 20
    });
    //找到密码输入框并输入密码
    await (await page.waitForSelector('.W_unlogin_v4 .W_login_form .password .input_wrap .W_input')).type('*********', {
        delay: 20
    });
    //点击确定按钮进行登录
    let okButtonElement = await page.$('.W_unlogin_v4 .W_login_form .login_btn .W_btn_a');
    await Promise.all([
        okButtonElement.click(),
        page.waitForNavigation()
    ]);
    console.log('登录成功');

page.waitForSelector() 等待用户名和密码对应的元素出现,返回对应的 ElementHandle ,然后通过 type() 输入账号密码,最后点击 click() 登录按钮。等待页面跳转完成,一般点击某个按钮需要跳转时,需要等待 page.waitForNavigation() 执行完毕才表示跳转成功。(点击后可能出现验证码校验,解决方法本文暂时不展开)

爬取数据

下面来爬取微博关键字为“疫情”热门文章。

//...
//插入抓取脚本
await page.evaluate(() => {
    let container = document.querySelector(`.m-wrap .m-con-l`),
        cardArr = document.querySelectorAll('.card-wrap'),
        data = [];

    // 获取每篇文章内容
    function getArticleData({
        container,
        selector
    }) {
        if (!container) return {};
        let node = container.querySelector(selector);
        //获取文章主要内容
        let title = node ? node.querySelector(` h3`).innerText : '',
            url = node ? node.querySelector(`.pic a`).attributes["href"].value : '',
            img = node ? node.querySelector(`.pic img`).src : '',
            content = node ? node.querySelector(`.detail p`).innerText : '',
            author = node ? node.querySelector(`.detail .act span:nth-child(1)`).innerText : '',
            time = node ? node.querySelector(`.detail .act div span:nth-child(2)`).innerText : '';
        return {
            title,
            url,
            img,
            content,
            author,
            time
        };
    }

    //获取所有文章
    for (let i = 2; i < cardArr.length + 1; i++) {
        let item = getArticleData({
            container,
            selector: `.card-wrap:nth-child(${i}) .card-article-a`
        });
        data.push(item);
    }
    console.log(data); 
   
});

page.evaluate(pageFunction[, ...args]) 用来在浏览器环境中执行函数,如上面我们在 pageFunction 中执行了抓取文章的js方法,如果需要在 evaluate 中使用全局变量等,可以直接传入使用。上面方法执行成功后,可获到如下数据,这样就可以拿来用了,也可以使用 xlsx 将数据导出为 Excel 文件。