javascript - scraping - Titiritero: variable de paso en.evaluate()
web scraping javascript tutorial (5)
Estoy tratando de pasar una variable a una función
page.evaluate()
en
Puppeteer
, pero cuando uso el siguiente ejemplo muy simplificado, la variable
evalVar
no está definida.
Soy nuevo en Puppeteer y no puedo encontrar ningún ejemplo sobre el que construir, así que necesito ayuda para pasar esa variable a la función
page.evaluate()
para poder usarla dentro.
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();
}
})();
Variable individual:
Puede pasar una variable a Puppeteer utilizando la siguiente sintaxis:
await page.evaluate(example => { /* ... */ }, example);
Nota: No necesita encerrar la variable en
()
, a menos que vaya a pasar múltiples variables.
Variables Múltiples
Puede pasar múltiples variables a Puppeteer utilizando la siguiente sintaxis:
await page.evaluate((example_1, example_2) => { /* ... */ }, example_1, example_2);
Nota: No es necesario encerrar sus variables dentro de
{}
.
Me llevó bastante tiempo darme cuenta de que
console.log()
en
evaluate()
no se puede mostrar en la consola de nodo.
Ref: https://github.com/GoogleChrome/puppeteer/issues/1944
todo lo que se ejecuta dentro de la página. la función de evaluación se realiza en el contexto de la página del navegador. El script se ejecuta en el navegador, no en node.js, por lo que si inicia sesión, se mostrará en la consola del navegador, que si está ejecutando sin cabeza no verá. Tampoco puede establecer un punto de interrupción de nodo dentro de la función.
Espero que esto pueda ayudar.
Para pasar una
function
, hay dos formas de hacerlo.
// 1. Define in evaluationContext
await page.evaluate(() => {
window.yourFunc = function() {...};
});
const links = await page.evaluate(() => {
const func = window.yourFunc;
func();
});
// 2. Transform function to serializable. (Function can not be serialized)
const yourFunc = function() {...};
const obj = {
func: yourFunc.toString()
};
const links = await page.evaluate((obj) => {
const funStr = obj.func;
const func = new Function(`return ${funStr}.apply(null, arguments)`)
func();
}, obj);
Te animo a seguir con este estilo, porque es más conveniente y fácil de leer .
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});
pageFunction
pasar la variable como argumento a la
pageFunction
esta manera:
const links = await page.evaluate((evalVar) => {
console.log(evalVar); // should be defined now
…
}, evalVar);
Los argumentos también se pueden serializar: Puppeteer .