Depurando scripts do Puppeteer: do modo slowMo às técnicas avançadas
Domine as técnicas essenciais de depuração para scripts do Puppeteer, desde métodos visuais até tratamento avançado de erros, para aumentar a confiabilidade dos scripts.

depuração Marionetista scripts podem parecer esmagadores, mas dominar algumas técnicas-chave pode economizar tempo e frustração. Aqui está um rápido resumo do que você aprenderá:
- Comece com a depuração visual: Usar
slowMomodo de navegação e modo de navegação headful para observar seu script em ação. - Erros de captura: Adicionar
try-catchblocos e automatizar capturas de tela de erros para melhor solução de problemas. - Aproveite os logs do console: Rastreie erros de página, solicitações com falha e mensagens personalizadas para obter insights mais profundos.
- Seletores de alça e temporização: Use estratégias de seleção robustas e gerencie tempos limite para evitar armadilhas comuns.
- Organize seu código: Divida os scripts em módulos para ações, seletores e validações para simplificar a manutenção.
Exemplo de configuração 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>
});
Dicas de depuração:
- Habilitar registro: Corra com
DEBUG="puppeteer:*"para registros detalhados. - Usar capturas de tela: Capture os estados das páginas para ver o que deu errado.
- Gerenciar recursos: Sempre limpe o navegador e as instâncias da página para evitar travamentos.
Ao combinar essas técnicas, você otimizará seu processo de depuração e aumentará a confiabilidade dos seus scripts do Puppeteer.
Configuração do ambiente de depuração
Configurações básicas de depuração
Configure o Puppeteer para depuração com estas opções de inicialização:
<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 o registro detalhado, execute seu script com o seguinte comando:
DEBUG=<span class="hljs-string">"puppeteer:*"</span> node script.js
Depois de configurado, use ferramentas de depuração para analisar e refinar o comportamento do seu script.
Ferramentas de depuração necessárias
Aqui estão algumas ferramentas para ajudar você a resolver problemas de forma eficaz:
| ferramenta | Propósito | Característica chave |
|---|---|---|
| chromedevtools | Inspecionar scripts | Ferramentas de console e rede |
| Depurador do VS Code | Gerenciar pontos de interrupção | Execução passo a passo |
| Utilitário de captura de tela | Solução de problemas visuais | Capturar estados da página |
Você também pode adicionar pontos de verificação no seu código para melhor visibilidade:
<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> });
Organização do Script
Uma boa organização é tão importante quanto as ferramentas que você usa. Divida seu script em módulos lógicos e inclua tratamento de erros para uma depuração mais suave:
<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 reduzir a chance de detecção de bots, integre o plugin stealth:
<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 fim, garanta o gerenciamento adequado dos recursos implementando procedimentos de limpeza:
<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 configuração fornece uma base sólida para depuração visual e de console em seus projetos.
Marionetista - 3 abordagens a considerar na depuração
Métodos de depuração visual
Observar seus scripts em ação pode revelar problemas que a análise de código tradicional pode deixar passar. Esses métodos expandem suas opções de depuração além dos logs de console e rastreamento de erros.
Guia do modo SlowMo
O SlowMo introduz um atraso entre as ações do Puppeteer, facilitando o acompanhamento do que está acontecendo:
<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>
});
O slowMo valor (em milissegundos) controla o atraso entre ações. Ajuste-o com base no que você está testando:
| Tipo de operação | SlowMo recomendado (ms) | Caso de uso |
|---|---|---|
| Cliques simples | 100-250 | Passos básicos de navegação |
| Preenchimento de formularios | 250-500 | Testando validação de entrada |
| Conteúdo dinâmico | 500-1000 | Verificando estados de carregamento |
Depois de configurar o SlowMo, emparelhe-o com o Modo de visualização do navegador para monitorar como a interface do usuário se comporta durante a execução do script.
Modo de visualização do navegador
O Modo de Exibição do Navegador permite que você veja seu script sendo executado em uma janela visível do navegador, o que é especialmente útil para depurar conteúdo dinâmico e interações complexas.
<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 exemplo, a Acme Corp.A equipe de QA da usou esse modo em junho de 2024 para solucionar problemas de um script de web scraping. Eles identificaram seletores incorretos e os corrigiram, reduzindo o tempo de depuração em 40%.
Para complementar isso, capture capturas de tela de estados visuais importantes para análise posterior.
Gravação Visual
Capturas de tela e vídeos podem criar um registro claro da execução do seu script, facilitando a depuração:
<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>
});
Comece habilitando o Modo de Visualização do Navegador, use o SlowMo para rastreamento detalhado e documente os principais momentos com capturas de tela. Juntos, esses passos criam um processo de depuração visual completo.
Métodos de depuração do console
Os métodos de console fornecem uma maneira direta de obter insights baseados em texto sobre como seus scripts estão se comportando. Essas saídas funcionam junto com a depuração visual para fornecer detalhes precisos sobre a execução do script.
Rastreamento de mensagens do console
O Puppeteer facilita a captura de mensagens do navegador com manipuladores de eventos como estes:
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 configuração cria um sistema de registro que rastreia mensagens de console, erros de página e solicitações com falha. Para deixar as coisas mais claras, você pode categorizar mensagens por tipo:
| Tipo de mensagem | Propósito | Exemplo de saída |
|---|---|---|
| Folhas para | Informações gerais | Fluxo de execução padrão |
| erro | Problemas maiores | Operações com falha |
| Aviso | Preocupações potenciais | Lentidão no desempenho |
| Info | Atualizações de status | Conclusão da tarefa |
Melhores práticas do Console.log
Utilizar painéis de piso ResinDek em sua unidade de self-storage em vez de concreto oferece diversos benefícios: console.log sabiamente pode tornar a depuração muito mais fácil. Coloque logs estrategicamente para rastrear o progresso 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 estendidos
Para problemas mais complexos, técnicas avançadas de registro podem mudar o jogo:
<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>);
Uma equipe viu uma queda de 40% nas falhas de teste após adotar o registro detalhado de protocolos.
<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>
Esses métodos adicionam uma camada baseada em texto ao seu processo de depuração, ajudando você a detectar e resolver problemas de forma mais eficaz.
sbb-itb-23997f1
Métodos de depuração avançados
A depuração de scripts complexos do Puppeteer envolve o uso de estratégias eficazes de tratamento de erros e técnicas avançadas para garantir que os scripts sejam executados sem problemas.
Try-Catch para tratamento de erros
Uso blocos try-catch para gerenciar erros de forma eficaz e manter seu script em execução:
<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>
}
}
}
Você pode melhorar o tratamento de erros combinando blocos try-catch com classes de erro personalizadas para melhor categorização e resposta.
Classes de erro personalizadas
A criação de classes de erro personalizadas ajuda você a identificar e classificar problemas de forma mais 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>;
}
}
Essas classes permitem que você rastreie e depure operações assíncronas com mais clareza.
Depuração de código assíncrono
Código assíncrono frequentemente introduz problemas de tempo e promessas não resolvidas. Enfrente esses problemas com as seguintes 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>
});
}
}
Ao utilizar a blockchain da debugInfo interface, você pode monitorar retornos de chamada pendentes e identificar promessas não resolvidas durante a comunicação do protocolo do navegador.
| Nível de depuração | Propósito | Implementação |
|---|---|---|
| Basico | Lidar com erros comuns | Blocos try-catch padrão |
| Nível intermediário | Classificar erros | Hierarquia de classes de erro personalizada |
| Avançado | Problemas de protocolo de rastreamento | Monitoramento de interface de depuração |
Soluções para problemas comuns
Esta seção aborda os desafios frequentes do Puppeteer e fornece correções claras para manter seus scripts de automação funcionando sem problemas.
Problemas com o seletor
Problemas de seletor podem frequentemente interromper a execução do script. Veja como lidar com eles efetivamente:
<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 ou Sombra DOM, use estas abordagens:
<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>);
O manuseio adequado dos seletores garante que seus scripts localizem elementos de forma confiável.
Problemas de tempo
Uma vez que os seletores estejam estáveis, gerenciar o tempo é crucial para uma execução tranquila:
<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>)
]);
}
Aqui está uma referência rápida para controles de tempo:
| Problema de tempo | Solução | Implementação |
|---|---|---|
| Carregamento de página | esperarPorNavegação | Aguarde a rede ociosa |
| Conteúdo Dinâmico | esperarPorSeletor | Use com tempo limite apropriado |
| Atualizações AJAX | esperarPorResposta | Monitorar solicitações de rede específicas |
Essas estratégias ajudam a alinhar o tempo do seu script com o comportamento da página.
Correções de travamento do navegador
Mesmo com estratégias sólidas de seletor e tempo, travamentos do navegador ainda podem ocorrer. Veja como minimizar e se recuperar deles:
<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 recuperação de falhas:
<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>();
}
}
Se você estiver trabalhando no Linux, verifique se há dependências ausentes:
ldd chrome | grep not
Para otimizar o uso de recursos, ajuste os sinalizadores do 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 a recuperação automática para maior resiliência:
<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;
}
Otimização de Depuração de Script
Aprimore seus scripts para facilitar a manutenção e agilizar a resolução de erros com base em técnicas comprovadas de depuração.
Clareza de código
Mantenha seu código legível agrupando configurações e usando nomes claros e descritivos:
<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;
}
Organização do módulo
Divida seus scripts em módulos separados para simplificar a depuração. Essa abordagem isola seletores, ações e validações, facilitando a localização e a correção de erros.
<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));
}
}
Essa estrutura modular não apenas organiza seu código, mas também ajuda a otimizar o rastreamento de erros.
Configuração de rastreamento de erros
Configure o rastreamento de erros para identificar problemas rapidamente e fornecer contexto detalhado para depuração:
<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>
);
}
}
Você também pode automatizar o registro de erros e avisos do console:
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>()
});
}
});
Validação para Operações Críticas
Adicione verificações de validação para garantir que operações críticas sejam concluídas com sucesso:
<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>
};
}
Essas técnicas, combinadas com métodos de depuração anteriores, ajudam você a identificar e resolver problemas rapidamente, mantendo seus scripts sustentáveis.
Conclusão
Principais técnicas de depuração
Usando depuração visual no modo headful com slowMo permite feedback imediato sobre scripts e ajustes precisos de tempo. Para cenários mais detalhados, o protocolo DevTools fornece depuração passo a passo e acesso a logs de processo para insights mais profundos.
<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 melhorar seu fluxo de trabalho, considere incorporar práticas de monitoramento contínuo e gerenciamento de recursos junto com esses métodos de depuração.
Próximos Passos
Agora que você tem uma base sólida em técnicas de depuração, veja como você pode otimizar e manter seus scripts do Puppeteer:
- Monitoramento de desempenho: Use o registro detalhado para rastrear tempos de execução e uso de recursos. Isso ajuda a identificar gargalos e torna a depuração mais eficiente.
- Prevenção de erros: Adicione o
puppeteer-extra-plugin-stealthplugin para minimizar a detecção de automação e reduzir falhas de script. - Gestão de Recursos: Concentre-se no uso eficiente da memória e implemente rotinas de limpeza para manter seus scripts funcionando sem problemas.
Aqui está um exemplo de uma função de limpeza para gerenciar recursos de forma 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>();
}
Fique à frente verificando regularmente o repositório Puppeteer GitHub para atualizações, novos recursos e melhores práticas. Manter seu kit de ferramentas atualizado garante que seus scripts permaneçam eficientes e adaptáveis conforme as tecnologias da web mudam.
Artigos Relacionados
- Instalando e configurando o Puppeteer: resolvendo problemas comuns de dependência e Chromium
- Otimizando estratégias de espera no Puppeteer: um guia completo para métodos de espera
- Automação de navegador com Puppeteer e JavaScript: implementação prática em Node.js
- Configurando o Modo Headless no Puppeteer: Equilibrando Velocidade e Funcionalidade



