Puppeteer v1.5.0 中文翻译

最近用到了 Puppeteer 这个库,既然用到了这个东西,顺便也就把它的 API给看了一遍,为了加深印象,在看的同时也就顺便翻译了一下,不过这API文档的内容量还是蛮大的,花费了好些时间才看完,有些地方不知道怎么翻译比较好,所以也就没翻译,有的地方可能官方说得不怎么详细,我也加了一点主观意见。


Table of Contents


- Overview
- Environment Variables
- class: Puppeteer
* puppeteer.connect(options)
* puppeteer.createBrowserFetcher([options])
* puppeteer.defaultArgs()
* puppeteer.executablePath()
* puppeteer.launch([options])
- class: BrowserFetcher
* browserFetcher.canDownload(revision)
* browserFetcher.download(revision[, progressCallback])
* browserFetcher.localRevisions()
* browserFetcher.platform()
* browserFetcher.remove(revision)
* browserFetcher.revisionInfo(revision)
- class: Browser
* event: ‘disconnected’
* event: ‘targetchanged’
* event: ‘targetcreated’
* event: ‘targetdestroyed’
* browser.browserContexts()
* browser.close()
* browser.createIncognitoBrowserContext()
* browser.disconnect()
* browser.newPage()
* browser.pages()
* browser.process()
* browser.targets()
* browser.userAgent()
* browser.version()
* browser.wsEndpoint()
- class: BrowserContext
* event: ‘targetchanged’
* event: ‘targetcreated’
* event: ‘targetdestroyed’
* browserContext.browser()
* browserContext.close()
* browserContext.isIncognito()
* browserContext.newPage()
* browserContext.targets()
- class: Page
* event: ‘close’
* event: ‘console’
* event: ‘dialog’
* event: ‘domcontentloaded’
* event: ‘error’
* event: ‘frameattached’
* event: ‘framedetached’
* event: ‘framenavigated’
* event: ‘load’
* event: ‘metrics’
* event: ‘pageerror’
* event: ‘request’
* event: ‘requestfailed’
* event: ‘requestfinished’
* event: ‘response’
* event: ‘workercreated’
* event: ‘workerdestroyed’
* page.$(selector)
* page.

eval(selector, pageFunction[, …args])
* page.$eval(selector, pageFunction[, …args])
* page.$x(expression)
* page.addScriptTag(options)
* page.addStyleTag(options)
* page.authenticate(credentials)
* page.bringToFront()
* page.browser()
* page.click(selector[, options])
* page.close(options)
* page.content()
* page.cookies(…urls)
* page.coverage
* page.deleteCookie(…cookies)
* page.emulate(options)
* page.emulateMedia(mediaType)
* page.evaluate(pageFunction, …args)
* page.evaluateHandle(pageFunction, …args)
* page.evaluateOnNewDocument(pageFunction, …args)
* page.exposeFunction(name, puppeteerFunction)
* page.focus(selector)
* page.frames()
* page.goBack(options)
* page.goForward(options)
* page.goto(url, options)
* page.hover(selector)
* page.isClosed()
* page.keyboard
* page.mainFrame()
* page.metrics()
* page.mouse
* page.pdf(options)
* page.queryObjects(prototypeHandle)
* page.reload(options)
* page.screenshot([options])
* page.select(selector, …values)
* page.setBypassCSP(enabled)
* page.setCacheEnabled(enabled)
* page.setContent(html)
* page.setCookie(…cookies)
* page.setDefaultNavigationTimeout(timeout)
* page.setExtraHTTPHeaders(headers)
* page.setJavaScriptEnabled(enabled)
* page.setOfflineMode(enabled)
* page.setRequestInterception(value)
* page.setUserAgent(userAgent)
* page.setViewport(viewport)
* page.tap(selector)
* page.target()
* page.title()
* page.touchscreen
* page.tracing
* page.type(selector, text[, options])
* page.url()
* page.viewport()
* [page.waitFor(selectorOrFunctionOrTimeout[, options[, …args]])](#pagewaitforselectororfunctionortimeout-options-args)
* [page.waitForFunction(pageFunction[, options[, …args]])](#pagewaitforfunctionpagefunction-options-args)
* page.waitForNavigation(options)
* page.waitForSelector(selector[, options])
* page.waitForXPath(xpath[, options])
* page.workers()
- class: Worker
* worker.evaluate(pageFunction, …args)
* worker.evaluateHandle(pageFunction, …args)
* worker.executionContext()
* worker.url()
- class: Keyboard
* keyboard.down(key[, options])
* keyboard.press(key[, options])
* keyboard.sendCharacter(char)
* keyboard.type(text, options)
* keyboard.up(key)
- class: Mouse
* mouse.click(x, y, [options])
* mouse.down([options])
* mouse.move(x, y, [options])
* mouse.up([options])
- class: Touchscreen
* touchscreen.tap(x, y)
- class: Tracing
* tracing.start(options)
* tracing.stop()
- class: Dialog
* dialog.accept([promptText])
* dialog.defaultValue()
* dialog.dismiss()
* dialog.message()
* dialog.type()
- class: ConsoleMessage
* consoleMessage.args()
* consoleMessage.text()
* consoleMessage.type()
- class: Frame
* frame.$(selector)
* frame.
(selector)](#frameselector-1)  * [frame.
eval(selector, pageFunction[, …args])

* frame.$eval(selector, pageFunction[, …args])
* frame.$x(expression)
* frame.addScriptTag(options)
* frame.addStyleTag(options)
* frame.childFrames()
* frame.click(selector[, options])
* frame.content()
* frame.evaluate(pageFunction, …args)
* frame.evaluateHandle(pageFunction, …args)
* frame.executionContext()
* frame.focus(selector)
* frame.hover(selector)
* frame.isDetached()
* frame.name()
* frame.parentFrame()
* frame.select(selector, …values)
* frame.setContent(html)
* frame.tap(selector)
* frame.title()
* frame.type(selector, text[, options])
* frame.url()
* [frame.waitFor(selectorOrFunctionOrTimeout[, options[, …args]])](#framewaitforselectororfunctionortimeout-options-args)
* [frame.waitForFunction(pageFunction[, options[, …args]])](#framewaitforfunctionpagefunction-options-args)
* frame.waitForSelector(selector[, options])
* frame.waitForXPath(xpath[, options])
- class: ExecutionContext
* executionContext.evaluate(pageFunction, …args)
* executionContext.evaluateHandle(pageFunction, …args)
* executionContext.frame()
* executionContext.queryObjects(prototypeHandle)
- class: JSHandle
* jsHandle.asElement()
* jsHandle.dispose()
* jsHandle.executionContext()
* jsHandle.getProperties()
* jsHandle.getProperty(propertyName)
* jsHandle.jsonValue()
- class: ElementHandle
* elementHandle.$(selector)
* elementHandle.
(selector)](#elementhandleselector-1)  * [elementHandle.
eval(selector, pageFunction, …args)

* elementHandle.$eval(selector, pageFunction, …args)
* elementHandle.$x(expression)
* elementHandle.asElement()
* elementHandle.boundingBox()
* elementHandle.boxModel()
* elementHandle.click([options])
* elementHandle.contentFrame()
* elementHandle.dispose()
* elementHandle.executionContext()
* elementHandle.focus()
* elementHandle.getProperties()
* elementHandle.getProperty(propertyName)
* elementHandle.hover()
* elementHandle.jsonValue()
* elementHandle.press(key[, options])
* elementHandle.screenshot([options])
* elementHandle.tap()
* elementHandle.toString()
* elementHandle.type(text[, options])
* elementHandle.uploadFile(…filePaths)
- class: Request
* request.abort([errorCode])
* request.continue([overrides])
* request.failure()
* request.frame()
* request.headers()
* request.isNavigationRequest()
* request.method()
* request.postData()
* request.redirectChain()
* request.resourceType()
* request.respond(response)
* request.response()
* request.url()
- class: Response
* response.buffer()
* response.fromCache()
* response.fromServiceWorker()
* response.headers()
* response.json()
* response.ok()
* response.request()
* response.securityDetails()
* response.status()
* response.text()
* response.url()
- class: SecurityDetails
* securityDetails.issuer()
* securityDetails.protocol()
* securityDetails.subjectName()
* securityDetails.validFrom()
* securityDetails.validTo()
- class: Target
* target.browser()
* target.browserContext()
* target.createCDPSession()
* target.opener()
* target.page()
* target.type()
* target.url()
- class: CDPSession
* cdpSession.detach()
* cdpSession.send(method[, params])
- class: Coverage
* coverage.startCSSCoverage(options)
* coverage.startJSCoverage(options)
* coverage.stopCSSCoverage()
* coverage.stopJSCoverage()

Overview

Puppeteer是一个通过 DevTools Protocol 来控制 Chromium 或者 Chrome的 Node库,并提供了一些高级API。

这些API层级分明,并能提现出浏览器的自身结构。

NOTE 在下面这个图例中,浅色实体代表的结构尚未在 Puppeteer中实现。

puppeteer overview

  • Puppeteer 使用 DevTools Protocol与浏览器进行通信。
  • Browser 浏览器实例可以包含多个浏览器上下文。
  • BrowserContext 用于保持浏览器session,一个浏览器上下文可以包含多个页面。
  • Page 一个Page最起码包含一个frame,即 main frame,允许存在其他的 frame,这些frame可以用 [iframe]创建。
  • Frame 一个 Frame最起码有一个 Javascript执行上下文环境,即默认的执行上下文环境。Frame允许存在额外附加的上下文环境
  • Worker 存在唯一的上下文环境,并可与 WebWorkers相互协作。

(图例来源: link)

Environment Variables

Puppeteer 需要明确的 environment variables 来协助其完成一系列操作,如果 Puppeteer没有在打钱执行环境中发现这些环境变量,那么将会直接从 npm config搜寻(忽略大小写)。

  • HTTP_PROXY, HTTPS_PROXY, NO_PROXY - 定义了 HTTP proxy的相关配置,常用于下载或启动 Chromium。
  • PUPPETEER_SKIP_CHROMIUM_DOWNLOAD - 用于指示 Puppeteer不要在安装的过程中下载 Chromium安装包。
  • PUPPETEER_DOWNLOAD_HOST - 用于覆写下载 Chromium安装包的地址url。
  • PUPPETEER_CHROMIUM_REVISION - 在安装阶段,用于明确指示 Puppeteer下载安装哪个版本的 Chromium。

class: Puppeteer

Puppeteer模块提供了一个用于启动一个Chromium实例的方法。
下面的代码展示了一种使用 Puppeteer来启动 Chromium实例的典型例子:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://www.google.com');
  // other actions...
  await browser.close();
});

puppeteer.connect(options)

  • options <Object>
    • browserWSEndpoint <string> a browser websocket endpoint to connect to.
    • ignoreHTTPSErrors <boolean> 在导航阶段是否忽略 HTTPS错误,默认为 false.
    • slowMo <number> 通过改变此值来减缓 Puppeteer的操作速度,单位是毫秒,当你想知道具体发生了什么情况的时候,此参数将会比较有用。
  • returns: <Promise<Browser>>:以 Promise的形式返回了一个 Browser实例对象。

此方法将会为 Puppeteer 附加上一个 Chromium 实例。

puppeteer.createBrowserFetcher([options])

  • options <Object>
    • host <string> 下载链接的host,默认为 https://storage.googleapis.com
    • path <string> 下载链接的 path路径,默认为 <root>/.local-chromium, 这里的root指的是是 puppeteer包的根目录.
    • platform <string> 可能的选项有: mac, win32, win64, linux。默认是当前的环境平台。
  • returns: <BrowserFetcher>

puppeteer.defaultArgs()

  • returns: <Array<string>> The default flags that Chromium will be launched with.

puppeteer.executablePath()

  • returns: <string> Puppeteer将会在此路径中搜寻 Chromium包, 如果在 PUPPETEER_SKIP_CHROMIUM_DOWNLOAD阶段 Chromium包被跳过下载,那么此包也有可能是不存在的。

puppeteer.launch([options])

  • options <Object> 启动浏览器时的配置,可能存在如下字段:
    • ignoreHTTPSErrors <boolean> 是否忽略在导航阶段 HTTPS引发的错误,默认为false
    • headless <boolean> 是否以一种 headless mode的模式来启动浏览器。 只要devtools 选项不为true,那么此选项的默认值就是 true
    • executablePath <string> Chromium 或 Chrome 的运行路径而不是安装路径。 如果 executablePath 是一个相对目录, 那么它应该是相对于 current working directory
    • slowMo <number> 通过改变此值来减缓 Puppeteer的操作速度,单位是毫秒,当你想知道具体发生了什么情况的时候,此参数将会比较有用。
    • args <Array<string>> 传递给浏览器实例的额外参数,这些参数的可选列表可见与此
    • ignoreDefaultArgs <boolean> 将会使 puppeteer.defaultArgs()失效。 属于比较危险的选项,需要小心使用。默认为 false
    • handleSIGINT <boolean> 程序终止信号,通过按下 Ctrl-C 来关闭浏览器进程,默认为 true
    • handleSIGTERM <boolean> 程序结束信号,当接收到程序结束信号时,关闭浏览器进程,默认为 true
    • handleSIGHUP <boolean> 程序挂起信号,当接收到程序挂起信号时,关闭浏览器进程,默认为 true
    • timeout <number> 等待浏览器实例启动的超时时间,单位为 ms,默认是30000 (30秒),设置为 0标识禁用此选项。
    • dumpio <boolean> 是否将浏览器的输入、输出流连通到控制台的 process.stdoutprocess.stderr上。 默认为 false.
    • userDataDir <string> User Data Directory所在路径。
    • env <Object> 明确指示浏览器实例可用的环境变量,默认为 process.env
    • devtools <boolean> 是否为每个标签页自动打开 DevTools面板,如果为 true, 那么 headless选项将被设置为 false
    • pipe <boolean> 通过一个 pipe 而不是 WebSocket来链接浏览器实例,默认为 false
  • returns: <Promise<Browser>> 一个返回 浏览器实例的 Promise.

此方法根据给定的参数来启动一个浏览器实例,此浏览器实例将会在其 node.js主进程关闭时被销毁。

NOTE Puppeteer 也可以直接用于控制 Chrome浏览器, 不过,只有当其控制的 Chrome浏览器的版本和其本身绑定的 Chromium版本一致时才能最大程度地发挥作用,如果版本不一致,可能无法正常运行, 特别是当你使用了 executablePath 选项的时候。

如果你更想使用 Google Chrome (而不是Chromium) 的话, a Chrome Canary or Dev Channel build is suggested.

在上面的 puppeteer.launch([options]) 选项中, 所有提及到 Chromium 的地方同样适用于 Chrome。

你可以在这篇文章中找到 Chromium 与 Chrome之间的不同之处, 这篇文章 则介绍了一些在 Linux平台上的差异。

class: BrowserFetcher

BrowserFetcher 能够下载和管理不同版本的 Chromium。

BrowserFetcher 的方法可以接收一个 版本号字符串,此版本号指定精确的 Chromium版本,例如 "533271",版本号列表可以在 omahaproxy.appspot.com获取。

下面这里例子展示了如何通过 BrowserFetcher来下载一个特定版本的 Chromium,以及使用 Puppeteer来启动这个 Chromium。

const browserFetcher = puppeteer.createBrowserFetcher();
const revisionInfo = await browserFetcher.download('533271');
const browser = await puppeteer.launch({executablePath: revisionInfo.executablePath})

NOTE BrowserFetcher无法与其他使用相同下载目录的 BrowserFetcher实例同时运行。

browserFetcher.canDownload(revision)

  • revision <string> 检查是否可用版本的版本号。
  • returns: <Promise<boolean>> 如果目标版本的浏览器可以从目标 host上下载下来,则返回 true

此方法通过发起一个 HEAD request来检查目标版本是否可用。

browserFetcher.download(revision[, progressCallback])

  • revision <string> 需要下载的浏览器的版本号.
  • progressCallback <function(number, number)> 此函数方法存在两个参数:
    • downloadedBytes <number> 已经下载了多少字节
    • totalBytes <number> 一共有多少字节.
  • returns: <Promise<Object>> 当目标版本的浏览器正在被下载和提取的时候,返回一个 Promise 对象,此对象包含目标版本浏览器的一些信息。
    • revision <string> the revision the info was created from
    • folderPath <string> 提取所下载的浏览器包的目录
    • executablePath <string> 目标版本的浏览器的运行目录
    • url <string> 目标版本的浏览器的下载url
    • local <boolean> 目标版本的浏览器是否可在本地磁盘上获取

此方法通过发起一个 GET请求来从目标 host下载指定版本的浏览器。

browserFetcher.localRevisions()

  • returns: <Promise<Array<string>>> 本地磁盘可获取到的所有版本浏览器的列表。

browserFetcher.platform()

  • returns: <string> 返回 mac, linux, win32win64 中的其中一个。

browserFetcher.remove(revision)

  • revision <string> 需要删除的版本。如果指定的版本的浏览器并没有被下载下来,此方法将会抛出错误(此错误可用 catch捕获)。
  • returns: <Promise> 当指定版本的浏览器被删除后返回一个 Promise。

browserFetcher.revisionInfo(revision)

  • revision <string> 希望获取相关信息的浏览器的版本号。
  • returns: <Object>

    • revision <string> 信息来源的版本号
    • folderPath <string> 提取所下载的浏览器包的目录
    • executablePath <string> 目标版本的浏览器的运行目录
    • url <string> 目标版本的浏览器的下载url
    • local <boolean> 目标版本的浏览器是否可在本地磁盘上获取

    class: Browser

  • extends: EventEmitter

当 Puppeteer 连接上一个 Chromium实例的时候,将会puppeteer.launch 或者 puppeteer.connect方法产生一个 Browser。

下面是一个使用 Browser 来创建一个 Page的例子 :

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await browser.close();
});

