Executando JavaScript no contexto da página com page.evaluate no Puppeteer
Aprenda como usar o método `page.evaluate` do Puppeteer de forma eficaz para executar JavaScript no contexto do navegador em tarefas de automação web.

page.evaluate() é uma chave Marionetista método que permite executar JavaScript diretamente no contexto do navegador. Ele faz a ponte Node.js e o navegador, permitindo tarefas como manipulação de DOM, extração de dados e automação de páginas web dinâmicas. Aqui está o que você precisa saber:
- O que faz: Executa JavaScript no navegador, como se você estivesse usando o console do navegador.
- Como Funciona : Converte uma função em uma string, envia-a ao navegador, executa-a e retorna o resultado.
- Principais usos:
- Extração de dados de sites (por exemplo, texto, tabelas, JSON).
- Automatizando envios de formulários e interações do usuário.
- Manipulando conteúdo dinâmico, como rolagem infinita ou atualizações AJAX.
- Limitações: As funções devem ser serializáveis em JSON, e as variáveis do Node.js não são diretamente acessíveis no contexto do navegador.
Exemplo rápido:
<span class="hljs-keyword">const</span> title = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">() =></span> <span class="hljs-variable language_">document</span>.<span class="hljs-property">title</span>);
Isso recupera o título da página diretamente do navegador.
Comparação: Node.js vs. Contexto do navegador
| Característica | Contexto Node.js | Contexto do navegador |
|---|---|---|
| Objetos Globais | processo, requer | janela, documento |
| Localização do script | Máquina local | Página da web de destino |
| Acesso API | APIs do Node.js | APIs da Web do navegador |
Uso page.evaluate() para tarefas de automação precisas e eficientes, especialmente ao trabalhar com sites com uso intenso de JavaScript.
NodeJS : Nodejs/Marionetista - Como usar page.evaluate
Contexto da página explicado
Ao trabalhar com o Puppeteer para automação web, é crucial entender a distinção entre Contexto Node.js e a contexto do navegador. Esses dois ambientes são isolados, cada um com suas próprias regras para executar código e trocar dados.
Comparando Node.js e contextos de navegador
O marionetista opera em dois ambientes: o Contexto Node.js, onde seu script principal é executado e o contexto do navegador, onde ocorrem as interações com a página web. São processos separados, cada um com sua própria máquina virtual .
Aqui está uma rápida comparação de suas principais características:
| Característica | Contexto Node.js | Contexto do navegador |
|---|---|---|
| Objetos Globais | processo, requer, __dirname | janela, documento, armazenamento local |
| Localização do script | Máquina local | Página da web de destino |
| Escopo Variável | Escopo do script do marionetista | Âmbito do contexto da página |
| Acesso API | APIs do Node.js | APIs da Web do navegador |
| Espaço de Memória | Processo separado | Processo do navegador |
Como funciona a comunicação de contexto
A troca de dados entre esses contextos envolve uma série de etapas, dependendo fortemente da serialização:
- A função é convertida em uma string usando
Function.prototype.toString(). - Esta sequência é enviada ao navegador por meio do Protocolo Chrome DevTools .
- O navegador avalia a função dentro de seu ambiente.
- Os resultados são serializados em JSON e enviados de volta ao contexto do Node.js .
Principais limitações: Funções no contexto do navegador não podem acessar variáveis diretamente do escopo do Node.js. O Puppeteer oferece ferramentas específicas para lidar com esses desafios:
page.evaluateHandle(): Retorna referências a objetos no contexto do navegador .page.exposeFunction(): Permite que o navegador chame funções do Node.js .evaluateOnNewDocument(): Executa o código antes de qualquer script de página ser carregado .
No entanto, a serialização JSON pode remover certas propriedades, especialmente com objetos complexos como nós DOM Para evitar problemas, passe dados como argumentos de função em vez de depender de variáveis do Node.js .
Dominar essas técnicas de comunicação garante que você possa usar page.evaluate efetivamente para tarefas de automação. Em seguida, vamos mergulhar em exemplos práticos para ver esses conceitos em ação.
Introdução ao page.evaluate
Estrutura e parâmetros do método
Sintaxe:
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(pageFunction, ...args)
| Parâmetro | Formato | Descrição |
|---|---|---|
| pageFunção | Função ou string | Código JavaScript para executar no contexto do navegador |
| args | Parâmetros opcionais | Valores passados do Node.js para o contexto do navegador |
| Valor de retorno | Promessa | Resolve com o valor de retorno da função |
A construção do XNUMXº e XNUMXº pavimentos pôde ocorrer de forma simultânea, pois não houve necessidade de aguardar a cura do concreto – permitindo que todas as frentes de trabalho e especialistas em pisos ESD atuassem nos dois níveis ao mesmo tempo. pageFunção pode ser uma função ou uma string contendo código JavaScript. Usar uma função geralmente é melhor para depuração e TypeScript compatibilidade. Abaixo estão alguns exemplos para demonstrar como funciona.
Exemplos de código básico
Exemplos:
- Extrair texto do primeiro
<h1>diretamente do DOM:
<span class="hljs-keyword">const</span> headingText = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'h1'</span>).<span class="hljs-property">textContent</span>;
});
- Automatize o envio de formulários passando parâmetros:
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">(<span class="hljs-params">username, password</span>) =></span> {
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'username'</span>).<span class="hljs-property">value</span> = username;
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'password'</span>).<span class="hljs-property">value</span> = password;
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'#login-form'</span>).<span class="hljs-title function_">submit</span>();
}, <span class="hljs-string">'myUsername'</span>, <span class="hljs-string">'myPassword'</span>);
- Manipule o DOM adicionando um novo elemento:
<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> div = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">createElement</span>(<span class="hljs-string">'div'</span>);
div.<span class="hljs-property">textContent</span> = <span class="hljs-string">'Added by Puppeteer'</span>;
<span class="hljs-variable language_">document</span>.<span class="hljs-property">body</span>.<span class="hljs-title function_">appendChild</span>(div);
<span class="hljs-keyword">return</span> div.<span class="hljs-property">textContent</span>;
});
Notas-chave para o desenvolvimento
- As funções são executadas isoladamente do seu código Node.js.
- Os argumentos passados para a função devem ser JSON-serializável.
- Os valores retornados são automaticamente encapsulados em um Promessa.
- Manipular objetos complexos como nós DOM requer cuidado extra.
Dica de depuração: Use a seguinte configuração para habilitar a depuração durante o desenvolvimento:
<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-comment">// Adds a 100ms delay to each operation</span>
});
Em seguida, veremos técnicas para troca de dados entre o Node.js e contextos de navegador.
Troca de dados entre contextos
Parâmetros de entrada
Ao transferir dados com page.evaluate, use valores serializáveis em JSON para argumentos de entrada.
Aqui está uma rápida análise dos tipos de parâmetros suportados:
| Tipo de Parâmetro | Suportado? | Exemplo |
|---|---|---|
| Primitivos | ✓ Totalmente | 'texto', 42, verdadeiro |
| Matrizes/Objetos | ✓ Compatível com JSON | { chave: 'valor' }, [1, 2, 3] |
| Funções | ✗ Não diretamente | Use page.exposeFunction |
| Elementos DOM | ✓ Através do JSHandle | Use page.evaluateHandle |
Agora, vamos ver como esses valores são retornados do contexto do navegador.
Manipulação de saída
Ao usar page.evaluate, os valores retornados são serializados automaticamente para JSON. Veja como funciona:
<span class="hljs-comment">// Returning a simple value</span>
<span class="hljs-keyword">const</span> pageTitle = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">() =></span> <span class="hljs-variable language_">document</span>.<span class="hljs-property">title</span>);
<span class="hljs-comment">// Returning a complex object</span>
<span class="hljs-keyword">const</span> metrics = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">() =></span> ({
<span class="hljs-attr">viewport</span>: <span class="hljs-variable language_">window</span>.<span class="hljs-property">innerWidth</span>,
<span class="hljs-attr">scrollHeight</span>: <span class="hljs-variable language_">document</span>.<span class="hljs-property">body</span>.<span class="hljs-property">scrollHeight</span>,
<span class="hljs-attr">timestamp</span>: <span class="hljs-title class_">Date</span>.<span class="hljs-title function_">now</span>()
}));
"Como regra geral, se o valor de retorno da função fornecida for mais complicado do que um objeto JSON (por exemplo, a maioria das classes), então
evaluateprovavelmente retornará algum valor truncado (ou{}). Isso ocorre porque não estamos retornando o valor de retorno real, mas uma versão desserializada como resultado da transferência do valor de retorno por meio de um protocolo para o Puppeteer."
Após recuperar a saída, você pode encontrar desafios relacionados à serialização. Veja como lidar com eles.
Lidando com problemas de serialização
Alguns cenários comuns exigem soluções alternativas específicas:
- Trabalhando com elementos DOM
<span class="hljs-keyword">const</span> bodyHandle = <span class="hljs-keyword">await</span> page.$(<span class="hljs-string">'body'</span>);
<span class="hljs-keyword">const</span> html = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function"><span class="hljs-params">body</span> =></span> body.<span class="hljs-property">innerHTML</span>, bodyHandle);
<span class="hljs-keyword">await</span> bodyHandle.<span class="hljs-title function_">dispose</span>(); <span class="hljs-comment">// Always clean up to avoid memory leaks</span>
- Usando funções do Node.js
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">exposeFunction</span>(<span class="hljs-string">'md5'</span>, <span class="hljs-function"><span class="hljs-params">text</span> =></span>
crypto.<span class="hljs-title function_">createHash</span>(<span class="hljs-string">'md5'</span>).<span class="hljs-title function_">update</span>(text).<span class="hljs-title function_">digest</span>(<span class="hljs-string">'hex'</span>)
);
<span class="hljs-keyword">const</span> hash = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-title function_">async</span> () => {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-variable language_">window</span>.<span class="hljs-title function_">md5</span>(<span class="hljs-string">'test-string'</span>);
});
- Ajustando as configurações do Transpiler
Se você estiver trabalhando com TypeScript, certifique-se de que seu transpilador esteja configurado corretamente:
<span class="hljs-comment">// tsconfig.json</span>
{
<span class="hljs-string">"compilerOptions"</span>: {
<span class="hljs-string">"target"</span>: <span class="hljs-string">"es2018"</span>
}
}
Essas estratégias ajudarão você a lidar com a troca de dados de forma eficaz em vários contextos.
sbb-itb-23997f1
Exemplos Práticos
Veja como você pode usar page.evaluate em cenários do mundo real, completos com trechos de código práticos.
Extraindo dados
Exemplo: raspagem de detalhes do produto
Este script coleta detalhes como título, preço, classificação e status de estoque de cartões de produtos em uma página da web:
<span class="hljs-keyword">const</span> productData = <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> products = <span class="hljs-title class_">Array</span>.<span class="hljs-title function_">from</span>(<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelectorAll</span>(<span class="hljs-string">'.product-card'</span>));
<span class="hljs-keyword">return</span> products.<span class="hljs-title function_">map</span>(<span class="hljs-function"><span class="hljs-params">product</span> =></span> ({
<span class="hljs-attr">title</span>: product.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.title'</span>).<span class="hljs-property">textContent</span>.<span class="hljs-title function_">trim</span>(),
<span class="hljs-attr">price</span>: product.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.price'</span>).<span class="hljs-property">textContent</span>.<span class="hljs-title function_">trim</span>(),
<span class="hljs-attr">rating</span>: <span class="hljs-built_in">parseFloat</span>(product.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.rating'</span>).<span class="hljs-property">dataset</span>.<span class="hljs-property">value</span>),
<span class="hljs-attr">inStock</span>: product.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.stock'</span>).<span class="hljs-property">textContent</span>.<span class="hljs-title function_">includes</span>(<span class="hljs-string">'Available'</span>)
}));
});
Exemplo: Extraindo dados da tabela
Essa abordagem recupera dados de uma tabela iterando por suas linhas e colunas:
<span class="hljs-keyword">const</span> tableData = <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> rows = <span class="hljs-title class_">Array</span>.<span class="hljs-title function_">from</span>(<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelectorAll</span>(<span class="hljs-string">'table tr'</span>));
<span class="hljs-keyword">return</span> rows.<span class="hljs-title function_">map</span>(<span class="hljs-function"><span class="hljs-params">row</span> =></span> {
<span class="hljs-keyword">const</span> columns = row.<span class="hljs-title function_">querySelectorAll</span>(<span class="hljs-string">'td'</span>);
<span class="hljs-keyword">return</span> <span class="hljs-title class_">Array</span>.<span class="hljs-title function_">from</span>(columns, <span class="hljs-function"><span class="hljs-params">column</span> =></span> column.<span class="hljs-property">innerText</span>);
});
});
Automatizando Formulários
Automação básica de formulários
Veja como preencher campos de formulário, acionar eventos e enviar o formulário:
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">() =></span> {
<span class="hljs-comment">// Fill form fields</span>
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'#username'</span>).<span class="hljs-property">value</span> = <span class="hljs-string">'testuser'</span>;
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'#password'</span>).<span class="hljs-property">value</span> = <span class="hljs-string">'secretpass'</span>;
<span class="hljs-comment">// Trigger input events for dynamic forms</span>
<span class="hljs-keyword">const</span> event = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Event</span>(<span class="hljs-string">'input'</span>, { <span class="hljs-attr">bubbles</span>: <span class="hljs-literal">true</span> });
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'#username'</span>).<span class="hljs-title function_">dispatchEvent</span>(event);
<span class="hljs-comment">// Submit form</span>
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'form'</span>).<span class="hljs-title function_">submit</span>();
});
Manipulando formulários complexos
Para tarefas como selecionar opções suspensas ou verificar botões de opção:
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">() =></span> {
<span class="hljs-comment">// Select dropdown option</span>
<span class="hljs-keyword">const</span> select = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'#country'</span>);
select.<span class="hljs-property">value</span> = <span class="hljs-string">'US'</span>;
select.<span class="hljs-title function_">dispatchEvent</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Event</span>(<span class="hljs-string">'change'</span>, { <span class="hljs-attr">bubbles</span>: <span class="hljs-literal">true</span> }));
<span class="hljs-comment">// Check radio button</span>
<span class="hljs-keyword">const</span> radio = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'input[value="express"]'</span>);
radio.<span class="hljs-property">checked</span> = <span class="hljs-literal">true</span>;
radio.<span class="hljs-title function_">dispatchEvent</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Event</span>(<span class="hljs-string">'change'</span>, { <span class="hljs-attr">bubbles</span>: <span class="hljs-literal">true</span> }));
});
Gerenciando Elementos Dinâmicos
Exemplo: rolagem infinita
Este script rola por uma página até coletar pelo menos 100 itens:
<span class="hljs-keyword">const</span> items = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-title function_">async</span> () => {
<span class="hljs-keyword">const</span> <span class="hljs-title function_">delay</span> = ms => <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function"><span class="hljs-params">resolve</span> =></span> <span class="hljs-built_in">setTimeout</span>(resolve, ms));
<span class="hljs-keyword">const</span> items = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Set</span>();
<span class="hljs-keyword">while</span> (items.<span class="hljs-property">size</span> < <span class="hljs-number">100</span>) {
<span class="hljs-comment">// Scroll to bottom</span>
<span class="hljs-variable language_">window</span>.<span class="hljs-title function_">scrollTo</span>(<span class="hljs-number">0</span>, <span class="hljs-variable language_">document</span>.<span class="hljs-property">body</span>.<span class="hljs-property">scrollHeight</span>);
<span class="hljs-comment">// Wait for new content</span>
<span class="hljs-keyword">await</span> <span class="hljs-title function_">delay</span>(<span class="hljs-number">1000</span>);
<span class="hljs-comment">// Collect items</span>
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelectorAll</span>(<span class="hljs-string">'.item'</span>).<span class="hljs-title function_">forEach</span>(<span class="hljs-function"><span class="hljs-params">item</span> =></span>
items.<span class="hljs-title function_">add</span>(item.<span class="hljs-property">textContent</span>.<span class="hljs-title function_">trim</span>())
);
}
<span class="hljs-keyword">return</span> <span class="hljs-title class_">Array</span>.<span class="hljs-title function_">from</span>(items);
});
Exemplo: Manipulando conteúdo AJAX
Para carregar mais conteúdo dinamicamente, este script clica no botão "Carregar mais" e aguarda que novos elementos apareçam:
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-title function_">async</span> () => {
<span class="hljs-comment">// Click load more button</span>
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'#loadMore'</span>).<span class="hljs-title function_">click</span>();
<span class="hljs-comment">// Wait for content update</span>
<span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function"><span class="hljs-params">resolve</span> =></span> {
<span class="hljs-keyword">const</span> observer = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MutationObserver</span>(<span class="hljs-function">(<span class="hljs-params">mutations, obs</span>) =></span> {
<span class="hljs-keyword">if</span> (<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelectorAll</span>(<span class="hljs-string">'.item'</span>).<span class="hljs-property">length</span> > <span class="hljs-number">10</span>) {
obs.<span class="hljs-title function_">disconnect</span>();
<span class="hljs-title function_">resolve</span>();
}
});
observer.<span class="hljs-title function_">observe</span>(<span class="hljs-variable language_">document</span>.<span class="hljs-property">body</span>, {
<span class="hljs-attr">childList</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">subtree</span>: <span class="hljs-literal">true</span>
});
});
});
Esses exemplos mostram como lidar com cenários diversos, como scraping, automação de formulários e conteúdo dinâmico. Ajustes podem ser feitos com base na estrutura e no comportamento específicos da página da web com a qual você está trabalhando.
Usando page.evaluate em Nó latente
O Latenode incorpora os principais recursos do Puppeteer em seus fluxos de trabalho de automação, facilitando a execução de JavaScript diretamente no navegador. Com page.evaluate, os usuários podem manipular o DOM e extrair dados de forma eficiente. Essa abordagem permite integração perfeita de manipulação avançada de dados e operações DOM dentro do ambiente de automação do Latenode.
Scripts de navegador em Latenode
O módulo de automação do navegador do Latenode usa page.evaluate para lidar com tudo, desde tarefas simples de DOM até execuções mais complexas de JavaScript. Veja como funciona em diferentes cenários:
<span class="hljs-comment">// Basic DOM interaction</span>
<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> loginButton = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'#login'</span>);
loginButton.<span class="hljs-title function_">click</span>();
<span class="hljs-comment">// Trigger a custom event</span>
loginButton.<span class="hljs-title function_">dispatchEvent</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Event</span>(<span class="hljs-string">'customClick'</span>));
});
<span class="hljs-comment">// Processing data with exposed functions</span>
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">exposeFunction</span>(<span class="hljs-string">'processData'</span>, <span class="hljs-title function_">async</span> (data) => {
<span class="hljs-comment">// Process data in Node.js context</span>
<span class="hljs-keyword">return</span> transformedData;
});
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-title function_">async</span> () => {
<span class="hljs-keyword">const</span> rawData = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'#data'</span>).<span class="hljs-property">textContent</span>;
<span class="hljs-keyword">const</span> processed = <span class="hljs-keyword">await</span> <span class="hljs-variable language_">window</span>.<span class="hljs-title function_">processData</span>(rawData);
<span class="hljs-keyword">return</span> processed;
});
O Latenode também mantém um registro do histórico de execução, facilitando a depuração de scripts.
Exemplos de automação
O Latenode é bem equipado para lidar com conteúdo dinâmico e tarefas complexas de automação. Aqui está um exemplo de processamento de conteúdo dinâmico em uma página:
<span class="hljs-keyword">const</span> extractProductData = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-title function_">async</span> () => {
<span class="hljs-keyword">const</span> <span class="hljs-title function_">delay</span> = ms => <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function"><span class="hljs-params">resolve</span> =></span> <span class="hljs-built_in">setTimeout</span>(resolve, ms));
<span class="hljs-comment">// Wait for dynamic content to load</span>
<span class="hljs-keyword">while</span> (!<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.product-grid'</span>)) {
<span class="hljs-keyword">await</span> <span class="hljs-title function_">delay</span>(<span class="hljs-number">100</span>);
}
<span class="hljs-keyword">return</span> <span class="hljs-title class_">Array</span>.<span class="hljs-title function_">from</span>(<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelectorAll</span>(<span class="hljs-string">'.product'</span>))
.<span class="hljs-title function_">map</span>(<span class="hljs-function"><span class="hljs-params">product</span> =></span> ({
<span class="hljs-attr">name</span>: product.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.name'</span>).<span class="hljs-property">textContent</span>,
<span class="hljs-attr">price</span>: product.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.price'</span>).<span class="hljs-property">textContent</span>,
<span class="hljs-attr">availability</span>: product.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.stock'</span>).<span class="hljs-property">dataset</span>.<span class="hljs-property">status</span>
}));
});
Para operações mais avançadas, page.exposeFunction permite interação perfeita entre o Node.js e o navegador:
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">exposeFunction</span>(<span class="hljs-string">'md5'</span>, <span class="hljs-function"><span class="hljs-params">text</span> =></span>
crypto.<span class="hljs-title function_">createHash</span>(<span class="hljs-string">'md5'</span>).<span class="hljs-title function_">update</span>(text).<span class="hljs-title function_">digest</span>(<span class="hljs-string">'hex'</span>)
);
<span class="hljs-keyword">const</span> processedData = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-title function_">async</span> () => {
<span class="hljs-keyword">const</span> sensitiveData = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'#secure-data'</span>).<span class="hljs-property">value</span>;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-variable language_">window</span>.<span class="hljs-title function_">md5</span>(sensitiveData);
});
Para manter referências aos elementos DOM em todas as etapas, o Latenode usa page.evaluateHandle:
<span class="hljs-keyword">const</span> elementHandle = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluateHandle</span>(<span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.dynamic-content'</span>);
});
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function"><span class="hljs-params">element</span> =></span> {
element.<span class="hljs-title function_">scrollIntoView</span>();
}, elementHandle);
Essas técnicas garantem que o Latenode possa lidar com conteúdo dinâmico de forma eficaz, mantendo um desempenho confiável. Para usuários no plano Prime, a plataforma suporta até 1.5 milhão de execuções de cenário por mês, fornecendo amplos recursos de automação.
Guia de resolução de erros
Ao trabalhar com page.evaluate na automação do navegador, você pode encontrar vários problemas. Aqui estão soluções práticas para lidar com eles e garantir uma execução mais suave.
Corrigindo erros de contexto
Configure corretamente suas configurações de TypeScript para evitar problemas causados pela transpilação. Por exemplo:
<span class="hljs-comment">// Use direct, non-transpiled functions</span>
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">() =></span> {
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'#button'</span>).<span class="hljs-title function_">click</span>();
});
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-string">`(async () => {
document.querySelector('#button').click();
})()`</span>);
Evite retornar elementos DOM diretamente de page.evaluate. Em vez disso, use ElementHandle para melhor manuseio:
<span class="hljs-comment">// Incorrect: Returning a DOM element</span>
<span class="hljs-keyword">const</span> element = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.dynamic-element'</span>);
});
<span class="hljs-comment">// Correct: Using ElementHandle</span>
<span class="hljs-keyword">const</span> element = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluateHandle</span>(<span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.dynamic-element'</span>);
});
Resolvendo problemas de tempo
Scripts podem ser executados antes que a página seja totalmente carregada, levando a erros de tempo. Use estas estratégias para lidar com tais casos:
<span class="hljs-comment">// Wait for navigation after an action</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-string">'#submit-button'</span>)
]);
<span class="hljs-comment">// Wait for a specific condition</span>
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">waitForFunction</span>(<span class="hljs-function">() =></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">'.lazy-loaded'</span>);
<span class="hljs-keyword">return</span> element && element.<span class="hljs-property">dataset</span>.<span class="hljs-property">loaded</span> === <span class="hljs-string">'true'</span>;
}, { <span class="hljs-attr">timeout</span>: <span class="hljs-number">5000</span> });
Para sites dinâmicos, adote mecanismos de espera mais direcionados:
<span class="hljs-comment">// Wait for specific network requests</span>
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">waitForResponse</span>(
<span class="hljs-function"><span class="hljs-params">response</span> =></span> response.<span class="hljs-title function_">url</span>().<span class="hljs-title function_">includes</span>(<span class="hljs-string">'/api/data'</span>)
);
<span class="hljs-comment">// Ensure elements are both present and visible</span>
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">waitForSelector</span>(<span class="hljs-string">'.dynamic-content'</span>, {
<span class="hljs-attr">visible</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">timeout</span>: <span class="hljs-number">3000</span>
});
Gerenciando referências DOM
Para evitar vazamentos de memória, gerencie cuidadosamente as referências DOM. Veja como:
<span class="hljs-comment">// Use and dispose ElementHandles</span>
<span class="hljs-keyword">const</span> handle = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluateHandle</span>(<span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.temporary-element'</span>);
});
<span class="hljs-keyword">await</span> handle.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function"><span class="hljs-params">element</span> =></span> {
<span class="hljs-comment">// Perform operations</span>
});
<span class="hljs-keyword">await</span> handle.<span class="hljs-title function_">dispose</span>(); <span class="hljs-comment">// Dispose of handle after use</span>
Ao trabalhar com vários elementos, passe dados com segurança entre contextos:
<span class="hljs-comment">// Extract data from the DOM</span>
<span class="hljs-keyword">const</span> selector = <span class="hljs-string">'.product-price'</span>;
<span class="hljs-keyword">const</span> price = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">(<span class="hljs-params">sel</span>) =></span> {
<span class="hljs-keyword">const</span> element = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(sel);
<span class="hljs-keyword">return</span> element ? element.<span class="hljs-property">textContent</span>.<span class="hljs-title function_">trim</span>() : <span class="hljs-literal">null</span>;
}, selector);
Para ouvintes de eventos, garanta uma limpeza adequada para evitar manipuladores persistentes:
<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> <span class="hljs-title function_">handler</span> = (<span class="hljs-params"></span>) => <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'clicked'</span>);
<span class="hljs-keyword">const</span> button = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'#button'</span>);
button.<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">'click'</span>, handler);
<span class="hljs-comment">// Store cleanup references</span>
<span class="hljs-variable language_">window</span>.<span class="hljs-property">_cleanupHandlers</span> = <span class="hljs-variable language_">window</span>.<span class="hljs-property">_cleanupHandlers</span> || [];
<span class="hljs-variable language_">window</span>.<span class="hljs-property">_cleanupHandlers</span>.<span class="hljs-title function_">push</span>(<span class="hljs-function">() =></span> {
button.<span class="hljs-title function_">removeEventListener</span>(<span class="hljs-string">'click'</span>, handler);
});
});
Diretrizes de implementação
Para obter os melhores resultados com page.evaluate, você precisa se concentrar em melhorar o desempenho, reduzir a troca desnecessária de contexto e garantir a segurança. Veja como você pode ajustar seus fluxos de trabalho de automação do navegador.
Otimização de performance
Executar código eficientemente dentro do contexto da página economiza tempo e recursos do sistema. Abaixo estão algumas técnicas para tornar seus scripts mais rápidos:
<span class="hljs-comment">// Block unnecessary resources like images and stylesheets</span>
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">setRequestInterception</span>(<span class="hljs-literal">true</span>);
page.<span class="hljs-title function_">on</span>(<span class="hljs-string">'request'</span>, <span class="hljs-function"><span class="hljs-params">request</span> =></span> {
<span class="hljs-keyword">if</span> ([<span class="hljs-string">'image'</span>, <span class="hljs-string">'stylesheet'</span>].<span class="hljs-title function_">includes</span>(request.<span class="hljs-title function_">resourceType</span>())) {
request.<span class="hljs-title function_">abort</span>();
} <span class="hljs-keyword">else</span> {
request.<span class="hljs-title function_">continue</span>();
}
});
<span class="hljs-comment">// Batch operations to reduce overhead</span>
<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> results = [];
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelectorAll</span>(<span class="hljs-string">'.product-item'</span>).<span class="hljs-title function_">forEach</span>(<span class="hljs-function"><span class="hljs-params">item</span> =></span> {
results.<span class="hljs-title function_">push</span>({
<span class="hljs-attr">title</span>: item.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.title'</span>).<span class="hljs-property">textContent</span>,
<span class="hljs-attr">price</span>: item.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.price'</span>).<span class="hljs-property">textContent</span>,
<span class="hljs-attr">stock</span>: item.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.stock'</span>).<span class="hljs-property">dataset</span>.<span class="hljs-property">value</span>
});
});
<span class="hljs-keyword">return</span> results;
});
A escolha dos seletores certos também desempenha um papel importante no desempenho:
| Tipo de seletor | Agilidade (Speed) | Exemplo |
|---|---|---|
| ID | Fastest | #conteúdo-principal |
| Aula | pomposidade | .item-do-produto |
| etiqueta | Moderado | div > span |
| XPath complexo | Mais lento | //div[@class='wrapper']//span |
Gerenciamento de troca de contexto
A troca de contexto entre o Node.js e o ambiente do navegador pode deixar as coisas lentas. Veja como minimizá-la:
<span class="hljs-comment">// Example of inefficient context switching</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> item <span class="hljs-keyword">of</span> items) {
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">(<span class="hljs-params">i</span>) =></span> {
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">`#item-<span class="hljs-subst">${i}</span>`</span>).<span class="hljs-title function_">click</span>();
}, item);
}
<span class="hljs-comment">// Better: Batch operations in a single context switch</span>
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">(<span class="hljs-params">itemsList</span>) =></span> {
itemsList.<span class="hljs-title function_">forEach</span>(<span class="hljs-function"><span class="hljs-params">i</span> =></span> {
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">`#item-<span class="hljs-subst">${i}</span>`</span>).<span class="hljs-title function_">click</span>();
});
}, items);
Se você precisar processar dados no Node.js e passá-los de volta para o navegador, exponha funções em vez de alternar contextos repetidamente:
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">exposeFunction</span>(<span class="hljs-string">'processData'</span>, <span class="hljs-title function_">async</span> (data) => {
<span class="hljs-comment">// Process data in Node.js</span>
<span class="hljs-keyword">return</span> transformedData;
});
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-title function_">async</span> () => {
<span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> <span class="hljs-variable language_">window</span>.<span class="hljs-title function_">processData</span>(documentData);
<span class="hljs-comment">// Use the processed data in the browser</span>
});
Diretrizes de segurança
Depois que o desempenho e a troca de contexto forem otimizados, concentre-se em manter seus scripts seguros. Aqui estão algumas práticas recomendadas:
<span class="hljs-comment">// Always sanitize inputs before using them</span>
<span class="hljs-keyword">const</span> sanitizedInput = <span class="hljs-title function_">sanitizeHtml</span>(userInput);
<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-function">(<span class="hljs-params">input</span>) =></span> {
<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'#search'</span>).<span class="hljs-property">value</span> = input;
}, sanitizedInput);
<span class="hljs-comment">// Use error handling for critical operations</span>
<span class="hljs-keyword">try</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">__securityCheck</span>) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">'Security check failed'</span>);
}
<span class="hljs-comment">// Continue with the operation</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">'Security violation:'</span>, error);
}
Para fluxos de trabalho do Latenode, considere estas dicas adicionais:
- Uso
userDataDirpara armazenar recursos em cache e melhorar o desempenho entre sessões. - Feche páginas e instâncias do navegador não utilizadas para economizar memória.
- Manipule capturas de tela com buffers em vez de depender de operações do sistema de arquivos.
- Implemente tratamento de erros robusto e verificações de segurança completas.
Resumo
Revisão dos pontos-chave
A construção do XNUMXº e XNUMXº pavimentos pôde ocorrer de forma simultânea, pois não houve necessidade de aguardar a cura do concreto – permitindo que todas as frentes de trabalho e especialistas em pisos ESD atuassem nos dois níveis ao mesmo tempo. page.evaluate O método conecta o Node.js e os contextos do navegador enviando uma função JavaScript stringificada para executar no navegador. Essa função opera independentemente do ambiente do Node.js, então você precisa lidar com a transferência de dados com cuidado.
Aqui está um exemplo comum para extração de dados:
<span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(<span class="hljs-title function_">async</span> () => {
<span class="hljs-keyword">const</span> results = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelectorAll</span>(<span class="hljs-string">'.data-item'</span>);
<span class="hljs-keyword">return</span> <span class="hljs-title class_">Array</span>.<span class="hljs-title function_">from</span>(results, <span class="hljs-function"><span class="hljs-params">item</span> =></span> ({
<span class="hljs-attr">id</span>: item.<span class="hljs-property">dataset</span>.<span class="hljs-property">id</span>,
<span class="hljs-attr">value</span>: item.<span class="hljs-property">textContent</span>.<span class="hljs-title function_">trim</span>()
}));
});
Coisas a ter em mente:
- Os argumentos devem ser serializáveis em JSON.
- Os valores de retorno são desserializados automaticamente.
- As APIs do navegador estão disponíveis apenas no
evaluatecontexto. - As variáveis do Node.js não são acessíveis no contexto do navegador.
Esses princípios básicos estabelecem a base para usar o Puppeteer de forma eficaz. Ferramentas adicionais podem simplificar ainda mais suas tarefas de automação.
Ferramentas adicionais para marionetistas
O Puppeteer oferece diversas ferramentas para expandir as capacidades do page.evaluate:
| ferramenta | Propósito | Melhor caso de uso |
|---|---|---|
| página.avaliarHandle | Retorna referências de objeto | Interagindo com elementos DOM diretamente |
| página.exporFunção | Torna as funções do Node.js utilizáveis no navegador | Gerenciando lógica complexa do lado do servidor |
| página.avaliarNovoDocumento | Executa scripts antes do carregamento de uma página | Preparando o ambiente do navegador com antecedência |
Por exemplo, expor funções do Node.js ao navegador pode simplificar o processamento avançado de dados em fluxos de trabalho como aqueles no Latenode. Enquanto page.evaluate funciona bem para manipular tipos primitivos e objetos serializáveis JSON, page.evaluateHandle é essencial para lidar com objetos complexos do navegador que não podem ser serializados.
Artigos Relacionados
- Operações de clique do marionetista: Manipulação de elementos complexos, cliques duplos e solução de problemas
- Automação de formulários com Puppeteer: entrada de texto, preenchimento de formulários e simulação de usuário
- Condições de espera personalizadas com waitForFunction no Puppeteer
- Automação de navegador com Puppeteer e JavaScript: implementação prática em Node.js



