Javascript Puppeteer:在 .evaluate() 中传递变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46088351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:19:56  来源:igfitidea点击:

Puppeteer: pass variable in .evaluate()

javascriptweb-scrapingevaluatepuppeteer

提问by Cat Burston

I'm trying to pass a variable into a page.evaluate()function in Puppeteer, but when I use the following very simplified example, the variable evalVaris undefined.

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

I'm new to Puppeteer and can't find any examples to build on, so I need help passing that variable into the page.evaluate()function so I can use it inside.

我是 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();

  }

})();

回答by flozia

You have to pass the variable as an argument to the pageFunctionlike this:

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

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

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

}, evalVar);

The arguments can also be serialized: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageevaluatepagefunction-args.

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

回答by Mehdi Raash

I encourage you to stick on this style, because it's more convenientand readable.

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

let name = 'Hyman';
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});

回答by Grant Miller

Single Variable:

单变量:

You can pass one variableto page.evaluate()using the following syntax:

你可以通过一个变量page.evaluate()使用的语法如下:

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

Note:You do not need to enclose the variable in (), unless you are going to be passing multiple variables.

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

Multiple Variables:

多个变量:

You can pass multiple variablesto page.evaluate()using the following syntax:

您可以通过多个变量page.evaluate()使用的语法如下:

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

Note:Enclosing your variables within {}is not necessary.

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

回答by harrrrrrry

It took me quite a while to figure out that console.log()in evaluate()can't show in node console.

我花了很长时间才发现console.log()inevaluate()无法在节点控制台中显示。

Ref: https://github.com/GoogleChrome/puppeteer/issues/1944

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

everything that is run inside the page.evaluate function is done in the context of the browser page. The script is running in the browser not in node.js so if you log it will show in the browsers console which if you are running headless you will not see. You also can't set a node breakpoint inside the function.

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

Hope this can help.

希望这能有所帮助。

回答by wolf

For pass a function, there are two ways you can do it.

对于 pass 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);

You can add devtools: trueto the launch options for test

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

回答by Srinivas Reddy Thatiparthy

I have a typescript example that could help someone new in typescript.

我有一个打字稿示例,可以帮助打字稿新手。

const hyperlinks: string [] = await page.evaluate((url: string, regex: RegExp, querySelect: string) => {
.........
}, url, regex, querySelect);

回答by voodoo417

With page.$$eval

page.$$eval

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

[ see also at page.$evalfor a single selector]

[另见page.$eval了解单个选择器]