下面是一个使用 Browser 来断开连接和重连的例子:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  // Store the endpoint to be able to reconnect to Chromium
  const browserWSEndpoint = browser.wsEndpoint();
  // Disconnect puppeteer from Chromium
  browser.disconnect();

  // Use the endpoint to reestablish a connection
  const browser2 = await puppeteer.connect({browserWSEndpoint});
  // Close Chromium
  await browser2.close();
});

event: ‘disconnected’

当 Puppeteer被从 Chromium实例上断开时被触发,包括如下几种情形:
- Chromium 被关闭或崩溃
- The browser.disconnect 方法被调用

event: ‘targetchanged’

当目标 url改变时触发。

NOTE 包括在匿名浏览器上下文中目标URL改变。

event: ‘targetcreated’

当目标被创建时触发, 例如,当一个新页面通过 window.open 或者 browser.newPage被打开时。

NOTE 包括在匿名浏览器上下文中目标的创建。

event: ‘targetdestroyed’

目标被销毁时触发, 例如,当一个页面关闭时。

NOTE 包括在匿名浏览器上下文中目标的销毁。

browser.browserContexts()

返回一个包含所有已经被打开的浏览器上下文的数组。 在一个最新被创建的浏览器中,将会返回一个唯一的BrowserContext的实例。

browser.close()

关闭 Chromium以及它所有的页面(如果存在被打开的页面的话)。Browser 对象将会被销毁,并且不再可用。

browser.createIncognitoBrowserContext()

创建一个新的匿名浏览器上下文,这个匿名浏览器上下文不会与其他浏览器上下文共享 cookies/cache。

const browser = await puppeteer.launch();
// Create a new incognito browser context.
const context = await browser.createIncognitoBrowserContext();
// Create a new page in a pristine context.
const page = await context.newPage();
// Do stuff
await page.goto('https://example.com');

browser.disconnect()

Disconnects Puppeteer from the browser, but leaves the Chromium process running. After calling disconnect, the Browser object is considered disposed and cannot be used anymore.

断开 Puppeteer与 浏览器之间的连接,不过 Chromium进程依旧继续运行。当调用了disconnect方法之后,Browser 对象将会被销毁,并且不再可用。

browser.newPage()

返回一个新的 Page Promise对象,Page将在一个默认的浏览器上下文中创建。

browser.pages()

  • returns: <Promise<Array<Page>>> resolve一个包含所有打开页面的数组,不可见的页面,例如 "background_page", 将不会包含在此数组中,你可以使用 target.page()方法来获取到(不可见页面)。

browser.process()

  • returns:

browser.targets()

An array of all active targets inside the Browser. In case of multiple browser contexts,
the method will return an array with all the targets in all browser contexts.

返回Browser实例中包含的所有的有效targets的一个数组,由于可能存在多个浏览器上下文,所以此方法将会返回一个由所有浏览器上下文中的所有 targets梭组成的数组。

browser.userAgent()

NOTE 可以使用 page.setUserAgent来改变浏览器的 user agent。

browser.version()

  • returns: <Promise<string>> 对于 headless Chromium来说,将返回一个类似于 HeadlessChrome/61.0.3153.0的字符串。 对于non-headless 浏览器来说, 将返回一个类似于 Chrome/61.0.3153.0的字符串。

NOTE 此方法返回的字符串格式可能会在将来的版本中发生变化。

browser.wsEndpoint()

  • returns: <string> 浏览器 websoket 的url。

此方法返回的 浏览器 websoket端口字符串格式如:ws://${host}:${port}/devtools/browser/<id>,此字符串可作为puppeteer.connect方法的一个参数传入。

You can find the webSocketDebuggerUrl from http://${host}:${port}/json/version. Learn more about the devtools protocol and the browser endpoint.

class: BrowserContext

BrowserContexts提供了一种操作多个独立浏览器session的方法。当启动一个浏览器的时候,将会同时产生一个BrowserContext,并且在这个 BrowserContext中,browser.newPage() 方法将会创建一个新页面。

如果使用例如 window.open的方法创建了另外的页面, the popup 将隶属于父页面的浏览器上下文。

Puppeteer允许通过 browser.createIncognitoBrowserContext() 方法来创建匿名浏览器上下文,匿名浏览器上下文不会向磁盘中记录任何浏览的内容。

// 创建匿名浏览器上下文
const context = await browser.createIncognitoBrowserContext();
// 在上下文中创建页面
const page = await context.newPage();
// ... do stuff with page ...
await page.goto('https://example.com');
// Dispose context once it's no longer needed.
await context.close();

event: ‘targetchanged’

当浏览器上下文中的某个target url改变时触发。

event: ‘targetcreated’

当浏览器上下文中创建了一个新target时触发,例如,当使用 window.openbrowserContext.newPage方法创建一个新页面的时候。

event: ‘targetdestroyed’

当浏览器上下文中的某个target 被销毁时触发,例如当一个页面被关闭时。

browserContext.browser()

浏览器上下文归属的浏览器实例。

browserContext.close()

关闭浏览器上下文。所有属于此浏览器上下文的target都将会一同销毁。

NOTE 只有匿名浏览器上下文可以被关闭(也就是只有通过 createIncognitoBrowserContext方法创建的匿名浏览器才可以使用此方法)。

browserContext.isIncognito()

  • returns: <boolean>
    返回 BrowserContext 是否是匿名的。
    浏览器的默认上下文是非匿名的。

NOTE 浏览器的默认浏览器上下文是不可关闭的。

browserContext.newPage()

在浏览器上下文中创建新页面。

browserContext.targets()

浏览器上下文中的所有有效target(例如Page页面)组成的一个数组。

class: Page

Page提供了一些能让你操作 Chromium中标签页的方法。一个 Browser实例中可能包含多个 Page实例。

下面的例子展示了如何创建一个地址为指定url的页面,并将这个页面保存为一张图片。

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'screenshot.png'});
  await browser.close();
});

使用 Node模块EventEmitter的一些方法,我们能够控制 Page类触发的一些事件,例如 on once 或者 removeListener等。

下面的例子展示了如何监听页面的 load事件。

page.once('load', () => console.log('Page loaded!'));

使用 removeListener方法来移除监听事件:

function logRequest(interceptedRequest) {
  console.log('A request was made:', interceptedRequest.url());
}
page.on('request', logRequest);
// Sometime later...
page.removeListener('request', logRequest);

event: ‘close’

当页面关闭的时候触发。

event: ‘console’

当页面上的Javascript脚本调用一些类似于 console.logconsole.dir的 console API时触发,除此之外,如果页面上的脚本抛出错误或者警告同样也会触发。

The arguments passed into console.log appear as arguments on the event handler.

下面是一个监听 console事件的例子:

page.on('console', msg => {
  for (let i = 0; i < msg.args().length; ++i)
    console.log(`${i}: ${msg.args()[i]}`);
});
page.evaluate(() => console.log('hello', 5, {foo: 'bar'}));

event: ‘dialog’

当页面上弹出 JavaScript对话框的时候触发,例如 alert, prompt, confirm 或者 beforeunload。Puppeteer能够通过 Dialogaccept 或者 dismiss 方法来对此事件作出回应。

event: ‘domcontentloaded’

当 JavaScript 的DOMContentLoaded 事件被触发时触发。

event: ‘error’

当页面崩溃时触发。

NOTE error 事件在 Node中具有特殊的含义,具体细节参见 error events

event: ‘frameattached’

当一个 frame 被附加到主页面上时触发。

event: ‘framedetached’

当一个 frame 从主页面上分离(删除)时触发。

event: ‘framenavigated’

当一个 frame 的url被定向到一个新的url上时触发。

event: ‘load’

当 JavaScript 的load 事件被触发时触发。

event: ‘metrics’

  • <Object>
    • title <string> console.timeStamp 的 title
    • metrics <Object> Object containing metrics as key/value pairs. The values
      of metrics are of <number> type.一个包含 metrics key/value对的对象。metrics的值为 number类型。

