Burattinaio: passa la variabile in .evaluate ()


128

Sto provando a passare una variabile in una page.evaluate()funzione in Puppeteer , ma quando utilizzo il seguente esempio molto semplificato, la variabile evalVarnon è definita.

Sono nuovo in Puppeteer e non riesco a trovare alcun esempio su cui costruire, quindi ho bisogno di aiuto per passare quella variabile nella page.evaluate()funzione in modo da poterla usare all'interno.

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

  }

})();

Risposte:


188

Devi passare la variabile come argomento in pageFunctionquesto modo:

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

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

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

Gli argomenti possono anche essere serializzati: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageevaluatepagefunction-args .


3
Ciao, come passeresti più variabili?
Chitzui

4
Inoltre, non sono realmente in grado di passare una funzione: var myFunction = function () {console.log ("hello")}; attende page.evaluate (func => func (), myFunction); mi da: Evaluation failed: TypeError: func is not a function.. Perché?
chitzui

1
Non dimenticare di digitare evalVarsia nella firma dell'argomento della funzione, sia come argomento passato a evaluate(alla fine dell'esempio di codice).
Flimm

2
@chitzui: non puoi passare una funzione a pate.evaluate(). Puoi presumibilmente "esporlo" con page.exposeFunction. Per ulteriori informazioni, vedere stackoverflow.com/a/58040978 .
informato il

poiché questo ha i voti più alti, qualcuno ha riscontrato errori di lanugine con questo? in particolare con il parametro già dichiarato nello scope superiore. a parte questo errore, funziona.
Mix Master Mike

61

Ti incoraggio a mantenere questo stile, perché è più comodo e leggibile .

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

Variabile singola:

È possibile passare una variabile a page.evaluate()utilizzando la seguente sintassi:

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

Nota: non è necessario racchiudere la variabile (), a meno che non si passino più variabili.

Variabili multiple:

È possibile passare più variabili a page.evaluate()utilizzando la seguente sintassi:

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

Nota:{} non è necessario includere le variabili all'interno .


12

Mi c'è voluto un bel po 'per capire che console.log()in evaluate()non può mostrare in consolle nodo.

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

tutto ciò che viene eseguito all'interno della funzione page.evaluate viene eseguito nel contesto della pagina del browser. Lo script è in esecuzione nel browser non in node.js quindi se effettui il log verrà mostrato nella console del browser che se stai eseguendo headless non vedrai. Inoltre, non è possibile impostare un punto di interruzione del nodo all'interno della funzione.

Spero che questo possa aiutare.


6

Per il passaggio a function, ci sono due modi per farlo.

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

È possibile aggiungere devtools: truealle opzioni di avvio per il test


E volevo passare un oggetto?
tramada

Come aggiungeresti un argomento nel 2 ° caso? ad esempio, voglio aggiungere passare una stringa a yourFunc
user3568719

Puoi sostituire yourFunccon oggetto se la tua proprietà non è una funzione. @tramada
wolf

func è simile a youFunc , quindi puoi chiamare func (stringArg) proprio come exec yourFunc @ user3568719
wolf

Ti dispiacerebbe mostrare come passare un oggetto alla finestra e poi accedervi?
wuno

2

Ho un esempio di dattiloscritto che potrebbe aiutare qualcuno di nuovo nel dattiloscritto.

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

Come corri puppeteerin dattiloscritto? Traspili in js ogni volta che modifichi il tuo codice?
valanga 1

Sì. Puoi dare un'occhiata a questo progetto qui - github.com/srinivasreddy/competies-list
Srinivas Reddy Thatiparthy,

-1

Con la pagina. $$ eval

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

[vedi anche a pagina. $ eval per un singolo selettore]


Come risponde alla domanda? Non vedo alcuna variabile che stai passando dal contesto di test al contesto del browser.
Ambroise Rabier
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.