Ляльковий: передати змінну в .evaluate ()


128

Я намагаюся передати змінну у page.evaluate()функцію в Puppeteer , але коли я використовую наступний дуже спрощений приклад, змінна 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
Привіт, як би ти передав кілька змінних?
чітцуї

4
Крім того, я не в змозі передати функцію: var myFunction = function () {console.log ("привіт")}; очікувати сторінку.evaluate (func => func (), myFunction); дає мені: Evaluation failed: TypeError: func is not a function.. Чому?
Чіцуї

1
Не забудьте ввести evalVarяк підпис аргументу функції, так і переданий аргумент evaluate(в кінці прикладу коду).
Flimm

2
@chitzui: Ви не можете передати функцію pate.evaluate(). Ви можете нібито "викрити" це page.exposeFunction. Докладніше див. У статті stackoverflow.com/a/58040978 .
knod

Оскільки це найвищий показник, чи не стикався хтось із пов’язаними помилками з цим? конкретно з параметром, уже оголошеним у верхній області. окрім цієї помилки, це дійсно працює.
Мікс Майк Майк

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

Єдина змінна:

Ви можете передати одну змінну до 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/isissue/1944

все, що виконується всередині сторінки. Функція оцінювання виконується в контексті сторінки браузера. Сценарій працює в браузері не в node.js, тому, якщо ви ввійдете в систему, він відобразиться на консолі браузера, який, якщо ви працюєте без голови, ви не побачите. Ви також не можете встановити точку розриву вузла всередині функції.

Сподіваюся, що це може допомогти.


6

Для передачі a functionє два способи зробити це.

// 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до параметрів запуску тесту


А я хотів здати об’єкт?
трамада

Як би ви додали аргумент у другому випадку? Наприклад, я хочу додати рядок передачі до вашогоFunc
user3568719

Ви можете замінити yourFuncоб'єктом, якщо ваше майно не є функцією. @tramada
вовк

func схожий на youFunc ,, тому ви можете зателефонувати func (stringArg) так само, як exec yourFunc @ user3568719
wolf

Ви б не хотіли показати, як ви передатимете об'єкт до вікна і потім отримаєте доступ до нього?
wuno

2

У мене є приклад машинопису, який може допомогти комусь новому в машинописі.

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

Як ви запускаєте puppeteerмашинопис? Чи перетворюєте ви в js щоразу, коли ви змінюєте код?
лавина1

Так. Ви можете подивитися на цей проект тут - github.com/srinivasreddy/companies-list
Шрінівас Редді Татіпарті

-1

Зі сторінкою. $$ eval

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

[див. також на сторінці. $ eval для одного селектора]


Як це відповідає на питання? Я не бачу жодної змінної, яку ви переходите від тестового контексту до контексту браузера.
Ambroise Rabier
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.