当页面上的JavaScript脚本调用 cnosole.timeStamp时触发。metrics的可选列表可见 page.metrics

event: ‘pageerror’

  • <Error> The exception message

当页面上出现未捕获的异常时触发。

event: ‘request’

当页面上发起一个请求的时候触发。request对象是只读的,如果你想拦截并改造请求,参照 page.setRequestInterception

event: ‘requestfailed’

当请求失败时触发,例如,请求超时。

event: ‘requestfinished’

当请求完成时触发。

event: ‘response’

当页面收到请求的响应时触发。

event: ‘workercreated’

当页面上产生一个新的 WebWorker线程时触发。

event: ‘workerdestroyed’

当页面上有 WebWorker线程结束时触发。

page.$(selector)

page.$$(selector)

此方法在页面上使用了 document.querySelectorAll。如果选择器没有匹配到元素,将会返回 []

page.mainFrame().$$(selector)的快捷方法。

page.$$eval(selector, pageFunction[, …args])

此方法在页面上使用了 Array.from(document.querySelectorAll(selector)),并将获取到的结果当做 pageFunction的第一个参数传递进去。

如果 pageFunction返回的结果是一个 Promise,则page.$$eval将会等到前者 resolve回一个结果后,才会继续返回自己的值。

例子:

const divsCounts = await page.$$eval('div', divs => divs.length);

page.$eval(selector, pageFunction[, …args])

此方法在页面上使用了 document.querySelector,并将获取到的结果当做 pageFunction的第一个参数传递进去。如果选择器没有匹配到元素,则将抛出一个错误。

如果 pageFunction返回的结果是一个 Promise,则page.$eval将会等到前者 resolve回一个结果后,才会继续返回自己的值。

例子:

const searchValue = await page.$eval('#search', el => el.value);
const preloadHref = await page.$eval('link[rel=preload]', el => el.href);
const html = await page.$eval('.main-container', e => e.outerHTML);

page.mainFrame().$eval(selector, pageFunction)的快捷方法。

#### page.$x(expression)
- expression <string> Expression to evaluate.
- returns: <Promise<Array<ElementHandle>>>

根据给定的 Xpath表达式获取 DOM元素。

page.mainFrame().$x(expression)的快捷方法。

page.addScriptTag(options)

  • options <Object>
    • url <string> 将要被添加的 script 的url.
    • path <string> 将要被添加的JavaScript文件的路径. 如果 path 是相对路径, 则其是相对于 current working directory
    • content <string> 将要被添加的JavaScript脚本的内容。
    • type <string> 脚本类型. 如果是 ‘module’ ,则将导入的是JS的 ES6模块。更多参见 script
  • returns: <Promise<ElementHandle>> 当script脚本加载完毕,或者脚本内容已经注入到页面上时,将会返回所添加的script标签元素。

向页面中增加指定 url或者 脚本内容的 script标签。

page.mainFrame().addScriptTag(options)的快捷方法。

page.addStyleTag(options)

  • options <Object>
    • url <string> 将要被添加的 style 的url
    • path <string> 将要被添加的 CSS文件的路径. 如果 path 是相对路径, 则其是相对于 current working directory
    • content <string> 将要被添加的CSS脚本的内容。
  • returns: <Promise<ElementHandle>>当style加载完毕,或者style内容已经注入到页面上时,将会返回所添加的style标签元素。

向页面中添加一个 带有指定 url的<link rel="stylesheet">标签,或者一个带有内容的<style type="text/css">标签。

page.mainFrame().addStyleTag(options)的快捷方法。

page.authenticate(credentials)

  • credentials

page.bringToFront()

Brings page to front (activates tab).

page.browser()

获取页面所属的 browser实例。

page.click(selector[, options])

  • selector <string> 将要被点击的元素的 选择器。如果选择器匹配出了多个元素,则点击事件只会作用在第一个匹配的元素上。
  • options <Object>
    • button <string> left, right, or middle, 默认是 left(即使用左键、右键还是中键进行点击操作)
    • clickCount <number> 默认点击一次。 更多参见UIEvent.detail
    • delay <number> mousedownmouseup 事件之间的时间间隔. 默认为 0.
  • returns: <Promise> 当匹配的元素被成功点击时将会resolve,如果没有匹配到元素,则将 reject。

此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 page.mouse方法点击匹配到的元素的中心位置。
如果没有匹配到元素,则将抛出一个错误。

需要注意的是,如果所点击的元素会触发页面跳转,并且还调用了page.waitForNavigation()方法,那么你可能不会得到期望的结果,正确的做法如下:

const [response] = await Promise.all([
  page.waitForNavigation(waitOptions),
  page.click(selector, clickOptions),
]);

page.mainFrame().click(selector[, options])的快捷方法。

page.close(options)

page.close()方法默认不调用 beforeunload句柄。

(这个方法的意思是,如果页面上注册了 onbeforeunload方法,那么在关闭页面时,将会调用这个onbeforeunload方法,如果 puppeteer.launchheadless参数设置为 true,那么你将看到页面在关闭时,弹出了一个询问是否离开页面的对话框)。

NOTE 如果runBeforeUnload 为 true, 页面在关闭时可能会弹出 beforeunload 对话框,
并且这个对话框可以被 page的 ‘dialog’事件捕获到.

page.content()

获取页面上包括 doctype在内的所有 HTML内容。

page.cookies(…urls)

如果没有提供 URLs,则此方法将会返回当前页面URL的 cookies。
如果指定了URLs,则只有这些指定URLS上的cookies才会被返回。

page.coverage

page.deleteCookie(…cookies)

page.emulate(options)

  • options <Object>
    • viewport <Object>
    • width <number> page width in pixels.
    • height <number> page height in pixels.
    • deviceScaleFactor <number> Specify device scale factor (can be thought of as dpr). Defaults to 1.
    • isMobile <boolean> Whether the meta viewport tag is taken into account. Defaults to false.
    • hasTouch<boolean> Specifies if viewport supports touch events. Defaults to false
    • isLandscape <boolean> Specifies if viewport is in landscape mode. Defaults to false.
    • userAgent <string>
  • returns: <Promise>

Emulates given device metrics and user agent. This method is a shortcut for calling two methods:
- page.setUserAgent(userAgent)
- page.setViewport(viewport)

puppeteer提供了一些描述设备信息的参数,这些参数可以通过 require('puppeteer/DeviceDescriptors')命令查看。
下面是一个使用 puppeteer模拟 iPhone 6的例子。

const puppeteer = require('puppeteer');
const devices = require('puppeteer/DeviceDescriptors');
const iPhone = devices['iPhone 6'];

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.emulate(iPhone);
  await page.goto('https://www.google.com');
  // other actions...
  await browser.close();
});

所有能够模拟的设备可以在DeviceDescriptors.js中找到。

page.emulateMedia(mediaType)

  • mediaType

page.evaluate(pageFunction, …args)

如果传递给 page.evaluatepageFunction函数返回一个 Promise,则page.evaluate将会等待得到resolve后,才会返回它自己的值。

如果传递给 page.evaluatepageFunction函数返回一个 non-Serializable的值,则page.evaluate将会返回 undefined

pageFunction传递参数:

const result = await page.evaluate(x => {
  return Promise.resolve(8 * x);
}, 7);
console.log(result); // prints "56"

可以传递一个字符串作为 pageFunction

console.log(await page.evaluate('1 + 2')); // prints "3"
const x = 10;
console.log(await page.evaluate(`1 + ${x}`)); // prints "11"

可以传递一个ElementHandle 作为 pageFunction参数:

const bodyHandle = await page.$('body');
const html = await page.evaluate(body => body.innerHTML, bodyHandle);
await bodyHandle.dispose();

page.mainFrame().evaluate(pageFunction, …args)的快捷方法。

page.evaluateHandle(pageFunction, …args)

  • pageFunction <function|string> 在page context 中执行的函数。
  • ...args <…Serializable|JSHandle> 传递给 pageFunction的参数
  • returns: <Promise<JSHandle>> Promise which resolves to the return value of pageFunction as in-page object (JSHandle)。

page.evaluatepage.evaluateHandle之间唯一的差别是,page.evaluateHandle返回的结果是 in-page object (JSHandle)。
(可能指的是此方法只返回页面元素的句柄,即此方法可以看作一个元素选择器)

如果传入 page.evaluateHandle的函数 返回的值是一个 Promise,则page.evaluateHandle将会等待这个 Promise到达resolve时才会返回自己的值。

可以传递一个 字符串作为 pageFunction

const aHandle = await page.evaluateHandle('document'); // Handle for the 'document'

JSHandle instances也可以作为page.evaluateHandle的传入参数:

const aHandle = await page.evaluateHandle(() => document.body);
const resultHandle = await page.evaluateHandle(body => body.innerHTML, aHandle);
console.log(await resultHandle.jsonValue());
await resultHandle.dispose();

page.mainFrame().executionContext().evaluateHandle(pageFunction, …args)的快捷方法。

page.evaluateOnNewDocument(pageFunction, …args)

pageFunction可能会在以下情况下呗调用:
Adds a function which would be invoked in one of the following scenarios:
- 页面重定向
- 子frame重定向或者增加新的子frame。在这种情况下,pageFunction将会在子frame中执行。

pageFunction会在文档(document)加载完毕后以及页面上JS脚本执行之前被调用,This is useful to amend the JavaScript environment, e.g. to seed Math.random.

下面是一个在页面加载之前重写 navigator.languages属性的例子:

// preload.js

// overwrite the `languages` property to use a custom getter
Object.defineProperty(navigator, "languages", {
  get: function() {
    return ["en-US", "en", "bn"];
  }
});

// In your puppeteer script, assuming the preload.js file is in same folder of our script
const preloadFile = fs.readFileSync('./preload.js', 'utf8');
await page.evaluateOnNewDocument(preloadFile);

page.exposeFunction(name, puppeteerFunction)

  • name <string> 在 window对象中添加的函数的名字
  • puppeteerFunction <function> 将会在 Puppeteer’s context中执行的函数。
  • returns: <Promise>

此方法将会在 window对象中添加一个 名为 name的函数。
当被调用时,其将会在 node.js中执行 puppeteerFunction,并且返回一个 Promise,此PromiseresolvepuppeteerFunction的返回结果。

如果puppeteerFunction返回的结果是一个 Promise,则此方法将会等到前者 Promise resolve之后,才会返回自己的 Promise

NOTE Functions installed via page.exposeFunction survive navigations.

下面是一个在页面中添加 md5函数的例子:

const puppeteer = require('puppeteer');
const crypto = require('crypto');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  page.on('console', msg => console.log(msg.text()));
  await page.exposeFunction('md5', text =>
    crypto.createHash('md5').update(text).digest('hex')
  );
  await page.evaluate(async () => {
    // use window.md5 to compute hashes
    const myString = 'PUPPETEER';
    const myHash = await window.md5(myString);
    console.log(`md5 of ${myString} is ${myHash}`);
  });
  await browser.close();
});

下面是一个在页面中添加 window.readfile函数的例子:

const puppeteer = require('puppeteer');
const fs = require('fs');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  page.on('console', msg => console.log(msg.text()));
  await page.exposeFunction('readfile', async filePath => {
    return new Promise((resolve, reject) => {
      fs.readFile(filePath, 'utf8', (err, text) => {
        if (err)
          reject(err);
        else
          resolve(text);
      });
    });
  });
  await page.evaluate(async () => {
    // use window.readfile to read contents of a file
    const content = await window.readfile('/etc/hosts');
    console.log(content);
  });
  await browser.close();
});

page.focus(selector)

  • selector <string> 需要focus的元素的选择器。 如果此选择器匹配到了多个元素,则只有第一个匹配的元素才会被focus。
  • returns: <Promise> 当成功匹配到元素后,Promise将resolve。如果没有匹配到任何元素,则将reject。

此方法将 focus给定 selector匹配到的元素。
如果根据给定的 selector没有匹配到任何元素,将会抛出异常。

page.mainFrame().focus(selector)的快捷方法。

page.frames()

  • returns: <Array<Frame>> 返回一个有页面上附加的所有 frames组成的数组。

page.goBack(options)

  • options <Object> 页面跳转参数,包括以下属性:
    • timeout <number> 连接超时时间,单位毫秒, 默认是 30秒, 如果设置为 0则表示禁用此选项。 此值也可以被 page.setDefaultNavigationTimeout(timeout) 方法修改。
    • waitUntil <string|Array<string>> 确认navigation成功的条件, 默认是load。如果给定的值是一个事件名称组成的数组,那么只有当数组中的所有事件全部被触发后才会认为 navigation成功,可选的事件列表如下:
    • load - consider navigation to be finished when the load event is fired.
    • domcontentloaded - consider navigation to be finished when the DOMContentLoaded event is fired.
    • networkidle0 - 如果在 500ms内发起的http请求数为0,则认为导航结束。
    • networkidle2 - 如果在 500ms内发起的http请求数为不超过 2条,则认为导航结束。
  • returns: <Promise

