├── README.md ├── LICENSE └── docs └── api.md /README.md: -------------------------------------------------------------------------------- 1 | # Puppeteer [![Linux Build Status](https://img.shields.io/travis/GoogleChrome/puppeteer/master.svg)](https://travis-ci.org/GoogleChrome/puppeteer) [![Windows Build Status](https://img.shields.io/appveyor/ci/aslushnikov/puppeteer/master.svg?logo=appveyor)](https://ci.appveyor.com/project/aslushnikov/puppeteer/branch/master) [![NPM puppeteer package](https://img.shields.io/npm/v/puppeteer.svg)](https://npmjs.org/package/puppeteer) 2 | 3 | 4 | 5 | > 此项目同步自 [GoogleChrome](https://github.com/GoogleChrome) / [puppeteer](https://github.com/GoogleChrome/puppeteer) 项目中的 docs. 6 | 7 | ###### [API](#api-文档) | [FAQ](#faq) | [Contributing](#贡献-puppeteer) 8 | 9 | > Puppeteer 是一个 Node 库,它提供了一系列高级 API 来通过 [DevTools 协议](https://chromedevtools.github.io/devtools-protocol/) 控制 [headless](https://developers.google.com/web/updates/2017/04/headless-chrome) Chrome 或 Chromium。 它也可以配置为使用完整的(non-headless)Chrome 或 Chromium。 10 | 11 | 12 | ###### Puppeteer 能做什么? 13 | 14 | 可以在浏览器中手动完成的大部分事情都可以使用 Puppeteer 完成! 你可以通过这里的几个例子来起步: 15 | 16 | * 生成页面的截图和PDF。 17 | * 抓取 SPA 并生成预渲染的内容(即“SSR”)。 18 | * 从网站抓取内容。 19 | * 自动表单提交,UI测试,键盘输入等。 20 | * 创建一个最新的自动化测试环境。 使用最新的 JavaScript 和浏览器功能,直接在最新版本的 Chrome 中运行测试。 21 | * 捕获你网站的 [timeline trace](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/reference),来帮助诊断性能问题。 22 | 23 | 在线尝试: https://try-puppeteer.appspot.com/ 24 | 25 | ## 起步 26 | 27 | ### 安装 28 | 29 | > **注意**:Puppeteer 至少需要 Node v6.4.0,而下面的例子中使用的 async/await,只有 Node v7.6.0 或更高版本支持 30 | 31 | 要在你的项目中使用 Puppeteer, 运行: 32 | 33 | ``` 34 | yarn add puppeteer 35 | # 或 "npm i puppeteer" 36 | ``` 37 | 38 | > **注意**:当你安装 Puppeteer,它会下载最新版本的 Chromium (~71Mb Mac, ~90Mb Linux, ~110Mb Win) 来保证与 API 协同工作。要跳过下载,参考 [Environment variables](docs/api.md#environment-variables)。 39 | 40 | ### 使用 41 | 42 | Puppeteer 对于使用过其他浏览器测试框架的人来说会很熟悉。 你创建一个 `Browser` 实例,打开页面,然后使用 [Puppeteer 的 API](docs/api.md#) 来操作它们。 43 | 44 | **示例** - 导航到 https://example.com 然后保存屏幕截图为 *example.png*: 45 | 46 | ```js 47 | const puppeteer = require('puppeteer'); 48 | 49 | (async () => { 50 | const browser = await puppeteer.launch(); 51 | const page = await browser.newPage(); 52 | await page.goto('https://example.com'); 53 | await page.screenshot({path: 'example.png'}); 54 | 55 | await browser.close(); 56 | })(); 57 | ``` 58 | 59 | Puppeteer 设定一个初始页面大小为 800px x 600px, 这决定了截图的大小. 页面大小可以用 [`Page.setViewport()`](docs/api.md#pagesetviewportviewport) 来自定义。 60 | 61 | **示例** - 创建一个 PDF. 62 | 63 | ```js 64 | const puppeteer = require('puppeteer'); 65 | 66 | (async () => { 67 | const browser = await puppeteer.launch(); 68 | const page = await browser.newPage(); 69 | await page.goto('https://news.ycombinator.com', {waitUntil: 'networkidle2'}); 70 | await page.pdf({path: 'hn.pdf', format: 'A4'}); 71 | 72 | await browser.close(); 73 | })(); 74 | ``` 75 | 76 | 参考 [`Page.pdf()`](docs/api.md#pagepdfoptions) 来获取关于 pdf 的更多内容。 77 | 78 | **示例** - 评估页面上下文中的脚本 79 | 80 | ```js 81 | const puppeteer = require('puppeteer'); 82 | 83 | (async () => { 84 | const browser = await puppeteer.launch(); 85 | const page = await browser.newPage(); 86 | await page.goto('https://example.com'); 87 | 88 | // Get the "viewport" of the page, as reported by the page. 89 | const dimensions = await page.evaluate(() => { 90 | return { 91 | width: document.documentElement.clientWidth, 92 | height: document.documentElement.clientHeight, 93 | deviceScaleFactor: window.devicePixelRatio 94 | }; 95 | }); 96 | 97 | console.log('Dimensions:', dimensions); 98 | 99 | await browser.close(); 100 | })(); 101 | ``` 102 | 103 | 请参阅 [`Page.evaluate()`](docs/api.md#pageevaluatepagefunction-args) 以获取更多关于 `evaluate` 和相关方法的信息,如`evaluateOnNewDocument` 和 `exposeFunction`。 104 | 105 | ## 默认运行时设置 106 | 107 | **1. 使用 Headless 模式** 108 | 109 | Puppeteer 在 [headless 模式](https://developers.google.com/web/updates/2017/04/headless-chrome) 中运行 Chromium。要运行完整版本的 Chromium, 需在浏览器加载时设置 ['headless' 参数](docs/api.md#puppeteerlaunchoptions): 110 | 111 | ```js 112 | const browser = await puppeteer.launch({headless: false}); // 默认是 true 113 | ``` 114 | 115 | **2. 运行 Chromium 的捆绑版本** 116 | 117 | 默认情况下,Puppeteer 下载并使用特定版本的 Chromium,以便使它的 API 保证能开箱即用。 要让 Puppeteer 使用不同版本的 Chrome 或 Chromium,则当创建一个 `Browser` 实例时传入可执行文件的路径: 118 | 119 | ```js 120 | const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'}); 121 | ``` 122 | 123 | 参考 [`Puppeteer.launch()`](docs/api.md#puppeteerlaunchoptions) 获取更多信息。 124 | 125 | 参考 [`本文`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) 来了解 Chromium 和 Chrome 之间的区别。 [`本文`](https://chromium.googlesource.com/chromium/src/+/lkcr/docs/chromium_browser_vs_google_chrome.md) 将介绍对于 Linux 用户的一些差异. 126 | 127 | **3. 创建一个新的用户配置文件** 128 | 129 | Puppeteer 创建它自己的 Chromium 用户配置文件,并在**每次运行时清理它**。 130 | 131 | ## API 文档 132 | 133 | 浏览 [API 文档](docs/api.md) 和 [示例](https://github.com/GoogleChrome/puppeteer/tree/master/examples/) 来学习更多内容。 134 | 135 | ## 调试提示 136 | 137 | 1. 关闭 headless 模式 - 有时查看浏览器显示的内容是非常有用的,而不是在 headless 模式下启动。使用 `headless:false` 启动完整版本的浏览器: 138 | 139 | ```js 140 | const browser = await puppeteer.launch({headless: false}); 141 | ``` 142 | 143 | 2. 慢下来 - `slowMo` 参数可是使 Puppeteer 操作速度减少指定的毫秒数。 这是另一种帮助查看发生了什么的方法。 144 | 145 | ```js 146 | const browser = await puppeteer.launch({ 147 | headless: false, 148 | slowMo: 250 // 放慢了 250ms 149 | }); 150 | ``` 151 | 152 | 3. 捕获控制台输出 - 您可以侦听 `console` 事件。在 `page.evaluate()` 中调试代码时,这也很方便: 153 | 154 | ```js 155 | page.on('console', msg => console.log('PAGE LOG:', ...msg.args)); 156 | 157 | await page.evaluate(() => console.log(`url is ${location.href}`)); 158 | ``` 159 | 160 | 4. 启用详细日志记录 - 所有公共 API 调用和内部协议流将通过 `puppeteer` 命名空间下的 [`debug`](https://github.com/visionmedia/debug) 模块进行记录。 161 | 162 | ```sh 163 | # 基本的详细记录 164 | env DEBUG="puppeteer:*" node script.js 165 | 166 | # DEBUG 输出可以通过命名空间来启用/禁用 167 | env DEBUG="puppeteer:*,-puppeteer:protocol" node script.js # 所有协议消息 168 | env DEBUG="puppeteer:session" node script.js # 协议会话消息(协议消息到目标) 169 | env DEBUG="puppeteer:mouse,puppeteer:keyboard" node script.js # 只有鼠标和键盘的 API 调用 170 | 171 | # 协议流可能相当嘈杂。 这个例子过滤掉所有网络域的消息 172 | env DEBUG="puppeteer:*" env DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network' 173 | ``` 174 | 175 | ## 贡献 Puppeteer 176 | 177 | 查看 [贡献指南](https://github.com/GoogleChrome/puppeteer/blob/master/CONTRIBUTING.md) 来获得有关 Puppeteer 开发的概述。 178 | 179 | # FAQ 180 | 181 | #### Q: Puppeteer 使用哪个 Chromium 版本? 182 | 183 | 在 [package.json](https://github.com/GoogleChrome/puppeteer/blob/master/package.json) 中查看 `chromium_revision`. 184 | 185 | Puppeteer 捆绑 Chromium 来确保它使用的最新功能可用。 随着 DevTools 协议和浏览器的不断改进,Puppeteer 将被更新为依赖于更新版本的 Chromium。 186 | 187 | #### Q: Puppeteer,Selenium / WebDriver 和 PhantomJS 有什么区别? 188 | 189 | Selenium / WebDriver是一个完善的跨浏览器API,可用于测试跨浏览器支持。 190 | 191 | Puppeteer 仅适用于 Chromium 或 Chrome。 但是,许多团队只使用一个浏览器(例如PhantomJS)进行单元测试。 在非测试用例中,Puppeteer 提供了一个功能强大但简单的API,因为它只针对一个浏览器,使您能够快速开发自动化脚本。 192 | 193 | Puppeteer 捆绑了最新版本的 Chromium。 194 | 195 | #### Q: 谁维护 Puppeteer? 196 | 197 | Chrome DevTools 团队负责维护该库,然而我们非常乐意在项目中提供帮助和专业知识! 198 | 参考 [Contributing](https://github.com/GoogleChrome/puppeteer/blob/master/CONTRIBUTING.md). 199 | 200 | #### Q: Chrome 团队为什么要打造 Puppeteer? 201 | 202 | 该项目的目标很简单: 203 | 204 | - 提供一个精简的,规范的库,强调 [DevTools 协议](https://chromedevtools.github.io/devtools-protocol/) 的功能。 205 | - 为类似的测试库的实现提供参考。 最终,这些其他框架可以采用 Puppeteer 作为其基础层。 206 | - 越来越多的采用 headless/automated 浏览器测试。 207 | - 帮助养成新的 DevTools 协议功能...并捕捉错误! 208 | - 详细了解自动浏览器测试的难点,并帮助填补这些空白。 209 | 210 | #### Q: Puppeteer 与其他 headless Chrome 项目相比如何? 211 | 212 | 过去几个月,[为自动化 headless Chrome 带来了一些新的库](https://medium.com/@kensoh/chromeless-chrominator-chromy-navalia-lambdium-ghostjs-autogcd-ef34bcd26907)。 作为开发 DevTools 协议的团队,我们很高兴看到和支持这个蓬勃发展的生态系统。 213 | 214 | 我们已经联系了一些这样的项目,看看是否有合作的机会,我们很乐意尽我们所能帮助。 215 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /docs/api.md: -------------------------------------------------------------------------------- 1 | # Puppeteer API v1.0.0-rc 2 | 3 | ##### 内容目录 4 | 5 | 6 | 7 | - [概览](#overview) 8 | - [环境变量](#environment-variables) 9 | - [class: Puppeteer](#class-puppeteer) 10 | * [puppeteer.connect(options)](#puppeteerconnectoptions) 11 | * [puppeteer.defaultArgs()](#puppeteerdefaultargs) 12 | * [puppeteer.executablePath()](#puppeteerexecutablepath) 13 | * [puppeteer.launch([options])](#puppeteerlaunchoptions) 14 | - [class: Browser](#class-browser) 15 | * [event: 'disconnected'](#event-disconnected) 16 | * [event: 'targetchanged'](#event-targetchanged) 17 | * [event: 'targetcreated'](#event-targetcreated) 18 | * [event: 'targetdestroyed'](#event-targetdestroyed) 19 | * [browser.close()](#browserclose) 20 | * [browser.disconnect()](#browserdisconnect) 21 | * [browser.newPage()](#browsernewpage) 22 | * [browser.pages()](#browserpages) 23 | * [browser.process()](#browserprocess) 24 | * [browser.targets()](#browsertargets) 25 | * [browser.userAgent()](#browseruseragent) 26 | * [browser.version()](#browserversion) 27 | * [browser.wsEndpoint()](#browserwsendpoint) 28 | - [class: Page](#class-page) 29 | * [event: 'console'](#event-console) 30 | * [event: 'dialog'](#event-dialog) 31 | * [event: 'error'](#event-error) 32 | * [event: 'frameattached'](#event-frameattached) 33 | * [event: 'framedetached'](#event-framedetached) 34 | * [event: 'framenavigated'](#event-framenavigated) 35 | * [event: 'load'](#event-load) 36 | * [event: 'metrics'](#event-metrics) 37 | * [event: 'pageerror'](#event-pageerror) 38 | * [event: 'request'](#event-request) 39 | * [event: 'requestfailed'](#event-requestfailed) 40 | * [event: 'requestfinished'](#event-requestfinished) 41 | * [event: 'response'](#event-response) 42 | * [page.$(selector)](#pageselector) 43 | * [page.$$(selector)](#pageselector) 44 | * [page.$$eval(selector, pageFunction[, ...args])](#pageevalselector-pagefunction-args) 45 | * [page.$eval(selector, pageFunction[, ...args])](#pageevalselector-pagefunction-args) 46 | * [page.$x(expression)](#pagexexpression) 47 | * [page.addScriptTag(options)](#pageaddscripttagoptions) 48 | * [page.addStyleTag(options)](#pageaddstyletagoptions) 49 | * [page.authenticate(credentials)](#pageauthenticatecredentials) 50 | * [page.bringToFront()](#pagebringtofront) 51 | * [page.click(selector[, options])](#pageclickselector-options) 52 | * [page.close()](#pageclose) 53 | * [page.content()](#pagecontent) 54 | * [page.cookies(...urls)](#pagecookiesurls) 55 | * [page.coverage](#pagecoverage) 56 | * [page.deleteCookie(...cookies)](#pagedeletecookiecookies) 57 | * [page.emulate(options)](#pageemulateoptions) 58 | * [page.emulateMedia(mediaType)](#pageemulatemediamediatype) 59 | * [page.evaluate(pageFunction, ...args)](#pageevaluatepagefunction-args) 60 | * [page.evaluateHandle(pageFunction, ...args)](#pageevaluatehandlepagefunction-args) 61 | * [page.evaluateOnNewDocument(pageFunction, ...args)](#pageevaluateonnewdocumentpagefunction-args) 62 | * [page.exposeFunction(name, puppeteerFunction)](#pageexposefunctionname-puppeteerfunction) 63 | * [page.focus(selector)](#pagefocusselector) 64 | * [page.frames()](#pageframes) 65 | * [page.goBack(options)](#pagegobackoptions) 66 | * [page.goForward(options)](#pagegoforwardoptions) 67 | * [page.goto(url, options)](#pagegotourl-options) 68 | * [page.hover(selector)](#pagehoverselector) 69 | * [page.keyboard](#pagekeyboard) 70 | * [page.mainFrame()](#pagemainframe) 71 | * [page.metrics()](#pagemetrics) 72 | * [page.mouse](#pagemouse) 73 | * [page.pdf(options)](#pagepdfoptions) 74 | * [page.queryObjects(prototypeHandle)](#pagequeryobjectsprototypehandle) 75 | * [page.reload(options)](#pagereloadoptions) 76 | * [page.screenshot([options])](#pagescreenshotoptions) 77 | * [page.select(selector, ...values)](#pageselectselector-values) 78 | * [page.setContent(html)](#pagesetcontenthtml) 79 | * [page.setCookie(...cookies)](#pagesetcookiecookies) 80 | * [page.setExtraHTTPHeaders(headers)](#pagesetextrahttpheadersheaders) 81 | * [page.setJavaScriptEnabled(enabled)](#pagesetjavascriptenabledenabled) 82 | * [page.setOfflineMode(enabled)](#pagesetofflinemodeenabled) 83 | * [page.setRequestInterception(value)](#pagesetrequestinterceptionvalue) 84 | * [page.setUserAgent(userAgent)](#pagesetuseragentuseragent) 85 | * [page.setViewport(viewport)](#pagesetviewportviewport) 86 | * [page.tap(selector)](#pagetapselector) 87 | * [page.title()](#pagetitle) 88 | * [page.touchscreen](#pagetouchscreen) 89 | * [page.tracing](#pagetracing) 90 | * [page.type(selector, text[, options])](#pagetypeselector-text-options) 91 | * [page.url()](#pageurl) 92 | * [page.viewport()](#pageviewport) 93 | * [page.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]])](#pagewaitforselectororfunctionortimeout-options-args) 94 | * [page.waitForFunction(pageFunction[, options[, ...args]])](#pagewaitforfunctionpagefunction-options-args) 95 | * [page.waitForNavigation(options)](#pagewaitfornavigationoptions) 96 | * [page.waitForSelector(selector[, options])](#pagewaitforselectorselector-options) 97 | - [class: Keyboard](#class-keyboard) 98 | * [keyboard.down(key[, options])](#keyboarddownkey-options) 99 | * [keyboard.press(key[, options])](#keyboardpresskey-options) 100 | * [keyboard.sendCharacter(char)](#keyboardsendcharacterchar) 101 | * [keyboard.type(text, options)](#keyboardtypetext-options) 102 | * [keyboard.up(key)](#keyboardupkey) 103 | - [class: Mouse](#class-mouse) 104 | * [mouse.click(x, y, [options])](#mouseclickx-y-options) 105 | * [mouse.down([options])](#mousedownoptions) 106 | * [mouse.move(x, y, [options])](#mousemovex-y-options) 107 | * [mouse.up([options])](#mouseupoptions) 108 | - [class: Touchscreen](#class-touchscreen) 109 | * [touchscreen.tap(x, y)](#touchscreentapx-y) 110 | - [class: Tracing](#class-tracing) 111 | * [tracing.start(options)](#tracingstartoptions) 112 | * [tracing.stop()](#tracingstop) 113 | - [class: Dialog](#class-dialog) 114 | * [dialog.accept([promptText])](#dialogacceptprompttext) 115 | * [dialog.defaultValue()](#dialogdefaultvalue) 116 | * [dialog.dismiss()](#dialogdismiss) 117 | * [dialog.message()](#dialogmessage) 118 | * [dialog.type()](#dialogtype) 119 | - [class: ConsoleMessage](#class-consolemessage) 120 | * [consoleMessage.args()](#consolemessageargs) 121 | * [consoleMessage.text()](#consolemessagetext) 122 | * [consoleMessage.type()](#consolemessagetype) 123 | - [class: Frame](#class-frame) 124 | * [frame.$(selector)](#frameselector) 125 | * [frame.$$(selector)](#frameselector) 126 | * [frame.$$eval(selector, pageFunction[, ...args])](#frameevalselector-pagefunction-args) 127 | * [frame.$eval(selector, pageFunction[, ...args])](#frameevalselector-pagefunction-args) 128 | * [frame.$x(expression)](#framexexpression) 129 | * [frame.addScriptTag(options)](#frameaddscripttagoptions) 130 | * [frame.addStyleTag(options)](#frameaddstyletagoptions) 131 | * [frame.childFrames()](#framechildframes) 132 | * [frame.content()](#framecontent) 133 | * [frame.evaluate(pageFunction, ...args)](#frameevaluatepagefunction-args) 134 | * [frame.executionContext()](#frameexecutioncontext) 135 | * [frame.isDetached()](#frameisdetached) 136 | * [frame.name()](#framename) 137 | * [frame.parentFrame()](#frameparentframe) 138 | * [frame.select(selector, ...values)](#frameselectselector-values) 139 | * [frame.setContent(html)](#framesetcontenthtml) 140 | * [frame.title()](#frametitle) 141 | * [frame.url()](#frameurl) 142 | * [frame.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]])](#framewaitforselectororfunctionortimeout-options-args) 143 | * [frame.waitForFunction(pageFunction[, options[, ...args]])](#framewaitforfunctionpagefunction-options-args) 144 | * [frame.waitForSelector(selector[, options])](#framewaitforselectorselector-options) 145 | - [class: ExecutionContext](#class-executioncontext) 146 | * [executionContext.evaluate(pageFunction, ...args)](#executioncontextevaluatepagefunction-args) 147 | * [executionContext.evaluateHandle(pageFunction, ...args)](#executioncontextevaluatehandlepagefunction-args) 148 | * [executionContext.queryObjects(prototypeHandle)](#executioncontextqueryobjectsprototypehandle) 149 | - [class: JSHandle](#class-jshandle) 150 | * [jsHandle.asElement()](#jshandleaselement) 151 | * [jsHandle.dispose()](#jshandledispose) 152 | * [jsHandle.executionContext()](#jshandleexecutioncontext) 153 | * [jsHandle.getProperties()](#jshandlegetproperties) 154 | * [jsHandle.getProperty(propertyName)](#jshandlegetpropertypropertyname) 155 | * [jsHandle.jsonValue()](#jshandlejsonvalue) 156 | - [class: ElementHandle](#class-elementhandle) 157 | * [elementHandle.$(selector)](#elementhandleselector) 158 | * [elementHandle.$$(selector)](#elementhandleselector) 159 | * [elementHandle.$x(expression)](#elementhandlexexpression) 160 | * [elementHandle.asElement()](#elementhandleaselement) 161 | * [elementHandle.boundingBox()](#elementhandleboundingbox) 162 | * [elementHandle.click([options])](#elementhandleclickoptions) 163 | * [elementHandle.dispose()](#elementhandledispose) 164 | * [elementHandle.executionContext()](#elementhandleexecutioncontext) 165 | * [elementHandle.focus()](#elementhandlefocus) 166 | * [elementHandle.getProperties()](#elementhandlegetproperties) 167 | * [elementHandle.getProperty(propertyName)](#elementhandlegetpropertypropertyname) 168 | * [elementHandle.hover()](#elementhandlehover) 169 | * [elementHandle.jsonValue()](#elementhandlejsonvalue) 170 | * [elementHandle.press(key[, options])](#elementhandlepresskey-options) 171 | * [elementHandle.screenshot([options])](#elementhandlescreenshotoptions) 172 | * [elementHandle.tap()](#elementhandletap) 173 | * [elementHandle.toString()](#elementhandletostring) 174 | * [elementHandle.type(text[, options])](#elementhandletypetext-options) 175 | * [elementHandle.uploadFile(...filePaths)](#elementhandleuploadfilefilepaths) 176 | - [class: Request](#class-request) 177 | * [request.abort([errorCode])](#requestaborterrorcode) 178 | * [request.continue([overrides])](#requestcontinueoverrides) 179 | * [request.failure()](#requestfailure) 180 | * [request.headers()](#requestheaders) 181 | * [request.method()](#requestmethod) 182 | * [request.postData()](#requestpostdata) 183 | * [request.resourceType()](#requestresourcetype) 184 | * [request.respond(response)](#requestrespondresponse) 185 | * [request.response()](#requestresponse) 186 | * [request.url()](#requesturl) 187 | - [class: Response](#class-response) 188 | * [response.buffer()](#responsebuffer) 189 | * [response.headers()](#responseheaders) 190 | * [response.json()](#responsejson) 191 | * [response.ok()](#responseok) 192 | * [response.request()](#responserequest) 193 | * [response.status()](#responsestatus) 194 | * [response.text()](#responsetext) 195 | * [response.url()](#responseurl) 196 | - [class: Target](#class-target) 197 | * [target.page()](#targetpage) 198 | * [target.type()](#targettype) 199 | * [target.url()](#targeturl) 200 | - [class: Coverage](#class-coverage) 201 | * [coverage.startCSSCoverage(options)](#coveragestartcsscoverageoptions) 202 | * [coverage.startJSCoverage(options)](#coveragestartjscoverageoptions) 203 | * [coverage.stopCSSCoverage()](#coveragestopcsscoverage) 204 | * [coverage.stopJSCoverage()](#coveragestopjscoverage) 205 | 206 | 207 | 208 | ### 概览 209 | 210 | Puppeteer 是一个 Node 库,它提供了一系列高级 API 来使用 DevTools协议 控制 Chromium 或者 Chrome。 211 | 212 | Puppeteer API 是分层并且镜像于浏览器的结构。在下面的图表上,褪色的实体当前没有在Puppeteer 中表现出来。 213 | 214 | ![puppeteer overview](https://user-images.githubusercontent.com/746130/31592143-089f6f9a-b1db-11e7-9a20-16b7fc754fa1.png) 215 | 216 | - [`Puppeteer`](#class-puppeteer) 使用 [devtools 协议](https://chromedevtools.github.io/devtools-protocol/) 与浏览器通信。 217 | - [`Browser`](#class-browser) 实例拥有多个页面。 218 | - [`Page`](#class-page) 至少有一个框架: 主框架。 可能还有其他由 [iframe](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe) 或 [frame](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frame) 标签创建的框架。 219 | - [`Frame`](#class-frame) 至少有一个可执行上下文 - 默认可执行上下文 - 其中框架的 JavaScript 被执行。框架可能有额外的与[扩展](https://developer.chrome.com/extensions)相关联的执行上下文。 220 | 221 | (图表资源: [link](https://docs.google.com/drawings/d/1Q_AM6KYs9kbyLZF-Lpp5mtpAWth73Cq8IKCsWYgi8MM/edit?usp=sharing)) 222 | 223 | 224 | ### 环境变量 225 | 226 | Puppeteer 会查找某些 [环境变量](https://en.wikipedia.org/wiki/Environment_variable) 来帮助其操作。 这些变量既可以在环境中设置,也可以在 [npm 配置](https://docs.npmjs.com/cli/config) 中设置。 227 | 228 | - `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY` - 定义用于下载和运行 Chromium 的 HTTP 代理设置。 229 | - `PUPPETEER_SKIP_CHROMIUM_DOWNLOAD` - 安装过程中不要下载捆绑的 Chromium。 230 | - `PUPPETEER_DOWNLOAD_HOST` - 覆盖用于下载 Chromium 的 URL 的主机部分 231 | 232 | ### class: Puppeteer 233 | 234 | Puppeteer module provides a method to launch a Chromium instance. 235 | The following is a typical example of using a Puppeteer to drive automation: 236 | ```js 237 | const puppeteer = require('puppeteer'); 238 | 239 | puppeteer.launch().then(async browser => { 240 | const page = await browser.newPage(); 241 | await page.goto('https://www.google.com'); 242 | // other actions... 243 | await browser.close(); 244 | }); 245 | ``` 246 | 247 | #### puppeteer.connect(options) 248 | - `options` <[Object]> 249 | - `browserWSEndpoint` <[string]> a [browser websocket endpoint](#browserwsendpoint) to connect to. 250 | - `ignoreHTTPSErrors` <[boolean]> Whether to ignore HTTPS errors during navigation. Defaults to `false`. 251 | - returns: <[Promise]<[Browser]>> 252 | 253 | This methods attaches Puppeteer to an existing Chromium instance. 254 | 255 | #### puppeteer.defaultArgs() 256 | - returns: <[Array]<[string]>> The default flags that Chromium will be launched with. 257 | 258 | #### puppeteer.executablePath() 259 | - returns: <[string]> A path where Puppeteer expects to find bundled Chromium. Chromium might not exist there if the download was skipped with [`PUPPETEER_SKIP_CHROMIUM_DOWNLOAD`](#environment-variables). 260 | 261 | #### puppeteer.launch([options]) 262 | - `options` <[Object]> Set of configurable options to set on the browser. Can have the following fields: 263 | - `ignoreHTTPSErrors` <[boolean]> Whether to ignore HTTPS errors during navigation. Defaults to `false`. 264 | - `headless` <[boolean]> Whether to run browser in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). Defaults to `true` unless the `devtools` option is `true`. 265 | - `executablePath` <[string]> Path to a Chromium or Chrome executable to run instead of bundled Chromium. If `executablePath` is a relative path, then it is resolved relative to [current working directory](https://nodejs.org/api/process.html#process_process_cwd). 266 | - `slowMo` <[number]> Slows down Puppeteer operations by the specified amount of milliseconds. Useful so that you can see what is going on. 267 | - `args` <[Array]<[string]>> Additional arguments to pass to the browser instance. List of Chromium flags can be found [here](http://peter.sh/experiments/chromium-command-line-switches/). 268 | - `ignoreDefaultArgs` <[boolean]> Do not use [`puppeteer.defaultArgs()`](#puppeteerdefaultargs). Dangerous option; use with care. Defaults to `false`. 269 | - `handleSIGINT` <[boolean]> Close browser process on Ctrl-C. Defaults to `true`. 270 | - `handleSIGTERM` <[boolean]> Close browser process on SIGTERM. Defaults to `true`. 271 | - `handleSIGHUP` <[boolean]> Close browser process on SIGHUP. Defaults to `true`. 272 | - `timeout` <[number]> Maximum time in milliseconds to wait for the browser instance to start. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. 273 | - `dumpio` <[boolean]> Whether to pipe browser process stdout and stderr into `process.stdout` and `process.stderr`. Defaults to `false`. 274 | - `userDataDir` <[string]> Path to a [User Data Directory](https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md). 275 | - `env` <[Object]> Specify environment variables that will be visible to browser. Defaults to `process.env`. 276 | - `devtools` <[boolean]> Whether to auto-open DevTools panel for each tab. If this option is `true`, the `headless` option will be set `false`. 277 | - returns: <[Promise]<[Browser]>> Promise which resolves to browser instance. 278 | 279 | The method launches a browser instance with given arguments. The browser will be closed when the parent node.js process is closed. 280 | 281 | > **NOTE** Puppeteer can also be used to control the Chrome browser, but it works best with the version of Chromium it is bundled with. There is no 282 | guarantee it will work with any other version. Use `executablePath` option with extreme caution. 283 | If Google Chrome (rather than Chromium) is preferred, a [Chrome Canary](https://www.google.com/chrome/browser/canary.html) or [Dev Channel](https://www.chromium.org/getting-involved/dev-channel) build is suggested. 284 | > 285 | > In [puppeteer.launch([options])](#puppeteerlaunchoptions) above, any mention of Chromium also applies to Chrome. 286 | > 287 | > See [`this article`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description 288 | of the differences between Chromium and Chrome. [`This article`](https://chromium.googlesource.com/chromium/src/+/lkcr/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users. 289 | 290 | ### class: Browser 291 | 292 | * extends: [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter) 293 | 294 | A Browser is created when Puppeteer connects to a Chromium instance, either through [`puppeteer.launch`](#puppeteerlaunchoptions) or [`puppeteer.connect`](#puppeteerconnectoptions). 295 | 296 | An example of using a [Browser] to create a [Page]: 297 | ```js 298 | const puppeteer = require('puppeteer'); 299 | 300 | puppeteer.launch().then(async browser => { 301 | const page = await browser.newPage(); 302 | await page.goto('https://example.com'); 303 | await browser.close(); 304 | }); 305 | ``` 306 | 307 | An example of disconnecting from and reconnecting to a [Browser]: 308 | ```js 309 | const puppeteer = require('puppeteer'); 310 | 311 | puppeteer.launch().then(async browser => { 312 | // Store the endpoint to be able to reconnect to Chromium 313 | const browserWSEndpoint = browser.wsEndpoint(); 314 | // Disconnect puppeteer from Chromium 315 | browser.disconnect(); 316 | 317 | // Use the endpoint to reestablish a connection 318 | const browser2 = await puppeteer.connect({browserWSEndpoint}); 319 | // Close Chromium 320 | await browser2.close(); 321 | }); 322 | ``` 323 | #### event: 'disconnected' 324 | Emitted when puppeteer gets disconnected from the Chromium instance. This might happen because one of the following: 325 | - Chromium is closed or crashed 326 | - `browser.disconnect` method was called 327 | 328 | #### event: 'targetchanged' 329 | - <[Target]> 330 | 331 | Emitted when the url of a target changes. 332 | 333 | #### event: 'targetcreated' 334 | - <[Target]> 335 | 336 | Emitted when a target is created, for example when a new page is opened by [`window.open`](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) or [`browser.newPage`](#browsernewpage). 337 | 338 | #### event: 'targetdestroyed' 339 | - <[Target]> 340 | 341 | Emitted when a target is destroyed, for example when a page is closed. 342 | 343 | #### browser.close() 344 | - returns: <[Promise]> 345 | 346 | Closes Chromium and all of its pages (if any were opened). The browser object itself is considered disposed and cannot be used anymore. 347 | 348 | #### browser.disconnect() 349 | 350 | 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. 351 | 352 | #### browser.newPage() 353 | - returns: <[Promise]<[Page]>> Promise which resolves to a new [Page] object. 354 | 355 | #### browser.pages() 356 | - returns: <[Promise]<[Array]<[Page]>>> Promise which resolves to an array of all open pages. 357 | 358 | #### browser.process() 359 | - returns: Spawned browser process. Returns `null` if the browser instance was created with `puppeteer.connect` method. 360 | 361 | #### browser.targets() 362 | - returns: <[Array]<[Target]>> An array of all active targets. 363 | 364 | #### browser.userAgent() 365 | - returns: <[Promise]<[string]>> Promise which resolves to the browser's original user agent. 366 | 367 | > **NOTE** Pages can override browser user agent with [page.setUserAgent](#pagesetuseragentuseragent) 368 | 369 | #### browser.version() 370 | - returns: <[Promise]<[string]>> For headless Chromium, this is similar to `HeadlessChrome/61.0.3153.0`. For non-headless, this is similar to `Chrome/61.0.3153.0`. 371 | 372 | > **NOTE** the format of browser.version() might change with future releases of Chromium. 373 | 374 | #### browser.wsEndpoint() 375 | - returns: <[string]> Browser websocket url. 376 | 377 | Browser websocket endpoint which can be used as an argument to 378 | [puppeteer.connect](#puppeteerconnectoptions). The format is `ws://${host}:${port}/devtools/browser/` 379 | 380 | You can find the `webSocketDebuggerUrl` from `http://${host}:${port}/json/version`. Learn more about the [devtools protocol](https://chromedevtools.github.io/devtools-protocol) and the [browser endpoint](https://chromedevtools.github.io/devtools-protocol/#how-do-i-access-the-browser-target). 381 | 382 | ### class: Page 383 | 384 | * extends: [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter) 385 | 386 | Page provides methods to interact with a single tab in Chromium. One [Browser] instance might have multiple [Page] instances. 387 | 388 | This example creates a page, navigates it to a URL, and then saves a screenshot: 389 | ```js 390 | const puppeteer = require('puppeteer'); 391 | 392 | puppeteer.launch().then(async browser => { 393 | const page = await browser.newPage(); 394 | await page.goto('https://example.com'); 395 | await page.screenshot({path: 'screenshot.png'}); 396 | await browser.close(); 397 | }); 398 | ``` 399 | 400 | The Page class emits various events (described below) which can be handled using any of Node's native EventEmitter methods, such as `on` or `once`. 401 | 402 | This example logs a message for a single page `load` event: 403 | ```js 404 | page.once('load', () => console.log('Page loaded!')); 405 | ``` 406 | 407 | #### event: 'console' 408 | - <[ConsoleMessage]> 409 | 410 | Emitted when JavaScript within the page calls one of console API methods, e.g. `console.log` or `console.dir`. Also emitted if the page throws an error or a warning. 411 | 412 | The arguments passed into `console.log` appear as arguments on the event handler. 413 | 414 | An example of handling `console` event: 415 | ```js 416 | page.on('console', msg => { 417 | for (let i = 0; i < msg.args.length; ++i) 418 | console.log(`${i}: ${msg.args[i]}`); 419 | }); 420 | page.evaluate(() => console.log('hello', 5, {foo: 'bar'})); 421 | ``` 422 | 423 | #### event: 'dialog' 424 | - <[Dialog]> 425 | 426 | Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` or `beforeunload`. Puppeteer can respond to the dialog via [Dialog]'s [accept](#dialogacceptprompttext) or [dismiss](#dialogdismiss) methods. 427 | 428 | #### event: 'error' 429 | - <[Error]> 430 | 431 | Emitted when the page crashes. 432 | 433 | > **NOTE** `error` event has a special meaning in Node, see [error events](https://nodejs.org/api/events.html#events_error_events) for details. 434 | 435 | #### event: 'frameattached' 436 | - <[Frame]> 437 | 438 | Emitted when a frame is attached. 439 | 440 | #### event: 'framedetached' 441 | - <[Frame]> 442 | 443 | Emitted when a frame is detached. 444 | 445 | #### event: 'framenavigated' 446 | - <[Frame]> 447 | 448 | Emitted when a frame is navigated to a new url. 449 | 450 | #### event: 'load' 451 | 452 | Emitted when the JavaScript [`load`](https://developer.mozilla.org/en-US/docs/Web/Events/load) event is dispatched. 453 | 454 | #### event: 'metrics' 455 | - <[Object]> 456 | - `title` <[string]> The title passed to `console.timeStamp`. 457 | - `metrics` <[Object]> Object containing metrics as key/value pairs. The values 458 | of metrics are of <[number]> type. 459 | 460 | Emitted when the JavaScript code makes a call to `console.timeStamp`. For the list 461 | of metrics see `page.metrics`. 462 | 463 | #### event: 'pageerror' 464 | - <[string]> The exception message 465 | 466 | Emitted when an uncaught exception happens within the page. 467 | 468 | #### event: 'request' 469 | - <[Request]> 470 | 471 | Emitted when a page issues a request. The [request] object is read-only. 472 | In order to intercept and mutate requests, see `page.setRequestInterception`. 473 | 474 | #### event: 'requestfailed' 475 | - <[Request]> 476 | 477 | Emitted when a request fails, for example by timing out. 478 | 479 | #### event: 'requestfinished' 480 | - <[Request]> 481 | 482 | Emitted when a request finishes successfully. 483 | 484 | #### event: 'response' 485 | - <[Response]> 486 | 487 | Emitted when a [response] is received. 488 | 489 | #### page.$(selector) 490 | - `selector` <[string]> A [selector] to query page for 491 | - returns: <[Promise]> 492 | 493 | The method runs `document.querySelector` within the page. If no element matches the selector, the return value resolve to `null`. 494 | 495 | Shortcut for [page.mainFrame().$(selector)](#frameselector). 496 | 497 | #### page.$$(selector) 498 | - `selector` <[string]> A [selector] to query page for 499 | - returns: <[Promise]<[Array]<[ElementHandle]>>> 500 | 501 | The method runs `document.querySelectorAll` within the page. If no elements match the selector, the return value resolve to `[]`. 502 | 503 | Shortcut for [page.mainFrame().$$(selector)](#frameselector-1). 504 | 505 | 506 | #### page.$$eval(selector, pageFunction[, ...args]) 507 | - `selector` <[string]> A [selector] to query frame for 508 | - `pageFunction` <[function]> Function to be evaluated in browser context 509 | - `...args` <...[Serializable]|[JSHandle]> Arguments to pass to `pageFunction` 510 | - returns: <[Promise]<[Serializable]>> Promise which resolves to the return value of `pageFunction` 511 | 512 | This method runs `document.querySelectorAll` within the page and passes it as the first argument to `pageFunction`. 513 | 514 | If `pageFunction` returns a [Promise], then `page.$$eval` would wait for the promise to resolve and return its value. 515 | 516 | Examples: 517 | ```js 518 | const divsCounts = await page.$$eval('div', divs => divs.length); 519 | ``` 520 | 521 | #### page.$eval(selector, pageFunction[, ...args]) 522 | - `selector` <[string]> A [selector] to query page for 523 | - `pageFunction` <[function]> Function to be evaluated in browser context 524 | - `...args` <...[Serializable]|[JSHandle]> Arguments to pass to `pageFunction` 525 | - returns: <[Promise]<[Serializable]>> Promise which resolves to the return value of `pageFunction` 526 | 527 | This method runs `document.querySelector` within the page and passes it as the first argument to `pageFunction`. If there's no element matching `selector`, the method throws an error. 528 | 529 | If `pageFunction` returns a [Promise], then `page.$eval` would wait for the promise to resolve and return its value. 530 | 531 | Examples: 532 | ```js 533 | const searchValue = await page.$eval('#search', el => el.value); 534 | const preloadHref = await page.$eval('link[rel=preload]', el => el.href); 535 | const html = await page.$eval('.main-container', e => e.outerHTML); 536 | ``` 537 | 538 | Shortcut for [page.mainFrame().$eval(selector, pageFunction)](#frameevalselector-pagefunction-args). 539 | 540 | #### page.$x(expression) 541 | - `expression` <[string]> Expression to [evaluate](https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate). 542 | - returns: <[Promise]<[Array]<[ElementHandle]>>> 543 | 544 | The method evluates the XPath expression. 545 | 546 | Shortcut for [page.mainFrame().$x(expression)](#frameexpression) 547 | 548 | #### page.addScriptTag(options) 549 | - `options` <[Object]> 550 | - `url` <[string]> Url of a script to be added. 551 | - `path` <[string]> Path to the JavaScript file to be injected into frame. If `path` is a relative path, then it is resolved relative to [current working directory](https://nodejs.org/api/process.html#process_process_cwd). 552 | - `content` <[string]> Raw JavaScript content to be injected into frame. 553 | - returns: <[Promise]<[ElementHandle]>> which resolves to the added tag when the script's onload fires or when the script content was injected into frame. 554 | 555 | Adds a `