ACCESIBLES
PRODUCTO
SOLUCIONES
por casos de uso
AI Plomo GestiónFacturaciónRedes socialesGestión de proyectos
Gestión de datos por sector
Más información
BlogPlantillasVideosYouTubeRECURSOS
COMUNIDADES Y REDES SOCIALES
SOCIOS
page.evaluate()
es una clave Titiritero método que permite ejecutar JavaScript directamente en el contexto del navegador. Une Node.js y el navegador, lo que permite tareas como la manipulación del DOM, la extracción de datos y la automatización de páginas web dinámicas. Esto es lo que necesita saber:
const title = await page.evaluate(() => document.title);
Esto recupera el título de la página directamente del navegador.
Feature | Contexto de Node.js | Contexto del navegador |
---|---|---|
Objetos globales | process , require |
window , document |
Ubicación del script | Máquina local | Página web de destino |
Acceso a la API | API de Node.js | API web del navegador |
Use page.evaluate()
para tareas de automatización precisas y eficientes, especialmente cuando se trabaja con sitios web que utilizan mucho JavaScript.
Al trabajar con Puppeteer para la automatización web, es fundamental comprender la distinción entre Contexto de Node.js y la contexto del navegadorEstos dos entornos están aislados, cada uno con sus propias reglas para ejecutar código e intercambiar datos.
Puppeteer opera en dos entornos: el Contexto de Node.js, donde se ejecuta el script principal y el contexto del navegador, donde se producen las interacciones con la página web. Son procesos separados, cada uno con su propia máquina virtual.
He aquí una rápida comparación de sus características clave:
Feature | Contexto de Node.js | Contexto del navegador |
---|---|---|
Objetos globales | process , require , __dirname |
window , document , localStorage |
Ubicación del script | Máquina local | Página web de destino |
Alcance variable | Alcance del script de Puppeteer | Ámbito del contexto de la página |
Acceso a la API | API de Node.js | API web del navegador |
Espacio de memoria | Proceso separado | Proceso del navegador |
El intercambio de datos entre estos contextos implica una serie de pasos que dependen en gran medida de la serialización:
Function.prototype.toString()
.Limitaciones claveLas funciones en el contexto del navegador no pueden acceder directamente a las variables del ámbito de Node.js. Puppeteer ofrece herramientas específicas para abordar estos desafíos:
page.evaluateHandle()
:Devuelve referencias a objetos en el contexto del navegador.page.exposeFunction()
: Permite que el navegador llame a funciones Node.js.evaluateOnNewDocument()
:Ejecuta el código antes de que se cargue cualquier script de página.Sin embargo, la serialización JSON puede eliminar ciertas propiedades, especialmente con objetos complejos como los nodos DOM. Para evitar problemas, pase los datos como argumentos de función en lugar de usar variables de Node.js.
Dominar estas técnicas de comunicación garantiza que puedas utilizarlas page.evaluate
Eficaz para tareas de automatización. A continuación, analizaremos ejemplos prácticos para ver estos conceptos en acción.
Sintaxis:
await page.evaluate(pageFunction, ...args)
Parámetro | Tipo | Descripción original |
---|---|---|
Función de página | Función o cadena | Código JavaScript para ejecutar en el contexto del navegador |
args | Parámetros opcionales | Valores pasados desde Node.js al contexto del navegador |
Valor de retorno | Promesa | Se resuelve con el valor de retorno de la función. |
La opción de Función de página Puede ser una función o una cadena que contiene código JavaScript. Usar una función suele ser mejor para la depuración y Mecanografiado Compatibilidad. A continuación se muestran algunos ejemplos para demostrar cómo funciona.
Ejemplos:
<h1>
directamente desde el DOM:const headingText = await page.evaluate(() => {
return document.querySelector('h1').textContent;
});
await page.evaluate((username, password) => {
document.getElementById('username').value = username;
document.getElementById('password').value = password;
document.querySelector('#login-form').submit();
}, 'myUsername', 'myPassword');
await page.evaluate(() => {
const div = document.createElement('div');
div.textContent = 'Added by Puppeteer';
document.body.appendChild(div);
return div.textContent;
});
Consejo de depuración: Utilice la siguiente configuración para habilitar la depuración durante el desarrollo:
const browser = await puppeteer.launch({
headless: false,
slowMo: 100 // Adds a 100ms delay to each operation
});
A continuación, profundizaremos en las técnicas para intercambiar datos entre Node.js y los contextos del navegador.
Al transferir datos con page.evaluate
, utilice valores serializables en JSON para los argumentos de entrada.
A continuación se muestra un desglose rápido de los tipos de parámetros admitidos:
Tipo de parámetro | ¿Soportado? | Ejemplo |
---|---|---|
Primitivas | ✓ Completamente | 'text' , 42 , true |
Matrices/Objetos | ✓ Compatible con JSON | { key: 'value' } , [1, 2, 3] |
Funciones | ✗ No directamente | Use page.exposeFunction |
Elementos DOM | ✓ A través de JSHandle | Use page.evaluateHandle |
Ahora, veamos cómo se devuelven estos valores desde el contexto del navegador.
Cuando usas page.evaluate
Los valores devueltos se serializan automáticamente a JSON. Así funciona:
// Returning a simple value
const pageTitle = await page.evaluate(() => document.title);
// Returning a complex object
const metrics = await page.evaluate(() => ({
viewport: window.innerWidth,
scrollHeight: document.body.scrollHeight,
timestamp: Date.now()
}));
"Como regla general, si el valor de retorno de la función dada es más complicado que un objeto JSON (por ejemplo, la mayoría de las clases), entonces
evaluate
Probablemente devolverá algún valor truncado (o{}
). Esto se debe a que no devolvemos el valor de retorno real, sino una versión deserializada como resultado de transferir el valor de retorno mediante un protocolo a Puppeteer.
Una vez que haya recuperado la salida, podría encontrar problemas relacionados con la serialización. Aquí le mostramos cómo solucionarlos.
Algunos escenarios comunes requieren soluciones alternativas específicas:
const bodyHandle = await page.$('body');
const html = await page.evaluate(body => body.innerHTML, bodyHandle);
await bodyHandle.dispose(); // Always clean up to avoid memory leaks
await page.exposeFunction('md5', text =>
crypto.createHash('md5').update(text).digest('hex')
);
const hash = await page.evaluate(async () => {
return await window.md5('test-string');
});
Si está trabajando con TypeScript, asegúrese de que su transpilador esté configurado correctamente:
// tsconfig.json
{
"compilerOptions": {
"target": "es2018"
}
}
Estas estrategias le ayudarán a gestionar eficazmente el intercambio de datos en diversos contextos.
Así es como puedes usar page.evaluate
en escenarios del mundo real, completos con fragmentos de código prácticos.
Ejemplo: Rastreo de detalles del producto
Este script recopila detalles como título, precio, calificación y estado de stock de las tarjetas de producto en una página web:
const productData = await page.evaluate(() => {
const products = Array.from(document.querySelectorAll('.product-card'));
return products.map(product => ({
title: product.querySelector('.title').textContent.trim(),
price: product.querySelector('.price').textContent.trim(),
rating: parseFloat(product.querySelector('.rating').dataset.value),
inStock: product.querySelector('.stock').textContent.includes('Available')
}));
});
Ejemplo: extracción de datos de una tabla
Este enfoque recupera datos de una tabla iterando a través de sus filas y columnas:
const tableData = await page.evaluate(() => {
const rows = Array.from(document.querySelectorAll('table tr'));
return rows.map(row => {
const columns = row.querySelectorAll('td');
return Array.from(columns, column => column.innerText);
});
});
Automatización básica de formularios
A continuación se explica cómo completar los campos del formulario, activar eventos y enviar el formulario:
await page.evaluate(() => {
// Fill form fields
document.querySelector('#username').value = 'testuser';
document.querySelector('#password').value = 'secretpass';
// Trigger input events for dynamic forms
const event = new Event('input', { bubbles: true });
document.querySelector('#username').dispatchEvent(event);
// Submit form
document.querySelector('form').submit();
});
Manejo de formularios complejos
Para tareas como seleccionar opciones desplegables o marcar botones de opción:
await page.evaluate(() => {
// Select dropdown option
const select = document.querySelector('#country');
select.value = 'US';
select.dispatchEvent(new Event('change', { bubbles: true }));
// Check radio button
const radio = document.querySelector('input[value="express"]');
radio.checked = true;
radio.dispatchEvent(new Event('change', { bubbles: true }));
});
Ejemplo: desplazamiento infinito
Este script se desplaza por una página hasta que recopila al menos 100 elementos:
const items = await page.evaluate(async () => {
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
const items = new Set();
while (items.size < 100) {
// Scroll to bottom
window.scrollTo(0, document.body.scrollHeight);
// Wait for new content
await delay(1000);
// Collect items
document.querySelectorAll('.item').forEach(item =>
items.add(item.textContent.trim())
);
}
return Array.from(items);
});
Ejemplo: Manejo de contenido AJAX
Para cargar más contenido dinámicamente, este script hace clic en el botón "Cargar más" y espera a que aparezcan nuevos elementos:
await page.evaluate(async () => {
// Click load more button
document.querySelector('#loadMore').click();
// Wait for content update
await new Promise(resolve => {
const observer = new MutationObserver((mutations, obs) => {
if (document.querySelectorAll('.item').length > 10) {
obs.disconnect();
resolve();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
});
});
Estos ejemplos muestran cómo gestionar diversos escenarios, como el scraping, la automatización de formularios y el contenido dinámico. Se pueden realizar ajustes según la estructura y el comportamiento específicos de la página web con la que se trabaja.
Latenode incorpora las funciones principales de Puppeteer en sus flujos de trabajo de automatización, lo que facilita la ejecución de JavaScript directamente en el navegador. Con page.evaluate
Los usuarios pueden manipular el DOM y extraer datos eficientemente. Este enfoque permite una integración fluida del manejo avanzado de datos y las operaciones del DOM en el entorno de automatización de Latenode.
El módulo de automatización del navegador de Latenode utiliza page.evaluate
Para gestionar todo, desde tareas DOM sencillas hasta la ejecución más compleja de JavaScript. Así funciona en diferentes escenarios:
// Basic DOM interaction
await page.evaluate(() => {
const loginButton = document.querySelector('#login');
loginButton.click();
// Trigger a custom event
loginButton.dispatchEvent(new Event('customClick'));
});
// Processing data with exposed functions
await page.exposeFunction('processData', async (data) => {
// Process data in Node.js context
return transformedData;
});
await page.evaluate(async () => {
const rawData = document.querySelector('#data').textContent;
const processed = await window.processData(rawData);
return processed;
});
Latenode también mantiene un registro del historial de ejecución, lo que facilita la depuración de scripts.
Latenode está bien equipado para gestionar contenido dinámico y tareas de automatización complejas. A continuación, se muestra un ejemplo de procesamiento de contenido dinámico en una página:
const extractProductData = await page.evaluate(async () => {
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
// Wait for dynamic content to load
while (!document.querySelector('.product-grid')) {
await delay(100);
}
return Array.from(document.querySelectorAll('.product'))
.map(product => ({
name: product.querySelector('.name').textContent,
price: product.querySelector('.price').textContent,
availability: product.querySelector('.stock').dataset.status
}));
});
Para operaciones más avanzadas, page.exposeFunction
permite una interacción fluida entre Node.js y el navegador:
await page.exposeFunction('md5', text =>
crypto.createHash('md5').update(text).digest('hex')
);
const processedData = await page.evaluate(async () => {
const sensitiveData = document.querySelector('#secure-data').value;
return await window.md5(sensitiveData);
});
Para mantener referencias a elementos DOM en todos los pasos, Latenode utiliza page.evaluateHandle
:
const elementHandle = await page.evaluateHandle(() => {
return document.querySelector('.dynamic-content');
});
await page.evaluate(element => {
element.scrollIntoView();
}, elementHandle);
Estas técnicas garantizan que Latenode pueda gestionar contenido dinámico eficazmente y mantener un rendimiento fiable. Para los usuarios del plan Prime, la plataforma admite hasta 1.5 millones de ejecuciones de escenarios al mes, lo que proporciona amplias capacidades de automatización.
Cuando se trabaja con page.evaluate
En la automatización del navegador, podrías encontrarte con varios problemas. Aquí tienes soluciones prácticas para solucionarlos y garantizar una ejecución más fluida.
Configure correctamente sus ajustes de TypeScript para evitar problemas causados por la transpilación. Por ejemplo:
// Use direct, non-transpiled functions
await page.evaluate(() => {
document.querySelector('#button').click();
});
await page.evaluate(`(async () => {
document.querySelector('#button').click();
})()`);
Evite devolver elementos DOM directamente desde page.evaluate
. En su lugar, use ElementHandle
Para un mejor manejo:
// Incorrect: Returning a DOM element
const element = await page.evaluate(() => {
return document.querySelector('.dynamic-element');
});
// Correct: Using ElementHandle
const element = await page.evaluateHandle(() => {
return document.querySelector('.dynamic-element');
});
Los scripts pueden ejecutarse antes de que la página se cargue por completo, lo que provoca errores de sincronización. Utilice estas estrategias para gestionar estos casos:
// Wait for navigation after an action
await Promise.all([
page.waitForNavigation(),
page.click('#submit-button')
]);
// Wait for a specific condition
await page.waitForFunction(() => {
const element = document.querySelector('.lazy-loaded');
return element && element.dataset.loaded === 'true';
}, { timeout: 5000 });
Para sitios web dinámicos, adopte mecanismos de espera más específicos:
// Wait for specific network requests
await page.waitForResponse(
response => response.url().includes('/api/data')
);
// Ensure elements are both present and visible
await page.waitForSelector('.dynamic-content', {
visible: true,
timeout: 3000
});
Para evitar fugas de memoria, gestione cuidadosamente las referencias DOM. A continuación, le explicamos cómo:
// Use and dispose ElementHandles
const handle = await page.evaluateHandle(() => {
return document.querySelector('.temporary-element');
});
await handle.evaluate(element => {
// Perform operations
});
await handle.dispose(); // Dispose of handle after use
Al trabajar con múltiples elementos, pase datos de forma segura entre contextos:
// Extract data from the DOM
const selector = '.product-price';
const price = await page.evaluate((sel) => {
const element = document.querySelector(sel);
return element ? element.textContent.trim() : null;
}, selector);
Para los oyentes de eventos, asegúrese de una limpieza adecuada para evitar controladores persistentes:
await page.evaluate(() => {
const handler = () => console.log('clicked');
const button = document.querySelector('#button');
button.addEventListener('click', handler);
// Store cleanup references
window._cleanupHandlers = window._cleanupHandlers || [];
window._cleanupHandlers.push(() => {
button.removeEventListener('click', handler);
});
});
Para obtener los mejores resultados con page.evaluate
Debes centrarte en mejorar el rendimiento, reducir los cambios de contexto innecesarios y garantizar la seguridad. Aquí te explicamos cómo optimizar los flujos de trabajo de automatización de tu navegador.
Ejecutar código eficientemente dentro del contexto de la página ahorra tiempo y recursos del sistema. A continuación, se presentan algunas técnicas para agilizar sus scripts:
// Block unnecessary resources like images and stylesheets
await page.setRequestInterception(true);
page.on('request', request => {
if (['image', 'stylesheet'].includes(request.resourceType())) {
request.abort();
} else {
request.continue();
}
});
// Batch operations to reduce overhead
await page.evaluate(() => {
const results = [];
document.querySelectorAll('.product-item').forEach(item => {
results.push({
title: item.querySelector('.title').textContent,
price: item.querySelector('.price').textContent,
stock: item.querySelector('.stock').dataset.value
});
});
return results;
});
La elección de los selectores adecuados también juega un papel importante en el rendimiento:
Tipo de selector | Velocidad | Ejemplo |
---|---|---|
ID | Empresarial | #main-content |
Clase | Rápido | .product-item |
Etiqueta | Moderado | div > span |
XPath complejo | El más lento | //div[@class='wrapper']//span |
El cambio de contexto entre Node.js y el entorno del navegador puede ralentizar el proceso. Aquí te explicamos cómo minimizarlo:
// Example of inefficient context switching
for (const item of items) {
await page.evaluate((i) => {
document.querySelector(`#item-${i}`).click();
}, item);
}
// Better: Batch operations in a single context switch
await page.evaluate((itemsList) => {
itemsList.forEach(i => {
document.querySelector(`#item-${i}`).click();
});
}, items);
Si necesita procesar datos en Node.js y pasarlos de vuelta al navegador, exponga funciones en lugar de cambiar de contexto repetidamente:
await page.exposeFunction('processData', async (data) => {
// Process data in Node.js
return transformedData;
});
await page.evaluate(async () => {
const result = await window.processData(documentData);
// Use the processed data in the browser
});
Una vez optimizado el rendimiento y el cambio de contexto, concéntrese en mantener la seguridad de sus scripts. Estas son algunas prácticas recomendadas:
// Always sanitize inputs before using them
const sanitizedInput = sanitizeHtml(userInput);
await page.evaluate((input) => {
document.querySelector('#search').value = input;
}, sanitizedInput);
// Use error handling for critical operations
try {
await page.evaluate(() => {
if (!window.__securityCheck) {
throw new Error('Security check failed');
}
// Continue with the operation
});
} catch (error) {
console.error('Security violation:', error);
}
Para los flujos de trabajo de Latenode, tenga en cuenta estos consejos adicionales:
userDataDir
para almacenar en caché recursos y mejorar el rendimiento en todas las sesiones.La opción de page.evaluate
El método conecta Node.js y los contextos del navegador mediante el envío de una función JavaScript convertida en cadena para su ejecución en el navegador. Esta función opera independientemente del entorno de Node.js, por lo que es necesario gestionar la transferencia de datos con cuidado.
He aquí un ejemplo común de extracción de datos:
const data = await page.evaluate(async () => {
const results = document.querySelectorAll('.data-item');
return Array.from(results, item => ({
id: item.dataset.id,
value: item.textContent.trim()
}));
});
Cosas para tener en cuenta:
evaluate
contexto.Estos conceptos básicos sientan las bases para usar Puppeteer eficazmente. Herramientas adicionales pueden optimizar aún más sus tareas de automatización.
Puppeteer ofrece varias herramientas para ampliar las capacidades de page.evaluate
:
Propósito | Mejor caso de uso | |
---|---|---|
page.evaluateHandle |
Devuelve referencias de objetos | Interactuar directamente con elementos DOM |
page.exposeFunction |
Hace que las funciones de Node.js sean utilizables en el navegador | Gestión de lógica compleja del lado del servidor |
page.evaluateOnNewDocument |
Ejecuta scripts antes de que se cargue una página | Preparar el entorno del navegador con antelación |
Por ejemplo, exponer las funciones de Node.js al navegador puede simplificar el procesamiento avanzado de datos en flujos de trabajo como los de Latenode. Mientras que page.evaluate
funciona bien para manejar tipos primitivos y objetos serializables en JSON, page.evaluateHandle
es esencial para tratar con objetos de navegador complejos que no se pueden serializar.