page.goForward(options)

  • options <Object> 页面跳转参数,包括以下属性:
    • timeout <number> 连接超时时间,单位毫秒, 默认是 30秒, 如果设置为 0则表示禁用此选项。 此值也可以被 page.setDefaultNavigationTimeout(timeout) 方法修改。
    • waitUntil <string|Array<string>> 确认navigation成功的条件, 默认是load。如果给定的值是一个事件组成的数组,那么只有当数组中的所有事件全部被触发后才会认为 navigation成功,可选的事件列表如下:
    • load - consider navigation to be finished when the load event is fired.
    • domcontentloaded - consider navigation to be finished when the DOMContentLoaded event is fired.
    • networkidle0 - 如果在 500ms内发起的http请求数为0,则认为导航结束。
    • networkidle2 - 如果在 500ms内发起的http请求数为不超过 2条,则认为导航结束。
  • returns: <Promise

page.goto(url, options)

  • url <string> 目标页面的url. url中应该包含协议头,例如 https://
  • options <Object> 页面跳转参数,包括以下属性:
    • timeout <number> 连接超时时间,单位毫秒, 默认是 30秒, 如果设置为 0则表示禁用此选项。 此值也可以被 page.setDefaultNavigationTimeout(timeout) 方法修改。
    • waitUntil <string|Array<string>> 确认navigation成功的条件, 默认是load。如果给定的值是一个事件组成的数组,那么只有当数组中的所有事件全部被触发后才会认为 navigation成功,可选的事件列表如下:
    • load - 当 load 事件触发时,则认为 navigation导航结束。
    • domcontentloaded - 当 DOMContentLoaded 事件触发时,则认为 navigation导航结束。
    • networkidle0 - 如果在 500ms内发起的http请求数为0,则认为导航结束。
    • networkidle2 - 如果在 500ms内发起的http请求数为不超过 2条,则认为导航结束。
  • returns: <Promise

page.hover(selector)

  • selector <string> 需要 hover的元素的选择器。 如果此选择器匹配到了多个元素,则只有第一个匹配的元素才会被hover。
  • returns: <Promise> 当成功匹配到元素后,Promise将resolve。如果没有匹配到任何元素,则将reject。

此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 page.mouse方法 hover匹配到的元素的中心位置。
如果没有匹配到元素,则将抛出一个错误。

page.mainFrame().hover(selector)的快捷方法。

page.isClosed()

  • returns: boolean

页面是否被关闭。

page.keyboard

page.mainFrame()

  • returns: <Frame> 返回页面的 主frame。

navigations过程中,Page一直存在一个 main frame。

page.metrics()

  • returns: <Promise<Object>> Object containing metrics as key/value pairs.
    • Timestamp <number> The timestamp when the metrics sample was taken.
    • Documents <number> Number of documents in the page.
    • Frames <number> Number of frames in the page.
    • JSEventListeners <number> Number of events in the page.
    • Nodes <number> Number of DOM nodes in the page.
    • LayoutCount <number> Total number of full or partial page layout.
    • RecalcStyleCount <number> Total number of page style recalculations.
    • LayoutDuration <number> Combined durations of all page layouts.
    • RecalcStyleDuration <number> Combined duration of all page style recalculations.
    • ScriptDuration <number> Combined duration of JavaScript execution.
    • TaskDuration <number> Combined duration of all tasks performed by the browser.
    • JSHeapUsedSize <number> Used JavaScript heap size.
    • JSHeapTotalSize <number> Total JavaScript heap size.

NOTE All timestamps are in monotonic time: monotonically increasing time in seconds since an arbitrary point in the past.

page.mouse

page.pdf(options)

  • options <Object> 具备以下属性的参数对象:
    • path <string> 保存PDF文件的路径. 如果path 是一个相对路径,则它是相对于current working directory. 如果没有提供此值项值, 将不会保存PDF。
    • scale <number> 网页缩放的值。默认为 1.
    • displayHeaderFooter <boolean> Display header and footer. Defaults to false.
    • headerTemplate <string> HTML template for the print header. Should be valid HTML markup with following classes used to inject printing values into them:
    • date formatted print date
    • title 文档标题
    • url 文档url
    • pageNumber 当前页码
    • totalPages 总页数
    • footerTemplate <string> HTML template for the print footer. Should use the same format as the headerTemplate.
    • printBackground <boolean> Print background graphics. Defaults to false.
    • landscape <boolean> Paper orientation. Defaults to false.
    • pageRanges <string> Paper ranges to print, e.g., ‘1-5, 8, 11-13’. Defaults to the empty string, which means print all pages.
    • format <string> Paper format. If set, takes priority over width or height options. Defaults to ‘Letter’.
    • width <string> Paper width, accepts values labeled with units.
    • height <string> Paper height, accepts values labeled with units.
    • margin <Object> Paper margins, defaults to none.
    • top <string> Top margin, accepts values labeled with units.
    • right <string> Right margin, accepts values labeled with units.
    • bottom <string> Bottom margin, accepts values labeled with units.
    • left <string> Left margin, accepts values labeled with units.
  • returns: <Promise<Buffer>> Promise which resolves with PDF buffer.

NOTE 生成pdf的操作只有Chrome浏览器才有效。

page.pdf()print的 css media生成pdf,如果想生成一个 screenmedia的PDF,请在使用 page.pdf()之前调用page.emulateMedia(‘screen’)方法。

// Generates a PDF with 'screen' media type.
await page.emulateMedia('screen');
await page.pdf({path: 'page.pdf'});

width, height, 和 margin属性接受的值应该明确带上相应的单位,否则将会被默认为 px单位。

一些例子:
- page.pdf({width: 100}) - 宽度为100px
- page.pdf({width: '100px'}) - 宽度为100px
- page.pdf({width: '10cm'}) - 宽度为 10厘米

所有可选的单位:
- px - pixel
- in - inch
- cm - centimeter
- mm - millimeter

format 属性的可选值:
- Letter: 8.5in x 11in
- Legal: 8.5in x 14in
- Tabloid: 11in x 17in
- Ledger: 17in x 11in
- A0: 33.1in x 46.8in
- A1: 23.4in x 33.1in
- A2: 16.5in x 23.4in
- A3: 11.7in x 16.5in
- A4: 8.27in x 11.7in
- A5: 5.83in x 8.27in
- A6: 4.13in x 5.83in

NOTE headerTemplate 以及 footerTemplate的标签有以下限制:
1. Script tags inside templates are not evaluated.
2. Page styles are not visible inside templates.

page.queryObjects(prototypeHandle)

  • prototypeHandle <JSHandle> A handle to the object prototype.
  • returns: <Promise<JSHandle>> Promise which resolves to a handle to an array of objects with this prototype.

此方法迭代给定的JavaScript堆的prototype,返回prototype上的所有对象

// Create a Map object
await page.evaluate(() => window.map = new Map());
// Get a handle to the Map object prototype
const mapPrototype = await page.evaluateHandle(() => Map.prototype);
// Query all map instances into an array
const mapInstances = await page.queryObjects(mapPrototype);
// Count amount of map objects in heap
const count = await page.evaluate(maps => maps.length, mapInstances);
await mapInstances.dispose();
await mapPrototype.dispose();

page.mainFrame().executionContext().queryObjects(prototypeHandle)的快捷方法。

page.reload(options)

  • options <Object> navigation 参数,允许具备以下属性:
    • timeout <number> 超时时间,单位为ms,默认为 30s, 如果设置为 0表示禁用此属性。也可以使用page.setDefaultNavigationTimeout(timeout) 方法来改变此值。
    • waitUntil <string|Array<string>> 确认navigation成功的条件, 默认是load。如果给定的值是一个事件组成的数组,那么只有当数组中的所有事件全部被触发后才会认为 navigation成功,可选的事件列表如下:
    • load - consider navigation to be finished when the load event is fired.
    • domcontentloaded - consider navigation to be finished when the DOMContentLoaded event is fired.
    • networkidle0 - 如果在 500ms内发起的http请求数为0,则认为导航结束。
    • networkidle2 - 如果在 500ms内发起的http请求数不超过 2条,则认为导航结束。
  • returns: <Promise<Response>> Promise which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect.

page.screenshot([options])

  • options <Object> 此对象允许具备以下属性:
    • path <string> 截图保存的地址路径。 截图的图片类型会自动根据文件名扩展来确定。如果 path是相对路径,则其应当是相对于 current working directory.。如果没有提供此属性值,则将不会保存截图。
    • type <string> 指定截图的文件类型。可选值有jpegpng。默认为 ‘png’。
    • quality <number> 图片质量, 值范围为 0-100。不适用于 png 图片。
    • fullPage <boolean> 当值为 true的话,则将截取包括可滚动区域在内的所有页面。默认为 false.
    • clip <Object> 用于确定一个指定的裁剪范围。必须具备以下属性:
    • x <number> x-coordinate of top-left corner of clip area裁剪范围的左上角的 x点坐标
    • y <number> 裁剪范围的左上角的 y点坐标
    • width <number> 裁剪范围的宽度
    • height <number> 裁剪范围的高度
    • omitBackground <boolean> 隐藏默认白色背景,并允许以透明方式截取屏幕截图。 默认为false.
    • encoding <string> 图片编码方式,可以是 base64 或者 binary。默认为 binary.
  • returns: <Promise<[Buffer|String]>> 返回一个Promise,此Promise的resolve值是截图的 buffer或者 base64编码数据的字符串。

NOTE 在OS X系统上,截图操作最少需要 1/6秒的时间。参见 https://crbug.com/741689

page.select(selector, …values)

  • selector <string> [select]标签的选择器
  • ...values <…string> 选择的值。如果 <select> 标签具有 multiple 属性, 所有的指定值都是有效值, 否则只会考虑第一个值。
  • returns: <Promise<Array<string>>> 返回一个由所有成功选中(selected)的选项(option)的值组成的数组。

当所有提供的 values值的选项(option)全被选中后会触发 change 以及 input事件。
如果根据所指定的选择器selector没有匹配到一个 <select>元素,将会抛出错误。
(这个方法就是用于控制 select的选择)

page.select('select#colors', 'blue'); // 单选
page.select('select#colors', 'red', 'green', 'blue'); // 多选

Shortcut for page.mainFrame().select()

page.setBypassCSP(enabled)

  • enabled <boolean> 设置是否绕过页面的Content-Security-Policy(内容安全策略)。
  • returns: <Promise>

控制是否绕过页面的Content-Security-Policy(内容安全策略)。

NOTE 绕过CSP的操作应该发生在CSP的初始化阶段而不是执行阶段。也就是说,在 navigating向目标主机之前就应该调用page.setBypassCSP方法。

page.setCacheEnabled(enabled)

  • enabled <boolean> sets the enabled state of the cache.
  • returns: <Promise>

是否使用资源缓存,默认启用缓存。
Toggles ignoring cache for each request based on the enabled state. By default, caching is enabled.

page.setContent(html)

  • html <string> 设置page页面的HTML内容。
  • returns: <Promise>

page.setCookie(…cookies)

page.setDefaultNavigationTimeout(timeout)

  • timeout <number> 导航超时时间。

此方法可以改变以下方法默认 30s的超时时间。
- page.goto(url, options)
- page.goBack(options)
- page.goForward(options)
- page.reload(options)
- page.waitForNavigation(options)

page.setExtraHTTPHeaders(headers)

  • headers <Object> 一个将为所有的请求增添额外 header属性的对象。所有的header值必须都是 string类型。
  • returns: <Promise>

这些额外的 header头将会被页面发出的所有请求链接携带上。

NOTE page.setExtraHTTPHeaders 无法保证请求header的顺序。

page.setJavaScriptEnabled(enabled)

  • enabled <boolean> 是否启用页面的 JavaScript。
  • returns: <Promise>

NOTE 改变此值无法影响到那些已经执行的 JS代码。不过会在下次导航 navigation中完全起作用。

page.setOfflineMode(enabled)

  • enabled <boolean> 当设置为 true时, 将会启用页面的离线模式。
  • returns: <Promise>

page.setRequestInterception(value)

启用请求拦截将会使request.abort, request.continue 以及 request.respond方法可用。这提供了能够修改页面请求的能力。

下面的例子展示如何拦截请求并断掉(abort)掉所有的图片请求:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.setRequestInterception(true);
  page.on('request', interceptedRequest => {
    if (interceptedRequest.url().endsWith('.png') || interceptedRequest.url().endsWith('.jpg'))
      interceptedRequest.abort();
    else
      interceptedRequest.continue();
  });
  await page.goto('https://example.com');
  await browser.close();
});

NOTE 启用请求拦截将会禁用页面缓存(也就是请求不再使用页面缓存)。

page.setUserAgent(userAgent)

  • userAgent <string> 指定页面的 user agent
  • returns: <Promise> resolve页面的 user agent

