Кукловод: передать переменную в.evaluate()
Я пытаюсь передать переменную в функцию 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();
}
})();
Ответы
Ответ 1
Вы должны передать переменную в качестве аргумента функции pageFunction
следующим образом:
const links = await page.evaluate((evalVar) => {
console.log(evalVar); // should be defined now
…
}, evalVar);
Аргументы также могут быть сериализованы: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageevaluatepagefunction-args.
Ответ 2
Я призываю вас придерживаться этого стиля, потому что это более удобно и удобочитаемо.
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});
Ответ 3
Одна переменная:
Вы можете передать одну переменную to page.evaluate()
, используя следующий синтаксис:
await page.evaluate(example => { /* ... */ }, example);
Примечание: Вам не нужно заключать переменную в ()
, если только вы не собираетесь передавать несколько переменных.
Несколько переменных:
Вы можете передать несколько переменных в page.evaluate()
, используя следующий синтаксис:
await page.evaluate((example_1, example_2) => { /* ... */ }, example_1, example_2);
Примечание. Заключать переменные в {}
необязательно.
Ответ 4
Мне потребовалось много времени, чтобы понять, что console.log()
в evaluate()
не может отображаться в консоли узла.
Ссылка: https://github.com/GoogleChrome/puppeteer/issues/1944
все, что выполняется внутри функции page.evaluate, делается в контексте страницы браузера. Сценарий выполняется в браузере, а не в файле node.js, поэтому, если вы войдете в систему, он отобразит в консоли браузера, которую, если вы используете безголовый, вы не увидите. Вы также не можете установить точку останова узла внутри функции.
Надеюсь, это поможет.
Ответ 5
Для прохождения 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
к опциям запуска теста