Puppeteer:.evaluate()で変数を渡す


128

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

  }

})();

回答:


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")}; await 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を参照してください。
ノド

これには最高の賛成票があるので、誰かがこれでリンティングエラーを経験しましたか?具体的には、パラメーターが既に上位スコープで宣言されています。このエラーは別として、これは機能します。
ミックスマスターマイク

61

より便利読みやすいので、このスタイルに固執することをお勧めします。

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

単一変数:

次の構文を使用して、1つの変数を渡すことができpage.evaluate()ます。

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

注:()複数の変数を渡す場合を除いて、変数をで囲む必要はありません。

複数の変数:

次の構文を使用して、複数の変数を渡すことができpage.evaluate()ます。

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

注:変数を囲む{}必要はありません。


12

それを理解するのにかなり時間がかかりましconsole.log()evaluate()ノードコンソールに表示することはできません。

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

page.evaluate関数内で実行されるすべてのものは、ブラウザーページのコンテキストで実行されます。スクリプトはnode.jsではなくブラウザーで実行されているため、ログに記録すると、ブラウザーコンソールに表示されます。ヘッドレスで実行している場合は表示されません。また、関数内にノードブレークポイントを設定することもできません。

これがお役に立てば幸いです。


6

パスa functionには、2つの方法があります。

// 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テストの起動オプションに追加できます


そして、私はオブジェクトを渡したかったのですか?
トラマダ

2番目のケースでは、どのように引数を追加しますか?たとえば、yourFuncに文字列を追加したいと思います
user3568719

yourFuncプロパティが関数でない場合は、オブジェクトに置き換えることができます。@tramada
オオカミ

funcはyouFuncに似ているため、exec yourFunc @ user3568719のようにfunc(stringArg)を呼び出すことができます
wolf

オブジェクトをウィンドウに渡してアクセスする方法を示していただけませんか?
wuno

2

私はタイプスクリプトの新しい人を助けることができるタイプスクリプトの例を持っています。

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

puppeteertypescriptではどのように実行しますか?コードを変更するたびにjsにトランスパイルしますか?
アバランシェ1

はい。あなたはこのプロジェクトをここで見ることができます-github.com/srinivasreddy/companies-list
Srinivas Reddy Thatiparthy

-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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.