Puppeteer 中文文档v25.8.0

JavaScript 执行

Puppeteer 允许在由 Puppeteer 驱动的页面上下文中求值 JavaScript 函数:

// 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');

// Evaluate JavaScript
const three = await page.evaluate(() => {
  return 1 + 2;
});

console.log(three);

// Close browser.
await browser.close();
⚠️警告

虽然函数是在你的脚本上下文中定义的,但实际上 Puppeteer 会将其转换为字符串,发送到目标页面并在那里求值。这意味着该函数无法访问作用域变量或调用在你的 Puppeteer 脚本中定义的其他函数,你需要将完整的函数逻辑定义在函数体内。

或者,你也可以以字符串形式提供函数体:

// Evaluate JavaScript
const three = await page.evaluate(`
    1 + 2
`);
⚠️警告

上面的示例产生了等效的结果,但它也说明,被求值函数可用的类型和全局变量无法得知。尤其是在 TypeScript 中,你应该小心确保被求值函数引用的对象是正确的。

返回类型

你求值的函数可以返回值。如果返回值是原始类型,Puppeteer 会像上一个示例那样,在脚本上下文中自动将其转换为原始类型。

如果脚本返回对象,Puppeteer 会将其序列化为 JSON,并在脚本端重建。这个过程不一定总能产生正确的结果,例如当你返回 DOM 节点时:

const body = await page.evaluate(() => {
  return document.body;
});
console.log(body); // {}, unexpected!

为了处理返回的对象,Puppeteer 提供了一种按引用返回对象的方式:

const body = await page.evaluateHandle(() => {
  return document.body;
});
console.log(body instanceof ElementHandle); // true

返回的对象是 JSHandleElementHandleElementHandle 继承自 JSHandle,且只为 DOM 元素创建。

关于句柄可用的方法,详见 API 文档

返回 Promise

如果你在 evaluate 调用中返回 Promise,该 Promise 会被自动等待。例如:

await page.evaluate(() => {
  // wait for 100ms.
  return new Promise(resolve => setTimeout(resolve, 100));
});
// Execution continues here once the Promise created in the page context resolves.

向求值函数传递参数

你可以为函数提供参数:

const three = await page.evaluate(
  (a, b) => {
    return a + b; // 1 + 2
  },
  1,
  2,
);

参数可以是原始值或 JSHandle

ℹ️注意

Page、JSHandle 和 ElementHandle 提供了几种不同的求值 JavaScript 的辅助方法,但它们都遵循本指南中概述的基本原则。