Puppeteer 入门

1674 字
8 分钟
Puppeteer 入门

一、Puppeteer 是什么#

Puppeteer,翻译成中文可以理解成傀儡的意思,他是一个Node库,主要是提供接口来控制 headless chrome ,也就是无头浏览器,无头浏览器是一种不使用chrome来运行chrome浏览器的方式,简单来讲,其实就是编写javascript 代码自动化控制 Chrome。

我们能用Puppeteer做些什么

  • 1、利用网页生成PDF,图片
  • 2、主要的从网站抓取内容。
  • 3、自动化表单提交、UI测试、键盘输入等。
  • 4、捕获站点的时间线,一遍追踪网站,帮助分析网站性能问题。

二、运行环境#

Node 版本大于 V7.6.0,因为Puppeteer中所有的操作几乎都是一步的,如果使用大量的then会使代码的可读性特别低,所以选择ES7中的 async,await 语法,这也是 Puppeteer 官方推荐的写法。


三、基本用法#

1、入门 Demo 屏幕截图#

const puppeteer = require('puppeteer');
async function getPic() {
// 启动 puppeteer
const browser = await puppeteer.launch({ headless: false });
// 在浏览器中创建一个新的页面
const page = await browser.newPage();
// 使用 goto 打开指定网页
await page.goto("https://www.baidu.com");
// 调整页面配置大小,截图更好看
await page.setViewport({ width: 1400, height: 900 });
// 使用 screenshot 函数对网页进行截屏
await page.screenshot({ path: 'baidu.png' })
// 关闭浏览器
await browser.close();
}
getPic();

2、基础使用属性#

① puppeteer.launch(options) options 参数详解#

参数名称参数类型参数说明
ignoreHTTPSErrorsboolean在请求的过程中是否忽略 Https 报错信息,默认为 false
headlessboolean是否以”无头”的模式运行 chrome, 也就是不显示 UI, 默认为 true
executablePathstring可执行文件的路劲,Puppeteer 默认是使用它自带的 chrome webdriver, 如果你想指定一个自己的 webdriver 路径,可以通过这个参数设置
slowMonumber使 Puppeteer 操作减速,单位是毫秒。如果你想看看 Puppeteer 的整个工作过程,这个参数将非常有用。
argsArray(String)传递给 chrome 实例的其他参数,比如你可以使用”–ash-host-window-bounds=1024x768” 来设置浏览器窗口大小。
handleSIGINTboolean是否允许通过进程信号控制 chrome 进程,也就是说是否可以使用 CTRL+C 关闭并退出浏览器.
timeoutnumber等待 Chrome 实例启动的最长时间。默认为30000(30秒)。如果传入 0 的话则不限制时间
userDataDirstring设置用户数据目录,默认linux 是在 ~/.config 目录,window 默认在 C:\Users{USER}\AppData\Local\Google\Chrome\User Data, 其中 {USER} 代表当前登录的用户名.
envObject指定对Chromium可见的环境变量。默认为process.env.
devtoolsboolean是否为每个选项卡自动打开DevTools面板, 这个选项只有当 headless 设置为 false 的时候有效

② Browser 对象#

当 Puppeteer 连接到一个 Chrome 实例的时候就会创建一个 Browser 对象,有以下两种方式: Puppeteer.launch 和 Puppeteer.connect. Browser 对象 API :

方法名称返回值说明
browser.close()Promise关闭浏览器
browser.disconnect()void断开浏览器连接
browser.newPage()Promise(Page)创建一个 Page 实例
browser.pages()Promise(Array(Page))获取所有打开的 Page 实例
browser.targets()Array(Target)获取所有活动的 targets
browser.version()Promise(Page)获取浏览器的版本
browser.wsEndpoint()String返回浏览器实例的 socket 连接 URL, 可以通过这个 URL 重连接 chrome 实例

Puppeteer 详细Api地址 https://github.com/puppeteer/puppeteer/blob/main/docs/api.md


四、实战获取京东商城手机商品#

首先梳理操作流程:

  • ①、打开京东首页
  • ②、输入手机关键字并搜索
  • ③、获取前10个商品的A标签,并获取商品详情链接。
  • ④、分别打开10个详情图,截取网页图片。

要实现上面的功能,需要用到查找元素,获取属性,键盘回车等,接下来一个一个讲解一下。

1、获取元素#

Page 对象提供了2个API来获取页面元素: (1). Page.$(selector) 获取单个元素,底层是调用的是 document.querySelector() , 所以选择器的 selector 格式遵循 css 选择器规范;

