Depuración de scripts de Puppeteer: del modo cámara lenta a técnicas avanzadas
Domine las técnicas de depuración esenciales para los scripts de Puppeteer, desde métodos visuales hasta el manejo avanzado de errores, para mejorar la confiabilidad del script.

Depuración Titiritero Los guiones pueden resultar abrumadores, pero dominar algunas técnicas clave puede ahorrarte tiempo y frustración. Aquí tienes un breve resumen de lo que aprenderás:
- Comience con la depuración visual: Utilice
slowMoModo y modo de navegador completo para ver su script en acción. - Errores de captura: Agrega
try-catchBloquea y automatiza capturas de pantalla de errores para una mejor resolución de problemas. - Aprovechar los registros de la consola:Realice un seguimiento de errores de página, solicitudes fallidas y mensajes personalizados para obtener información más detallada.
- Selectores de manijas y sincronización:Utilice estrategias de selección sólidas y administre los tiempos de espera para evitar errores comunes.
- Organiza tu código:Divida los scripts en módulos para acciones, selectores y validaciones para simplificar el mantenimiento.
Ejemplo de configuración rápida:
<span class="hljs-keyword">const</span> browser = <span class="hljs-keyword">await</span> puppeteer.<span class="hljs-title function_">launch</span>({
<span class="hljs-attr">headless</span>: <span class="hljs-literal">false</span>,
<span class="hljs-attr">slowMo</span>: <span class="hljs-number">100</span>,
<span class="hljs-attr">devtools</span>: <span class="hljs-literal">true</span>
});
Consejos de depuración:
- Habilitar registro:Corre con
DEBUG="puppeteer:*"para registros detallados. - Usar capturas de pantalla:Captura los estados de la página para ver qué salió mal.
- Gestionar recursos:Limpie siempre las instancias del navegador y de la página para evitar fallos.
Al combinar estas técnicas, agilizará su proceso de depuración y mejorará la confiabilidad de sus scripts de Puppeteer.
Configuración del entorno de depuración
Configuración básica de depuración
Configure Puppeteer para la depuración con estas opciones de inicio:
<span class="hljs-keyword">const</span> browser = <span class="hljs-keyword">await</span> puppeteer.<span class="hljs-title function_">launch</span>({
<span class="hljs-attr">headless</span>: <span class="hljs-literal">false</span>,
<span class="hljs-attr">slowMo</span>: <span class="hljs-number">20</span>,
<span class="hljs-attr">devtools</span>: <span class="hljs-literal">true</span>
});
Para habilitar el registro detallado, ejecute su script con el siguiente comando:
DEBUG=<span class="hljs-string">"puppeteer:*"</span> node script.js
Una vez configurado, utilice herramientas de depuración para analizar y refinar el comportamiento de su script.
Herramientas de depuración necesarias
Aquí hay algunas herramientas que le ayudarán a resolver problemas de manera efectiva:
| Proposito | Función clave | |
|---|---|---|
| DevTools de Chrome | Inspeccionar scripts | Herramientas de consola y red |
| Depurador de VS Code | Administrar puntos de interrupción | Ejecución paso a paso |
| Utilidad de captura de pantalla | Solución de problemas visuales | Capturar estados de página |
También puedes agregar puntos de control en tu código para una mejor visibilidad:
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">screenshot</span>({ <span class="hljs-attr">path</span>: <span class="hljs-string">'before_click.png'</span> });
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">click</span>(<span class="hljs-string">'#button'</span>);
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">screenshot</span>({ <span class="hljs-attr">path</span>: <span class="hljs-string">'after_click.png'</span> });
Organización del guión
Una buena organización es tan importante como las herramientas que utilizas. Divide tu script en módulos lógicos e incluye gestión de errores para una depuración más fluida.
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">waitForSelector</span>(<span class="hljs-string">'#target-element'</span>);
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">click</span>(<span class="hljs-string">'#target-element'</span>);
} <span class="hljs-keyword">catch</span> (error) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">`Navigation failed: <span class="hljs-subst">${error.message}</span>`</span>);
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">screenshot</span>({ <span class="hljs-attr">path</span>: <span class="hljs-string">'error-state.png'</span> });
}
Para reducir la posibilidad de detección de bots, integre el complemento oculto:
<span class="hljs-keyword">const</span> puppeteer = <span class="hljs-built_in">require</span>(<span class="hljs-string">'puppeteer-extra'</span>);
<span class="hljs-keyword">const</span> <span class="hljs-title class_">StealthPlugin</span> = <span class="hljs-built_in">require</span>(<span class="hljs-string">'puppeteer-extra-plugin-stealth'</span>);
puppeteer.<span class="hljs-title function_">use</span>(<span class="hljs-title class_">StealthPlugin</span>());
Por último, asegúrese de gestionar adecuadamente los recursos implementando procedimientos de limpieza:
<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">cleanup</span>(<span class="hljs-params"></span>) {
<span class="hljs-keyword">if</span> (page) <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">close</span>();
<span class="hljs-keyword">if</span> (browser) <span class="hljs-keyword">await</span> browser.<span class="hljs-title function_">close</span>();
}
Esta configuración proporciona una base sólida para la depuración visual y de consola en sus proyectos.
Titiritero - 3 enfoques a considerar en la depuración
Métodos de depuración visual
Observar tus scripts en acción puede revelar problemas que el análisis de código tradicional podría pasar por alto. Estos métodos amplían tus opciones de depuración más allá de los registros de consola y el seguimiento de errores.
Guía del modo cámara lenta
SlowMo introduce un retraso entre las acciones de Puppeteer, lo que hace que sea más fácil seguir lo que está sucediendo:
<span class="hljs-keyword">const</span> browser = <span class="hljs-keyword">await</span> puppeteer.<span class="hljs-title function_">launch</span>({
<span class="hljs-attr">headless</span>: <span class="hljs-literal">false</span>,
<span class="hljs-attr">slowMo</span>: <span class="hljs-number">250</span>,
<span class="hljs-attr">devtools</span>: <span class="hljs-literal">true</span>
});
La slowMo El valor (en milisegundos) controla el retraso entre acciones. Ajústalo según lo que estés probando:
| Tipo de operación | Cámara lenta recomendada (ms) | Caso de uso |
|---|---|---|
| Clics simples | 100-250 | Pasos básicos de navegación |
| El rellenado de formularios | 250-500 | Prueba de validación de entrada |
| Contenido dinámico | 500-1000 | Comprobación de estados de carga |
Una vez que haya configurado SlowMo, combínelo con el modo de vista del navegador para monitorear cómo se comporta la interfaz de usuario durante la ejecución del script.
Modo de vista del navegador
El modo de vista del navegador le permite ver su script ejecutarse en una ventana visible del navegador, lo que es especialmente útil para depurar contenido dinámico e interacciones complejas.
<span class="hljs-keyword">const</span> browser = <span class="hljs-keyword">await</span> puppeteer.<span class="hljs-title function_">launch</span>({
<span class="hljs-attr">headless</span>: <span class="hljs-literal">false</span>,
<span class="hljs-attr">defaultViewport</span>: { <span class="hljs-attr">width</span>: <span class="hljs-number">1700</span>, <span class="hljs-attr">height</span>: <span class="hljs-number">800</span> },
<span class="hljs-attr">args</span>: [<span class="hljs-string">'--start-maximized'</span>]
});
Por ejemplo, acme corporaciónEl equipo de control de calidad de [nombre del sitio web] utilizó este modo en junio de 2024 para solucionar problemas con un script de web scraping. Detectaron selectores incorrectos y los solucionaron, reduciendo el tiempo de depuración en un 40 %.
Para complementar esto, capture capturas de pantalla de estados visuales importantes para su posterior análisis.
Grabación visual
Las capturas de pantalla y los videos pueden crear un registro claro de la ejecución de su script, lo que facilita la depuración:
<span class="hljs-comment">// Screenshot of a specific element</span>
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">screenshot</span>({
<span class="hljs-attr">path</span>: <span class="hljs-string">'element-state.png'</span>,
<span class="hljs-attr">clip</span>: {
<span class="hljs-attr">x</span>: <span class="hljs-number">0</span>,
<span class="hljs-attr">y</span>: <span class="hljs-number">0</span>,
<span class="hljs-attr">width</span>: <span class="hljs-number">500</span>,
<span class="hljs-attr">height</span>: <span class="hljs-number">300</span>
}
});
<span class="hljs-comment">// Full-page screenshot</span>
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">screenshot</span>({
<span class="hljs-attr">path</span>: <span class="hljs-string">'full-page.png'</span>,
<span class="hljs-attr">fullPage</span>: <span class="hljs-literal">true</span>
});
Empieza por activar el modo de vista del navegador, usa SlowMo para un seguimiento detallado y documenta los momentos clave con capturas de pantalla. Juntos, estos pasos crean un proceso de depuración visual exhaustivo.
Métodos de depuración de la consola
Los métodos de consola ofrecen una forma sencilla de obtener información textual sobre el comportamiento de tus scripts. Estas salidas se complementan con la depuración visual para brindarte detalles precisos sobre la ejecución del script.
Seguimiento de mensajes de la consola
Puppeteer facilita la captura de mensajes del navegador con controladores de eventos como estos:
page.<span class="hljs-title function_">on</span>(<span class="hljs-string">'console'</span>, <span class="hljs-function"><span class="hljs-params">msg</span> =></span> {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'PAGE LOG:'</span>, msg.<span class="hljs-title function_">text</span>());
});
page.<span class="hljs-title function_">on</span>(<span class="hljs-string">'pageerror'</span>, <span class="hljs-function"><span class="hljs-params">err</span> =></span> {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">'PAGE ERROR:'</span>, err.<span class="hljs-property">message</span>);
});
page.<span class="hljs-title function_">on</span>(<span class="hljs-string">'requestfailed'</span>, <span class="hljs-function"><span class="hljs-params">request</span> =></span> {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">'REQUEST FAILED:'</span>, request.<span class="hljs-title function_">url</span>());
});
Esta configuración crea un sistema de registro que rastrea los mensajes de la consola, los errores de página y las solicitudes fallidas. Para mayor claridad, puede categorizar los mensajes por tipo:
| Tipo de mensaje | Proposito | Salida de ejemplo |
|---|---|---|
| Log | Información general | Flujo de ejecución estándar |
| Error | Problemas mayores | Operaciones fallidas |
| Advertencia | Posibles preocupaciones | Ralentizaciones del rendimiento |
| Información | Actualizaciones de estado | La terminación de la tarea |
Mejores prácticas para Console.log
El uso de console.log Depurar con prudencia puede facilitar mucho la depuración. Coloque los registros estratégicamente para seguir el progreso e identificar problemas.
<span class="hljs-comment">// Log before attempting to find an element</span>
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`Looking for element: <span class="hljs-subst">${selector}</span>`</span>);
<span class="hljs-keyword">const</span> element = <span class="hljs-keyword">await</span> page.$(selector);
<span class="hljs-comment">// Log after confirming the element exists</span>
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`Element found: <span class="hljs-subst">${!!element}</span>`</span>);
<span class="hljs-comment">// Log form data before filling it out</span>
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`Form data: <span class="hljs-subst">${<span class="hljs-built_in">JSON</span>.stringify(formData)}</span>`</span>);
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">type</span>(<span class="hljs-string">'#email'</span>, formData.<span class="hljs-property">email</span>);
Métodos de registro extendidos
Para problemas más complejos, las técnicas de registro avanzadas pueden marcar la diferencia:
<span class="hljs-comment">// Enable detailed debugging for Puppeteer</span>
process.<span class="hljs-property">env</span>.<span class="hljs-property">DEBUG</span> = <span class="hljs-string">'puppeteer:*'</span>;
process.<span class="hljs-property">env</span>.<span class="hljs-property">DEBUG_MAX_STRING_LENGTH</span> = <span class="hljs-literal">null</span>;
<span class="hljs-comment">// Monitor pending protocol calls</span>
<span class="hljs-keyword">const</span> browser = <span class="hljs-keyword">await</span> puppeteer.<span class="hljs-title function_">launch</span>({
<span class="hljs-attr">dumpio</span>: <span class="hljs-literal">true</span>
});
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(browser.<span class="hljs-property">debugInfo</span>.<span class="hljs-property">pendingProtocolErrors</span>);
Un equipo observó una caída del 40% en las fallas de pruebas luego de adoptar un registro de protocolo detallado.
<span class="hljs-comment">// Filter out specific network domain messages</span>
<span class="hljs-comment">// Command: DEBUG="puppeteer:*" DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'</span>
Estos métodos agregan una capa basada en texto a su proceso de depuración, ayudándolo a detectar y resolver problemas de manera más efectiva.
sbb-itb-23997f1
Métodos de depuración avanzados
La depuración de scripts complejos de Puppeteer implica el uso de estrategias efectivas de manejo de errores y técnicas avanzadas para garantizar que los scripts se ejecuten sin problemas.
Try-Catch para el manejo de errores
Usa bloques try-catch Para gestionar errores de forma eficaz y mantener su script en ejecución:
<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">navigateAndScreenshot</span>(<span class="hljs-params">url, selector</span>) {
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">goto</span>(url, { <span class="hljs-attr">waitUntil</span>: <span class="hljs-string">'networkidle0'</span> });
<span class="hljs-keyword">const</span> element = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">waitForSelector</span>(selector, { <span class="hljs-attr">timeout</span>: <span class="hljs-number">5000</span> });
<span class="hljs-keyword">await</span> element.<span class="hljs-title function_">screenshot</span>({ <span class="hljs-attr">path</span>: <span class="hljs-string">'element.png'</span> });
} <span class="hljs-keyword">catch</span> (error) {
<span class="hljs-keyword">if</span> (error <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">TimeoutError</span>) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">`Element <span class="hljs-subst">${selector}</span> not found within timeout`</span>);
<span class="hljs-comment">// Add recovery logic if needed</span>
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">reload</span>();
} <span class="hljs-keyword">else</span> {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">`Navigation failed: <span class="hljs-subst">${error.message}</span>`</span>);
<span class="hljs-keyword">throw</span> error; <span class="hljs-comment">// Re-throw unexpected errors</span>
}
}
}
Puede mejorar el manejo de errores combinando bloques try-catch con clases de error personalizadas para una mejor categorización y respuesta.
Clases de error personalizadas
La creación de clases de error personalizadas le ayuda a identificar y clasificar problemas de manera más eficiente:
<span class="hljs-keyword">class</span> <span class="hljs-title class_">PuppeteerScriptError</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">Error</span> {
<span class="hljs-title function_">constructor</span>(<span class="hljs-params">message, details = {}</span>) {
<span class="hljs-variable language_">super</span>(message);
<span class="hljs-variable language_">this</span>.<span class="hljs-property">name</span> = <span class="hljs-string">'PuppeteerScriptError'</span>;
<span class="hljs-variable language_">this</span>.<span class="hljs-property">details</span> = details;
<span class="hljs-variable language_">this</span>.<span class="hljs-property">timestamp</span> = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>().<span class="hljs-title function_">toISOString</span>();
}
}
<span class="hljs-keyword">class</span> <span class="hljs-title class_">SelectorError</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">PuppeteerScriptError</span> {
<span class="hljs-title function_">constructor</span>(<span class="hljs-params">selector, context</span>) {
<span class="hljs-variable language_">super</span>(<span class="hljs-string">`Failed to find selector: <span class="hljs-subst">${selector}</span>`</span>, {
selector,
context,
<span class="hljs-attr">type</span>: <span class="hljs-string">'SELECTOR_ERROR'</span>
});
<span class="hljs-variable language_">this</span>.<span class="hljs-property">name</span> = <span class="hljs-string">'SelectorError'</span>;
}
}
Estas clases le permiten rastrear y depurar operaciones asincrónicas con más claridad.
Depuración de código asincrónico
El código asincrónico suele generar problemas de sincronización y promesas sin resolver. Aborde estos problemas con las siguientes técnicas:
<span class="hljs-comment">// Enable detailed debugging for protocol calls</span>
<span class="hljs-keyword">const</span> browser = <span class="hljs-keyword">await</span> puppeteer.<span class="hljs-title function_">launch</span>({
<span class="hljs-attr">dumpio</span>: <span class="hljs-literal">true</span>
});
<span class="hljs-comment">// Monitor unresolved promises periodically</span>
<span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =></span> {
<span class="hljs-keyword">const</span> pending = browser.<span class="hljs-property">debugInfo</span>.<span class="hljs-property">pendingProtocolErrors</span>;
<span class="hljs-keyword">if</span> (pending.<span class="hljs-property">length</span> > <span class="hljs-number">0</span>) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'Pending protocol calls:'</span>, pending);
}
}, <span class="hljs-number">5000</span>);
<span class="hljs-comment">// Handle async errors with a timeout mechanism</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">safeExecute</span>(<span class="hljs-params">promiseFn</span>) {
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-title class_">Promise</span>.<span class="hljs-title function_">race</span>([
<span class="hljs-title function_">promiseFn</span>(),
<span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">_, reject</span>) =></span>
<span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =></span> <span class="hljs-title function_">reject</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">'Operation timed out'</span>)), <span class="hljs-number">30000</span>)
)
]);
} <span class="hljs-keyword">catch</span> (error) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">`Operation failed: <span class="hljs-subst">${error.message}</span>`</span>);
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">PuppeteerScriptError</span>(<span class="hljs-string">'Execution timeout'</span>, {
<span class="hljs-attr">originalError</span>: error,
<span class="hljs-attr">operation</span>: promiseFn.<span class="hljs-property">name</span>
});
}
}
Mediante el uso de la debugInfo Interfaz, puede monitorear devoluciones de llamadas pendientes e identificar promesas no resueltas durante la comunicación del protocolo del navegador.
| Nivel de depuración | Proposito | Implementación |
|---|---|---|
| Básico | Manejar errores comunes | Bloques try-catch estándar |
| Intermedio | Clasificar errores | Jerarquía de clases de error personalizada |
| Avanzado | Problemas con el protocolo de seguimiento | Monitoreo de la interfaz de depuración |
Soluciones a problemas comunes
Esta sección analiza los desafíos frecuentes con Puppeteer y proporciona soluciones claras para mantener sus scripts de automatización funcionando sin problemas.
Problemas con el selector
Los problemas con el selector a menudo pueden interrumpir la ejecución del script. Aquí te explicamos cómo solucionarlos eficazmente:
<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">findElement</span>(<span class="hljs-params">page</span>) {
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">const</span> element = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">waitForSelector</span>(<span class="hljs-string">'[data-testid="target"]'</span>, {
<span class="hljs-attr">timeout</span>: <span class="hljs-number">5000</span>
});
<span class="hljs-keyword">return</span> element;
} <span class="hljs-keyword">catch</span> {
<span class="hljs-keyword">return</span> page.<span class="hljs-title function_">waitForSelector</span>(<span class="hljs-string">'.target-class'</span>, {
<span class="hljs-attr">timeout</span>: <span class="hljs-number">5000</span>
});
}
}
Para elementos dentro de iframes o DOM de sombra, utilice estos enfoques:
<span class="hljs-comment">// Access iframe content</span>
<span class="hljs-keyword">const</span> frame = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">frames</span>().<span class="hljs-title function_">find</span>(<span class="hljs-function"><span class="hljs-params">f</span> =></span> f.<span class="hljs-title function_">name</span>() === <span class="hljs-string">'content-frame'</span>);
<span class="hljs-keyword">const</span> button = <span class="hljs-keyword">await</span> frame.$(<span class="hljs-string">'button[data-hook="create"]'</span>);
<span class="hljs-comment">// Handle Shadow DOM elements</span>
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluateHandle</span>(<span class="hljs-function"><span class="hljs-params">selector</span> =></span> {
<span class="hljs-keyword">const</span> element = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'parent-element'</span>)
.<span class="hljs-property">shadowRoot</span>
.<span class="hljs-title function_">querySelector</span>(selector);
<span class="hljs-keyword">return</span> element;
}, <span class="hljs-string">'target-selector'</span>);
El manejo adecuado de los selectores garantiza que sus scripts localicen los elementos de manera confiable.
Problemas de sincronización
Una vez que los selectores son estables, la gestión del tiempo es crucial para una ejecución fluida:
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">setDefaultNavigationTimeout</span>(<span class="hljs-number">30000</span>);
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">setDefaultTimeout</span>(<span class="hljs-number">10000</span>);
<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">waitForContent</span>(<span class="hljs-params">page</span>) {
<span class="hljs-keyword">await</span> <span class="hljs-title class_">Promise</span>.<span class="hljs-title function_">all</span>([
page.<span class="hljs-title function_">waitForNavigation</span>({ <span class="hljs-attr">waitUntil</span>: <span class="hljs-string">'networkidle0'</span> }),
page.<span class="hljs-title function_">click</span>(<span class="hljs-string">'#load-more-button'</span>)
]);
}
A continuación se muestra una referencia rápida para los controles de tiempo:
| Problema de tiempo | Solución: | Implementación |
|---|---|---|
| Carga de página | esperarNavegación | Espere a que la red esté inactiva |
| Contenido dinámico | esperarAlSelector | Úselo con el tiempo de espera apropiado |
| Actualizaciones de AJAX | esperarRespuesta | Monitorear solicitudes de red específicas |
Estas estrategias ayudan a alinear el tiempo de su guión con el comportamiento de la página.
Correcciones de fallos del navegador
Incluso con estrategias de selección y sincronización sólidas, el navegador puede fallar. Aquí te explicamos cómo minimizarlas y recuperarte:
<span class="hljs-keyword">const</span> browser = <span class="hljs-keyword">await</span> puppeteer.<span class="hljs-title function_">launch</span>({
<span class="hljs-attr">args</span>: [
<span class="hljs-string">'--disable-dev-shm-usage'</span>,
<span class="hljs-string">'--enable-gpu'</span>,
<span class="hljs-string">'--no-first-run'</span>,
<span class="hljs-string">'--disable-extensions'</span>
]
});
Para la recuperación ante fallos:
<span class="hljs-keyword">let</span> browser;
<span class="hljs-keyword">try</span> {
browser = <span class="hljs-keyword">await</span> puppeteer.<span class="hljs-title function_">launch</span>();
<span class="hljs-keyword">const</span> page = <span class="hljs-keyword">await</span> browser.<span class="hljs-title function_">newPage</span>();
page.<span class="hljs-title function_">on</span>(<span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">err</span> =></span> {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">'Page crashed:'</span>, err);
});
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">goto</span>(<span class="hljs-string">'https://example.com'</span>);
} <span class="hljs-keyword">catch</span> (error) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">'Browser error:'</span>, error);
} <span class="hljs-keyword">finally</span> {
<span class="hljs-keyword">if</span> (browser) {
<span class="hljs-keyword">await</span> browser.<span class="hljs-title function_">close</span>();
}
}
Si está trabajando en Linux, verifique si faltan dependencias:
ldd chrome | grep not
Para optimizar el uso de recursos, ajuste las banderas del navegador:
<span class="hljs-keyword">const</span> browser = <span class="hljs-keyword">await</span> puppeteer.<span class="hljs-title function_">launch</span>({
<span class="hljs-attr">args</span>: [
<span class="hljs-string">'--disable-dev-shm-usage'</span>,
<span class="hljs-string">'--disable-accelerated-2d-canvas'</span>,
<span class="hljs-string">'--disable-gpu'</span>
]
});
Configure la recuperación automática para una mayor resiliencia:
<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">checkAndRecoverPage</span>(<span class="hljs-params">page</span>) {
<span class="hljs-keyword">if</span> (!page.<span class="hljs-title function_">isClosed</span>()) {
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">reload</span>();
} <span class="hljs-keyword">catch</span> {
page = <span class="hljs-keyword">await</span> browser.<span class="hljs-title function_">newPage</span>();
}
}
<span class="hljs-keyword">return</span> page;
}
Optimización de depuración de scripts
Mejore sus scripts para facilitar el mantenimiento y lograr una resolución de errores más rápida aprovechando técnicas de depuración probadas.
Claridad de código
Mantenga su código legible agrupando configuraciones y utilizando nombres claros y descriptivos:
<span class="hljs-comment">// Group related configurations</span>
<span class="hljs-keyword">const</span> browserConfig = {
<span class="hljs-attr">headless</span>: <span class="hljs-literal">false</span>,
<span class="hljs-attr">defaultViewport</span>: { <span class="hljs-attr">width</span>: <span class="hljs-number">1920</span>, <span class="hljs-attr">height</span>: <span class="hljs-number">1080</span> },
<span class="hljs-attr">args</span>: [<span class="hljs-string">'--no-sandbox'</span>, <span class="hljs-string">'--disable-setuid-sandbox'</span>]
};
<span class="hljs-comment">// Use descriptive function names</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">validatePageContent</span>(<span class="hljs-params">page</span>) {
<span class="hljs-keyword">const</span> pageTitle = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">title</span>();
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`Validating content for page: <span class="hljs-subst">${pageTitle}</span>`</span>);
<span class="hljs-keyword">const</span> contentExists = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">() =></span> {
<span class="hljs-keyword">const</span> mainContent = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.main-content'</span>);
<span class="hljs-keyword">return</span> {
<span class="hljs-attr">hasHeader</span>: !!<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'header'</span>),
<span class="hljs-attr">hasContent</span>: !!mainContent,
<span class="hljs-attr">contentLength</span>: mainContent?.<span class="hljs-property">textContent</span>.<span class="hljs-property">length</span> || <span class="hljs-number">0</span>
};
});
<span class="hljs-keyword">return</span> contentExists;
}
Organización del módulo
Divida sus scripts en módulos separados para simplificar la depuración. Este enfoque aísla selectores, acciones y validaciones, lo que facilita la localización y corrección de errores.
<span class="hljs-comment">// selectors.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> <span class="hljs-variable constant_">SELECTORS</span> = {
<span class="hljs-attr">loginForm</span>: <span class="hljs-string">'#login-form'</span>,
<span class="hljs-attr">submitButton</span>: <span class="hljs-string">'[data-testid="submit-btn"]'</span>,
<span class="hljs-attr">errorMessage</span>: <span class="hljs-string">'.error-notification'</span>
};
<span class="hljs-comment">// actions.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">performLogin</span>(<span class="hljs-params">page, credentials</span>) {
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">type</span>(<span class="hljs-variable constant_">SELECTORS</span>.<span class="hljs-property">loginForm</span> + <span class="hljs-string">' input[name="username"]'</span>, credentials.<span class="hljs-property">username</span>);
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">type</span>(<span class="hljs-variable constant_">SELECTORS</span>.<span class="hljs-property">loginForm</span> + <span class="hljs-string">' input[name="password"]'</span>, credentials.<span class="hljs-property">password</span>);
<span class="hljs-keyword">await</span> <span class="hljs-title class_">Promise</span>.<span class="hljs-title function_">all</span>([
page.<span class="hljs-title function_">waitForNavigation</span>(),
page.<span class="hljs-title function_">click</span>(<span class="hljs-variable constant_">SELECTORS</span>.<span class="hljs-property">submitButton</span>)
]);
}
<span class="hljs-comment">// validators.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">checkLoginStatus</span>(<span class="hljs-params">page</span>) {
<span class="hljs-keyword">const</span> errorElement = <span class="hljs-keyword">await</span> page.$(<span class="hljs-variable constant_">SELECTORS</span>.<span class="hljs-property">errorMessage</span>);
<span class="hljs-keyword">if</span> (errorElement) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">'Login failed: '</span> + <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function"><span class="hljs-params">el</span> =></span> el.<span class="hljs-property">textContent</span>, errorElement));
}
}
Esta estructura modular no solo organiza su código sino que también ayuda a optimizar el seguimiento de errores.
Configuración de seguimiento de errores
Configure el seguimiento de errores para identificar problemas rápidamente y proporcionar un contexto detallado para la depuración:
<span class="hljs-keyword">class</span> <span class="hljs-title class_">PuppeteerError</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">Error</span> {
<span class="hljs-title function_">constructor</span>(<span class="hljs-params">message, action, selector</span>) {
<span class="hljs-variable language_">super</span>(message);
<span class="hljs-variable language_">this</span>.<span class="hljs-property">name</span> = <span class="hljs-string">'PuppeteerError'</span>;
<span class="hljs-variable language_">this</span>.<span class="hljs-property">action</span> = action;
<span class="hljs-variable language_">this</span>.<span class="hljs-property">selector</span> = selector;
<span class="hljs-variable language_">this</span>.<span class="hljs-property">timestamp</span> = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>().<span class="hljs-title function_">toISOString</span>();
}
}
<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">executeWithTracking</span>(<span class="hljs-params">page, action, description</span>) {
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">await</span> <span class="hljs-title function_">action</span>();
} <span class="hljs-keyword">catch</span> (error) {
<span class="hljs-keyword">const</span> screenshot = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">screenshot</span>({
<span class="hljs-attr">path</span>: <span class="hljs-string">`error-<span class="hljs-subst">${<span class="hljs-built_in">Date</span>.now()}</span>.png`</span>,
<span class="hljs-attr">fullPage</span>: <span class="hljs-literal">true</span>
});
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">PuppeteerError</span>(
<span class="hljs-string">`Failed to <span class="hljs-subst">${description}</span>`</span>,
error.<span class="hljs-property">message</span>,
error.<span class="hljs-property">selector</span>
);
}
}
También puede automatizar el registro de errores y advertencias de la consola:
page.<span class="hljs-title function_">on</span>(<span class="hljs-string">'console'</span>, <span class="hljs-function"><span class="hljs-params">message</span> =></span> {
<span class="hljs-keyword">const</span> type = message.<span class="hljs-title function_">type</span>();
<span class="hljs-keyword">const</span> text = message.<span class="hljs-title function_">text</span>();
<span class="hljs-keyword">if</span> (type === <span class="hljs-string">'error'</span> || type === <span class="hljs-string">'warning'</span>) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`[<span class="hljs-subst">${type.toUpperCase()}</span>] <span class="hljs-subst">${text}</span>`</span>);
<span class="hljs-comment">// Log to external service or file</span>
logger.<span class="hljs-title function_">log</span>({
<span class="hljs-attr">level</span>: type,
<span class="hljs-attr">message</span>: text,
<span class="hljs-attr">timestamp</span>: <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>().<span class="hljs-title function_">toISOString</span>(),
<span class="hljs-attr">url</span>: page.<span class="hljs-title function_">url</span>()
});
}
});
Validación para operaciones críticas
Agregue comprobaciones de validación para garantizar que las operaciones críticas se completen correctamente:
<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">validateOperation</span>(<span class="hljs-params">page, action</span>) {
<span class="hljs-keyword">const</span> beforeState = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">() =></span> ({
<span class="hljs-attr">url</span>: <span class="hljs-variable language_">window</span>.<span class="hljs-property">location</span>.<span class="hljs-property">href</span>,
<span class="hljs-attr">elements</span>: <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelectorAll</span>(<span class="hljs-string">'*'</span>).<span class="hljs-property">length</span>
}));
<span class="hljs-keyword">await</span> <span class="hljs-title function_">action</span>();
<span class="hljs-keyword">const</span> afterState = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">() =></span> ({
<span class="hljs-attr">url</span>: <span class="hljs-variable language_">window</span>.<span class="hljs-property">location</span>.<span class="hljs-property">href</span>,
<span class="hljs-attr">elements</span>: <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelectorAll</span>(<span class="hljs-string">'*'</span>).<span class="hljs-property">length</span>
}));
<span class="hljs-keyword">return</span> {
<span class="hljs-attr">urlChanged</span>: beforeState.<span class="hljs-property">url</span> !== afterState.<span class="hljs-property">url</span>,
<span class="hljs-attr">elementsDelta</span>: afterState.<span class="hljs-property">elements</span> - beforeState.<span class="hljs-property">elements</span>
};
}
Estas técnicas, combinadas con métodos de depuración anteriores, le ayudan a identificar y resolver problemas rápidamente y, al mismo tiempo, a mantener sus scripts en condiciones de mantenimiento.
Conclusión
Técnicas clave de depuración
Usando la depuración visual en modo headful con slowMo Permite obtener retroalimentación inmediata sobre los scripts y ajustes precisos de la sincronización. Para escenarios más detallados, el protocolo DevTools proporciona depuración paso a paso y acceso a los registros de procesos para obtener información más detallada.
<span class="hljs-keyword">const</span> browser = <span class="hljs-keyword">await</span> puppeteer.<span class="hljs-title function_">launch</span>({
<span class="hljs-attr">headless</span>: <span class="hljs-literal">false</span>,
<span class="hljs-attr">slowMo</span>: <span class="hljs-number">100</span>,
<span class="hljs-attr">devtools</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">dumpio</span>: <span class="hljs-literal">true</span>
});
Para mejorar su flujo de trabajo, considere incorporar prácticas de monitoreo continuo y gestión de recursos junto con estos métodos de depuración.
Próximos Pasos
Ahora que tienes una base sólida en técnicas de depuración, aquí te mostramos cómo puedes optimizar y mantener tus scripts de Puppeteer:
- Supervisión del rendimientoUtilice registros detallados para controlar los tiempos de ejecución y el uso de recursos. Esto ayuda a identificar cuellos de botella y a optimizar la depuración.
- Prevención de errores: Añade el
puppeteer-extra-plugin-stealthComplemento para minimizar la detección de automatización y reducir fallas de script. - Gestión de Recursos:Concéntrese en el uso eficiente de la memoria e implemente rutinas de limpieza para mantener sus scripts funcionando sin problemas.
A continuación se muestra un ejemplo de una función de limpieza para administrar recursos de manera eficaz:
<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">cleanupResources</span>(<span class="hljs-params">page</span>) {
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">() =></span> {
<span class="hljs-keyword">if</span> (<span class="hljs-variable language_">window</span>.<span class="hljs-property">performance</span>.<span class="hljs-property">memory</span>) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`Heap size limit: <span class="hljs-subst">${(<span class="hljs-variable language_">window</span>.performance.memory.jsHeapSizeLimit / <span class="hljs-number">1024</span> / <span class="hljs-number">1024</span>).toFixed(<span class="hljs-number">2</span>)}</span> MB`</span>);
}
});
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">close</span>();
}
Manténgase a la vanguardia consultando regularmente el repositorio de Puppeteer en GitHub para obtener actualizaciones, nuevas funciones y mejores prácticas. Mantener su conjunto de herramientas actualizado garantiza que sus scripts se mantengan eficientes y adaptables a medida que las tecnologías web cambian.
Artículos relacionados con
- Instalación y configuración de Puppeteer: Solución de problemas comunes de dependencias y Chromium
- Optimización de estrategias de espera en Puppeteer: Guía completa de métodos de espera
- Automatización del navegador con Puppeteer y JavaScript: Implementación práctica en Node.js
- Configuración del modo sin cabeza en Puppeteer: equilibrio entre velocidad y funcionalidad