page.setViewport(viewport)

  • viewport <Object>
    • width <number> 页面的宽度,单位为px
    • height <number> 页面的高度,单位为px
    • deviceScaleFactor <number> 指定页面缩放比例 (can be thought of as dpr). 默认为 1.
    • isMobile <boolean> 是否考虑 meta viewport 标签。 默认为 false.
    • hasTouch<boolean> 设置 viewport是否支持触摸事件。 默认为 false
    • isLandscape <boolean> 设置 viewport是否是 landscape mode。 默认为 false.
  • returns: <Promise>

NOTE 在某些的情况下,设置 viewportin 将会导致页面 reload 以便让 isMobile 或者 hasTouch属性生效。

如果一个浏览器中开启了多个页面,则每个页面都有其自己的 viewport大小。

page.tap(selector)

  • selector <string> 将要被tap的元素的 选择器。如果选择器匹配出了多个元素,则tap事件只会作用在第一个匹配的元素上。
  • returns: <Promise>

此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 page.touchscreen方法tap匹配到的元素的中心位置。
如果没有匹配到元素,则将抛出一个错误。

page.mainFrame().tap(selector)的快捷方法。

page.target()

  • returns: <Target> a target this page was created from.

page.title()

page.mainFrame().title()的快捷方法。

page.touchscreen

page.tracing

page.type(selector, text[, options])

  • selector <string> 文本框(包括 texarea和input)的选择器。如果选择器匹配出了多个元素,则只会选择第一个匹配的元素上。
  • text <string> 将要输入到文本框内的文字。
  • options <Object>
    • delay <number> 按键输入的间隔速度,单位为ms。默认为 0.
  • returns: <Promise>

Sends a keydown, keypress/input, and keyup event for each character in the text.

为了按下一些特殊按键,例如 ControlArrowDown,请使用keyboard.press

page.type('#mytextarea', 'Hello'); // Types instantly
page.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user

page.mainFrame().type(selector, text[, options])的快捷方法。

page.url()

page.mainFrame().url()的快捷方法。

page.viewport()

  • returns: <Object>
    • width <number> 页面宽度,单位为px。
    • height <number> 页面高度,单位为px。
    • deviceScaleFactor <number> 设备的缩放比例 (can be though of as dpr)。默认为 1.
    • isMobile <boolean>是否考虑 meta viewport标签。默认为 false.
    • hasTouch<boolean> 是否支持 touch事件。默认为 false
    • isLandscape <boolean> 设置 viewport 是否处于landscape mode。默认为 false.

page.waitFor(selectorOrFunctionOrTimeout[, options[, …args]])

根据第一个参数的不同,此方法可实现的场景如下:
- 如果 selectorOrFunctionOrTimeout是一个 string, 那么它如果是以 ‘//’开头, 就是xpath,否则就是 selector,此方法是
page.waitForSelector 或者 page.waitForXPath方法的快捷方法。
- 如果 selectorOrFunctionOrTimeout 是一个 function, then the first argument is treated as a predicate to wait for and the method is a shortcut for page.waitForFunction().
- 如果 selectorOrFunctionOrTimeout 是一个 number, 那么它就会被当做是等待时间(ms),超过等到时间后将会resolve。
- 如果不是以上三种情况中的任何一个,那么将会抛出错误。

[page.mainFrame().waitFor(selectorOrFunctionOrTimeout[, options[, …args]])](#framewaitforselectororfunctionortimeout-options-args)的快捷方法。

page.waitForFunction(pageFunction[, options[, …args]])

  • pageFunction <function|string> 将要在 browser context中执行的函数(可以是function,也可以是string,如果是string,则是有返回值的可以执行的 js表达式)
  • options <Object> Optional waiting parameters
    • polling <string|number> An interval at which the pageFunction is executed, defaults to raf. If polling is a number, then it is treated as an interval in milliseconds at which the function would be executed. 如果 polling 取值类型是 string, 那么只能是以下两个之一:
    • raf - 在 requestAnimationFrame 的回调函数中不断地执行 pageFunction。 这是最紧凑的轮询模式,适合于观察样式的变化。
    • mutation - 当任意 DOM发生变化的时候执行 pageFunction
    • timeout <number> pageFunction函数执行的最大等待时间(ms)。。默认是 30000 (30 秒)。如果取值为 0,则表示禁用此选项。
  • ...args <…Serializable|JSHandle> 传递给 pageFunction的额外参数。
  • returns: <Promise<JSHandle>> 当 pageFunction函数返回 truthy value (true或者可以转化为 true的值)时,将会resolve。 It resolves to a JSHandle of the truthy value.

下面是一个使用此方法来监控 viewport 尺寸改变的例子:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  const watchDog = page.waitForFunction('window.innerWidth < 100');
  await page.setViewport({width: 50, height: 50});
  await watchDog;
  await browser.close();
});

[page.mainFrame().waitForFunction(pageFunction[, options[, …args]])](#framewaitforfunctionpagefunction-options-args)的快捷方法。

page.waitForNavigation(options)

  • options <Object> Navigation 参数,允许存在以下属性:
    • timeout <number> navigation超时时间(ms),默认是 30 seconds, 取值 0则表示禁用此选项。也可以使用 page.setDefaultNavigationTimeout(timeout) 方法来改变默认值。
    • waitUntil <string|Array<string>> navigation导航成功的界限, 默认是 load. 如果给定的值是一个事件名称组成的数组,那么只有当数组中的所有事件全部被触发后才会认为 navigation成功,可选的事件列表如下:
    • load - 当 load 事件触发时,则认为 navigation导航结束。
    • domcontentloaded - 当 DOMContentLoaded 事件触发时,则认为 navigation导航结束。
    • networkidle0 - 如果在 500ms内发起的http请求数为0,则认为导航结束。
    • networkidle2 - 如果在 500ms内发起的http请求数为不超过 2条,则认为导航结束。
  • returns: <Promise<Response>> Promise which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect.

适应于当页面重定向到一个新的url或者reload的场景,例如,当执行了一段可能间接导致页面跳转的代码:

const navigationPromise = page.waitForNavigation();
await page.click('a.my-link'); // 点击此链接将会间接导致页面跳转
await navigationPromise; // 当页面跳转完毕后,将会 resolve

NOTE 使用 History API 方法改变 URL也会被当成是一个 navigation。

page.waitForSelector(selector[, options])

  • selector <string> 被等待的元素的选择器selector
  • options <Object> 可选参数:
    • visible <boolean> 出现在DOM中的元素必须是可见的(visible),例如,不能有 display: none 或者 visibility: hidden CSS 属性。默认是 false
    • hidden <boolean> 元素不存在于DOM中(包括一开始就不存在,或者存在了又被移除掉),或者是被隐藏了, 例如, 具有 display: none 或者 visibility: hidden CSS 属性。默认是 false.
    • timeout <number> 最大等待时间(ms)。默认是 30000 (30 秒)。取值为的 0则表示禁用此参数。
  • returns: <Promise<ElementHandle>> 当在 DOM中找到 selector指定的元素时,Promise 将会 resolves 这个元素的ElementHandle。

等到 selector选择器选择的元素出现在页面中,如果在调用此方法的同时选择器选取的元素就已经存在于页面中了,
则此方法将会立即返回结果,如果超过了最大等待时间 timeout之后,选择器还没有匹配到元素,则将会抛出错误。

此方法即便是在页面跳转(across navigations)的时候依旧有效:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  let currentURL;
  page
    .waitForSelector('img')
    .then(() => console.log('First URL with image: ' + currentURL));
  for (currentURL of ['https://example.com', 'https://google.com', 'https://bbc.com'])
    await page.goto(currentURL);
  await browser.close();
});

page.mainFrame().waitForSelector(selector[, options])的快捷方法。

page.waitForXPath(xpath[, options])

  • xpath <string> 匹配xpath的元素
  • options <Object> 可选参数如下:
    • visible <boolean> 出现在DOM中的元素必须是可见的(visible),例如,不能有 display: none 或者 visibility: hidden CSS 属性。默认是 false
    • hidden <boolean> 元素不存在于DOM中(包括一开始就不存在,或者存在了又被移除掉),或者是被隐藏了, 例如, 具有 display: none 或者 visibility: hidden CSS 属性。默认是 false.
    • timeout <number> 最大等待时间(ms)。默认是 30000 (30 秒)。取值为的 0则表示禁用此参数。
  • returns: <Promise<ElementHandle>> 当在 DOM中找到匹配 xpath的元素时,Promise 将会 resolves 这个元素的ElementHandle。

等到匹配 xpath的元素出现在页面中,如果在调用此方法的同时匹配 xpath的元素就已经存在于页面中了,
则此方法将会立即返回结果,如果超过了最大等待时间 timeout之后,还没有出现匹配 xpath的元素,则将会抛出错误。

此方法即便是在页面跳转(across navigations)的时候依旧有效:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  let currentURL;
  page
    .waitForXPath('//img')
    .then(() => console.log('First URL with image: ' + currentURL));
  for (currentURL of ['https://example.com', 'https://google.com', 'https://bbc.com'])
    await page.goto(currentURL);
  await browser.close();
});

page.mainFrame().waitForXPath(xpath[, options])的快捷方法。

page.workers()

NOTE 不包括 ServiceWorkers。

class: Worker

The Worker class represents a WebWorker.
workercreatedworkerdestroyed事件将会被当做 worker的生命周期,在 page实例中被触发。

page.on('workercreated', worker => console.log('Worker created: ' + worker.url()));
page.on('workerdestroyed', worker => console.log('Worker destroyed: ' + worker.url()));

console.log('Current workers:');
for (const worker of page.workers())
  console.log('  ' + worker.url());

worker.evaluate(pageFunction, …args)

如果pageFunction返回的值是一个 Promise,则 worker.evaluate方法将会等到前者 resolve后,才会返回它自己的值。

如果pageFunction返回的值是一个 non-Serializable 的值, 则 worker.evaluate 将会 resolves undefined

(await worker.executionContext()).evaluate(pageFunction, …args)的快捷方法。

worker.evaluateHandle(pageFunction, …args)

  • pageFunction <function|string> 将在page context中执行的函数。
  • ...args <…Serializable|JSHandle> 传递给 pageFunction函数的参数。
  • returns: <Promise<JSHandle>> Promise which resolves to the return value of pageFunction as in-page object (JSHandle)

worker.evaluateworker.evaluateHandle之间唯一的区别在于,worker.evaluateHandle返回一个 in-page object (JSHandle)

如果pageFunction返回的值是一个 Promise,则 worker.evaluateHandle方法将会等到前者 resolve后,才会返回它自己的值。

(await worker.executionContext()).evaluateHandle(pageFunction, …args)的快捷方法。

worker.executionContext()

worker.url()

class: Keyboard

Keyboard提供了一些用于操纵虚拟键盘的api。高级api是keyboard.type,此api可自动根据场景整合keydown, keypress/input, 以及 keyup事件。

为了得到更细致的控制,你也可以使用keyboard.down, keyboard.up, and keyboard.sendCharacter方法来触发相应的键盘事件,以此达到模拟真实体验的目的。

下面是一个按住 Shift键,然后选中并删除一些文本的例子:

await page.keyboard.type('Hello World!');
await page.keyboard.press('ArrowLeft');

await page.keyboard.down('Shift');
for (let i = 0; i < ' World'.length; i++)
  await page.keyboard.press('ArrowLeft');
await page.keyboard.up('Shift');

await page.keyboard.press('Backspace');
// 最终得到的文本将是 'Hello!'

下面是一个输入 ‘A 字母的例子:

await page.keyboard.down('Shift');
await page.keyboard.press('KeyA');
await page.keyboard.up('Shift');

NOTE 在MacOS系统上,一些键盘快捷键,例如 全选 的快捷键⌘ A将不起作用。更多参见 #1313

keyboard.down(key[, options])

  • key <string> 按下的按键名称, such as ArrowLeft. 参见 USKeyboardLayout 获取按键名称列表。
  • options <Object>
    • text <string> 如果指定了此属性值, generates an input event with this text.
  • returns: <Promise>

触发 keydown事件。

如果 key值是一个单个字母,并且没有除了 Shift之外的修饰按键被按下,那么将会继续触发 keypress/input事件。可以指定 ‘text’选项以强制生成输入事件。

如果 key值是一个修饰按键,例如 Shift, Meta, Control, 或者 Alt,随后按下的按键将会与前者组合形成组合键,如果想要释放修饰按键,可以使用 keyboard.up方法。

After the key is pressed once, subsequent calls to keyboard.down will have repeat set to true. To release the key, use keyboard.up.

NOTE 修饰键将会影响 keyboard.down的效果。如果你按住 Shift键,然后再按其他的字母键,则你将输入一个大写的字母。

keyboard.press(key[, options])

  • key <string> 需要按下的按键的名称, 例如 ArrowLeft. 更多按键名称列表参见 USKeyboardLayout
  • options <Object>
    • text <string> 如果指定,则将根据 text进行按键操作。
    • delay <number> keydownkeyup 之间的时间间隔(ms). 默认是 0.
  • returns: <Promise>

