最近用到了 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.
* 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.
* 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.
* 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
使用 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>
- returns: <BrowserFetcher>
puppeteer.defaultArgs()
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.stdout
和process.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)
此方法通过发起一个 HEAD request来检查目标版本是否可用。
browserFetcher.download(revision[, progressCallback])
revision
<string> 需要下载的浏览器的版本号.progressCallback
<function(number, number)> 此函数方法存在两个参数:
- returns: <Promise<Object>> 当目标版本的浏览器正在被下载和提取的时候,返回一个 Promise 对象,此对象包含目标版本浏览器的一些信息。
此方法通过发起一个 GET请求来从目标 host下载指定版本的浏览器。
browserFetcher.localRevisions()
browserFetcher.platform()
- returns: <string> 返回
mac
,linux
,win32
、win64
中的其中一个。
browserFetcher.remove(revision)
revision
<string> 需要删除的版本。如果指定的版本的浏览器并没有被下载下来,此方法将会抛出错误(此错误可用 catch捕获)。- returns: <Promise> 当指定版本的浏览器被删除后返回一个 Promise。
browserFetcher.revisionInfo(revision)
revision
<string> 希望获取相关信息的浏览器的版本号。returns: <Object>
revision
<string> 信息来源的版本号folderPath
<string> 提取所下载的浏览器包的目录executablePath
<string> 目标版本的浏览器的运行目录url
<string> 目标版本的浏览器的下载urllocal
<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’
- <Target>
当目标 url改变时触发。
NOTE 包括在匿名浏览器上下文中目标URL改变。
event: ‘targetcreated’
- <Target>
当目标被创建时触发, 例如,当一个新页面通过 window.open
或者 browser.newPage
被打开时。
NOTE 包括在匿名浏览器上下文中目标的创建。
event: ‘targetdestroyed’
- <Target>
目标被销毁时触发, 例如,当一个页面关闭时。
NOTE 包括在匿名浏览器上下文中目标的销毁。
browser.browserContexts()
- returns: <Array<BrowserContext>>
返回一个包含所有已经被打开的浏览器上下文的数组。 在一个最新被创建的浏览器中,将会返回一个唯一的BrowserContext的实例。
browser.close()
- returns: <Promise>
关闭 Chromium以及它所有的页面(如果存在被打开的页面的话)。Browser 对象将会被销毁,并且不再可用。
browser.createIncognitoBrowserContext()
- returns: <Promise<BrowserContext>>
创建一个新的匿名浏览器上下文,这个匿名浏览器上下文不会与其他浏览器上下文共享 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
- extends:
EventEmitter
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>
当浏览器上下文中的某个target url改变时触发。
event: ‘targetcreated’
- <Target>
当浏览器上下文中创建了一个新target时触发,例如,当使用 window.open
或 browserContext.newPage
方法创建一个新页面的时候。
event: ‘targetdestroyed’
- <Target>
当浏览器上下文中的某个target 被销毁时触发,例如当一个页面被关闭时。
browserContext.browser()
- returns: <Browser>
浏览器上下文归属的浏览器实例。
browserContext.close()
- returns: <Promise>
关闭浏览器上下文。所有属于此浏览器上下文的target都将会一同销毁。
NOTE 只有匿名浏览器上下文可以被关闭(也就是只有通过
createIncognitoBrowserContext
方法创建的匿名浏览器才可以使用此方法)。
browserContext.isIncognito()
- returns: <boolean>
返回 BrowserContext 是否是匿名的。
浏览器的默认上下文是非匿名的。
NOTE 浏览器的默认浏览器上下文是不可关闭的。
browserContext.newPage()
在浏览器上下文中创建新页面。
browserContext.targets()
浏览器上下文中的所有有效target(例如Page页面)组成的一个数组。
class: Page
- extends:
EventEmitter
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.log
或 console.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’
- <Dialog>
当页面上弹出 JavaScript对话框的时候触发,例如 alert
, prompt
, confirm
或者 beforeunload
。Puppeteer能够通过 Dialog的 accept 或者 dismiss 方法来对此事件作出回应。
event: ‘domcontentloaded’
当 JavaScript 的DOMContentLoaded
事件被触发时触发。
event: ‘error’
- <Error>
当页面崩溃时触发。
NOTE
error
事件在 Node中具有特殊的含义,具体细节参见 error events 。
event: ‘frameattached’
- <Frame>
当一个 frame 被附加到主页面上时触发。
event: ‘framedetached’
- <Frame>
当一个 frame 从主页面上分离(删除)时触发。
event: ‘framenavigated’
- <Frame>
当一个 frame 的url被定向到一个新的url上时触发。
event: ‘load’
当 JavaScript 的load
事件被触发时触发。
event: ‘metrics’
- <Object>
当页面上的JavaScript脚本调用 cnosole.timeStamp
时触发。metrics的可选列表可见 page.metrics
。
event: ‘pageerror’
- <Error> The exception message
当页面上出现未捕获的异常时触发。
event: ‘request’
- <Request>
当页面上发起一个请求的时候触发。request对象是只读的,如果你想拦截并改造请求,参照 page.setRequestInterception
。
event: ‘requestfailed’
- <Request>
当请求失败时触发,例如,请求超时。
event: ‘requestfinished’
- <Request>
当请求完成时触发。
event: ‘response’
- <Response>
当页面收到请求的响应时触发。
event: ‘workercreated’
- <Worker>
当页面上产生一个新的 WebWorker线程时触发。
event: ‘workerdestroyed’
- <Worker>
当页面上有 WebWorker线程结束时触发。
page.$(selector)
page.$$(selector)
selector
<string> 选择器- returns: <Promise<Array<ElementHandle>>>
此方法在页面上使用了 document.querySelectorAll
。如果选择器没有匹配到元素,将会返回 []
。
page.mainFrame().$$(selector)的快捷方法。
page.$$eval(selector, pageFunction[, …args])
selector
<string> 选择器pageFunction
<function> 将在浏览器上下文中执行的函数...args
<…Serializable|JSHandle> 传递给pageFunction
的额外参数- returns: <Promise<Serializable>>
pageFunction
返回的结果。
此方法在页面上使用了 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])
selector
<string> 选择器pageFunction
<function> 将在浏览器上下文中执行的函数...args
<…Serializable|JSHandle> 传递给pageFunction
的额外参数- returns: <Promise<Serializable>>
pageFunction
返回的结果。
此方法在页面上使用了 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>
- returns: <Promise<ElementHandle>> 当script脚本加载完毕,或者脚本内容已经注入到页面上时,将会返回所添加的script标签元素。
向页面中增加指定 url或者 脚本内容的 script
标签。
page.mainFrame().addScriptTag(options)的快捷方法。
page.addStyleTag(options)
options
<Object>
url
<string> 将要被添加的 style 的urlpath
<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()
- returns: <Promise>
Brings page to front (activates tab).
page.browser()
- returns: <Browser>
获取页面所属的 browser实例。
page.click(selector[, options])
selector
<string> 将要被点击的元素的 选择器。如果选择器匹配出了多个元素,则点击事件只会作用在第一个匹配的元素上。options
<Object>
button
<string>left
,right
, ormiddle
, 默认是left
(即使用左键、右键还是中键进行点击操作)clickCount
<number> 默认点击一次。 更多参见UIEvent.detail。delay
<number>mousedown
和mouseup
事件之间的时间间隔. 默认为 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)
options
<Object>
runBeforeUnload
<boolean> 默认为false
. 是否在关闭前调用
before unload。
- returns: <Promise>
page.close()
方法默认不调用 beforeunload句柄。
(这个方法的意思是,如果页面上注册了 onbeforeunload方法,那么在关闭页面时,将会调用这个onbeforeunload方法,如果 puppeteer.launch
的 headless
参数设置为 true
,那么你将看到页面在关闭时,弹出了一个询问是否离开页面的对话框)。
NOTE 如果
runBeforeUnload
为 true, 页面在关闭时可能会弹出beforeunload
对话框,
并且这个对话框可以被 page的 ‘dialog’事件捕获到.
page.content()
获取页面上包括 doctype在内的所有 HTML内容。
page.cookies(…urls)
如果没有提供 URLs,则此方法将会返回当前页面URL的 cookies。
如果指定了URLs,则只有这些指定URLS上的cookies才会被返回。
page.coverage
- returns: <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 to1
.isMobile
<boolean> Whether themeta viewport
tag is taken into account. Defaults tofalse
.hasTouch
<boolean> Specifies if viewport supports touch events. Defaults tofalse
isLandscape
<boolean> Specifies if viewport is in landscape mode. Defaults tofalse
.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)
pageFunction
<function|string> 将在 page context中执行的函数...args
<…Serializable|JSHandle> 传递给pageFunction
的参数- returns: <Promise<Serializable>> Promise which resolves to the return value of
pageFunction
如果传递给 page.evaluate
的 pageFunction
函数返回一个 Promise,则page.evaluate
将会等待得到resolve后,才会返回它自己的值。
如果传递给 page.evaluate
的 pageFunction
函数返回一个 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.evaluate
和 page.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
<function|string> 在browser context中执行的函数。...args
<…Serializable> 传递给pageFunction
的参数- returns: <Promise>
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,此Promise会 resolve
回 puppeteerFunction
的返回结果。
如果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()
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 theload
event is fired.domcontentloaded
- consider navigation to be finished when theDOMContentLoaded
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 theload
event is fired.domcontentloaded
- consider navigation to be finished when theDOMContentLoaded
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
- returns: <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
- returns: <Mouse>
page.pdf(options)
options
<Object> 具备以下属性的参数对象:
path
<string> 保存PDF文件的路径. 如果path
是一个相对路径,则它是相对于current working directory. 如果没有提供此值项值, 将不会保存PDF。scale
<number> 网页缩放的值。默认为1
.displayHeaderFooter
<boolean> Display header and footer. Defaults tofalse
.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 datetitle
文档标题url
文档urlpageNumber
当前页码totalPages
总页数footerTemplate
<string> HTML template for the print footer. Should use the same format as theheaderTemplate
.printBackground
<boolean> Print background graphics. Defaults tofalse
.landscape
<boolean> Paper orientation. Defaults tofalse
.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 overwidth
orheight
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,如果想生成一个 screen
media的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 theload
event is fired.domcontentloaded
- consider navigation to be finished when theDOMContentLoaded
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> 指定截图的文件类型。可选值有jpeg
和png
。默认为 ‘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)
控制是否绕过页面的Content-Security-Policy(内容安全策略)。
NOTE 绕过CSP的操作应该发生在CSP的初始化阶段而不是执行阶段。也就是说,在 navigating向目标主机之前就应该调用
page.setBypassCSP
方法。
page.setCacheEnabled(enabled)
是否使用资源缓存,默认启用缓存。
Toggles ignoring cache for each request based on the enabled state. By default, caching is enabled.
page.setContent(html)
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)
这些额外的 header头将会被页面发出的所有请求链接携带上。
NOTE page.setExtraHTTPHeaders 无法保证请求header的顺序。
page.setJavaScriptEnabled(enabled)
NOTE 改变此值无法影响到那些已经执行的 JS代码。不过会在下次导航 navigation中完全起作用。
page.setOfflineMode(enabled)
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)
page.setViewport(viewport)
NOTE 在某些的情况下,设置 viewportin 将会导致页面 reload 以便让
isMobile
或者hasTouch
属性生效。
如果一个浏览器中开启了多个页面,则每个页面都有其自己的 viewport大小。
page.tap(selector)
此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 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
- returns: <Touchscreen>
page.tracing
- returns: <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.
为了按下一些特殊按键,例如 Control
或 ArrowDown
,请使用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()
- returns: <string>
page.mainFrame().url()的快捷方法。
page.viewport()
- returns: <Object>
page.waitFor(selectorOrFunctionOrTimeout[, options[, …args]])
selectorOrFunctionOrTimeout
<string|number|function> A selector, predicate or timeout to wait foroptions
<Object> Optional waiting parameters...args
<…Serializable|JSHandle>pageFunction
的参数。- returns: <Promise<JSHandle>> Promise which resolves to a JSHandle of the success value
根据第一个参数的不同,此方法可实现的场景如下:
- 如果 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 thepageFunction
is executed, defaults toraf
. Ifpolling
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> 被等待的元素的选择器selectoroptions
<Object> 可选参数:
- 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> 可选参数如下:
- 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()
- returns: <Array<Worker>>
此方法返回当前页面所有的 WebWorkers。
NOTE 不包括 ServiceWorkers。
class: Worker
The Worker class represents a WebWorker.
workercreated
和 workerdestroyed
事件将会被当做 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
<function|string> worker context中将被执行的函数...args
<…Serializable|JSHandle> 传递给pageFunction
的参数- returns: <Promise<Serializable>> Promise将会 resolve
pageFunction
函数的返回值。
如果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.evaluate
和 worker.evaluateHandle
之间唯一的区别在于,worker.evaluateHandle
返回一个 in-page object (JSHandle)
如果pageFunction
返回的值是一个 Promise,则 worker.evaluateHandle
方法将会等到前者 resolve
后,才会返回它自己的值。
(await worker.executionContext()).evaluateHandle(pageFunction, …args)的快捷方法。
worker.executionContext()
- returns: <Promise<ExecutionContext>>
worker.url()
- returns: <string>
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 asArrowLeft
. 参见 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>
- returns: <Promise>
如果 key
值是一个单个字母,并且没有除了 Shift
之外的修饰按键被按下,那么将会继续触发 keypress
/input
事件。可以指定 ‘text’选项以强制生成输入事件。
NOTE 修饰键将会影响
keyboard.press
的效果。如果你按住Shift
键,然后再按其他的字母键,则你将输入一个大写的字母。
keyboard.down
和 keyboard.up
的快捷方法。
keyboard.sendCharacter(char)
触发 keypress
和 input
事件,不会触发 keydown
或者 keyup
事件。
page.keyboard.sendCharacter('嗨');1
NOTE 修饰键将会影响
keyboard.sendCharacter
的效果。如果你按住Shift
键,然后再按其他的字母键,则你将输入一个大写的字母。
keyboard.type(text, options)
输入文本的时候,每个字符都会触发 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)
key
<string> 需要释放的按键的名称, 例如ArrowLeft
. 更多按键名称列表参见 USKeyboardLayout。- returns: <Promise>
触发 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>mousedown
和mouseup
之间的时间间隔(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])
x
<number>y
<number>options
<Object>
steps
<number>默认是 1. Sends intermediatemousemove
events.
- returns: <Promise>
触发 mousemove
事件。
mouse.up([options])
options
<Object>
button
<string>left
,right
, 或者middle
, 默认是left
。clickCount
<number> 默认是 1. 参见 UIEvent.detail.
- returns: <Promise>
触发 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)
每个浏览器一次只能执行一个跟踪任务。
tracing.stop()
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
orprompt
.
class: ConsoleMessage
ConsoleMessage objects are dispatched by page via the ‘console’ event.
consoleMessage.args()
consoleMessage.text()
- returns: <string>
consoleMessage.type()
- returns: <string>
允许以下值: '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])
selector
<string> frame上目标元素的 selectorpageFunction
<function> 将在 browser context执行的函数...args
<…Serializable|JSHandle> 传递给pageFunction
的额外参数- returns: <Promise<Serializable>> Promise which resolves to the return value of
pageFunction
此方法使用了 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])
selector
<string> frame上目标元素的 selectorpageFunction
<function> 将在 browser context执行的函数...args
<…Serializable|JSHandle> 传递给pageFunction
的额外参数- returns: <Promise<Serializable>> Promise which resolves to the return value of
pageFunction
此方法使用了 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)
expression
<string> Expression to evaluate.- returns: <Promise<Array<ElementHandle>>>
此方法用于执行给定的 XPath 表达式。
frame.addScriptTag(options)
options
<Object>
url
<string> 需要被增加的script标签的urlpath
<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 的urlpath
<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
, ormiddle
, 默认是left
(即使用左键、右键还是中键进行点击操作)clickCount
<number> 默认点击一次。 更多参见UIEvent.detail。delay
<number>mousedown
和mouseup
事件之间的时间间隔. 默认为 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)
pageFunction
<function|string> 将在 browser context中执行的函数...args
<…Serializable|JSHandle> 传递给pageFunction
的参数- returns: <Promise<Serializable>> Promise which resolves to the return value of
pageFunction
如果传递给 frame.evaluate
的 pageFunction
函数返回一个 Promise,则frame.evaluate
将会等待得到resolve后,才会返回它自己的值。
如果传递给 frame.evaluate
的 pageFunction
函数返回一个 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.evaluate
和 paframege.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()
- returns: <Promise<ExecutionContext>> 与当前frame 关联的执行上下文。
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()
- returns: <boolean>
如果 frame已经detached了,则返回 true
, 否则返回 false
frame.name()
- returns: <string>
返回 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)
frame.tap(selector)
此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 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.
为了按下一些特殊按键,例如 Control
或 ArrowDown
,请使用keyboard.press
。
frame.type('#mytextarea', 'Hello'); // 快速输入
frame.type('#mytextarea', 'World', {delay: 100}); // 减缓输入速度以模拟真实输入
frame.url()
- returns: <string>
返回 frame的url
frame.waitFor(selectorOrFunctionOrTimeout[, options[, …args]])
selectorOrFunctionOrTimeout
<string|number|function> A selector, predicate or timeout to wait foroptions
<Object> Optional waiting parameters...args
<…Serializable|JSHandle>pageFunction
的参数。- returns: <Promise<JSHandle>> Promise which resolves to a JSHandle of the success value
根据第一个参数的不同,此方法可实现的场景如下:
- 如果 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 thepageFunction
is executed, defaults toraf
. Ifpolling
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> 被等待的元素的选择器selectoroptions
<Object> 可选参数
- 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> 可选参数如下:
- 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
<function|string> 在executionContext
中执行的函数...args
<…Serializable|JSHandle> 传递给pageFunction
的参数- returns: <Promise<Serializable>> Promise 将会resolve回
pageFunction
函数的结果。
如果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.evaluate
和 executionContext.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()
- returns: 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)
selector
<string> 目标元素的 selector- returns: <Promise<Array<ElementHandle>>>
此方法将在页面上使用element.querySelectorAll
,如果没有匹配到任何元素,则将resolve 回[]
elementHandle.$$eval(selector, pageFunction, …args)
selector
<string> 目标元素的 selectorpageFunction
<function> 将在 browser context中执行的函数...args
<…Serializable|JSHandle> 传递给pageFunction
的参数- returns: <Promise<Serializable>> Promise 将resolve回
pageFunction
函数的返回值。
此方法将在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)
selector
<string> 目标元素的 selectorpageFunction
<function> 将在 browser context中执行的函数...args
<…Serializable|JSHandle> 传递给pageFunction
的参数- returns: <Promise<Serializable>> Promise 将resolve回
pageFunction
函数的返回值。
此方法将在 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)
expression
<string> Expression to evaluate.- returns: <Promise<Array<ElementHandle>>>
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()
- returns: <elementhandle>
elementHandle.boundingBox()
- returns: <Promise
elementHandle.boxModel()
- returns: <Promise
elementHandle.click([options])
options
<Object>
button
<string>left
,right
, 或者middle
, 默认是left
。(意思是用鼠标的哪个按键进行点击操作,左键、右键或者中键)clickCount
<number> 点击次数,默认是 1. 参见 UIEvent.detail.delay
<number>mousedown
和mouseup
之间的时间间隔(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()
- returns: <Promise
elementHandle.dispose()
- returns: <Promise> Promise which resolves when the element handle is successfully disposed.
此方法断开 element handle的引用
elementHandle.executionContext()
- returns: ExecutionContext
elementHandle.focus()
- returns: <Promise>
调用 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>
- returns: <Promise>
聚焦在 element上,然后使用 keyboard.down
以及 keyboard.up
方法。
如果 key
值是一个单个字母,并且没有除了 Shift
之外的修饰按键被按下,那么将会继续触发 keypress
/input
事件。可以指定 ‘text’选项以强制生成输入事件。
NOTE 修饰键将会影响
elementHandle.press
的效果。如果你按住Shift
键,然后再按其他的字母键,则你将输入一个大写的字母。
elementHandle.screenshot([options])
options
<Object> 参数和 page.screenshot方法的参数类似。- returns: <Promise<Buffer>> Promise将会resolve截屏图片的 buffer。
此方法将会在需要的时候将元素滚动到可视区域内,然后使用 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()
- returns: <string>
elementHandle.type(text[, options])
聚焦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 thefilePaths
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:
- 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()
- returns: <boolean>
当前请求是否是一个 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()
- returns: <string>
包含所有被渲染引擎使用到的请求资源的类型,允许以下几种: document
, stylesheet
, image
, media
, font
, script
, texttrack
, xhr
, fetch
, eventsource
, websocket
, manifest
, other
.
request.respond(response)
用给定的响应来完成请求。 为了使此功能有效可用, 请设置 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()
- returns: <boolean>
如果响应数据来自于磁盘或者内存,则返回 true
response.fromServiceWorker()
- returns: <boolean>
如果响应数据来自于 service worker,则返回 true
response.headers()
- returns: <Object> http响应头对象. 所有的 header name 都是小写.
response.json()
- returns:
response.ok()
- returns: <boolean>
包含一个用于标记数据响应是否成功(状态码为 200-299)的布尔值。
response.request()
response.securityDetails()
- returns:
response.status()
- returns: <number>
包含响应状态码(例如,200,表示响应成功)
response.text()
response.url()
- returns: <string>
包含响应的 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()
securityDetails.validTo()
class: Target
target.browser()
- returns: <Browser>
获取 target(可以认为是page) 隶属于的 browser。
target.browserContext()
- returns: <BrowserContext>
The browser context the target belongs to.
target.createCDPSession()
- returns: <Promise<CDPSession>>
Creates a Chrome Devtools Protocol session attached to the target.
target.opener()
- returns:
target.page()
- returns: <Promise
target.type()
- returns: <string>
返回 target的类型,可以是 "page"
, "background_page"
, "service_worker"
, "browser"
or "other"
target.url()
- returns: <string>
class: CDPSession
- extends:
EventEmitter
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()
- returns: <Promise>
将 cdpSession从 target上 detach掉,一旦cdpSession从 target上 detach掉了,则 the cdpSession object将不可再触发任何事件,也不再可以用于发送信息
cdpSession.send(method[, params])
method
<string> protocol method nameparams
<Object> Optional method parameters- returns: <Promise<Object>>
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 totrue
.
- 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 totrue
.
- 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
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
NOTE JavaScript Coverage 不包括匿名脚本。但是,会包括带有sourceURLs的脚本。