木偶:在.evaluate()中传递变量


127

我正在尝试将变量传递给Puppeteer中page.evaluate()函数,但是当我使用以下非常简单的示例时,该变量未定义。evalVar

我是Puppeteer的新手,找不到任何可建立的示例,因此我需要帮助将该变量传递到page.evaluate()函数中,以便在内部使用它。

const puppeteer = require('puppeteer');

(async() => {

  const browser = await puppeteer.launch({headless: false});
  const page = await browser.newPage();

  const evalVar = 'WHUT??';

  try {

    await page.goto('https://www.google.com.au');
    await page.waitForSelector('#fbar');
    const links = await page.evaluate((evalVar) => {

      console.log('evalVar:', evalVar); // appears undefined

      const urls = [];
      hrefs = document.querySelectorAll('#fbar #fsl a');
      hrefs.forEach(function(el) {
        urls.push(el.href);
      });
      return urls;
    })
    console.log('links:', links);

  } catch (err) {

    console.log('ERR:', err.message);

  } finally {

    // browser.close();

  }

})();

Answers:


188

您必须pageFunction像这样将变量作为参数传递给:

const links = await page.evaluate((evalVar) => {

  console.log(evalVar); // 2. should be defined now
  

}, evalVar); // 1. pass variable as an argument

该参数也可以序列化:https : //github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageevaluatepagefunction-args


3
您好,您将如何传递多个变量?
chitzui

4
另外,我实际上不能传递函数:var myFunction = function(){console.log(“ hello”)}; 等待page.evaluate(func => func(),myFunction); 给我:Evaluation failed: TypeError: func is not a function..为什么?
chitzui

1
不要忘记evalVar在函数参数签名中以及在evaluate(在代码示例的末尾)作为传递参数来输入。
Flimm

2
@chitzui:您无法将函数传递给pate.evaluate()。您应该可以使用来“暴露”它page.exposeFunction。有关更多信息,请参见stackoverflow.com/a/58040978
knod

由于这具有最高的投票率,因此有人遇到过掉毛错误吗?特别是已经在上限范围中声明的参数。除了这个错误,这确实可以。
混合大师Mike

60

我鼓励你坚持这种风格,因为它更方便可读性

let name = 'jack';
let age  = 33;
let location = 'Berlin/Germany';

await page.evaluate(({name, age, location}) => {

    console.log(name);
    console.log(age);
    console.log(location);

},{name, age, location});

40

单变量:

您可以使用以下语法将一个变量传递给page.evaluate()

await page.evaluate(example => { /* ... */ }, example);

注意:不需要将变量括在中(),除非要传递多个变量。

多个变量:

您可以使用以下语法将多个变量传递给page.evaluate()

await page.evaluate((example_1, example_2) => { /* ... */ }, example_1, example_2);

注意:{}不需要将变量包含在其中。


12

我花了很长时间才弄清楚console.log()in evaluate()无法在节点控制台中显示。

参考:https : //github.com/GoogleChrome/puppeteer/issues/1944

在page.evaluate函数中运行的所有操作都是在浏览器页面的上下文中完成的。该脚本在浏览器中而不是在node.js中运行,因此如果您登录,它将在浏览器控制台中显示;如果您无头运行,则不会看到。您也不能在函数内部设置节点断点。

希望这会有所帮助。


6

对于传递a function,有两种方法可以实现。

// 1. Defined in evaluationContext
await page.evaluate(() => {
  window.yourFunc = function() {...};
});
const links = await page.evaluate(() => {
  const func = window.yourFunc;
  func();
});


// 2. Transform function to serializable(string). (Function can not be serialized)
const yourFunc = function() {...};
const obj = {
  func: yourFunc.toString()
};
const otherObj = {
  foo: 'bar'
};
const links = await page.evaluate((obj, aObj) => {
   const funStr = obj.func;
   const func = new Function(`return ${funStr}.apply(null, arguments)`)
   func();

   const foo = aObj.foo; // bar, for object
   window.foo = foo;
   debugger;
}, obj, otherObj);

您可以添加devtools: true到启动选项进行测试


我想传递一个物体?
特拉马达

在第二种情况下,如何添加参数?例如,我想添加一个传递字符串到yourFunc
user3568719 18-10-30

yourFunc如果您的属性不是函数,则可以用object 替换。@tramada

func与youFunc类似,因此您可以像exec yourFunc @ user3568719一样调用func(stringArg)
wolf

您介意展示如何将对象传递到窗口然后访问它吗?
Wuno


-1

页面。$$ eval

//..
const page = await browser.newPage();
const hrefs = await page.$$eval('#fbar #fsl a', as => as.map(a => a.href));
console.log(hrefs);
//..

[另请参阅第page。$ eval中的单个选择器]


那如何回答这个问题?我没有看到您从测试上下文传递到浏览器上下文的任何变量。
Ambroise Rabier
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.