如果 key值是一个单个字母,并且没有除了 Shift之外的修饰按键被按下,那么将会继续触发 keypress/input事件。可以指定 ‘text’选项以强制生成输入事件。

NOTE 修饰键将会影响 keyboard.press的效果。如果你按住 Shift键,然后再按其他的字母键,则你将输入一个大写的字母。

keyboard.downkeyboard.up的快捷方法。

keyboard.sendCharacter(char)

触发 keypressinput事件,不会触发 keydown 或者 keyup 事件。

page.keyboard.sendCharacter('嗨');1

NOTE 修饰键将会影响 keyboard.sendCharacter的效果。如果你按住 Shift键,然后再按其他的字母键,则你将输入一个大写的字母。

keyboard.type(text, options)

  • text <string> 需要向聚焦的输入框中输入的文本
  • options <Object>
    • delay <number> 按键按下的时间间隔. 默认是 0.
  • returns: <Promise>

输入文本的时候,每个字符都会触发 keydown, keypress/input, 以及 keyup事件。

如果想要输按下特殊字符,例如Control 以及 ArrowDown,参见keyboard.press

page.keyboard.type('Hello'); // 快速输入
page.keyboard.type('World', {delay: 100}); // 模拟真实输入

NOTE 修饰键不会影响 keyboard.type的效果。也就是说,调用此方法时,就算你已经按住了 Shift键,也不会将你想要输入的文本全都强制变成大写的。

keyboard.up(key)

触发 keyup事件。

class: Mouse

mouse.click(x, y, [options])

  • x <number>
  • y <number>
  • options <Object>
    • button <string> left, right, 或者 middle, 默认是 left。(意思是用鼠标的哪个按键进行点击操作,左键、右键或者中键)
    • clickCount <number> 点击次数,默认是 1. 参见 UIEvent.detail.
    • delay <number> mousedownmouseup 之间的时间间隔(ms).默认是 0.
  • returns: <Promise>

mouse.move, mouse.down 以及 mouse.up的联合方法。

mouse.down([options])

  • options <Object>
    • button <string> left, right, 或者 middle, 默认是 left。(意思是用鼠标的哪个按键进行点击操作,左键、右键或者中键)
    • clickCount <number>默认是 1. 参见 UIEvent.detail.
  • returns: <Promise>

触发 mousedown事件。

mouse.move(x, y, [options])

触发 mousemove事件。

mouse.up([options])

触发 mouseup事件。

class: Touchscreen

touchscreen.tap(x, y)

Dispatches a touchstart and touchend event.

class: Tracing

你可以使用 tracing.start 以及 tracing.stop来创建一个跟踪文件,此跟踪文件可以被 Chrome DevTools 或者 timeline viewer打开。

await page.tracing.start({path: 'trace.json'});
await page.goto('https://www.google.com');
await page.tracing.stop();

tracing.start(options)

  • options <Object>
    • path <string> 跟踪文件的存储路径.
    • screenshots <boolean> captures screenshots in the trace.
    • categories <Array<string>> specify custom categories to use instead of default.
  • returns: <Promise>

每个浏览器一次只能执行一个跟踪任务。

tracing.stop()

  • returns: <Promise<Buffer>> Promise which resolves to buffer with trace data.

class: Dialog

Dialog objects are dispatched by page via the ‘dialog’ event.

下面是一个 使用Dialog class的例子:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  page.on('dialog', async dialog => {
    console.log(dialog.message());
    await dialog.dismiss();
    await browser.close();
  });
  page.evaluate(() => alert('1'));
});

dialog.accept([promptText])

  • promptText <string> 在提示框中输入的文件内容。。如果dialog的类型不是prompt(提示框),则此方法将不起任何作用。
  • returns: <Promise> Promise which resolves when the dialog has been accepted.

dialog.defaultValue()

  • returns: <string> 如果 dialog是一个 prompt(提示框),返回提示框的默认值,否则将返回空字符串。

dialog.dismiss()

  • returns: <Promise> 提示框被取消时,Promise 返回resolves 。

dialog.message()

  • returns: <string> dialog展示的文本。

dialog.type()

  • returns: <string> Dialog的类型, 可以是以下其中之一 alert, beforeunload, confirm or prompt.

class: ConsoleMessage

ConsoleMessage objects are dispatched by page via the ‘console’ event.

consoleMessage.args()

consoleMessage.text()

consoleMessage.type()

允许以下值: 'log', 'debug', 'info', 'error', 'warning', 'dir', 'dirxml', 'table', 'trace', 'clear', 'startGroup', 'startGroupCollapsed', 'endGroup', 'assert', 'profile', 'profileEnd', 'count', 'timeEnd'

class: Frame

无论在哪个时间点,都能够通过page.mainFrame()frame.childFrames()方法来获取的页面当前的 frame tree。

Frame对象的生命周期,由三个事件组成:
- ‘frameattached’ - 当frame attach到page上时触发。一个 Frame只能 attach到页面上一次。
- ‘framenavigated’ - 当Frame重定向到一个新的 URL时触发.
- ‘framedetached’ - 当Frame从页面上 detach时触发。一个 Frame只能从页面上 detach一次。

An example of dumping frame tree:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://www.google.com/chrome/browser/canary.html');
  dumpFrameTree(page.mainFrame(), '');
  await browser.close();

  function dumpFrameTree(frame, indent) {
    console.log(indent + frame.url());
    for (let child of frame.childFrames())
      dumpFrameTree(child, indent + '  ');
  }
});

frame.$(selector)

frame.$$(selector)

  • selector <string> Selector to query page for
  • returns: <Promise<Array<ElementHandle>>> Promise which resolves to ElementHandles pointing to the frame elements.

此方法使用了 document.querySelectorAll,如果没有匹配到任何元素,则resolve回 []

frame.$$eval(selector, pageFunction[, …args])

此方法使用了 Array.from(document.querySelectorAll(selector)),并将其返回的结果作为 pageFunction函数的第一个参数传递进去。

如果 pageFunction返回的结果是一个 Promise,则 frame.$$eval将会等到前者成功resolve,然后再返回自己的值。

Examples:

const divsCounts = await frame.$$eval('div', divs => divs.length);

frame.$eval(selector, pageFunction[, …args])

此方法使用了 document.querySelector,并将其返回的结果作为 pageFunction函数的第一个参数传递进去。如果没有匹配到任何元素,则将抛出错误。

如果 pageFunction返回的结果是一个 Promise,则 frame.$eval将会等到前者成功resolve,然后再返回自己的值。

例子:

const searchValue = await frame.$eval('#search', el => el.value);
const preloadHref = await frame.$eval('link[rel=preload]', el => el.href);
const html = await frame.$eval('.main-container', e => e.outerHTML);

frame.$x(expression)

此方法用于执行给定的 XPath 表达式。

frame.addScriptTag(options)

  • options <Object>
    • url <string> 需要被增加的script标签的url
    • path <string> 将要被添加的JavaScript文件的路径. 如果 path 是相对路径, 则其是相对于 current working directory
    • content <string> 将要被添加的 JavaScript脚本的内容。
    • type <string> 脚本类型. 如果是 ‘module’ ,则将导入的是JS的 ES6模块。更多参见 [script]
  • returns: <Promise<ElementHandle>> 当script脚本加载完毕,或者脚本内容已经注入到frame上时,将会返回所添加的script标签元素。

向frame中增加指定 url或者 脚本内容的 script标签。

frame.addStyleTag(options)

  • options <Object>
    • url <string> 将要被添加的 style 的url
    • path <string>将要被添加的 CSS文件的路径. 如果 path 是相对路径, 则其是相对于 current working directory
    • content <string> 将要被添加的CSS脚本的内容。
  • returns: <Promise<ElementHandle>> 当style加载完毕,或者style内容已经注入到frame上时,将会返回所添加的style标签元素。

向页面中添加一个 带有指定 url的<link rel="stylesheet">标签,或者一个带有内容的<style type="text/css">标签。

frame.childFrames()

frame.click(selector[, options])

  • selector <string> 将要被点击的元素的 选择器。如果选择器匹配出了多个元素,则点击事件只会作用在第一个匹配的元素上。
  • options <Object>
    • button <string> left, right, or middle, 默认是 left(即使用左键、右键还是中键进行点击操作)
    • clickCount <number> 默认点击一次。 更多参见UIEvent.detail
    • delay <number> mousedownmouseup 事件之间的时间间隔. 默认为 0.
  • returns: <Promise> 当匹配的元素被成功点击时将会resolve,如果没有匹配到元素,则将 reject。

此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 page.mouse方法点击匹配到的元素的中心位置。
如果没有匹配到元素,则将抛出一个错误。

需要注意的是,如果所点击的元素会触发页面跳转,并且还调用了page.waitForNavigation()方法,那么你可能不会得到期望的结果,正确的做法如下:

const [response] = await Promise.all([
  page.waitForNavigation(waitOptions),
  frame.click(selector, clickOptions),
]);

frame.content()

获取frame包括doctype在内的完整HTML内容

frame.evaluate(pageFunction, …args)

如果传递给 frame.evaluatepageFunction函数返回一个 Promise,则frame.evaluate将会等待得到resolve后,才会返回它自己的值。

如果传递给 frame.evaluatepageFunction函数返回一个 non-Serializable的值,则page.evaluate将会返回 undefined

const result = await frame.evaluate(() => {
  return Promise.resolve(8 * 7);
});
console.log(result); // prints "56"

可以传递一个字符串作为 pageFunction

console.log(await frame.evaluate('1 + 2')); // prints "3"

可以传递一个ElementHandle 作为 pageFunction参数:

const bodyHandle = await frame.$('body');
const html = await frame.evaluate(body => body.innerHTML, bodyHandle);
await bodyHandle.dispose();

frame.evaluateHandle(pageFunction, …args)

  • pageFunction <function|string> 在page context 中执行的函数。
  • ...args <…Serializable|JSHandle> 传递给 pageFunction的参数
  • returns: <Promise<JSHandle>> Promise which resolves to the return value of pageFunction as in-page object (JSHandle)

frame.evaluatepaframege.evaluateHandle之间唯一的差别是,frame.evaluateHandle返回的结果是 in-page object (JSHandle)。
(可能指的是此方法只返回页面元素的句柄,即此方法可以看作一个元素选择器)

如果传入 frame.evaluateHandle的函数 返回的值是一个 Promise,则frame.evaluateHandle将会等待这个 Promise到达resolve时才会返回自己的值。

const aWindowHandle = await frame.evaluateHandle(() => Promise.resolve(window));
aWindowHandle; // window对象的handle.

可以传递一个 字符串作为 pageFunction

const aHandle = await frame.evaluateHandle('document'); // Handle for the 'document'.

JSHandle instances也可以作为frame.evaluateHandle的传入参数:

const aHandle = await frame.evaluateHandle(() => document.body);
const resultHandle = await frame.evaluateHandle(body => body.innerHTML, aHandle);
console.log(await resultHandle.jsonValue());
await resultHandle.dispose();

frame.executionContext()

frame.focus(selector)

  • selector <string> 需要focus的元素的选择器。 如果此选择器匹配到了多个元素,则只有第一个匹配的元素才会被focus。
  • returns: <Promise> 当成功匹配到元素后,Promise将resolve。如果没有匹配到任何元素,则将reject。

此方法将 focus给定 selector匹配到的元素。
如果根据给定的 selector没有匹配到任何元素,将会抛出异常。

frame.hover(selector)

  • selector <string> 需要 hover的元素的选择器。 如果此选择器匹配到了多个元素,则只有第一个匹配的元素才会被hover。
  • returns: <Promise> 当成功匹配到元素后,Promise将resolve。如果没有匹配到任何元素,则将reject。

此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 page.mouse方法 hover匹配到的元素的中心位置。
如果没有匹配到元素,则将抛出一个错误。

frame.isDetached()

如果 frame已经detached了,则返回 true, 否则返回 false

frame.name()

返回 frame的name属性值。

如果name属性不存在或者为空字符串,则返回 id属性的值,如果 id属性也不存在或者为空字符串,则返回空字符串。

NOTE 此方法的返回值只会在frame被创建后计算一次,如果稍后frame的相关属性(name或者id)发生变化,此方法的返回值也不会改变。

frame.parentFrame()

  • returns:

frame.select(selector, …values)

  • selector <string> [select]标签的选择器
  • ...values <…string> 选择的值。如果 <select> 标签具有 multiple 属性, 所有的指定值都是有效值, 否则只会考虑第一个值。
  • returns: <Promise<Array<string>>> 返回一个由所有成功选中(selected)的选项(option)的值组成的数组。

当所有提供的 values值的选项(option)全被选中后会触发 change 以及 input事件。
如果根据所指定的选择器selector没有匹配到一个 <select>元素,将会抛出错误。
(这个方法就是用于控制 select的选择)