let inputElement = await page.$('#search');

(2). Page.$$(selector) 获取一组元素,底层调用的是 document.querySelectorAll(). 返回 Promise(Array(ElemetHandle)) 元素数组.

const links = await page.$$("a");

2、获取元素属性#

(1). Page.$eval(selector, pageFunction[, …args]), 获取单个元素的属性

const value = await page.$eval('input[name=search]', input => input.value);
const href = await page.$eval('#a", ele => ele.href);
const content = await page.$eval('.content', ele => ele.outerHTML);

(2). Page.$$eval(selector, pageFunction[, …args]), 获取元素数组的属性

3、键盘和鼠标事件#

键盘和鼠标的API比较简单,键盘的几个API如下:

  • keyboard.down(key[, options]) 触发 keydown 事件
  • keyboard.press(key[, options]) 按下某个键,key 表示键的名称
  • keyboard.sendCharacter(char) 输入一个字符
  • keyboard.type(text, options) 输入一个字符串
  • keyboard.up(key) 触发 keyup 事件
  • page.keyboard.press(“Shift”); //按下 Shift 键
  • page.keyboard.sendCharacter(‘嗨’);
  • page.keyboard.type(‘Hello’); // 一次输入完成
  • page.keyboard.type(‘World’, {delay: 100}); // 像用户一样慢慢输入 鼠标Api如下:
  • mouse.click(x, y, [options]) 移动鼠标指针到指定的位置,然后按下鼠标,这个其实 mouse.move 和 mouse.down 或 mouse.up 的快捷操作 > * mouse.down([options]) 触发 mousedown 事件,options 可配置: > * options.button 按下了哪个键,可选值为[left, right, middle], 默认是 left, 表示鼠标左键 > * options.clickCount 按下的次数,单击,双击或者其他次数 > * delay 按键延时时间 > * mouse.move(x, y, [options]) 移动鼠标到指定位置, options.steps 表示移动的步长 > * mouse.up([options]) 触发 mouseup 事件

4、其他实用API#

page.waitForSelector(selector[, options]) 等待某个选择器的元素加载之后,这个元素可以是异步加载的,这个 API 非常有用,比如我想获取某个通过 js 异步加载的元素,那么直接获取肯定是获取不到的。这个时候就可以使用 page.waitForSelector 来解决。

5、实现代码#

const puppeteer = require('puppeteer');
const fs = require('fs');
const path = require('path');
async function getShopDetail() {
// 启动 puppeteer
const browser = await puppeteer.launch({ headless: false, ignoreHTTPSErrors: true });
let page = await browser.newPage();
// 启用Javascript,允许执行js脚本
await page.setJavaScriptEnabled(true);
// 打开京东网页
await page.goto("https://www.jd.com/");
// 获取搜索框元素
const searchInput = await page.$("#key");
// 定位到搜索框
await searchInput.focus();
// 输入搜索内容
await page.keyboard.type("手机");
// 获取搜索按钮
const searchBtn = await page.$(".button");
// 执行点击事件
await searchBtn.click();
// 等待元素加载之后,否则获取不异步加载的元素
await page.waitForSelector('.gl-item');
// 获取搜索结果
const links = await page.$$eval('.gl-item > .gl-i-wrap > .p-img > a', links => {
return links.map(a => {
return {
href: a.href.trim(),
title: a.title
}
});
});
const content = JSON.stringify(links);
const file = path.join(__dirname, 'resource/index.json');
fs.writeFile(file, content, ()=> {});
await browser.close();
}
getShopDetail();

五、定制属于自己的个人资讯网站#

  • 抓取资讯 puppeteer
  • 定时任务 node-schedule
  • 部署 docker + github pages

主要思路: puppeteer 定时抓取各个网站板块信息,每次获取内容后,保存至数据库或者简单的用Json保存,保存完成,只需要请求这个文件就可以渲染出需要的内容,定时任务可以用过 node-schedule 库来实现,部署可以采用 docker + gittpage 部署。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Puppeteer 入门
https://luoruihuan.top/posts/puppeteer/
作者
技术派罗恩
发布于
2023-06-22
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
技术派罗恩
94 年全栈工程师,10+ 年互联网经验,专注 AI Agent 开发与 GEO。
公告
欢迎来到我的博客!这是一则示例公告。
分类
标签
站点统计
文章
26
分类
5
标签
19
总字数
51,593
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
GitHub Actions
文章许可
CC BY-NC-SA 4.0
文章目录