Preços
PRODUTO
SOLUÇÕES
por casos de uso
AI Gestão de leadsFacturaçãoMídia socialGestão de ProjetosGestão de dadospor setor
saber mais
BlogModelosVÍDEOSYoutubeRECURSOS
COMUNIDADES E MÍDIAS SOCIAIS
PARCEIROS
Lutando com Marionetista scripts com tempo limite esgotado ou falhando? Veja como consertar.
Marionetista, um Node.js biblioteca para controle Chrome, é poderoso para automação web. Mas conteúdo dinâmico e páginas orientadas por API podem tornar o tempo complicado. Estratégias de espera adequadas garantem que seus scripts funcionem de forma confiável e eficiente.
waitForSelector()
: Aguarda que elementos apareçam (por exemplo, botões ou formulários).waitForNavigation()
: Lida com transições de página e garante carregamentos completos da página.waitForNetworkIdle()
: Ideal para páginas com uso intenso de API, aguarda a conclusão de todas as solicitações de rede.waitForFunction()
para cenários complexos como conteúdo dinâmico ou animações.page.setDefaultTimeout()
para lidar com páginas de carregamento lento.Promise.all()
para maior confiabilidade.Comece com essas estratégias para tornar seus scripts do Puppeteer mais rápidos, confiáveis e mais adequados para aplicativos web modernos.
Ao usar o Puppeteer para automação, entender como ele lida com a espera é essencial para criar scripts que funcionem de forma confiável. O Puppeteer inclui configurações de tempo limite padrão para evitar que os scripts parem indefinidamente, mas essas configurações podem precisar ser ajustadas ou suplementadas com estratégias personalizadas para cenários mais complexos.
O Puppeteer define tempos limite padrão para gerenciar tarefas como navegação, seleção de elementos, solicitações de rede, consultas XPath e funções personalizadas. Isso garante que seus scripts não travem indefinidamente se algo der errado ou demorar muito.
Você pode modificar esses padrões com page.setDefaultTimeout(timeout)
. Por exemplo, se seu aplicativo levar mais tempo para carregar recursos complexos, aumentar o tempo limite pode ajudar seu script a evitar sair muito cedo. Embora convenientes, essas configurações padrão podem nem sempre se alinhar ao comportamento de aplicativos dinâmicos.
Os aplicativos da web modernos geralmente dependem do carregamento dinâmico de conteúdo, o que pode tornar os mecanismos de espera padrão do Puppeteer insuficientes. O Puppeteer oferece duas condições de ociosidade de rede para ajudar a gerenciar isso:
networkidle0
: Aguarda até que não haja conexões de rede por 500 ms.networkidle2
: Aguarda até que não haja mais de 2 conexões de rede por 500 ms.No entanto, essas condições nem sempre correspondem ao comportamento dos aplicativos da web. Problemas comuns incluem:
Para lidar com esses desafios, tente usar um try-catch
bloco para gerenciar erros de tempo limite. Isso permite que seu script evite falhas abruptas e aplique estratégias de fallback quando necessário. Em vez de depender de atrasos fixos, considere criar condições de espera com base no status real da página. Essa abordagem é mais flexível e mais adequada para ambientes dinâmicos.
O Puppeteer oferece três métodos principais para lidar com detecção de elementos, navegação de página e atividade de rede. Esses métodos ajudam a gerenciar interações de forma eficaz, especialmente em ambientes web dinâmicos.
waitForSelector()
A waitForSelector()
método pausa a execução até que um elemento específico apareça na página. Isso é especialmente útil para conteúdo carregado dinamicamente em Single Page Applications (SPAs).
Veja como você pode usá-lo:
// Wait for an element to appear
await page.waitForSelector('.button-class');
// Wait for the element to be visible
await page.waitForSelector('.button-class', { visible: true });
// Set a custom timeout
await page.waitForSelector('.button-class', { timeout: 5000 });
Este método garante que seu script interaja com elementos somente quando eles estiverem prontos.
waitForNavigation()
A waitForNavigation()
O método é projetado para lidar com transições de página. Ele espera que a página carregue completamente após eventos como clicar em um link ou enviar um formulário.
await Promise.all([
page.waitForNavigation(),
page.click('.navigation-link')
]);
Você pode personalizar seu comportamento com opções:
Opção | Descrição | melhor para |
---|---|---|
waitUntil: 'load' |
Aguarda o evento de carregamento da página ser disparado | Páginas estáticas |
waitUntil: 'domcontentloaded' |
Aguarda que o DOM seja totalmente carregado | Interações rápidas |
waitUntil: 'networkidle0' |
Aguarda até que nenhuma solicitação de rede esteja ativa | Aplicações complexas |
Essa flexibilidade garante um manuseio de navegação suave para diferentes cenários.
waitForNetworkIdle()
A waitForNetworkIdle()
opção é ideal para monitorar a atividade da rede. Ela espera até que a rede esteja completamente ociosa ou quase ociosa.
// Wait for all network requests to finish
await page.goto(url, { waitUntil: 'networkidle0' });
// Allow up to 2 active connections (e.g., WebSockets)
await page.goto(url, { waitUntil: 'networkidle2' });
Por exemplo:
try {
await page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 30000 });
await page.waitForSelector('.dynamic-content', { visible: true });
} catch (error) {
console.error('Loading timeout occurred');
}
Use networkidle0
para conclusão completa da solicitação ou networkidle2
nos casos em que as conexões em segundo plano podem permanecer ativas.
Esses métodos são essenciais para criar scripts de automação web confiáveis, garantindo que suas interações com páginas web sejam consistentes e eficientes.
Às vezes, métodos básicos de espera simplesmente não funcionam. Para cenários mais intrincados, técnicas avançadas são o caminho a seguir.
Quando os seletores padrão não forem suficientes, você pode usar waitForFunction()
para definir condições de espera personalizadas com base no estado da página ou em expressões JavaScript.
// Wait for a specific number of elements to load
await page.waitForFunction(() => {
return document.querySelectorAll('.product-card').length > 5;
});
// Wait for dynamic content and validate its state
await page.waitForFunction(
(expectedText) => {
const element = document.querySelector('.status');
return element && element.innerText.includes(expectedText);
},
{},
'Ready'
);
Você também pode combinar várias condições para cenários mais complexos:
await page.waitForFunction(() => {
const isLoaded = document.readyState === 'complete';
const hasContent = document.querySelector('.content')?.innerHTML.length > 0;
const noSpinner = !document.querySelector('.loading-spinner');
return isLoaded && hasContent && noSpinner;
});
Agora vamos dar um passo adiante e lidar com diversas condições simultaneamente.
Para aplicações complexas, muitas vezes você precisa esperar por várias condições ao mesmo tempo. Usando Promise.all()
pode ajudar a gerenciá-los de forma eficiente.
Exemplo de envio de formulário dinâmico:
// Handle form submission with multiple conditions
const submitForm = async () => {
await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle0' }),
page.waitForFunction(() => !document.querySelector('.processing')),
page.click('#submit-button')
]);
};
Lidando com as condições da corrida:
Às vezes, você precisa prosseguir assim que a primeira condição for atendida. Para isso, você pode usar Promise.race()
:
// Wait for either a success or error message
const waitForResponse = async () => {
await Promise.race([
page.waitForSelector('.success-message'),
page.waitForSelector('.error-message')
]);
};
Cenários de carregamento complexos:
Veja um exemplo de gerenciamento de carregamento de conteúdo dinâmico com múltiplas condições:
const loadDynamicContent = async () => {
await page.click('.load-more');
await Promise.all([
page.waitForFunction(() => {
return window.scrollY + window.innerHeight >= document.documentElement.scrollHeight;
}),
page.waitForSelector('.new-items', { visible: true }),
page.waitForFunction(() => {
return document.querySelectorAll('.item').length > 10;
})
]);
};
Essas técnicas ajudam você a criar scripts de automação mais fortes, capazes de lidar com aplicativos web complexos com operações assíncronas e conteúdo dinâmico.
Melhorar os métodos de espera pode aumentar significativamente a velocidade e a confiabilidade dos scripts de automação. Ao combinar técnicas manuais mais inteligentes com estratégias orientadas por IA, você pode obter uma execução mais rápida sem sacrificar a estabilidade.
Um fator-chave na otimização de métodos de espera é entender como sua página carrega. Adaptar os tempos de espera para corresponder ao comportamento da página no mundo real é essencial.
// Set a default timeout for all operations
page.setDefaultTimeout(30000);
// Use efficient wait conditions
const waitForContent = async () => {
try {
await page.waitForSelector('.content', {
visible: true,
timeout: 5000 // Shorter timeout for specific elements
});
} catch (error) {
console.error('Content load timeout');
throw error;
}
};
Para carregamentos de página completos, use 'networkidle0'
, e para conteúdo dinâmico, use 'networkidle2'
. Isso equilibra velocidade com confiabilidade.
"Embora esperar um período fixo de tempo seja uma prática ruim, no mundo real é difícil encontrar uma solução que funcione bem em todos os casos." - Dmytro Krasun
Outra maneira de aumentar o desempenho é desabilitando recursos não essenciais. No entanto, para uma eficiência ainda maior, considere soluções alimentadas por IA.
A IA pode levar a otimização de espera para o próximo nível, analisando o comportamento da página e ajustando as condições dinamicamente. Ferramentas como Nó latente use IA para ajustar estratégias de espera.
// AI-enhanced wait logic example
const smartWait = async () => {
await page.waitForFunction(() => {
const contentReady = document.querySelector('.content')?.offsetHeight > 0;
const apiLoaded = window._apiData && Object.keys(window._apiData).length > 0;
const animationsComplete = !document.querySelector('.loading-animation');
return contentReady && apiLoaded && animationsComplete;
}, {
timeout: 15000,
polling: 'mutation' // Optimized polling strategy
});
};
Para cenários mais complexos, a espera paralela com tempos limite otimizados pode mudar o jogo:
// Parallel waiting with timeout optimization
const optimizedLoad = async () => {
const timeoutPromise = new Promise((_, reject) =>
setTimeout(() => reject(new Error('Operation timed out')), 10000)
);
try {
await Promise.race([
Promise.all([
page.waitForSelector('.content'),
page.waitForFunction(() => window.dataLoaded === true),
page.waitForNetworkIdle({
idleTime: 500,
timeout: 8000
})
]),
timeoutPromise
]);
} catch (error) {
console.error('Loading failed:', error.message);
throw error;
}
};
Esses métodos ajudam seus scripts a se adaptarem a diversas condições de rede e tempos de carregamento de página, garantindo velocidade e confiabilidade.
Para garantir que seus scripts de automação sejam executados sem problemas, é importante corrigir erros de tempo limite após otimizar os métodos de espera.
Erros de tempo limite acontecem quando uma página demora mais para carregar do que o esperado. Por padrão, o Puppeteer define um tempo limite de 30 segundos, o que pode não ser suficiente para conexões de internet mais lentas ou páginas pesadas.
Veja como você pode ajustar as configurações de tempo limite:
// Set a global timeout for all operations
await page.setDefaultTimeout(60000); // 60 seconds
// Set a specific timeout for navigation
await page.setDefaultNavigationTimeout(60000); // 60 seconds
try {
await page.waitForSelector('.dynamic-content', {
visible: true,
timeout: 10000 // 10 seconds
});
} catch (error) {
console.error('Element wait timeout:', error.message);
// Consider adding a fallback strategy here
}
Para cenários mais complexos, tente timeouts incrementais. Esta abordagem tenta novamente a operação com intervalos de tempo crescentes:
const waitWithRetry = async (selector, maxAttempts = 3) => {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
await page.waitForSelector(selector, {
timeout: 5000 * attempt // Increase timeout with each attempt
});
return true;
} catch (error) {
if (attempt === maxAttempts) throw error;
console.warn(`Attempt ${attempt} failed, retrying...`);
}
}
};
Para depurar erros de espera, use técnicas de monitoramento sistemático. Por exemplo:
// Monitor network requests for potential timing issues
await page.setRequestInterception(true);
page.on('request', request => {
console.log(`${request.method()} ${request.url()}`);
request.continue();
});
// Check if an element is visible on the page
const elementVisibilityCheck = async (selector) => {
const isVisible = await page.evaluate((sel) => {
const element = document.querySelector(sel);
if (!element) return false;
const style = window.getComputedStyle(element);
return style.display !== 'none' &&
style.visibility !== 'hidden' &&
style.opacity !== '0';
}, selector);
return isVisible;
};
Erros comuns de espera e suas soluções:
Tipo de Erro | Causar | Solução |
---|---|---|
Tempo limite de navegação | Carregamento de página pesado | Aumentar o tempo limite para 60000 ms |
Elemento não encontrado | Conteúdo dinâmico | Use waitForFunction com um observador de mutação |
Tempo limite de inatividade da rede | Várias chamadas de API | Use o networkidle2 estratégia |
Falha na interação | Estado do elemento | Adicionar verificações para interatividade do elemento |
Aqui está um exemplo robusto para lidar com erros de espera de forma eficaz:
const robustWait = async (page, selector) => {
try {
const element = await page.waitForSelector(selector, {
visible: true,
timeout: 15000 // 15 seconds
});
// Ensure the element is interactive
await page.waitForFunction(
(sel) => {
const el = document.querySelector(sel);
return el && !el.disabled && el.getBoundingClientRect().height > 0;
},
{ timeout: 5000 }, // Additional check timeout
selector
);
return element;
} catch (error) {
console.error(`Wait error: ${error.message}`);
throw new Error(`Element ${selector} isn't ready`);
}
};
Essas estratégias podem ajudar você a resolver e depurar problemas de tempo limite de forma eficaz, garantindo que seus scripts lidem com cenários variados com elegância.
Obter o equilíbrio certo entre velocidade e estabilidade é essencial ao usar estratégias de espera no Puppeteer. Escolher o método de espera certo garante que suas interações automatizadas na web sejam executadas sem problemas e forneçam resultados confiáveis.
Aqui está uma rápida visão geral das estratégias comuns de espera e quando usá-las:
Estratégia de espera | Melhor caso de uso | Benefício principal |
---|---|---|
waitForSelector() |
Elementos dinâmicos da IU | Confirma que o elemento está presente antes do uso |
waitForNavigation() |
Transições de página | Mantém seu script sincronizado com as alterações de página |
waitForNetworkIdle() |
Páginas com API pesada | Confirma que todas as solicitações de rede foram concluídas |
Condições de espera personalizadas | Cenários complexos | Oferece controle preciso sobre o tempo |
Para conteúdo dinâmico, combinando waitForSelector()
com condições de espera personalizadas geralmente funciona melhor do que ficar preso a timeouts padrão. Essa abordagem dá a você mais controle e reduz as chances de erros.
Usar ferramentas como o Latenode pode simplificar o processo de configuração de estratégias de espera eficazes, ajudando você a melhorar a velocidade e a confiabilidade. Além disso, definir tempos limite com page.setDefaultTimeout()
pode ajudar a evitar falhas de script e, ao mesmo tempo, manter sua automação eficiente.