Puppeteer: berikan variabel dalam .evaluate ()

128

Saya mencoba untuk memasukkan variabel ke dalam page.evaluate()fungsi Puppeteer , tetapi ketika saya menggunakan contoh yang sangat disederhanakan berikut, variabel evalVartidak terdefinisi.

Saya baru mengenal Puppeteer dan tidak dapat menemukan contoh untuk dikembangkan, jadi saya butuh bantuan untuk meneruskan variabel itu ke dalam page.evaluate()fungsi sehingga saya dapat menggunakannya di dalam.

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

  }

})();
Kucing Burston
sumber

Jawaban:

188

Anda harus meneruskan variabel sebagai argumen pageFunctionseperti ini:

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

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

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

Argumen juga dapat dibuat bersambung: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageevaluatepagefunction-args .

flozia
sumber
3
Halo, bagaimana Anda melewatkan banyak variabel?
chitzui
4
Selain itu, saya tidak benar-benar bisa mengirimkan fungsi: var myFunction = function () {console.log ("hello")}; menunggu halaman.evaluate (func => func (), myFunction); memberi saya: Evaluation failed: TypeError: func is not a function.. Mengapa?
chitzui
1
Jangan lupa untuk mengetik evalVarkeduanya dalam tanda tangan argumen fungsi, dan sebagai argumen yang diteruskan ke evaluate(di akhir contoh kode).
Flimm
2
@ chitzui: Anda tidak dapat meneruskan fungsi ke pate.evaluate(). Anda seharusnya bisa 'mengeksposnya' dengan page.exposeFunction. Untuk selengkapnya, lihat stackoverflow.com/a/58040978 .
Knod
karena ini memiliki suara positif tertinggi, apakah ada yang mengalami kesalahan linting dengan ini? khususnya dengan parameter yang sudah dideklarasikan di lingkup atas. Selain kesalahan ini, ini berfungsi.
Mix Master Mike
61

Saya mendorong Anda untuk tetap menggunakan gaya ini, karena lebih nyaman dan mudah dibaca .

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});
Mehdi Raash
sumber
40

Variabel Tunggal:

Anda dapat memberikan satu variabel untuk page.evaluate()menggunakan sintaks berikut:

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

Catatan: Anda tidak perlu menyertakan variabel di dalamnya (), kecuali Anda akan meneruskan beberapa variabel.

Variabel Ganda:

Anda dapat memberikan beberapa variabel untuk page.evaluate()menggunakan sintaks berikut:

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

Catatan: Anda {}tidak perlu menyertakan variabel Anda di dalamnya .

Berikan Miller
sumber
12

Butuh waktu cukup lama bagi saya untuk mengetahui bahwa console.log()in evaluate()tidak dapat ditampilkan di konsol node.

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

semua yang dijalankan di dalam fungsi page.evaluate dilakukan dalam konteks halaman browser. Skrip berjalan di browser bukan di node.js jadi jika Anda masuk, itu akan ditampilkan di konsol browser yang jika Anda menjalankan tanpa kepala, Anda tidak akan melihatnya. Anda juga tidak dapat menyetel titik putus node di dalam fungsi.

Semoga ini bisa membantu.

harrrrrrry
sumber
6

Untuk lulus a function, ada dua cara yang bisa dilakukan.

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

Anda dapat menambahkan devtools: trueke opsi peluncuran untuk pengujian

serigala
sumber
Dan saya ingin melewati suatu benda?
tramada
Bagaimana Anda menambahkan argumen dalam kasus kedua? misalnya saya ingin menambahkan pass string ke yourFunc
user3568719
Anda bisa mengganti yourFuncdengan objek jika properti Anda bukan fungsi. @tramada
serigala
func mirip dengan youFunc, jadi Anda dapat memanggil func (stringArg) seperti exec FungsiAnda @ user3568719
wolf
Maukah Anda menunjukkan bagaimana Anda akan mengirimkan objek ke jendela dan kemudian mengaksesnya?
wuno
2

Saya memiliki contoh ketikan yang dapat membantu orang baru dalam naskah ketikan.

const hyperlinks: string [] = await page.evaluate((url: string, regex: RegExp, querySelect: string) => {
.........
}, url, regex, querySelect);
Srinivas Reddy Thatiparthy
sumber
Bagaimana Anda menjalankan puppeteernaskah ketikan? Apakah Anda mentranspilasi ke js setiap kali Anda mengubah kode?
longsoran
Iya. Anda dapat melihat proyek ini di sini - github.com/srinivasreddy/companies-list
Srinivas Reddy Thatiparthy
-1

Dengan halaman. $$ eval

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

[lihat juga di halaman. $ eval untuk satu pemilih]

voodoo417
sumber
Bagaimana itu menjawab pertanyaan itu? Saya tidak melihat variabel apa pun yang Anda teruskan dari konteks pengujian ke konteks browser.
Ambroise Rabier