原文:Introduction to Puppeteer
Puppeteer使用真实浏览器测试JavaScript应用,是非常好的工具。
Puppeteer是谷歌官方支持的用Node.js控制Chrome的库。你可以从Node.js打开Chrome、跳转到谷歌、搜索点什么、然后查看结果。你也可以用无头模式运行Puppeteer,让它在后台运行。
例如,你可以用Puppeteer和Node.js让Chrome加载谷歌的首页:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const puppeteer = require('puppeteer');
run().then(() => console.log('Done')).catch(error => console.log(error));
async function run() { const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage(); await page.goto('https://google.com');
await new Promise(resolve => setTimeout(resolve, 5000));
await browser.close(); }
|
输出结果类似下图:
执行JavaScript
Puppeteer的页面有一个好用的evaluate()
函数,可以在Chrome窗口中执行JavaScript。evaluate()
函数是Puppeteer最灵活的交互方式,因为它允许你使用浏览器API控制Chrome,例如document.querySelector()
。
以下示例脚本在谷歌搜索了“JavaScript”,获取了前10个结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage(); await page.goto('https://google.com');
await page.evaluate(() => { document.querySelector('input[name="q"]').value = 'JavaScript'; });
await Promise.all([ page.waitForNavigation(), page.evaluate(() => { document.querySelector('input[value="Google Search"]').click(); }) ]);
const links = await page.evaluate(function getUrls() { return Array.from(document.querySelectorAll('a cite').values()). map(el => el.innerHTML); });
await browser.close();
|
在本地Web服务器使用Puppeteer
因为Node.js使用事件循环,在同一个脚本启动express服务器并连接到Puppeteer是非常方便的。这意味着很容易用Puppeteer测试Vue页面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| const express = require('express'); const puppeteer = require('puppeteer');
const app = express(); app.get('/', function(req, res) { res.send(` <html> <body> <script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="content"></div>
<script type="text/javascript"> const app = new Vue({ data: () => ({ count: 0 }), template: \` <div> <div id="count"> Count: {{count}} </div> <button v-on:click="++count">Increment</button> </div> \` }); app.$mount('#content'); </script> </body> </html> `); }); const server = await app.listen(3000);
const browser = await puppeteer.launch({ headless: true }); const page = await browser.newPage(); await page.goto('http://localhost:3000');
let count = await page.evaluate(() => { return document.querySelector('#count').innerHTML.trim(); }); count;
await page.evaluate(() => { document.querySelector('button').click(); });
count = await page.evaluate(() => { return document.querySelector('#count').innerHTML.trim(); }); count;
await browser.close(); await server.close();
|