前面写了一篇关于 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 文件。