puppeteer
简介
Puppeteer 是一个 JavaScript 库,其功能如下
- 模拟用户事件,执行自动化测试
- 生成页面的屏幕截图和 PDF。
- 抓取 SPA(单页应用)并生成预渲染内容
核心概念
浏览器管理
js
import puppeteer from 'puppeteer';
// 启动浏览器
const browser = await puppeteer.launch();
// 新建页面
const page = await browser.newPage();
// 关闭浏览器
await browser.close();页面交互
定位器
定位器在单击前自动检查以下内容:
- 确保元素位于视口中。
- 等待元素变为 visible 或隐藏。
- 等待元素启用。
- 等待元素在两个连续的动画帧上具有稳定的边界框。
js
// 'button' is a CSS selector.
//使用定位器单击元素
await page.locator('button').click();
// 自动检测输入类型并选择合适的方式用提供的值填写。例如,它将填充 <select> 元素以及 <input> 元素。
await page.locator('input').fill('value');
// 将鼠标悬停在元素上
await page.locator('div').hover();
// [.scroll()] 函数使用鼠标滚轮事件来滚动元素。
await page.locator('div').scroll({
scrollLeft: 10,
scrollTop: 20,
});
// 有时你只需要等待元素可见。
await page.locator('.loading').wait();waitForSelector
与定位器相比,waitForSelector 是一种更底层的 API,允许等待元素在 DOM 中可用。如果操作失败,它不会自动重试该操作,并且需要手动处理生成的 ElementHandle 以防止内存泄漏。该方法存在于 Page、Frame 和 ElementHandle 实例上。
js
// Import puppeteer
import puppeteer from 'puppeteer';
// Launch the browser.
const browser = await puppeteer.launch();
// Create a page.
const page = await browser.newPage();
// Go to your site.
await page.goto('YOUR_SITE');
// Query for an element handle.
const element = await page.waitForSelector('div > .class-name');
// Do something with element...
await element.click(); // Just an example.
// Dispose of handle.
await element.dispose();
// Close browser.
await browser.close();出于向后兼容的原因,某些页面级 API(例如 page.click(selector)、page.type(selector)、page.hover(selector))是使用 waitForSelector 实现的。
无需等待即可查询
有时你知道元素已在页面上。在这种情况下,Puppeteer 提供了多种方法来查找与选择器匹配的元素或多个元素。这些方法存在于 Page、Frame 和 ElementHandle 实例中。
page.$()返回与选择器匹配的单个元素。page.$$()返回与选择器匹配的所有元素。page.$eval()返回对与选择器匹配的第一个元素运行 JavaScript 函数的结果。page.$$eval()返回对与选择器匹配的每个元素运行 JavaScript 函数的结果。
JavaScript 执行
Puppeteer 允许在 Puppeteer 驱动的页面上下文中评估 JavaScript 函数:
js
// Import puppeteer
import puppeteer from 'puppeteer';
(async () => {
// Launch the browser
const browser = await puppeteer.launch();
// Create a page
const page = await browser.newPage();
// Go to your site
await page.goto('YOUR_SITE');
// Evaluate JavaScript
const three = await page.evaluate(() => {
return 1 + 2;
});
console.log(three);
// 如果你从评估调用中返回 Promise,则将自动等待该 promise。例如
await page.evaluate(() => {
// wait for 100ms.
return new Promise(resolve => setTimeout(resolve, 100));
});
// Close browser.
await browser.close();
})();尽管该函数是在脚本上下文中定义的,但它实际上会被 Puppeteer 转换为字符串,发送到目标页面并在那里进行评估。这意味着该函数无法访问范围变量或调用 Puppeteer 脚本中定义的其他函数,并且你需要在函数体内定义整个函数逻辑。
网络日志记录
默认情况下,Puppeteer 监听所有网络请求和响应,并在页面上触发网络事件。
js
const page = await browser.newPage();
page.on('request', request => {
console.log(request.url());
});
page.on('response', response => {
console.log(response.url());
});调试
关闭
headless捕获
console.*输出jspage.on('console', msg => console.log('PAGE LOG:', msg.text())); await page.evaluate(() => console.log(`url is ${location.href}`));使用浏览器中的调试器
启动 Puppeteer 时将
devtools设置为true:const browser = await puppeteer.launch({devtools: true});在你想要调试的任何客户端代码中添加
debugger。例如,tsawait page.evaluate(() => { debugger; });