Puppenspieler: Variable in .evaluate () übergeben

127

Ich versuche, eine Variable in Puppeteer an eine page.evaluate()Funktion zu übergeben , aber wenn ich das folgende sehr vereinfachte Beispiel verwende, ist die Variable undefiniert.evalVar

Ich bin neu bei Puppeteer und kann keine Beispiele finden, auf denen ich aufbauen kann. Daher benötige ich Hilfe beim Übergeben dieser Variablen an die page.evaluate()Funktion, damit ich sie im Inneren verwenden kann.

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

  }

})();
Katze Burston
quelle

Antworten:

188

Sie müssen die Variable als Argument an pageFunctionFolgendes übergeben:

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

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

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

Die Argumente können auch serialisiert werden: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageevaluatepagefunction-args .

Flozia
quelle
3
Hallo, wie würden Sie mehrere Variablen übergeben?
Chitzui
4
Außerdem kann ich eine Funktion nicht wirklich übergeben: var myFunction = function () {console.log ("Hallo")}; warte auf page.evaluate (func => func (), myFunction); gibt mir: Evaluation failed: TypeError: func is not a function.. Warum?
Chitzui
1
Vergessen Sie nicht, evalVarsowohl die Signatur des Funktionsarguments als auch ein übergebenes Argument an evaluate(am Ende des Codebeispiels) einzugeben.
Flimm
2
@chitzui: Sie können keine Funktion an übergeben pate.evaluate(). Sie können es angeblich mit "belichten" page.exposeFunction. Weitere Informationen finden Sie unter stackoverflow.com/a/58040978 .
Knod
Hat jemand Flusenfehler damit gemacht, da dies die höchsten Upvotes hat? speziell mit dem Parameter, der bereits im oberen Bereich deklariert ist. Abgesehen von diesem Fehler funktioniert dies.
Mix Master Mike
60

Ich ermutige Sie, an diesem Stil festzuhalten, da er bequemer und lesbarer ist .

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
quelle
40

Einzelne Variable:

Sie können passieren eine Variable zu page.evaluate()mit folgenden Syntax:

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

Hinweis: Sie müssen die Variable nicht einschließen (), es sei denn, Sie übergeben mehrere Variablen.

Mehrere Variablen:

Sie können passieren mehrere Variablen zu page.evaluate()mit folgenden Syntax:

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

Hinweis: Das Einschließen Ihrer Variablen in {}ist nicht erforderlich.

Grant Miller
quelle
12

Es dauerte eine ganze Weile, um das herauszufinden console.log()in evaluate()nicht in Knoten Konsole anzeigen kann.

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

Alles, was innerhalb der page.evaluate-Funktion ausgeführt wird, erfolgt im Kontext der Browserseite. Das Skript wird im Browser ausgeführt, nicht in node.js. Wenn Sie sich also anmelden, wird es in der Browserkonsole angezeigt. Wenn Sie kopflos ausgeführt werden, wird dies nicht angezeigt. Sie können auch keinen Knoten-Haltepunkt innerhalb der Funktion festlegen.

Hoffe das kann helfen.

harrrrrrry
quelle
6

Für Pass a functiongibt es zwei Möglichkeiten.

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

Sie können devtools: truedie Startoptionen für den Test hinzufügen

Wolf
quelle
Und ich wollte ein Objekt übergeben?
Straßenbahn
Wie würden Sie im 2. Fall ein Argument hinzufügen? zB möchte ich hinzufügen, übergeben Sie einen String zu yourFunc
user3568719
Sie können durch ein yourFuncObjekt ersetzen, wenn Ihre Eigenschaft keine Funktion ist. @ Tramada
Wolf
func ist ähnlich wie youFunc ,, so dass Sie func (stringArg) genau wie exec yourFunc @ user3568719
wolf
Würde es Ihnen etwas ausmachen zu zeigen, wie Sie ein Objekt an das Fenster übergeben und dann darauf zugreifen würden?
Wuno
2

Ich habe ein Typoskript-Beispiel, das jemandem helfen könnte, der neu in Typoskript ist.

const hyperlinks: string [] = await page.evaluate((url: string, regex: RegExp, querySelect: string) => {
.........
}, url, regex, querySelect);
Srinivas Reddy Thatiparthy
quelle
Wie läuft man puppeteerin Typoskript? Transpilieren Sie jedes Mal, wenn Sie Ihren Code ändern, zu js?
avalanche1
Ja. Sie können sich dieses Projekt hier ansehen - github.com/srinivasreddy/companies-list
Srinivas Reddy Thatiparthy
-1

Mit Seite. $$ eval

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

[Siehe auch auf Seite. $ eval für einen einzelnen Selektor]

voodoo417
quelle
Wie beantwortet das die Frage? Ich sehe keine Variable, die Sie vom Testkontext an den Browserkontext übergeben.
Ambroise Rabier