是什么?
就是我们平时用的浏览器,完整的浏览器,只是不显示界面(如果你需要也可以设置显示),完整的渲染html,js,css.启动速度快,通常用于测试或者爬虫工具.
有哪些?
无头浏览器很多,包括但不限于:
- PhantomJS, 基于 Webkit
- SlimerJS, 基于 Gecko
- HtmlUnit, 基于 Rhnio
- TrifleJS, 基于 Trident
- Splash, 基于 Webkit
但是上边这些基本都不推荐使用,最新,最好用的应该是谷歌的无头浏览器(headless Chrome), 他基于 Chrome DevTools protocol 提供了不少高度封装的接口方便我们控制浏览器。
puppeteer
中文翻译:木偶,很形象的解释.
通过chrome的devTools 协议操作,调用谷歌浏览器,进行页面渲染或模拟人工操作.
使用nodejs语法做的api,方便快捷.因为nodejs本身就是js嘛,上手很容易.
快速上手
需要环境: nodejs v8版本以上
打开google.com,然后搜一个关键词
示例动图:
/**
* 在无头浏览器自动填写表单并提交
*/
const puppeteer = require('puppeteer');
const autoSubmitForm = async (url, path) => {
// 启动浏览器
const browser = await puppeteer.launch({
// 关闭无头模式,方便我们看到这个无头浏览器执行的过程
headless: false,
});
// 打开页面
const page = await browser.newPage();
// 设置浏览器视窗
page.setViewport({
width: 1376,
height: 768,
});
// 地址栏输入网页地址
await page.goto(url, {
waitUntil: 'networkidle', // 等待网络状态为空闲的时候才继续执行
});
// await page.click('#lst-ib');
await page.focus('#lst-ib');
await page.type('辣子鸡', {
delay: 1000, // 控制 keypress 也就是每个字母输入的间隔
});
await page.press('Enter');
// 不关闭浏览器,看看效果
// await browser.close();
};
module.exports = autoSubmitForm;
if (require.main === module) {
// for test
autoSubmitForm('http://google.com');
}
Puppeteer 官方文档
官方地址
- 官网 : https://pptr.dev/
- 源码:https://github.com/GoogleChrome/puppeteer
- 中文文档: https://zhaoqize.github.io/puppeteer-api-zh_CN/#?product=Puppeteer&version=v1.18.1&show=api-overview
概述
Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。
Puppeteer API 是分层次的,反映了浏览器结构。
注意:在下面的图表中,浅色框体内容目前不在 Puppeteer 中体现。
Puppeteer
使用 DevTools 协议 与浏览器进行通信。Browser
实例可以拥有浏览器上下文。BrowserContext
实例定义了一个浏览会话并可拥有多个页面。Page
至少有一个框架:主框架。 可能还有其他框架由 iframe 或 框架标签 创建。frame
至少有一个执行上下文 - 默认的执行上下文 - 框架的 JavaScript 被执行。 一个框架可能有额外的与 扩展关联的执行上下文。Worker
具有单一执行上下文,并且便于与 WebWorkers 进行交互。一些概念和名词
puppeteer vs puppeteer-core
自 v1.7.0 以来的每个版本我们都发布了两个包:
- puppeteer-core
puppeteer
是浏览器自动化的 产品。安装后,它会下载一个版本的 Chromium,然后使用puppeteer-core
驱动工作。作为最终用户产品,puppeteer
支持一堆方便的 PUPPETEER_*
env 变量来调整行为。puppeteer-core
是一个 库 来帮助驱动任何支持 DevTools 协议的东西。puppeteer-core
在安装时不会下载 Chromium。作为一个库,puppeteer-core
是完全是通过其编程接口驱动的并忽略所有PUPPETEER_*
env 变量。
总结一下,puppeteer-core
与 puppeteer
不同的地方:
puppeteer-core
在安装时不会自动下载 Chromium。puppeteer-core
忽略所有的PUPPETEER_*
env 变量.
在大多数情况下,你可以使用 puppeteer
包。
然而, 如果是下面这些情况那你需要使用 puppeteer-core
:
- 你正在构建 DevTools 协议顶部的另一个最终用户产品或库。例如,可以使用
puppeteer-core
构建 PDF 生成器并编写下载headless_shell
的自定义install.js
脚本而不是 Chromium 来节省磁盘空间。 - 你正在打包 Puppeteer 用在 Chrome 扩展应用或浏览器中以使用 DevTools 协议,因为下载额外的 Chromium 二进制文件不是必须的。
当使用 puppeteer-core
时,使用下面这行代替原来的使用方式:
const puppeteer = require('puppeteer-core');
环境变量 Environment Variables
Puppeteer 寻找某些环境变量来帮助其操作。 如果 puppeteer 在环境中没有找到它们,这些变量的小写变体将从 npm 配置 中使用。
HTTP_PROXY
,HTTPS_PROXY
,NO_PROXY
- 定义用于下载和运行 Chromium 的 HTTP 代理设置。PUPPETEER_SKIP_CHROMIUM_DOWNLOAD
- 请勿在安装步骤中下载绑定的 Chromium。PUPPETEER_DOWNLOAD_HOST
- 覆盖用于下载 Chromium 的 URL 的主机部分。PUPPETEER_CHROMIUM_REVISION
- 在安装步骤中指定一个你喜欢 puppeteer 使用的特定版本的 Chromium。PUPPETEER_EXECUTABLE_PATH
- 指定一个 Chrome 或者 Chromium 的可执行路径,会被用于puppeteer.launch
。具体关于可执行路径参数的意义,可参考puppeteer.launch([options])
。NOTE 在使用
puppeteer-core
时,上述环境变量中以 PUPPETEER_* 开头的会被忽略.
错误处理 Error handling
如果 Puppeteer 方法无法执行一个请求,就会抛出一个错误。例如,page.waitForSelector(selector[, options]) 选择器如果在给定的时间范围内无法匹配节点,就会失败。
对于某些类型的错误,Puppeteer 使用特定的错误类处理。这些类可以通过 require('puppeteer/Errors')
获得。
支持的类列表:
一个处理超时错误的例子:
const {TimeoutError} = require('puppeteer/Errors');
// ...
try {
await page.waitForSelector('.foo');
} catch (e) {
if (e instanceof TimeoutError) {
// 如果超时,做一些处理。
}
}
测试浏览器的扩展 Working with Chrome Extensions
Puppeteer 可以用来测试 Chrome 扩展
注意 Chrome / Chromium 扩展当前只能在非无头模式下使用。
下面的代码用来处理扩展的 background page,该扩展的代码在 ./my-extension
:
const puppeteer = require('puppeteer');
(async () => {
const pathToExtension = require('path').join(__dirname, 'my-extension');
const browser = puppeteer.launch({
headless: false,
args: [
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`
]
});
const targets = await browser.targets();
const backgroundPageTarget = targets.find(target => target.type() === 'background_page');
const backgroundPage = await backgroundPageTarget.page();
// 像处理任何其他页面一样测试背景页面。
await browser.close();
})();
注意 目前还无法测试扩展弹出窗口或内容脚本。