Puppeteer笔记
声明
我只是一个菜B,之所以写这些东西,一来为了加深记忆,二来发个文章以后看到也是一种回忆,三来锻炼写文的能力,所以文章写得很烂,不喜勿喷,每一个点进来的都是一种缘分,谢谢了。
介绍
Puppeteer是一个Node库,提供一套可以操作Chrome的API。其取名挺有意思,翻译为“操纵木偶的人;傀儡师
”,代表着我们可以通过操纵她来完成很多功能,例如:
爬虫,爬取网页上的各种信息;
模拟键盘表单等输入,实现自动化测试等...
开始
因为,因为Puppeteer有很多的异步操作,所以推荐使用的是async/await的写法;这样可读性会更好。所以,Node的版本最少为V7.6.6。
下载
通过npm来下载puppeteer:npm install --save puppeteer
Hello World
下载完成Puppeteer后,可以通过引入来模拟打开一个谷歌浏览器。
const puppeteer = require('puppeteer');
async function run() {
const brower = await puppeteer.launch({
headless: false,
defaultViewport: {
width: 1366,
height: 728
}
});
const page = await brower.newPage();
await page.goto('https://www.baidu.com');
const ipt = await page.$('#kw');
await ipt.type('Hello World!');
}
run();
以上代码执行后,将会打开一个谷歌浏览器,并且在输入框中输入:Hello World!
这就是Puppeteer的第一个程序,上面代码用到的几个API意义(因为是async/await,所以就直接说意思了,不说返回的是Promise):
| API | 意义 |
|---|---|
| lauch | 返回一个brower示例 |
| newPage | 创建一个 Page 实例 |
| goto | 跳转到一个页面 |
| type | 给DOM元素设置值 |
| $ | 选项元素,同querySelector |
这就是以上用到的API的一些见解。
获取DOM元素的属性
获取一个元素的属性可以通过:$eval来获取。
代码省略...
const page = await brower.newPage();
await page.goto('https://www.baidu.com');
const iptValue = await page.$eval('#kw', el => el.value);
$eval的第一个参数,是一个选择器,第二个参数是一个函数,代表选中的元素,最终的返回值通过await处理后的,就是第二个参数的返回值。
常用的简单API
| 对象 | API | 作用 | 示例 |
|---|---|---|---|
| element | type | 给DOM元素设置值 | el.type('Hello World!'); |
| element | click | 模拟DOM元素的点击事件 | el.click(); |
| element | uploadFile | 模拟DOM元素的上传事件 | el.uploadFile('...'); |
| page | $ | 选取一个元素 | page.$('selector'); |
| page | ? | 选取一组元素 | page.?('selector'); |
| page | $eval | 获取一个元素的属性 | page.$('selector', fn => {...}); |
| page | ?eval | 获取一组元素的属性 | page.?eval('selector', fn => {...}); |
| page | goto | 跳转到一个页面 | page.goto('...'); |
模拟登录掘金点赞一篇文章
通过上面的笔记,我们就可以写一个小Demo——登录掘金,点赞一篇文章!
思路:
- 通过goto这个API跳转到掘金首页;
- 使用click模拟按登录这个按钮,此时会有一个登录框的弹层;
- 使用type这个方法输入用户名和密码,模拟点击登录;
- 登录成功后,找到第一篇文章的点赞按钮,模拟点击;
- 点赞成功,功能完成!
const puppeteer = require('puppeteer');
async function run() {
const brower = await puppeteer.launch({
headless: false,
defaultViewport: {
width: 1366,
height: 768
}
});
const page = await brower.newPage();
await page.goto('https://juejin.im/timeline');
const loginBtn = await page.$('#juejin > div.view-container > div > header > div > nav > ul > li.nav-item.auth > span.login');
await loginBtn.click();
await page.waitForSelector('#juejin > div.global-component-box > div.auth-modal-box > form > div.panel > div.input-group > div:nth-child(1) > input');
const userInput = await page.$('#juejin > div.global-component-box > div.auth-modal-box > form > div.panel > div.input-group > div:nth-child(1) > input');
await userInput.type('username');
const pwdInput = await page.$('#juejin > div.global-component-box > div.auth-modal-box > form > div.panel > div.input-group > div:nth-child(2) > input');
await pwdInput.type('password');
const loginBtnConfirm = await page.$('#juejin > div.global-component-box > div.auth-modal-box > form > div.panel > button');
await loginBtnConfirm.click();
await page.waitForSelector('#juejin > div.view-container.container > main > div > div > div > div > div > ul > li:nth-child(1) > div > div > a > div > div > div.info-row.action-row > ul > li.item.like.clickable > a');
const goodBtn = await page.$('#juejin > div.view-container.container > main > div > div > div > div > div > ul > li:nth-child(1) > div > div > a > div > div > div.info-row.action-row > ul > li.item.like.clickable > a');
await goodBtn.click();
}
run();
看看执行效果图
这里有些要注意的
- 弹出登录框的时候,需要使用waitForSelector这个方法来等待元素加成出来,再用$去选择元素,否则可能会出错
- 登录后,会刷新页面,所以此时也需要用waitForSelector来等待元素加载完成
- 这里最新的Chromium浏览器,不知道为啥,我掘金登录只能用邮箱,所以我就绑定了一个。
以上用到的方法主要就几个:
$: 选中元素
click:模拟点击
type: 模拟输入
waitForSelector: 等待元素加载完成
对于这个简单的Demo,仅仅只是Puppeteer的小小开始,我知道笔记记录的又很多不足,但我也会努力学习,慢慢掀开她美丽的面纱