最近用到了 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.$$(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]])
- page.waitForFunction(pageFunction[, 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)
- 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]])
- frame.waitForFunction(pageFunction[, 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)
- 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
使用 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
- returns:
>:以 Promise的形式返回了一个 Browser实例对象。
此方法将会为 Puppeteer 附加上一个 Chromium 实例。
puppeteer.createBrowserFetcher([options])
options
- returns:
puppeteer.defaultArgs()
- returns:
> The default flags that Chromium will be launched with.
puppeteer.executablePath()
- returns:
Puppeteer将会在此路径中搜寻 Chromium包, 如果在 PUPPETEER_SKIP_CHROMIUM_DOWNLOAD
阶段 Chromium包被跳过下载,那么此包也有可能是不存在的。
puppeteer.launch([options])
options
- returns:
> 一个返回 浏览器实例的 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
检查是否可用版本的版本号。 - returns:
> 如果目标版本的浏览器可以从目标 host上下载下来,则返回 true
。
此方法通过发起一个 HEAD request来检查目标版本是否可用。
browserFetcher.download(revision[, progressCallback])
revision
需要下载的浏览器的版本号. progressCallback
此函数方法存在两个参数: downloadedBytes
已经下载了多少字节 totalBytes
一共有多少字节.
- returns:
> 当目标版本的浏览器正在被下载和提取的时候,返回一个 Promise 对象,此对象包含目标版本浏览器的一些信息。 revision
the revision the info was created from folderPath
提取所下载的浏览器包的目录 executablePath
目标版本的浏览器的运行目录 url
目标版本的浏览器的下载url local
目标版本的浏览器是否可在本地磁盘上获取
此方法通过发起一个 GET请求来从目标 host下载指定版本的浏览器。
browserFetcher.localRevisions()
- returns:
>> 本地磁盘可获取到的所有版本浏览器的列表。
browserFetcher.platform()
- returns:
返回 mac
,linux
,win32
、win64
中的其中一个。
browserFetcher.remove(revision)
revision
需要删除的版本。如果指定的版本的浏览器并没有被下载下来,此方法将会抛出错误(此错误可用 catch捕获)。 - returns:
当指定版本的浏览器被删除后返回一个 Promise。
browserFetcher.revisionInfo(revision)
-
revision
希望获取相关信息的浏览器的版本号。 -
returns:
revision
信息来源的版本号 folderPath
提取所下载的浏览器包的目录 executablePath
目标版本的浏览器的运行目录 url
目标版本的浏览器的下载url local
目标版本的浏览器是否可在本地磁盘上获取
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()
- returns:
>
返回一个包含所有已经被打开的浏览器上下文的数组。 在一个最新被创建的浏览器中,将会返回一个唯一的BrowserContext的实例。
browser.close()
- returns:
关闭 Chromium以及它所有的页面(如果存在被打开的页面的话)。Browser 对象将会被销毁,并且不再可用。
browser.createIncognitoBrowserContext()
- returns:
>
创建一个新的匿名浏览器上下文,这个匿名浏览器上下文不会与其他浏览器上下文共享 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()
- returns:
>
返回一个新的 Page Promise对象,Page将在一个默认的浏览器上下文中创建。
browser.pages()
- returns:
>> resolve一个包含所有打开页面的数组,不可见的页面,例如 "background_page"
, 将不会包含在此数组中,你可以使用 target.page()方法来获取到(不可见页面)。
browser.process()
- returns: 开启一个浏览器主进程的子进程。如果浏览器实例是使用
puppeteer.connect
方法创建,那么将会返回null
。
browser.targets()
- returns:
>
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()
- returns:
> resolve 浏览器的user agent.
NOTE 可以使用 page.setUserAgent来改变浏览器的 user agent。
browser.version()
- returns:
> 对于 headless Chromium来说,将返回一个类似于 HeadlessChrome/61.0.3153.0
的字符串。 对于non-headless 浏览器来说, 将返回一个类似于Chrome/61.0.3153.0
的字符串。
NOTE 此方法返回的字符串格式可能会在将来的版本中发生变化。
browser.wsEndpoint()
- returns:
浏览器 websoket 的url。
此方法返回的 浏览器 websoket端口字符串格式如:ws://${host}:${port}/devtools/browser/
,此字符串可作为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 url改变时触发。
event: 'targetcreated'
当浏览器上下文中创建了一个新target时触发,例如,当使用 window.open
或 browserContext.newPage
方法创建一个新页面的时候。
event: 'targetdestroyed'
当浏览器上下文中的某个target 被销毁时触发,例如当一个页面被关闭时。
browserContext.browser()
- returns:
浏览器上下文归属的浏览器实例。
browserContext.close()
- returns:
关闭浏览器上下文。所有属于此浏览器上下文的target都将会一同销毁。
NOTE 只有匿名浏览器上下文可以被关闭(也就是只有通过
createIncognitoBrowserContext
方法创建的匿名浏览器才可以使用此方法)。
browserContext.isIncognito()
- returns:
返回 BrowserContext 是否是匿名的。 浏览器的默认上下文是非匿名的。
NOTE 浏览器的默认浏览器上下文是不可关闭的。
browserContext.newPage()
- returns:
>
在浏览器上下文中创建新页面。
browserContext.targets()
- returns:
>
浏览器上下文中的所有有效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'
当页面上弹出 JavaScript对话框的时候触发,例如 alert
, prompt
, confirm
或者 beforeunload
。Puppeteer能够通过 Dialog的 accept 或者 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'
title
console.timeStamp
的 titlemetrics
Object containing metrics as key/value pairs. The values of metrics are of type.一个包含 metrics key/value对的对象。metrics的值为 number类型。
当页面上的JavaScript脚本调用 cnosole.timeStamp
时触发。metrics的可选列表可见 page.metrics
。
event: 'pageerror'
The exception message
当页面上出现未捕获的异常时触发。
event: 'request'
当页面上发起一个请求的时候触发。request对象是只读的,如果你想拦截并改造请求,参照 page.setRequestInterception
。
event: 'requestfailed'
当请求失败时触发,例如,请求超时。
event: 'requestfinished'
当请求完成时触发。
event: 'response'
当页面收到请求的响应时触发。
event: 'workercreated'
当页面上产生一个新的 WebWorker线程时触发。
event: 'workerdestroyed'
当页面上有 WebWorker线程结束时触发。
page.$(selector)
selector
选择器 - returns:
>
此方法在页面上使用了 document.querySelector
。如果选择器没有匹配到元素,将会返回 null
。
page.mainFrame().$(selector)的快捷方法。
page.$$(selector)
selector
选择器 - returns:
>>
此方法在页面上使用了 document.querySelectorAll
。如果选择器没有匹配到元素,将会返回 []
。
page.mainFrame().$$(selector)的快捷方法。
page.$$eval(selector, pageFunction[, ...args])
selector
选择器 pageFunction
将在浏览器上下文中执行的函数 ...args
<...Serializable|JSHandle> 传递给pageFunction
的额外参数- returns:
> 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
选择器 pageFunction
将在浏览器上下文中执行的函数 ...args
<...Serializable|JSHandle> 传递给pageFunction
的额外参数- returns:
> 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
Expression to evaluate. - returns:
>>
根据给定的 Xpath表达式获取 DOM元素。
page.mainFrame().$x(expression)的快捷方法。
page.addScriptTag(options)
options
url
将要被添加的 script 的url. path
将要被添加的JavaScript文件的路径. 如果 path
是相对路径, 则其是相对于 current working directory。content
将要被添加的JavaScript脚本的内容。 type
脚本类型. 如果是 'module' ,则将导入的是JS的 ES6模块。更多参见 script。
- returns:
> 当script脚本加载完毕,或者脚本内容已经注入到页面上时,将会返回所添加的script标签元素。
向页面中增加指定 url或者 脚本内容的 script
标签。
page.mainFrame().addScriptTag(options)的快捷方法。
page.addStyleTag(options)
options
url
将要被添加的 style 的url path
将要被添加的 CSS文件的路径. 如果 path
是相对路径, 则其是相对于 current working directory。content
将要被添加的CSS脚本的内容。
- returns:
>当style加载完毕,或者style内容已经注入到页面上时,将会返回所添加的style标签元素。
向页面中添加一个 带有指定 url的标签,或者一个带有内容的
标签。
page.mainFrame().addStyleTag(options)的快捷方法。
page.authenticate(credentials)
credentials
username
password
- returns:
Provide credentials for http authentication.
如果是无效的authentication,则返回 null
page.bringToFront()
- returns:
Brings page to front (activates tab).
page.browser()
- returns:
获取页面所属的 browser实例。
page.click(selector[, options])
selector
将要被点击的元素的 选择器。如果选择器匹配出了多个元素,则点击事件只会作用在第一个匹配的元素上。 options
button
left
,right
, ormiddle
, 默认是left
(即使用左键、右键还是中键进行点击操作)clickCount
默认点击一次。 更多参见UIEvent.detail。 delay
mousedown
和mouseup
事件之间的时间间隔. 默认为 0.
- returns:
当匹配的元素被成功点击时将会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
runBeforeUnload
默认为 false
. 是否在关闭前调用 before unload。
- returns:
page.close()
方法默认不调用 beforeunload句柄。
(这个方法的意思是,如果页面上注册了 onbeforeunload方法,那么在关闭页面时,将会调用这个onbeforeunload方法,如果 puppeteer.launch
的 headless
参数设置为 true
,那么你将看到页面在关闭时,弹出了一个询问是否离开页面的对话框)。
NOTE 如果
runBeforeUnload
为 true, 页面在关闭时可能会弹出beforeunload
对话框, 并且这个对话框可以被 page的 'dialog'事件捕获到.
page.content()
- returns:
>
获取页面上包括 doctype在内的所有 HTML内容。
page.cookies(...urls)
...urls
<...string>- returns:
>> name
value
domain
path
expires
Unix time in seconds. httpOnly
secure
session
sameSite
"Strict"
or"Lax"
.
如果没有提供 URLs,则此方法将会返回当前页面URL的 cookies。 如果指定了URLs,则只有这些指定URLS上的cookies才会被返回。
page.coverage
- returns:
page.deleteCookie(...cookies)
...cookies
<...Object>name
required url
domain
path
secure
- returns:
page.emulate(options)
options
viewport
width
page width in pixels. height
page height in pixels. deviceScaleFactor
Specify device scale factor (can be thought of as dpr). Defaults to 1
.isMobile
Whether the meta viewport
tag is taken into account. Defaults tofalse
.hasTouch
Specifies if viewport supports touch events. Defaults to false
isLandscape
Specifies if viewport is in landscape mode. Defaults to false
.
userAgent
- returns:
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
改变页面CSS media的类型。允许的值有'screen'
,'print'
andnull
,如果传入null
则表示不进行模拟。- returns:
page.evaluate(pageFunction, ...args)
pageFunction
将在 page context中执行的函数 ...args
<...Serializable|JSHandle> 传递给pageFunction
的参数- returns:
> 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
在page context 中执行的函数。 ...args
<...Serializable|JSHandle> 传递给pageFunction
的参数- returns:
> 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
在browser context中执行的函数。 ...args
<...Serializable> 传递给pageFunction
的参数- returns:
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
在 window对象中添加的函数的名字 puppeteerFunction
将会在 Puppeteer's context中执行的函数。 - returns:
此方法将会在 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
需要focus的元素的选择器。 如果此选择器匹配到了多个元素,则只有第一个匹配的元素才会被focus。 - returns:
当成功匹配到元素后,Promise将resolve。如果没有匹配到任何元素,则将reject。
此方法将 focus给定 selector匹配到的元素。 如果根据给定的 selector没有匹配到任何元素,将会抛出异常。
page.mainFrame().focus(selector)的快捷方法。
page.frames()
- returns:
> 返回一个有页面上附加的所有 frames组成的数组。
page.goBack(options)
options
页面跳转参数,包括以下属性: timeout
连接超时时间,单位毫秒, 默认是 30秒, 如果设置为 0
则表示禁用此选项。 此值也可以被 page.setDefaultNavigationTimeout(timeout) 方法修改。waitUntil
> 确认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 which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect.
如果无法 go back
,则 resolve回的数据为 null
返回上一页。
page.goForward(options)
options
页面跳转参数,包括以下属性: timeout
连接超时时间,单位毫秒, 默认是 30秒, 如果设置为 0
则表示禁用此选项。 此值也可以被 page.setDefaultNavigationTimeout(timeout) 方法修改。waitUntil
> 确认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 which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect.
如果无法 go forward
,则 resolve回的数据为 null
跳转到 history里的下一页。
page.goto(url, options)
url
目标页面的url. url中应该包含协议头,例如 https://
。options
页面跳转参数,包括以下属性: timeout
连接超时时间,单位毫秒, 默认是 30秒, 如果设置为 0
则表示禁用此选项。 此值也可以被 page.setDefaultNavigationTimeout(timeout) 方法修改。waitUntil
> 确认navigation成功的条件, 默认是 load
。如果给定的值是一个事件组成的数组,那么只有当数组中的所有事件全部被触发后才会认为 navigation成功,可选的事件列表如下:load
- 当load
事件触发时,则认为 navigation导航结束。domcontentloaded
- 当DOMContentLoaded
事件触发时,则认为 navigation导航结束。networkidle0
- 如果在500ms
内发起的http请求数为0,则认为导航结束。networkidle2
- 如果在500ms
内发起的http请求数为不超过 2条,则认为导航结束。
- returns:
> Promise which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect.
如果在页面跳转过程中发生以下情况,则此方法将抛出错误:
- SSL error (例如,如果是私有证书).
- 目标 URL失效
- 连接超时
- the main resource failed to load.
NOTE
page.goto
方法要么抛出一个错误,要么返回 a main resource response,除非跳转的链接是about:blank
, 这时候,此方法将返回null
。
NOTE 在 Headless mode下,此方法不支持 跳转到 一个 PDF document。参见upstream issue.
page.hover(selector)
selector
需要 hover的元素的选择器。 如果此选择器匹配到了多个元素,则只有第一个匹配的元素才会被hover。 - returns:
当成功匹配到元素后,Promise将resolve。如果没有匹配到任何元素,则将reject。
此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 page.mouse方法 hover匹配到的元素的中心位置。 如果没有匹配到元素,则将抛出一个错误。
page.mainFrame().hover(selector)的快捷方法。
page.isClosed()
- returns: boolean
页面是否被关闭。
page.keyboard
- returns:
page.mainFrame()
- returns: 返回页面的 主frame。
navigations过程中,Page一直存在一个 main frame。
page.metrics()
- returns:
> Object containing metrics as key/value pairs. Timestamp
The timestamp when the metrics sample was taken. Documents
Number of documents in the page. Frames
Number of frames in the page. JSEventListeners
Number of events in the page. Nodes
Number of DOM nodes in the page. LayoutCount
Total number of full or partial page layout. RecalcStyleCount
Total number of page style recalculations. LayoutDuration
Combined durations of all page layouts. RecalcStyleDuration
Combined duration of all page style recalculations. ScriptDuration
Combined duration of JavaScript execution. TaskDuration
Combined duration of all tasks performed by the browser. JSHeapUsedSize
Used JavaScript heap size. JSHeapTotalSize
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:
page.pdf(options)
options
具备以下属性的参数对象: path
保存PDF文件的路径. 如果 path
是一个相对路径,则它是相对于current working directory. 如果没有提供此值项值, 将不会保存PDF。scale
网页缩放的值。默认为 1
.displayHeaderFooter
Display header and footer. Defaults to false
.headerTemplate
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
HTML template for the print footer. Should use the same format as the headerTemplate
.printBackground
Print background graphics. Defaults to false
.landscape
Paper orientation. Defaults to false
.pageRanges
Paper ranges to print, e.g., '1-5, 8, 11-13'. Defaults to the empty string, which means print all pages. format
Paper format. If set, takes priority over width
orheight
options. Defaults to 'Letter'.width
Paper width, accepts values labeled with units. height
Paper height, accepts values labeled with units. margin
Paper margins, defaults to none. top
Top margin, accepts values labeled with units. right
Right margin, accepts values labeled with units. bottom
Bottom margin, accepts values labeled with units. left
Left margin, accepts values labeled with units.
- returns:
> 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})
- 宽度为100pxpage.pdf({width: '100px'})
- 宽度为100pxpage.pdf({width: '10cm'})
- 宽度为 10厘米
所有可选的单位:
px
- pixelin
- inchcm
- centimetermm
- millimeter
format
属性的可选值:
Letter
: 8.5in x 11inLegal
: 8.5in x 14inTabloid
: 11in x 17inLedger
: 17in x 11inA0
: 33.1in x 46.8inA1
: 23.4in x 33.1inA2
: 16.5in x 23.4inA3
: 11.7in x 16.5inA4
: 8.27in x 11.7inA5
: 5.83in x 8.27inA6
: 4.13in x 5.83in
NOTE
headerTemplate
以及footerTemplate
的标签有以下限制:
- Script tags inside templates are not evaluated.
- Page styles are not visible inside templates.
page.queryObjects(prototypeHandle)
prototypeHandle
A handle to the object prototype. - returns:
> 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
navigation 参数,允许具备以下属性: timeout
超时时间,单位为ms,默认为 30s, 如果设置为 0
表示禁用此属性。也可以使用page.setDefaultNavigationTimeout(timeout) 方法来改变此值。waitUntil
> 确认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 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
此对象允许具备以下属性: path
截图保存的地址路径。 截图的图片类型会自动根据文件名扩展来确定。如果 path
是相对路径,则其应当是相对于 current working directory.。如果没有提供此属性值,则将不会保存截图。type
指定截图的文件类型。可选值有 jpeg
和png
。默认为 'png'。quality
图片质量, 值范围为 0-100。不适用于 png
图片。fullPage
当值为 true
的话,则将截取包括可滚动区域在内的所有页面。默认为false
.clip
用于确定一个指定的裁剪范围。必须具备以下属性: x
x-coordinate of top-left corner of clip area裁剪范围的左上角的 x点坐标 y
裁剪范围的左上角的 y点坐标 width
裁剪范围的宽度 height
裁剪范围的高度
omitBackground
隐藏默认白色背景,并允许以透明方式截取屏幕截图。 默认为 false
.encoding
图片编码方式,可以是 base64
或者binary
。默认为binary
.
- returns:
> 返回一个Promise,此Promise的resolve值是截图的 buffer或者 base64编码数据的字符串。
NOTE 在OS X系统上,截图操作最少需要 1/6秒的时间。参见 crbug.com/741689 。
page.select(selector, ...values)
selector
[select]标签的选择器 ...values
<...string> 选择的值。如果标签具有
multiple
属性, 所有的指定值都是有效值, 否则只会考虑第一个值。- returns:
>> 返回一个由所有成功选中(selected)的选项(option)的值组成的数组。
当所有提供的 values
值的选项(option)全被选中后会触发 change
以及 input
事件。 如果根据所指定的选择器selector
没有匹配到一个 元素,将会抛出错误。 (这个方法就是用于控制 select的选择)
page.select('select#colors', 'blue'); // 单选
page.select('select#colors', 'red', 'green', 'blue'); // 多选
复制代码
Shortcut for page.mainFrame().select()
page.setBypassCSP(enabled)
enabled
设置是否绕过页面的Content-Security-Policy(内容安全策略)。 - returns:
控制是否绕过页面的Content-Security-Policy(内容安全策略)。
NOTE 绕过CSP的操作应该发生在CSP的初始化阶段而不是执行阶段。也就是说,在 navigating向目标主机之前就应该调用
page.setBypassCSP
方法。
page.setCacheEnabled(enabled)
enabled
sets the enabled
state of the cache.- returns:
是否使用资源缓存,默认启用缓存。 Toggles ignoring cache for each request based on the enabled state. By default, caching is enabled.
page.setContent(html)
html
设置page页面的HTML内容。 - returns:
page.setCookie(...cookies)
...cookies
<...Object>name
必选 value
必选 url
domain
path
expires
以秒为单位的 Unix时间 httpOnly
secure
sameSite
"Strict"
or"Lax"
.
- returns:
page.setDefaultNavigationTimeout(timeout)
timeout
导航超时时间。
此方法可以改变以下方法默认 30s的超时时间。
- page.goto(url, options)
- page.goBack(options)
- page.goForward(options)
- page.reload(options)
- page.waitForNavigation(options)
page.setExtraHTTPHeaders(headers)
headers
一个将为所有的请求增添额外 header属性的对象。所有的header值必须都是 string类型。 - returns:
这些额外的 header头将会被页面发出的所有请求链接携带上。
NOTE page.setExtraHTTPHeaders 无法保证请求header的顺序。
page.setJavaScriptEnabled(enabled)
enabled
是否启用页面的 JavaScript。 - returns:
NOTE 改变此值无法影响到那些已经执行的 JS代码。不过会在下次导航 navigation中完全起作用。
page.setOfflineMode(enabled)
enabled
当设置为 true
时, 将会启用页面的离线模式。- returns:
page.setRequestInterception(value)
value
是否启用请求拦截。 - returns:
启用请求拦截将会使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
指定页面的 user agent - returns:
resolve页面的 user agent
page.setViewport(viewport)
viewport
width
页面的宽度,单位为px height
页面的高度,单位为px deviceScaleFactor
指定页面缩放比例 (can be thought of as dpr). 默认为 1
.isMobile
是否考虑 meta viewport
标签。 默认为false
.hasTouch
设置 viewport是否支持触摸事件。 默认为 false
isLandscape
设置 viewport是否是 landscape mode。 默认为 false
.
- returns:
NOTE 在某些的情况下,设置 viewportin 将会导致页面 reload 以便让
isMobile
或者hasTouch
属性生效。
如果一个浏览器中开启了多个页面,则每个页面都有其自己的 viewport大小。
page.tap(selector)
selector
将要被tap的元素的 选择器。如果选择器匹配出了多个元素,则tap事件只会作用在第一个匹配的元素上。 - returns:
此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 page.touchscreen方法tap匹配到的元素的中心位置。 如果没有匹配到元素,则将抛出一个错误。
page.mainFrame().tap(selector)的快捷方法。
page.target()
- returns:
a target this page was created from.
page.title()
- returns:
> 返回页面的title。
page.mainFrame().title()的快捷方法。
page.touchscreen
- returns:
page.tracing
- returns:
page.type(selector, text[, options])
selector
文本框(包括 texarea和input)的选择器。如果选择器匹配出了多个元素,则只会选择第一个匹配的元素上。 text
将要输入到文本框内的文字。 options
delay
按键输入的间隔速度,单位为ms。默认为 0.
- returns:
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:
page.mainFrame().url()的快捷方法。
page.viewport()
- returns:
width
页面宽度,单位为px。 height
页面高度,单位为px。 deviceScaleFactor
设备的缩放比例 (can be though of as dpr)。默认为 1
.isMobile
是否考虑 meta viewport
标签。默认为false
.hasTouch
是否支持 touch事件。默认为 false
isLandscape
设置 viewport 是否处于landscape mode。默认为 false
.
page.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]])
selectorOrFunctionOrTimeout
A selector, predicate or timeout to wait for options
Optional waiting parameters ...args
<...Serializable|JSHandle>pageFunction
的参数。- returns:
> 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]])的快捷方法。
page.waitForFunction(pageFunction[, options[, ...args]])
pageFunction
将要在 browser context中执行的函数(可以是function,也可以是string,如果是string,则是有返回值的可以执行的 js表达式) options
Optional waiting parameters polling
An interval at which the pageFunction
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
pageFunction
函数执行的最大等待时间(ms)。。默认是30000
(30 秒)。如果取值为0
,则表示禁用此选项。
...args
<...Serializable|JSHandle> 传递给pageFunction
的额外参数。- returns:
> 当 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]])的快捷方法。
page.waitForNavigation(options)
options
Navigation 参数,允许存在以下属性: timeout
navigation超时时间(ms),默认是 30 seconds, 取值 0
则表示禁用此选项。也可以使用 page.setDefaultNavigationTimeout(timeout) 方法来改变默认值。waitUntil
> navigation导航成功的界限, 默认是 load
. 如果给定的值是一个事件名称组成的数组,那么只有当数组中的所有事件全部被触发后才会认为 navigation成功,可选的事件列表如下:load
- 当load
事件触发时,则认为 navigation导航结束。domcontentloaded
- 当DOMContentLoaded
事件触发时,则认为 navigation导航结束。networkidle0
- 如果在500ms
内发起的http请求数为0,则认为导航结束。networkidle2
- 如果在500ms
内发起的http请求数为不超过 2条,则认为导航结束。
- returns:
> 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
被等待的元素的选择器selector options
可选参数: visible
出现在DOM中的元素必须是可见的(visible),例如,不能有 display: none
或者visibility: hidden
CSS 属性。默认是false
。hidden
元素不存在于DOM中(包括一开始就不存在,或者存在了又被移除掉),或者是被隐藏了, 例如, 具有 display: none
或者visibility: hidden
CSS 属性。默认是false
.timeout
最大等待时间(ms)。默认是 30000
(30 秒)。取值为的0
则表示禁用此参数。
- returns:
> 当在 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
匹配xpath的元素 options
可选参数如下: visible
出现在DOM中的元素必须是可见的(visible),例如,不能有 display: none
或者visibility: hidden
CSS 属性。默认是false
。hidden
元素不存在于DOM中(包括一开始就不存在,或者存在了又被移除掉),或者是被隐藏了, 例如, 具有 display: none
或者visibility: hidden
CSS 属性。默认是false
.timeout
最大等待时间(ms)。默认是 30000
(30 秒)。取值为的0
则表示禁用此参数。
- returns:
> 当在 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:
> 此方法返回当前页面所有的 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
worker context中将被执行的函数 ...args
<...Serializable|JSHandle> 传递给pageFunction
的参数- returns:
> 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
将在page context中执行的函数。 ...args
<...Serializable|JSHandle> 传递给pageFunction
函数的参数。- returns:
> 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:
>
worker.url()
- returns:
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
按下的按键名称, such as ArrowLeft
. 参见 USKeyboardLayout 获取按键名称列表。options
text
如果指定了此属性值, generates an input event with this text.
- returns:
触发 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
需要按下的按键的名称, 例如 ArrowLeft
. 更多按键名称列表参见 USKeyboardLayout 。options
text
如果指定,则将根据 text
进行按键操作。delay
keydown
和keyup
之间的时间间隔(ms). 默认是 0.
- returns:
如果 key
值是一个单个字母,并且没有除了 Shift
之外的修饰按键被按下,那么将会继续触发 keypress
/input
事件。可以指定 'text'选项以强制生成输入事件。
NOTE 修饰键将会影响
keyboard.press
的效果。如果你按住Shift
键,然后再按其他的字母键,则你将输入一个大写的字母。
keyboard.down
和 keyboard.up
的快捷方法。
keyboard.sendCharacter(char)
char
向页面中输入的字母 - returns:
触发 keypress
和 input
事件,不会触发 keydown
或者 keyup
事件。
page.keyboard.sendCharacter('嗨');1
复制代码
NOTE 修饰键将会影响
keyboard.sendCharacter
的效果。如果你按住Shift
键,然后再按其他的字母键,则你将输入一个大写的字母。
keyboard.type(text, options)
text
需要向聚焦的输入框中输入的文本 options
delay
按键按下的时间间隔. 默认是 0.
- returns:
输入文本的时候,每个字符都会触发 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
需要释放的按键的名称, 例如 ArrowLeft
. 更多按键名称列表参见 USKeyboardLayout。- returns:
触发 keyup
事件。
class: Mouse
mouse.click(x, y, [options])
x
y
options
button
left
,right
, 或者middle
, 默认是left
。(意思是用鼠标的哪个按键进行点击操作,左键、右键或者中键)clickCount
点击次数,默认是 1. 参见 UIEvent.detail. delay
mousedown
和mouseup
之间的时间间隔(ms).默认是 0.
- returns:
mouse.move
, mouse.down
以及 mouse.up
的联合方法。
mouse.down([options])
options
button
left
,right
, 或者middle
, 默认是left
。(意思是用鼠标的哪个按键进行点击操作,左键、右键或者中键)clickCount
默认是 1. 参见 UIEvent.detail.
- returns:
触发 mousedown
事件。
mouse.move(x, y, [options])
x
y
options
steps
默认是 1. Sends intermediate mousemove
events.
- returns:
触发 mousemove
事件。
mouse.up([options])
options
button
left
,right
, 或者middle
, 默认是left
。clickCount
默认是 1. 参见 UIEvent.detail.
- returns:
触发 mouseup
事件。
class: Touchscreen
touchscreen.tap(x, y)
x
y
- returns:
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
path
跟踪文件的存储路径. screenshots
captures screenshots in the trace. categories
> specify custom categories to use instead of default.
- returns:
每个浏览器一次只能执行一个跟踪任务。
tracing.stop()
- returns:
> 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
在提示框中输入的文件内容。。如果dialog的类型不是prompt(提示框),则此方法将不起任何作用。 - returns:
Promise which resolves when the dialog has been accepted.
dialog.defaultValue()
- returns:
如果 dialog是一个 prompt(提示框),返回提示框的默认值,否则将返回空字符串。
dialog.dismiss()
- returns:
提示框被取消时,Promise 返回resolves 。
dialog.message()
- returns:
dialog展示的文本。
dialog.type()
- returns:
Dialog的类型, 可以是以下其中之一 alert
,beforeunload
,confirm
orprompt
.
class: ConsoleMessage
ConsoleMessage objects are dispatched by page via the 'console' event.
consoleMessage.args()
- returns:
>
consoleMessage.text()
- returns:
consoleMessage.type()
- returns:
允许以下值: '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)
selector
Selector to query page for - returns:
> Promise which resolves to ElementHandle pointing to the frame element.
在 frame上搜索元素。如果没有找到所需匹配的元素,则resolve会 null
frame.$$(selector)
selector
Selector to query page for - returns:
>> Promise which resolves to ElementHandles pointing to the frame elements.
此方法使用了 document.querySelectorAll
,如果没有匹配到任何元素,则resolve回 []
frame.$$eval(selector, pageFunction[, ...args])
selector
frame上目标元素的 selector pageFunction
将在 browser context执行的函数 ...args
<...Serializable|JSHandle> 传递给pageFunction
的额外参数- returns:
> 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
frame上目标元素的 selector pageFunction
将在 browser context执行的函数 ...args
<...Serializable|JSHandle> 传递给pageFunction
的额外参数- returns:
> 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
Expression to evaluate. - returns:
>>
此方法用于执行给定的 XPath 表达式。
frame.addScriptTag(options)
options
url
需要被增加的script标签的url path
将要被添加的JavaScript文件的路径. 如果 path
是相对路径, 则其是相对于 current working directory。content
将要被添加的 JavaScript脚本的内容。 type
脚本类型. 如果是 'module' ,则将导入的是JS的 ES6模块。更多参见 [script]
- returns:
> 当script脚本加载完毕,或者脚本内容已经注入到frame上时,将会返回所添加的script标签元素。
向frame中增加指定 url或者 脚本内容的 script
标签。
frame.addStyleTag(options)
options
url
将要被添加的 style 的url path
将要被添加的 CSS文件的路径. 如果 path
是相对路径, 则其是相对于 current working directory。content
将要被添加的CSS脚本的内容。
- returns:
> 当style加载完毕,或者style内容已经注入到frame上时,将会返回所添加的style标签元素。
向页面中添加一个 带有指定 url的标签,或者一个带有内容的
标签。
frame.childFrames()
- returns:
>
frame.click(selector[, options])
selector
将要被点击的元素的 选择器。如果选择器匹配出了多个元素,则点击事件只会作用在第一个匹配的元素上。 options
button
left
,right
, ormiddle
, 默认是left
(即使用左键、右键还是中键进行点击操作)clickCount
默认点击一次。 更多参见UIEvent.detail。 delay
mousedown
和mouseup
事件之间的时间间隔. 默认为 0.
- returns:
当匹配的元素被成功点击时将会resolve,如果没有匹配到元素,则将 reject。
此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 page.mouse方法点击匹配到的元素的中心位置。 如果没有匹配到元素,则将抛出一个错误。
需要注意的是,如果所点击的元素会触发页面跳转,并且还调用了page.waitForNavigation()
方法,那么你可能不会得到期望的结果,正确的做法如下:
const [response] = await Promise.all([
page.waitForNavigation(waitOptions),
frame.click(selector, clickOptions),
]);
复制代码
frame.content()
- returns:
>
获取frame包括doctype在内的完整HTML内容
frame.evaluate(pageFunction, ...args)
pageFunction
将在 browser context中执行的函数 ...args
<...Serializable|JSHandle> 传递给pageFunction
的参数- returns:
> 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
在page context 中执行的函数。 ...args
<...Serializable|JSHandle> 传递给pageFunction
的参数- returns:
> 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:
> 与当前frame 关联的执行上下文。
frame.focus(selector)
selector
需要focus的元素的选择器。 如果此选择器匹配到了多个元素,则只有第一个匹配的元素才会被focus。 - returns:
当成功匹配到元素后,Promise将resolve。如果没有匹配到任何元素,则将reject。
此方法将 focus给定 selector匹配到的元素。 如果根据给定的 selector没有匹配到任何元素,将会抛出异常。
frame.hover(selector)
selector
需要 hover的元素的选择器。 如果此选择器匹配到了多个元素,则只有第一个匹配的元素才会被hover。 - returns:
当成功匹配到元素后,Promise将resolve。如果没有匹配到任何元素,则将reject。
此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 page.mouse方法 hover匹配到的元素的中心位置。 如果没有匹配到元素,则将抛出一个错误。
frame.isDetached()
- returns:
如果 frame已经detached了,则返回 true
, 否则返回 false
frame.name()
- returns:
返回 frame的name属性值。
如果name属性不存在或者为空字符串,则返回 id属性的值,如果 id属性也不存在或者为空字符串,则返回空字符串。
NOTE 此方法的返回值只会在frame被创建后计算一次,如果稍后frame的相关属性(name或者id)发生变化,此方法的返回值也不会改变。
frame.parentFrame()
- returns: 如果存在父级 frame,则返回父级 frame, 对已经 detach的frame或者 main frame使用此方法将会返回
null
。
frame.select(selector, ...values)
selector
[select]标签的选择器 ...values
<...string> 选择的值。如果标签具有
multiple
属性, 所有的指定值都是有效值, 否则只会考虑第一个值。- returns:
>> 返回一个由所有成功选中(selected)的选项(option)的值组成的数组。
当所有提供的 values
值的选项(option)全被选中后会触发 change
以及 input
事件。 如果根据所指定的选择器selector
没有匹配到一个 元素,将会抛出错误。 (这个方法就是用于控制 select的选择)
frame.select('select#colors', 'blue'); // 单选
frame.select('select#colors', 'red', 'green', 'blue'); // 多选
复制代码
frame.setContent(html)
html
设置 page页面的HTML内容。 - returns:
frame.tap(selector)
selector
将要被tap的元素的 选择器。如果选择器匹配出了多个元素,则tap事件只会作用在第一个匹配的元素上。 - returns:
此方法将会根据给定的选择器匹配到元素,如果所匹配到的元素不在视界内,将会将其滚动到视界内,然后使用 page.touchscreen方法tap匹配到的元素的中心位置。 如果没有匹配到元素,则将抛出一个错误。
frame.title()
- returns:
> 返回页面的title。
frame.type(selector, text[, options])
selector
文本框(包括 texarea和input)的选择器。如果选择器匹配出了多个元素,则只会选择第一个匹配的元素上。 text
将要输入到文本框内的文字。 options
delay
按键输入的间隔速度,单位为ms。默认为 0.
- returns:
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:
返回 frame的url
frame.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]])
selectorOrFunctionOrTimeout
A selector, predicate or timeout to wait for options
Optional waiting parameters ...args
<...Serializable|JSHandle>pageFunction
的参数。- returns:
> 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
将要在 browser context中执行的函数(可以是function,也可以是string,如果是string,则是有返回值的可以执行的 js表达式) options
Optional waiting parameters polling
An interval at which the pageFunction
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
函数执行的最大等待时间(ms)。。默认是 30000
(30 秒)。如果取值为0
,则表示禁用此选项。
...args
<...Serializable|JSHandle> 传递给pageFunction
的额外参数。- returns:
> 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
被等待的元素的选择器selector options
可选参数 visible
出现在DOM中的元素必须是可见的(visible),例如,不能有 display: none
或者visibility: hidden
CSS 属性。默认是false
。hidden
元素不存在于DOM中(包括一开始就不存在,或者存在了又被移除掉),或者是被隐藏了, 例如, 具有 display: none
或者visibility: hidden
CSS 属性。默认是false
.timeout
最大等待时间(ms)。默认是 30000
(30 秒)。取值为的0
则表示禁用此参数。
- returns:
> 当在 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
匹配xpath的元素 options
可选参数如下: visible
出现在DOM中的元素必须是可见的(visible),例如,不能有 display: none
或者visibility: hidden
CSS 属性。默认是false
。hidden
元素不存在于DOM中(包括一开始就不存在,或者存在了又被移除掉),或者是被隐藏了, 例如, 具有 display: none
或者visibility: hidden
CSS 属性。默认是false
.timeout
最大等待时间(ms)。默认是 30000
(30 秒)。取值为的0
则表示禁用此参数。
- returns:
> 当在 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
在 executionContext
中执行的函数...args
<...Serializable|JSHandle> 传递给pageFunction
的参数- returns:
> 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
将在 executionContext
中执行的函数...args
<...Serializable|JSHandle> 传递给pageFunction
函数的参数。- returns:
> 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: Frame associated with this execution context.
NOTE 并不是每一个 execution context都存在一个frame。例如, workers 以及 extensions 都存在 execution context,但是没有 frame。
executionContext.queryObjects(prototypeHandle)
prototypeHandle
A handle to the object prototype. - returns:
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:
如果当前 object handle是ElementHandle的实例,则将返回object handle本身,否则返回 null
jsHandle.dispose()
- returns:
当 object handle成功释放(dispose)后,Promise将 resolve。
此方法用于断开element handle的引用
jsHandle.executionContext()
- returns: ExecutionContext
返回 handle所在的执行上下文。
jsHandle.getProperties()
- returns:
>>
此方法返回一个由属性名称作为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)
propertyName
property to get - returns:
>
从引用的object中获取给定 propertyName
对应的 property。
jsHandle.jsonValue()
- returns:
>
返回 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)
selector
目标元素的 selector - returns:
>
此方法将在页面上使用element.querySelector
,如果没有匹配到任何元素,则将resolve 回null
elementHandle.$$(selector)
selector
目标元素的 selector - returns:
>>
此方法将在页面上使用element.querySelectorAll
,如果没有匹配到任何元素,则将resolve 回[]
elementHandle.$$eval(selector, pageFunction, ...args)
selector
目标元素的 selector pageFunction
将在 browser context中执行的函数 ...args
<...Serializable|JSHandle> 传递给pageFunction
的参数- returns:
> 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
目标元素的 selector pageFunction
将在 browser context中执行的函数 ...args
<...Serializable|JSHandle> 传递给pageFunction
的参数- returns:
> 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
Expression to evaluate. - returns:
>>
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.boundingBox()
- returns:
> - x
element 的 x坐标, 单位是px. - y
element 的 y坐标, 单位是px. - width
element 的宽度, 单位是px. - height
element 的高度, 单位是px.
- x
此方法返回 element 的 bounding box(即坐标和长、宽信息,坐标是相对于main frame的),如果element不可见(not visible),则返回 null
elementHandle.boxModel()
- returns:
> - content
> Content box, represented as an array of {x, y} points. - padding
> Padding box, represented as an array of {x, y} points. - border
> Border box, represented as an array of {x, y} points. - margin
> Margin box, represented as an array of {x, y} points. - width
Element's width. - height
Element's height.
- content
此方法返回element的盒模型信息,如果element不可见(not visible),则返回 null
Boxes are represented as an array of points; each Point is an object {x, y}
. Box points are sorted clock-wise.
elementHandle.click([options])
options
button
left
,right
, 或者middle
, 默认是left
。(意思是用鼠标的哪个按键进行点击操作,左键、右键或者中键)clickCount
点击次数,默认是 1. 参见 UIEvent.detail. delay
mousedown
和mouseup
之间的时间间隔(ms).默认是 0.
- returns:
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:
> Resolves to the content frame for element handles referencing iframe nodes, or null otherwise
elementHandle.dispose()
- returns:
Promise which resolves when the element handle is successfully disposed.
此方法断开 element handle的引用
elementHandle.executionContext()
- returns: ExecutionContext
elementHandle.focus()
- returns:
调用 element的focus 方法。
elementHandle.getProperties()
- returns:
>>
此方法返回一个由属性名称作为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
需要按下的按键的名称, 例如 ArrowLeft
. 更多按键名称列表参见 USKeyboardLayout。options
text
If specified, generates an input event with this text. delay
keydown
和keyup
之间的时间间隔(ms). 默认是 0.
- returns:
聚焦在 element上,然后使用 keyboard.down
以及 keyboard.up
方法。
如果 key
值是一个单个字母,并且没有除了 Shift
之外的修饰按键被按下,那么将会继续触发 keypress
/input
事件。可以指定 'text'选项以强制生成输入事件。
NOTE 修饰键将会影响
elementHandle.press
的效果。如果你按住Shift
键,然后再按其他的字母键,则你将输入一个大写的字母。
elementHandle.screenshot([options])
options
参数和 page.screenshot方法的参数类似。 - returns:
> Promise将会resolve截屏图片的 buffer。
此方法将会在需要的时候将元素滚动到可视区域内,然后使用 page.screenshot方法来对 element进行截图操作。 如果 element 已经从DOM上 detach掉了,则此方法将抛出错误。
elementHandle.tap()
- returns:
如果成功在element上执行了 tap操作,则 Promise将会resolve。如果 element 已经从DOM上 detach掉了,则 Promise将会reject。
此方法将会在需要的时候将元素滚动到可视区域内,然后使用 touchscreen.tap来 tap element的中间位置。 如果 element 已经从DOM上 detach掉了,则将抛出错误。
elementHandle.toString()
- returns:
elementHandle.type(text[, options])
text
将要在聚焦元素内输入的文本内容 options
delay
输入字符间的时间间隔。 默认是 0.
- returns:
聚焦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:
This method expects elementHandle
to point to an input element.
class: Request
当页面发起请求的时候,例如请求网络资源,下面这些事件都将会被触发:
- 'request' 当页面发起请求时触发。
- 'response' 当请求收到响应的时候触发。
- 'requestfinished' 当响应内容完全接受并且请求结束的时候触发。
如果请求动作在某个地方失败,那么 requestfinished
(也可能是 response
)事件会被 'requestfailed'所替代。
如果收到了重定向的响应指令,则当前请求结束,并触发 requestfinished
事件,然后会发起一个对新链接的获取请求。
request.abort([errorCode])
errorCode
可选的错误码. 默认是 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:
Aborts request. To use this, 应确保请求拦截可用,使用 page.setRequestInterception
来设置。
如果未启用请求拦截,则将立即抛出异常。
request.continue([overrides])
overrides
Optional request overwrites, which can be one of the following: url
如果设置此属性值,则请求url将会被重置。 method
如果设置此属性值,则请求方式将会被重置。 (例如 GET
orPOST
)postData
如果设置此属性值,则post body将会被重置 headers
如果设置此属性值,则 HTTP headers将会被重置
- returns:
拦截并改变请求参数。为了确保此方法可用,请使用 page.setRequestInterception
方法来保证请求拦截处于可用状态(enable)。
如果未启用请求拦截,则将立即抛出异常。
request.failure()
- returns: 请求失败的原因(如果有的话)
errorText
Human-readable error message, e.g. 'net::ERR_FAILED'
.
如果请求失败,则此方法返回请求失败的原因(如果有的话),并且触发 requestfailed
事件,如果请求成功,则此方法返回 null
,
下面是一个记录所有请求失败的例子:
page.on('requestfailed', request => {
console.log(request.url() + ' ' + request.failure().errorText);
});
复制代码
request.frame()
- returns: A matching Frame object, or
null
if navigating to error pages.
request.headers()
- returns:
An object with HTTP headers associated with the request. All header names are lower-case.
request.isNavigationRequest()
- returns:
当前请求是否是一个 navigation的请求(即,当前请求是否会触发页面跳转或reload事件。)
request.method()
- returns:
请求方式 (例如,GET, POST等)
request.postData()
- returns:
Request's post body, if any.
request.redirectChain()
- returns:
>
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:
包含所有被渲染引擎使用到的请求资源的类型,允许以下几种: document
, stylesheet
, image
, media
, font
, script
, texttrack
, xhr
, fetch
, eventsource
, websocket
, manifest
, other
.
request.respond(response)
response
请求对应的响应对象 status
响应状态安, 默认是 200
。headers
可选的响应头 contentType
如果设置了此属性值,则相当于是 设置响应头的 Content-Type
body
可选的 response body
- returns:
用给定的响应来完成请求。 为了使此功能有效可用, 请设置 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: 一个 matching Response object, 如果还没有收到响应,则返回
null
request.url()
- returns:
URL of the request.
class: Response
Response class represents responses which are received by page.
response.buffer()
- returns:
> Promise which resolves to a buffer with response body.
response.fromCache()
- returns:
如果响应数据来自于磁盘或者内存,则返回 true
response.fromServiceWorker()
- returns:
如果响应数据来自于 service worker,则返回 true
response.headers()
- returns:
http响应头对象. 所有的 header name 都是小写.
response.json()
- returns:
> Promise which resolves to a JSON representation of response body.
如果响应数据体(response body)无法使用 JSON.parse
解析,则此方法将抛出错误。
response.ok()
- returns:
包含一个用于标记数据响应是否成功(状态码为 200-299)的布尔值。
response.request()
- returns:
A matching Request object.
response.securityDetails()
- returns: 如果是在 安全连接(https)上收到的响应数据,则为 Security details,否则将是
null
response.status()
- returns:
包含响应状态码(例如,200,表示响应成功)
response.text()
- returns:
> Promise which resolves to a text representation of response body.
response.url()
- returns:
包含响应的 URL
class: SecurityDetails
SecurityDetails class represents responses which are received by page.
securityDetails.issuer()
- returns:
带有证书颁发机构名称的字符串。
securityDetails.protocol()
- returns:
安全协议名, 例如 "TLS 1.2".
securityDetails.subjectName()
- returns:
证书签发对象的名称
securityDetails.validFrom()
- returns:
UnixTime,安全证书开始生效的时间,用 Unix时间表示。
securityDetails.validTo()
- returns:
UnixTime ,安全证书失效的时间,用 Unix时间表示。
class: Target
target.browser()
- returns:
获取 target(可以认为是page) 隶属于的 browser。
target.browserContext()
- returns:
The browser context the target belongs to.
target.createCDPSession()
- returns:
>
Creates a Chrome Devtools Protocol session attached to the target.
target.opener()
- returns:
Get the target that opened this target. Top-level targets return null
.
target.page()
- returns:
>
如果 target的类型不是 page
或者 background_page
, 则返回 null
target.type()
- returns:
返回 target的类型,可以是 "page"
, "background_page"
, "service_worker"
, "browser"
or "other"
target.url()
- returns:
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:
将 cdpSession从 target上 detach掉,一旦cdpSession从 target上 detach掉了,则 the cdpSession object将不可再触发任何事件,也不再可以用于发送信息
cdpSession.send(method[, params])
method
protocol method name params
Optional method parameters - returns:
>
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
Set of configurable options for coverage resetOnNavigation
Whether to reset coverage on every navigation. Defaults to true
.
- returns:
Promise that resolves when coverage is started
coverage.startJSCoverage(options)
options
Set of configurable options for coverage resetOnNavigation
Whether to reset coverage on every navigation. Defaults to true
.
- returns:
Promise that resolves when coverage is started
coverage.stopCSSCoverage()
- returns:
>> Promise that resolves to the array of coverage reports for all stylesheets url
StyleSheet URL text
StyleSheet content ranges
> StyleSheet ranges that were used. Ranges are sorted and non-overlapping. start
A start offset in text, inclusive end
An end offset in text, exclusive
NOTE CSS Coverage 不包括那些没有 sourceURLs的动态加载得 style标签。
coverage.stopJSCoverage()
- returns:
>> Promise that resolves to the array of coverage reports for all non-anonymous scripts url
Script URL text
Script content ranges
> Script ranges that were executed. Ranges are sorted and non-overlapping. start
A start offset in text, inclusive end
An end offset in text, exclusive
NOTE JavaScript Coverage 不包括匿名脚本。但是,会包括带有sourceURLs的脚本。