Titereiro: passe a variável em .evaluate ()


128

Estou tentando passar uma variável para uma page.evaluate()função em Puppeteer , mas quando uso o seguinte exemplo muito simplificado, a variável evalVaré indefinida.

Eu sou novo no Puppeteer e não consigo encontrar nenhum exemplo para construir, então preciso de ajuda para passar essa variável para a page.evaluate()função para que possa usá-la internamente.

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

  }

})();

Respostas:


188

Você deve passar a variável como um argumento da pageFunctionseguinte maneira:

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

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

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

Os argumentos também podem ser serializados: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageevaluatepagefunction-args .


3
Olá, como você passaria várias variáveis?
— chitzui

4
Além disso, não consigo passar uma função: var myFunction = function () {console.log ("hello")}; aguardar page.evaluate (func => func (), myFunction); me dá: Evaluation failed: TypeError: func is not a function.. Por quê?
— chitzui

1
Não se esqueça de digitar evalVartanto na assinatura do argumento da função quanto como um argumento passado para evaluate(no final do exemplo de código).
— Flimm

2
@chitzui: Você não pode passar uma função para pate.evaluate(). Você pode supostamente 'expor' isso com page.exposeFunction. Para obter mais informações, consulte stackoverflow.com/a/58040978 .
— knod

uma vez que tem os votos positivos mais altos, alguém já experimentou erros de linting com isso? especificamente com o parâmetro já declarado no escopo superior. além desse erro, isso funciona.
— Mix Master Mike

61

Eu o encorajo a manter este estilo, porque é mais conveniente e legível .

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

Variável única:

Você pode passar uma variável para page.evaluate()usar a seguinte sintaxe:

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

Nota: Você não precisa incluir a variável (), a menos que vá passar várias variáveis.

Variáveis ​​múltiplas:

Você pode passar múltiplas variáveis para page.evaluate()usando a seguinte sintaxe:

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

Nota: Não {}é necessário incluir suas variáveis .


12

Levei muito tempo para descobrir que console.log()na evaluate()não pode mostrar na consola nó.

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

tudo o que é executado dentro da função page.evaluate é feito no contexto da página do navegador. O script está sendo executado no navegador, não em node.js, portanto, se você registrar, ele será exibido no console do navegador, o que não será visto se estiver executando sem comando. Você também não pode definir um ponto de interrupção de nó dentro da função.

Espero que isso possa ajudar.


6

Para a aprovação a function, há duas maneiras de fazer isso.

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

Você pode adicionar devtools: trueopções de lançamento para teste


E eu queria passar um objeto?
— tramada

Como você adicionaria um argumento no segundo caso? por exemplo, eu quero adicionar uma string para seuFunc
— user3568719

Você pode substituir yourFuncpor objeto se sua propriedade não for uma função. @tramada
— wolf

func é semelhante a youFunc, então você pode chamar func (stringArg) assim como exec yourFunc @ user3568719
— wolf

Você se importaria de mostrar como passaria um objeto para a janela e, em seguida, acessaria?
— wuno

2

Eu tenho um exemplo datilografado que pode ajudar alguém novo na datilografia.

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

Como você executa puppeteerem typescript? Você transpila para js cada vez que modifica seu código?
— avalanche 1 de

Sim. Você pode dar uma olhada neste projeto aqui - github.com/srinivasreddy/companies-list
— Srinivas Reddy Thatiparthy

-1

Com a página. $$ eval

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

[veja também na página. $ eval para um único seletor]


Como isso responde à pergunta? Não vejo nenhuma variável que você está passando do contexto de teste para o contexto do navegador.
— Ambroise Rabier
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.