frame.select('select#colors', 'blue'); // 单选
frame.select('select#colors', 'red', 'green', 'blue'); // 多选

frame.setContent(html)

  • html <string> 设置 page页面的HTML内容。
  • returns: <Promise>

frame.tap(selector)

  • selector <string> 将要被tap的元素的 选择器。如果选择器匹配出了多个元素,则tap事件只会作用在第一个匹配的元素上。
  • returns: <Promise>

此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 page.touchscreen方法tap匹配到的元素的中心位置。
如果没有匹配到元素,则将抛出一个错误。

frame.title()

frame.type(selector, text[, options])

  • selector <string> 文本框(包括 texarea和input)的选择器。如果选择器匹配出了多个元素,则只会选择第一个匹配的元素上。
  • text <string> 将要输入到文本框内的文字。
  • options <Object>
    • delay <number> 按键输入的间隔速度,单位为ms。默认为 0.
  • returns: <Promise>

Sends a keydown, keypress/input, and keyup event for each character in the text.

为了按下一些特殊按键,例如 ControlArrowDown,请使用keyboard.press

frame.type('#mytextarea', 'Hello'); // 快速输入
frame.type('#mytextarea', 'World', {delay: 100}); // 减缓输入速度以模拟真实输入

frame.url()

返回 frame的url

frame.waitFor(selectorOrFunctionOrTimeout[, options[, …args]])

根据第一个参数的不同,此方法可实现的场景如下:
- 如果 selectorOrFunctionOrTimeout是一个 string, 那么它如果是以 ‘//’开头, 就是xpath,否则就是 selector,此方法是
frame.waitForSelector 或者 frame.waitForXPath方法的快捷方法。
- 如果 selectorOrFunctionOrTimeout 是一个 function, then the first argument is treated as a predicate to wait for and the method is a shortcut for frame.waitForFunction().
- 如果 selectorOrFunctionOrTimeout 是一个 number, 那么它就会被当做是等待时间(ms),超过等到时间后将会resolve。
- 如果不是以上三种情况中的任何一个,那么将会抛出错误。

frame.waitForFunction(pageFunction[, options[, …args]])

  • pageFunction <function|string> 将要在 browser context中执行的函数(可以是function,也可以是string,如果是string,则是有返回值的可以执行的 js表达式)
  • options <Object> Optional waiting parameters
    • polling <string|number> An interval at which the pageFunction is executed, defaults to raf. If polling is a number, then it is treated as an interval in milliseconds at which the function would be executed. 如果 polling 取值类型是 string, 那么只能是以下两个之一:
    • raf - 在 requestAnimationFrame 的回调函数中不断地执行 pageFunction。 这是最紧凑的轮询模式,适合于观察样式的变化。
    • mutation - 当任意 DOM发生变化的时候执行
    • timeout <number> 函数执行的最大等待时间(ms)。。默认是 30000 (30 秒)。如果取值为 0,则表示禁用此选项。
  • ...args <…Serializable|JSHandle> 传递给 pageFunction的额外参数。
  • returns: <Promise<JSHandle>> Promise which resolves when the pageFunction returns a truthy value. It resolves to a JSHandle of the truthy value.

下面是一个使用此方法来监控 viewport 尺寸改变的例子:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100');
  page.setViewport({width: 50, height: 50});
  await watchDog;
  await browser.close();
});

frame.waitForSelector(selector[, options])

  • selector <string> 被等待的元素的选择器selector
  • options <Object> 可选参数
    • visible <boolean> 出现在DOM中的元素必须是可见的(visible),例如,不能有 display: none 或者 visibility: hidden CSS 属性。默认是 false
    • hidden <boolean> 元素不存在于DOM中(包括一开始就不存在,或者存在了又被移除掉),或者是被隐藏了, 例如, 具有 display: none 或者 visibility: hidden CSS 属性。默认是 false.
    • timeout <number> 最大等待时间(ms)。默认是 30000 (30 秒)。取值为的 0则表示禁用此参数。
  • returns: <Promise<ElementHandle>> 当在 DOM中找到 selector指定的元素时,Promise 将会 resolves 这个元素的ElementHandle。

等到 selector选择器选择的元素出现在页面中,如果在调用此方法的同时选择器选取的元素就已经存在于页面中了,
则此方法将会立即返回结果,如果超过了最大等待时间 timeout之后,选择器还没有匹配到元素,则将会抛出错误。

此方法即便是在页面跳转(across navigations)的时候依旧有效:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  let currentURL;
  page.mainFrame()
    .waitForSelector('img')
    .then(() => console.log('First URL with image: ' + currentURL));
  for (currentURL of ['https://example.com', 'https://google.com', 'https://bbc.com'])
    await page.goto(currentURL);
  await browser.close();
});

frame.waitForXPath(xpath[, options])

  • xpath <string> 匹配xpath的元素
  • options <Object> 可选参数如下:
    • visible <boolean> 出现在DOM中的元素必须是可见的(visible),例如,不能有 display: none 或者 visibility: hidden CSS 属性。默认是 false
    • hidden <boolean> 元素不存在于DOM中(包括一开始就不存在,或者存在了又被移除掉),或者是被隐藏了, 例如, 具有 display: none 或者 visibility: hidden CSS 属性。默认是 false.
    • timeout <number> 最大等待时间(ms)。默认是 30000 (30 秒)。取值为的 0则表示禁用此参数。
  • returns: <Promise<ElementHandle>> 当在 DOM中找到匹配 xpath的元素时,Promise 将会 resolves 这个元素的ElementHandle。

等到匹配 xpath的元素出现在页面中,如果在调用此方法的同时匹配 xpath的元素就已经存在于页面中了,
则此方法将会立即返回结果,如果超过了最大等待时间 timeout之后,还没有出现匹配 xpath的元素,则将会抛出错误。

此方法即便是在页面跳转(across navigations)的时候依旧有效:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  let currentURL;
  page.mainFrame()
    .waitForXPath('//img')
    .then(() => console.log('First URL with image: ' + currentURL));
  for (currentURL of ['https://example.com', 'https://google.com', 'https://bbc.com'])
    await page.goto(currentURL);
  await browser.close();
});

class: ExecutionContext

The class represents a context for JavaScript execution. Examples of JavaScript contexts are:
- 每个 frame 都有一个独立的JS执行上下文
- 所有类型的 workers 都有它们自己的上下文

executionContext.evaluate(pageFunction, …args)

如果pageFunction函数的返回值是一个 Promise,则executionContext.evaluate将会等到前者resolve后才会返回它自己的值。

const executionContext = await page.mainFrame().executionContext();
const result = await executionContext.evaluate(() => Promise.resolve(8 * 7));
console.log(result); // prints "56"

字符串也可以被当做pageFunction

console.log(await executionContext.evaluate('1 + 2')); // prints "3"

JSHandle instances 可以被当做 ...args

const oneHandle = await executionContext.evaluateHandle(() => 1);
const twoHandle = await executionContext.evaluateHandle(() => 2);
const result = await executionContext.evaluate((a, b) => a + b, oneHandle, twoHandle);
await oneHandle.dispose();
await twoHandle.dispose();
console.log(result); // prints '3'.

executionContext.evaluateHandle(pageFunction, …args)

  • pageFunction <function|string> 将在executionContext中执行的函数
  • ...args <…Serializable|JSHandle> 传递给 pageFunction函数的参数。
  • returns: <Promise<JSHandle>> Promise which resolves to the return value of pageFunction as in-page object (JSHandle)

executionContext.evaluateexecutionContext.evaluateHandle之间唯一的区别在于,worker.evaluateHandle返回一个 in-page object (JSHandle)

如果pageFunction返回的值是一个 Promise,则 executionContext.evaluateHandle方法将会等到前者 resolve后,才会返回它自己的值。

const context = await page.mainFrame().executionContext();
const aHandle = await context.evaluateHandle(() => Promise.resolve(self));
aHandle; // Handle for the global object.

字符串也可以被当做pageFunction

const aHandle = await context.evaluateHandle('1 + 2'); // Handle for the '3' object.

JSHandle instances 可以被当做 ...args

const aHandle = await context.evaluateHandle(() => document.body);
const resultHandle = await context.evaluateHandle(body => body.innerHTML, aHandle);
console.log(await resultHandle.jsonValue()); // prints body's innerHTML
await aHandle.dispose();
await resultHandle.dispose();

executionContext.frame()

  • returns:

executionContext.queryObjects(prototypeHandle)

  • prototypeHandle <JSHandle> A handle to the object prototype.
  • returns: <JSHandle> A handle to an array of objects with this prototype

此方法迭代(iterates)遍历 JavaScript堆栈,获取给定 prototype下所有 object组成的数组。

// Create a Map object
await page.evaluate(() => window.map = new Map());
// Get a handle to the Map object prototype
const mapPrototype = await page.evaluateHandle(() => Map.prototype);
// Query all map instances into an array
const mapInstances = await page.queryObjects(mapPrototype);
// Count amount of map objects in heap
const count = await page.evaluate(maps => maps.length, mapInstances);
await mapInstances.dispose();
await mapPrototype.dispose();

class: JSHandle

JSHandle represents an in-page JavaScript object. JSHandles 可以通过 page.evaluateHandle 方法来创建。

const windowHandle = await page.evaluateHandle(() => window);
// ...

JSHandle能够防止被引用的 JavaScript object 被垃圾回收机制给回收掉,除非 the handle被主动 disposed。JSHandles能够在源frame重定向或者父级上下文被销毁的时候,自动释放(auto-disposed)。

JSHandle instances 可以作为 page.$eval(), page.evaluate() 以及 page.evaluateHandle 方法的参数。

jsHandle.asElement()

  • returns:

jsHandle.dispose()

  • returns: <Promise> 当 object handle成功释放(dispose)后,Promise将 resolve。

此方法用于断开element handle的引用

jsHandle.executionContext()

返回 handle所在的执行上下文。

jsHandle.getProperties()

此方法返回一个由属性名称作为key和 JSHandle instances作为value组成的 map对象

const handle = await page.evaluateHandle(() => ({window, document}));
const properties = await handle.getProperties();
const windowHandle = properties.get('window');
const documentHandle = properties.get('document');
await handle.dispose();

jsHandle.getProperty(propertyName)

从引用的object中获取给定 propertyName对应的 property。

jsHandle.jsonValue()

返回 object的 json。如果 object具有toJSON函数方法,也不会调用此函数方法.
Returns a JSON representation of the object. If the object has a

NOTE 如果引用的object无法字符串化,则此方法将返回空 JSON对象。如果引用的object存在循环引用,则将抛出错误。

class: ElementHandle

NOTE Class ElementHandle extends JSHandle.

ElementHandle represents an in-page DOM element. ElementHandles 可以通过 the page.$ 方法创建。

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://google.com');
  const inputElement = await page.$('input[type=submit]');
  await inputElement.click();
  // ...
});

ElementHandle 能够防止被引用的 DOM element 被垃圾回收机制给回收掉,除非 the handle被主动 disposed。ElementHandles 能够在源frame重定向的时候,自动释放(auto-disposed)。

ElementHandle instances 可以作为 page.$eval(), page.evaluate() 以及 page.evaluate 方法的参数。

elementHandle.$(selector)

elementHandle.$$(selector)

此方法将在页面上使用element.querySelectorAll,如果没有匹配到任何元素,则将resolve 回[]

elementHandle.$$eval(selector, pageFunction, …args)

此方法将在element上使用element.querySelectorAll,并且将结果作为pageFunction的第一个参数传入,如果没有匹配到任何元素,则抛出错误。

如果 pageFunction返回的值是一个 Promise,则 elementHandle.$$eval将等到前者 resolve回结果后,才返回它自己的值。

例子:

<div class="feed">
  <div class="tweet">Hello!</div>
  <div class="tweet">Hi!</div>
