如何在Puppeteers .evaluate()方法中传递函数?

chi*_*zui 8 javascript google-chrome node.js puppeteer

每当我尝试传递一个函数时,就像这样:

var myFunc = function() { console.log("lol"); };

await page.evaluate(func => {
 func();
 return true;
}, myFunc);
Run Code Online (Sandbox Code Playgroud)

我得到:

(node:13108) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Evaluation failed: TypeError: func is not a function
at func (<anonymous>:9:9)
(node:13108) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Run Code Online (Sandbox Code Playgroud)

为什么?如何正确做?

谢谢!

€:让我澄清一下:我这样做是因为我想先找到一些DOM元素,然后在该函数内部使用它们,更像这样(简化):

var myFunc = function(element) { element.innerHTML = "baz" };

await page.evaluate(func => {
  var foo = document.querySelector('.bar');
  func(foo);
  return true;
}, myFunc);
Run Code Online (Sandbox Code Playgroud)

use*_*ser 31

您不能将函数直接传递给page.evaluate(),但您可以调用另一个特殊方法 ( page.exposeFunction),该方法将您的函数公开为全局函数(也可作为页面window对象的属性提供),因此您可以在内部调用它page.evaluate()

var myFunc = function() { console.log("lol"); };
await page.exposeFunction("myFunc", myFunc);

await page.evaluate(async () => {
   await myFunc();
   return true;
});
Run Code Online (Sandbox Code Playgroud)

请记住,page.exposeFunction()这将使您的函数返回 a Promise,然后,您需要使用asyncand await。发生这种情况是因为您的函数不会在您的浏览器中运行,而是在您的nodejs应用程序中运行。

  1. 在 goto() 之后,exposeFunction() 不起作用
  2. 为什么我不能使用 Puppeteer 在exposeFunction() 函数中访问“窗口”?
  3. 如何使用evaluateOnNewDocument 和exposeFunction?
  4. ExposureFunction 保留在内存中吗?
  5. Puppeteer:在 .evaluate() 中传递变量
  6. Puppeteer 评估函数
  7. 允许将参数化函数作为字符串传递给 page.evaluate
  8. 与 page.exposeFunction() 绑定的函数会产生未处理的承诺拒绝
  9. 暴露的函数 queryseldtcor 在 puppeteer 中不起作用
  10. 如何动态注入函数以使用 Puppeteer 进行评估?


Md.*_*her 11

在伪人问题中讨论了类似的问题。

有几种方法可以解决您的问题。第一条规则是保持简单。

评估功能

这是最快的处理方式,您只需传递函数并执行即可。

await page.evaluate(() => {
  var myFunc = function(element) { element.innerHTML = "baz" };
  var foo = document.querySelector('.bar');
  myFunc(foo);
  return true;
});
Run Code Online (Sandbox Code Playgroud)

预先显示功能

您可以使用page.evaluate或page.addScriptTag预先公开该函数。

// add it manually and expose to window
await page.evaluate(() => {
  window.myFunc = function(element) { element.innerHTML = "baz" };
});

// add some scripts
await page.addScriptTag({path: "myFunc.js"});

// Now I can evaluate as many times as I want
await page.evaluate(() => {
  var foo = document.querySelector('.bar');
  myFunc(foo);
  return true;
});
Run Code Online (Sandbox Code Playgroud)

使用ElementHandle

页面。$(选择器)

您可以传递元素句柄进行.evaluate并根据需要进行更改。

const bodyHandle = await page.$('body');
const html = await page.evaluate(body => body.innerHTML, bodyHandle);
Run Code Online (Sandbox Code Playgroud)

页面。$ eval

您可以定位一个元素并根据需要进行更改。

const html = await page.$eval('.awesomeSelector', e => {
e.outerHTML = "whatever"
});
Run Code Online (Sandbox Code Playgroud)

诀窍是阅读文档并使其保持简单。

  • 第一个解决方案的重点是什么,*您只需传递函数并执行它即可。*?如果我们想在多个“evaluate”调用中使用相同的“myFunc”怎么办? (2认同)

归档时间:

查看次数:

4167 次

最近记录:

6 年,9 月 前