</div>
const feedHandle = await page.$('.feed');
expect(await feedHandle.$$eval('.tweet', nodes => nodes.map(n => n.innerText)).toEqual(['Hello!', 'Hi!']);

elementHandle.$eval(selector, pageFunction, …args)

此方法将在 element上使用document.querySelector,并且将结果作为pageFunction的第一个参数传入,如果没有匹配到任何元素,则抛出错误。

如果 pageFunction返回的值是一个 Promise,则 elementHandle.$eval将等到前者 resolve回结果后,才返回它自己的值。

Examples:

const tweetHandle = await page.$('.tweet');
expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe('100');
expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10');

elementHandle.$x(expression)

The method evaluates the XPath expression relative to the elementHandle. If there are no such elements, the method will resolve to an empty array.

elementHandle.asElement()

elementHandle.boundingBox()

elementHandle.boxModel()

elementHandle.click([options])

  • options <Object>
    • button <string> left, right, 或者 middle, 默认是 left。(意思是用鼠标的哪个按键进行点击操作,左键、右键或者中键)
    • clickCount <number> 点击次数,默认是 1. 参见 UIEvent.detail.
    • delay <number> mousedownmouseup 之间的时间间隔(ms).默认是 0.
  • returns: <Promise> Promise which resolves when the element is successfully clicked. Promise gets rejected if the element is detached from DOM.

此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 page.mouse方法点击匹配到的元素的中心位置。
如果element 已经从DOM上 detach掉了,则将抛出一个错误。

elementHandle.contentFrame()

elementHandle.dispose()

  • returns: <Promise> Promise which resolves when the element handle is successfully disposed.

此方法断开 element handle的引用

elementHandle.executionContext()

elementHandle.focus()

调用 element的focus 方法。

elementHandle.getProperties()

此方法返回一个由属性名称作为key和 JSHandle instances作为value组成的 map对象

const listHandle = await page.evaluateHandle(() => document.body.children);
const properties = await listHandle.getProperties();
const children = [];
for (const property of properties.values()) {
  const element = property.asElement();
  if (element)
    children.push(element);
}
children; // holds elementHandles to all children of document.body

elementHandle.press(key[, options])

  • key <string> 需要按下的按键的名称, 例如 ArrowLeft. 更多按键名称列表参见 USKeyboardLayout
  • options <Object>
    • text <string> If specified, generates an input event with this text.
    • delay <number> keydownkeyup 之间的时间间隔(ms). 默认是 0.
  • returns: <Promise>

聚焦在 element上,然后使用 keyboard.down 以及 keyboard.up方法。

如果 key值是一个单个字母,并且没有除了 Shift之外的修饰按键被按下,那么将会继续触发 keypress/input事件。可以指定 ‘text’选项以强制生成输入事件。

NOTE 修饰键将会影响 elementHandle.press的效果。如果你按住 Shift键,然后再按其他的字母键,则你将输入一个大写的字母。

elementHandle.screenshot([options])

此方法将会在需要的时候将元素滚动到可视区域内,然后使用 page.screenshot方法来对 element进行截图操作。
如果 element 已经从DOM上 detach掉了,则此方法将抛出错误。

elementHandle.tap()

  • returns: <Promise> 如果成功在element上执行了 tap操作,则 Promise将会resolve。如果 element 已经从DOM上 detach掉了,则 Promise将会reject。

此方法将会在需要的时候将元素滚动到可视区域内,然后使用 touchscreen.tap来 tap element的中间位置。
如果 element 已经从DOM上 detach掉了,则将抛出错误。

elementHandle.toString()

elementHandle.type(text[, options])

  • text <string> 将要在聚焦元素内输入的文本内容
  • options <Object>
    • delay <number> 输入字符间的时间间隔。 默认是 0.
  • returns: <Promise>

聚焦element,然后为每个输入的字符触发 keydown, keypress/input, 以及 keyup事件。

为了press一些特殊字符,例如 Control 或者 ArrowDown,请使用 elementHandle.press方法。

elementHandle.type('Hello'); // 快速输入
elementHandle.type('World', {delay: 100}); // 输入速度减慢以模拟真实输入

下面是一个输入文本并提交表单的例子:

const elementHandle = await page.$('input');
await elementHandle.type('some text');
await elementHandle.press('Enter');

elementHandle.uploadFile(…filePaths)

  • ...filePaths <…string> Sets the value of the file input these paths. If some of the filePaths are relative paths, then they are resolved relative to current working directory.
  • returns: <Promise>

This method expects elementHandle to point to an input element.

class: Request

当页面发起请求的时候,例如请求网络资源,下面这些事件都将会被触发:
- ‘request’ 当页面发起请求时触发。
- ‘response’ 当请求收到响应的时候触发。
- ‘requestfinished’ 当响应内容完全接受并且请求结束的时候触发。

如果请求动作在某个地方失败,那么 requestfinished(也可能是 response)事件会被 ‘requestfailed’所替代。

如果收到了重定向的响应指令,则当前请求结束,并触发 requestfinished事件,然后会发起一个对新链接的获取请求。

request.abort([errorCode])

  • errorCode <string> 可选的错误码. 默认是 failed, 允许以下值:
    • aborted - 某个操作 aborted (来源于 user)
    • accessdenied - 访问除网络之外的资源的权限被拒绝
    • addressunreachable - The IP address is unreachable. 这通常意味着没有路由到指定的主机或网络。
    • connectionaborted - 由于没有收到发送的数据的ACK,导致连接超时
    • connectionclosed - 连接被关闭 (corresponding to a TCP FIN).
    • connectionfailed - 连接请求失败.
    • connectionrefused - 连接请求被拒绝.
    • connectionreset - 连接请求被重置 (reset) (corresponding to a TCP RST).
    • internetdisconnected - 网络连接丢失(也就是没有网络了)
    • namenotresolved - 无法解析主机名。
    • timedout - 操作超时.
    • failed - 一个通用的故障发生
  • returns: <Promise>

Aborts request. To use this, 应确保请求拦截可用,使用 page.setRequestInterception来设置。

如果未启用请求拦截,则将立即抛出异常。

request.continue([overrides])

  • overrides <Object> Optional request overwrites, which can be one of the following:
    • url <string> 如果设置此属性值,则请求url将会被重置。
    • method <string> 如果设置此属性值,则请求方式将会被重置。 (例如 GET or POST)
    • postData <string> 如果设置此属性值,则post body将会被重置
    • headers <Object> 如果设置此属性值,则 HTTP headers将会被重置
  • returns: <Promise>

拦截并改变请求参数。为了确保此方法可用,请使用 page.setRequestInterception方法来保证请求拦截处于可用状态(enable)。

如果未启用请求拦截,则将立即抛出异常。

request.failure()

  • returns:
page.on('requestfailed', request => {
  console.log(request.url() + ' ' + request.failure().errorText);
});

request.frame()

  • returns:

request.headers()

  • returns: <Object> An object with HTTP headers associated with the request. All header names are lower-case.

request.isNavigationRequest()

当前请求是否是一个 navigation的请求(即,当前请求是否会触发页面跳转或reload事件。)

request.method()

  • returns: <string> 请求方式 (例如,GET, POST等)

request.postData()

  • returns: <string> Request’s post body, if any.

request.redirectChain()

A redirectChain is a chain of requests initiated to fetch a resource.
- 如果没有重定向,并且请求成功,则返回 空数组 []
- If a server responds with at least a single redirect, then the chain will
contain all the requests that were redirected.

redirectChain is shared between all the requests of the same chain.

例如,如果 http://example.com有一个重定向到 https://example.com的动作,则 redirectChain将包含一个请求:

const response = await page.goto('http://example.com');
const chain = response.request().redirectChain();
console.log(chain.length); // 1
console.log(chain[0].url()); // 'http://example.com'

如果https://google.com网站没有重定向的动作,则 redirectChain将会是空数组:

const response = await page.goto('https://google.com');
const chain = response.request().redirectChain();
console.log(chain.length); // 0

request.resourceType()

包含所有被渲染引擎使用到的请求资源的类型,允许以下几种: document, stylesheet, image, media, font, script, texttrack, xhr, fetch, eventsource, websocket, manifest, other.

request.respond(response)

  • response <Object> 请求对应的响应对象
    • status <number> 响应状态安, 默认是 200
    • headers <Object> 可选的响应头
    • contentType <string> 如果设置了此属性值,则相当于是 设置响应头的 Content-Type
    • body <Buffer|string> 可选的 response body
  • returns: <Promise>

用给定的响应来完成请求。 为了使此功能有效可用, 请设置 page.setRequestInterception,以确保请求拦截可用。如果请求拦截不可用,则将抛出错误。

下面是一个给请求响应 404状态的例子:

await page.setRequestInterception(true);
page.on('request', request => {
  request.respond({
    status: 404,
    contentType: 'text/plain',
    body: 'Not Found!'
  });
});

NOTE 不支持对 dataURL请求的模拟响应。
对一个 dataURL请求使用 request.respond 将不会产生任何效果。

request.response()

  • returns:

request.url()

  • returns: <string> URL of the request.

class: Response

Response class represents responses which are received by page.

response.buffer()

  • returns:

response.fromCache()

如果响应数据来自于磁盘或者内存,则返回 true

response.fromServiceWorker()

如果响应数据来自于 service worker,则返回 true

response.headers()

  • returns: <Object> http响应头对象. 所有的 header name 都是小写.

response.json()

  • returns:

response.ok()

包含一个用于标记数据响应是否成功(状态码为 200-299)的布尔值。

response.request()

response.securityDetails()

  • returns:

response.status()

包含响应状态码(例如,200,表示响应成功)

response.text()

  • returns: <Promise<string>> Promise which resolves to a text representation of response body.

response.url()

包含响应的 URL

class: SecurityDetails

SecurityDetails class represents responses which are received by page.

securityDetails.issuer()

  • returns: <string> 带有证书颁发机构名称的字符串。

securityDetails.protocol()

  • returns: <string> 安全协议名, 例如 “TLS 1.2”.

securityDetails.subjectName()

  • returns: <string> 证书签发对象的名称

securityDetails.validFrom()

  • returns: <number> UnixTime,安全证书开始生效的时间,用 Unix时间表示。

securityDetails.validTo()

  • returns: <number> UnixTime ,安全证书失效的时间,用 Unix时间表示。

class: Target

target.browser()

获取 target(可以认为是page) 隶属于的 browser。

target.browserContext()

The browser context the target belongs to.

target.createCDPSession()

Creates a Chrome Devtools Protocol session attached to the target.

target.opener()

  • returns:

target.page()

target.type()

返回 target的类型,可以是 "page", "background_page", "service_worker", "browser" or "other"

target.url()

class: CDPSession

The CDPSession instances are used to talk raw Chrome Devtools Protocol:
- protocol methods can be called with session.send method.
- protocol events can be subscribed to with session.on method.

DevTools Protocol的文档参见: DevTools Protocol Viewer.

const client = await page.target().createCDPSession();
await client.send('Animation.enable');
client.on('Animation.animationCreated', () => console.log('Animation created!'));
const response = await client.send('Animation.getPlaybackRate');
console.log('playback rate is ' + response.playbackRate);
await client.send('Animation.setPlaybackRate', {
  playbackRate: response.playbackRate / 2
});

cdpSession.detach()

将 cdpSession从 target上 detach掉,一旦cdpSession从 target上 detach掉了,则 the cdpSession object将不可再触发任何事件,也不再可以用于发送信息

cdpSession.send(method[, params])

class: Coverage

Coverage用于收集记录页面使用了哪些 JavaScript 以及 CSS代码。

下面的例子展示了如何获取 页面在初始化的时候,用到了所加载得 JavaScript 以及 CSS文件多少比例的内容:

// Enable both JavaScript and CSS coverage
await Promise.all([
  page.coverage.startJSCoverage(),
  page.coverage.startCSSCoverage()
]);
// Navigate to page
await page.goto('https://example.com');
// Disable both JavaScript and CSS coverage
const [jsCoverage, cssCoverage] = await Promise.all([
  page.coverage.stopJSCoverage(),
  page.coverage.stopCSSCoverage(),
]);
let totalBytes = 0;
let usedBytes = 0;
const coverage = [...jsCoverage, ...cssCoverage];
for (const entry of coverage) {
  totalBytes += entry.text.length;
  for (const range of entry.ranges)
    usedBytes += range.end - range.start - 1;
}
console.log(`Bytes used: ${usedBytes / totalBytes * 100}%`);

_To output coverage in a form consumable by Istanbul,
see puppeteer-to-istanbul._

coverage.startCSSCoverage(options)

  • options <Object> Set of configurable options for coverage
    • resetOnNavigation <boolean> Whether to reset coverage on every navigation. Defaults to true.
  • returns: <Promise> Promise that resolves when coverage is started

coverage.startJSCoverage(options)

  • options <Object> Set of configurable options for coverage
    • resetOnNavigation <boolean> Whether to reset coverage on every navigation. Defaults to true.
  • returns: <Promise> Promise that resolves when coverage is started

coverage.stopCSSCoverage()

  • returns: <Promise<Array<Object>>> Promise that resolves to the array of coverage reports for all stylesheets
    • url <string> StyleSheet URL
    • text <string> StyleSheet content
    • ranges <Array<Object>> StyleSheet ranges that were used. Ranges are sorted and non-overlapping.
    • start <number> A start offset in text, inclusive
    • end <number> An end offset in text, exclusive

NOTE CSS Coverage 不包括那些没有 sourceURLs的动态加载得 style标签。

coverage.stopJSCoverage()

  • returns: <Promise<Array<Object>>> Promise that resolves to the array of coverage reports for all non-anonymous scripts
    • url <string> Script URL
    • text <string> Script content
    • ranges <Array<Object>> Script ranges that were executed. Ranges are sorted and non-overlapping.
    • start <number> A start offset in text, inclusive
    • end <number> An end offset in text, exclusive

NOTE JavaScript Coverage 不包括匿名脚本。但是,会包括带有sourceURLs的脚本。

猜你喜欢

转载自blog.csdn.net/DeepLies/article/details/80861761