Abonnements
PRODUIT
SOLUTIONS
par cas d'utilisation
AI Gestion du leadFacturationRéseaux SociauxGestion de projetGestion des donnéespar industrie
en savoir plus
BlogGabaritsVidéosYoutubeRESSOURCES
COMMUNAUTÉS ET RÉSEAUX SOCIAUX
PARTENAIRES
Aux prises avec Marionnettiste Les scripts expirent ou échouent ? Voici comment résoudre ce problème.
Marionnettiste, un Node.js bibliothèque pour le contrôle Chrome, est puissant pour l'automatisation web. Cependant, le contenu dynamique et les pages pilotées par API peuvent compliquer le timing. Des stratégies d'attente appropriées garantissent le fonctionnement fiable et efficace de vos scripts.
waitForSelector()
: Attend que des éléments apparaissent (par exemple, des boutons ou des formulaires).waitForNavigation()
: Gère les transitions de page et assure le chargement complet des pages.waitForNetworkIdle()
:Idéal pour les pages riches en API, attend que toutes les requêtes réseau soient terminées.waitForFunction()
pour des scénarios complexes comme du contenu dynamique ou des animations.page.setDefaultTimeout()
pour gérer les pages à chargement lent.Promise.all()
pour une meilleure fiabilité.Commencez par ces stratégies pour rendre vos scripts Puppeteer plus rapides, plus fiables et mieux adaptés aux applications Web modernes.
Lorsque vous utilisez Puppeteer pour l'automatisation, il est essentiel de comprendre comment il gère l'attente pour créer des scripts fiables. Puppeteer inclut des paramètres de délai d'attente par défaut pour éviter que les scripts ne se bloquent indéfiniment, mais ces paramètres peuvent nécessiter un ajustement ou des stratégies personnalisées pour les scénarios plus complexes.
Puppeteer définit des délais d'expiration par défaut pour gérer des tâches telles que la navigation, la sélection d'éléments, les requêtes réseau, les requêtes XPath et les fonctions personnalisées. Cela garantit que vos scripts ne se bloquent pas indéfiniment en cas de problème ou de durée excessive.
Vous pouvez modifier ces valeurs par défaut avec page.setDefaultTimeout(timeout)
Par exemple, si le chargement de fonctionnalités complexes par votre application prend plus de temps, augmenter le délai d'expiration peut éviter que votre script ne s'arrête trop tôt. Bien que pratiques, ces paramètres par défaut ne sont pas toujours adaptés au comportement des applications dynamiques.
Les applications web modernes reposent souvent sur le chargement dynamique du contenu, ce qui peut rendre les mécanismes d'attente par défaut de Puppeteer insuffisants. Puppeteer propose deux conditions d'inactivité réseau pour gérer ce problème :
networkidle0
: Attend qu'il n'y ait plus de connexions réseau pendant 500 ms.networkidle2
: Attend qu'il n'y ait plus de 2 connexions réseau pendant 500 ms.Cependant, ces conditions ne correspondent pas toujours au comportement des applications web. Les problèmes courants incluent :
Pour relever ces défis, essayez d’utiliser un try-catch
Bloc pour gérer les erreurs de dépassement de délai. Cela permet à votre script d'éviter les échecs soudains et d'appliquer des stratégies de secours si nécessaire. Au lieu de vous fier à des délais fixes, envisagez de créer des conditions d'attente basées sur l'état réel de la page. Cette approche est plus flexible et mieux adaptée aux environnements dynamiques.
Puppeteer propose trois méthodes clés pour gérer la détection des éléments, la navigation dans les pages et l'activité réseau. Ces méthodes permettent de gérer efficacement les interactions, notamment dans les environnements web dynamiques.
waitForSelector()
Le waitForSelector()
La méthode suspend l'exécution jusqu'à l'apparition d'un élément spécifique sur la page. Ceci est particulièrement utile pour le contenu chargé dynamiquement dans les applications monopage (SPA).
Voici comment vous pouvez l'utiliser:
// 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 });
Cette méthode garantit que votre script interagit avec les éléments uniquement lorsqu'ils sont prêts.
waitForNavigation()
Le waitForNavigation()
La méthode est conçue pour gérer les transitions entre les pages. Elle attend que la page soit complètement chargée après des événements tels qu'un clic sur un lien ou l'envoi d'un formulaire.
await Promise.all([
page.waitForNavigation(),
page.click('.navigation-link')
]);
Vous pouvez personnaliser son comportement avec des options :
Option | Description | Idéal pour |
---|---|---|
waitUntil: 'load' |
Attend que l'événement de chargement de la page se déclenche | Pages statiques |
waitUntil: 'domcontentloaded' |
Attend que le DOM soit entièrement chargé | Interactions rapides |
waitUntil: 'networkidle0' |
Attend qu'aucune demande réseau ne soit active | Applications complexes |
Cette flexibilité garantit une gestion fluide de la navigation pour différents scénarios.
waitForNetworkIdle()
Le waitForNetworkIdle()
Cette option est idéale pour surveiller l'activité du réseau. Elle attend que le réseau soit complètement inactif ou presque.
// 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' });
Par exemple :
try {
await page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 30000 });
await page.waitForSelector('.dynamic-content', { visible: true });
} catch (error) {
console.error('Loading timeout occurred');
}
Utilisez networkidle0
pour compléter la demande ou networkidle2
dans les cas où les connexions en arrière-plan peuvent rester actives.
Ces méthodes sont essentielles pour créer des scripts d’automatisation Web fiables, garantissant que vos interactions avec les pages Web sont cohérentes et efficaces.
Parfois, les méthodes d'attente de base ne suffisent pas. Pour les scénarios plus complexes, des techniques avancées sont la solution.
Lorsque les sélecteurs standards ne suffisent pas, vous pouvez utiliser waitForFunction()
pour définir des conditions d'attente personnalisées en fonction de l'état de la page ou des expressions 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'
);
Vous pouvez également combiner plusieurs conditions pour des scénarios plus complexes :
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;
});
Allons maintenant plus loin en gérant plusieurs conditions simultanément.
Pour les applications complexes, il est souvent nécessaire d'attendre plusieurs conditions simultanément. Promise.all()
peut aider à les gérer efficacement.
Exemple de soumission de formulaire dynamique :
// 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')
]);
};
Gestion des conditions de course :
Parfois, il est nécessaire de procéder dès que la première condition est remplie. Pour cela, vous pouvez utiliser Promise.race()
:
// Wait for either a success or error message
const waitForResponse = async () => {
await Promise.race([
page.waitForSelector('.success-message'),
page.waitForSelector('.error-message')
]);
};
Scénarios de chargement complexes :
Voici un exemple de gestion du chargement de contenu dynamique avec plusieurs conditions :
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;
})
]);
};
Ces techniques vous aident à créer des scripts d’automatisation plus puissants, capables de gérer des applications Web complexes avec des opérations asynchrones et du contenu dynamique.
L'amélioration des méthodes d'attente peut considérablement améliorer la vitesse et la fiabilité des scripts d'automatisation. En combinant des techniques manuelles plus intelligentes avec des stratégies basées sur l'IA, vous pouvez accélérer l'exécution sans compromettre la stabilité.
Un facteur clé pour optimiser les méthodes d'attente est de comprendre le fonctionnement de votre page. Il est essentiel d'adapter les temps d'attente au comportement réel de la page.
// 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;
}
};
Pour des chargements de page complets, utilisez 'networkidle0'
, et pour le contenu dynamique, utilisez 'networkidle2'
Cela équilibre la vitesse et la fiabilité.
« Bien qu'attendre une période déterminée soit une mauvaise pratique, dans le monde réel, il est difficile de trouver une solution qui fonctionne bien dans tous les cas. » – Dmytro Krasun
Une autre façon d'améliorer les performances consiste à désactiver les ressources non essentielles. Cependant, pour une efficacité encore plus grande, envisagez des solutions basées sur l'IA.
L'IA peut propulser l'optimisation de l'attente à un niveau supérieur en analysant le comportement des pages et en ajustant les conditions de manière dynamique. Des outils comme Laténode utiliser l’IA pour affiner les stratégies d’attente.
// 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
});
};
Pour les scénarios plus complexes, l'attente parallèle avec des délais d'attente optimisés peut changer la donne :
// 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;
}
};
Ces méthodes aident vos scripts à s’adapter à diverses conditions de réseau et à différents temps de chargement de pages, garantissant à la fois vitesse et fiabilité.
Pour garantir le bon fonctionnement de vos scripts d'automatisation, il est important de traiter les erreurs de délai d'attente après avoir optimisé les méthodes d'attente.
Des erreurs de délai d'attente se produisent lorsqu'une page met plus de temps à charger que prévu. Par défaut, Puppeteer définit un délai d'attente de 30 secondes, ce qui peut être insuffisant pour les connexions Internet lentes ou les pages chargées.
Voici comment vous pouvez ajuster les paramètres de délai d’expiration :
// 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
}
Pour les scénarios plus complexes, essayez les délais d'expiration incrémentiels. Cette approche permet de relancer l'opération à intervalles de temps croissants :
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...`);
}
}
};
Pour corriger les erreurs d'attente, utilisez des techniques de surveillance systématique. Par exemple :
// 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;
};
Erreurs d’attente courantes et leurs solutions :
Type d'erreur | Causes | Solution |
---|---|---|
Délai d'expiration de la navigation | Chargement de page important | Augmenter le délai d'attente à 60000 XNUMX ms |
Élément introuvable | Contenu dynamique | Utilisez waitForFunction avec un observateur de mutation |
Délai d'inactivité du réseau | Appels API multiples | Utilisez l'option networkidle2 stratégie |
Échec de l'interaction | État de l'élément | Ajouter des vérifications pour l'interactivité des éléments |
Voici un exemple robuste pour gérer efficacement les erreurs d’attente :
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`);
}
};
Ces stratégies peuvent vous aider à résoudre et à déboguer efficacement les problèmes de délai d'attente, garantissant que vos scripts gèrent différents scénarios avec élégance.
Trouver le juste équilibre entre rapidité et stabilité est essentiel pour utiliser des stratégies d'attente dans Puppeteer. Choisir la bonne méthode d'attente garantit le bon déroulement de vos interactions web automatisées et la fiabilité de vos résultats.
Voici un aperçu rapide des stratégies d’attente courantes et du moment où les utiliser :
Stratégie d'attente | Meilleur cas d'utilisation | Avantage clé |
---|---|---|
waitForSelector() |
Éléments d'interface utilisateur dynamiques | Confirme que l'élément est présent avant utilisation |
waitForNavigation() |
Transitions de pages | Maintient votre script synchronisé avec les changements de page |
waitForNetworkIdle() |
Pages riches en API | Confirme que toutes les demandes réseau sont terminées |
Conditions d'attente personnalisées | Scénarios complexes | Offre un contrôle précis du timing |
Pour un contenu dynamique, combinant waitForSelector()
L'utilisation de conditions d'attente personnalisées est souvent plus efficace que les délais d'attente par défaut. Cette approche vous offre un meilleur contrôle et réduit les risques d'erreurs.
L'utilisation d'outils comme Latenode peut simplifier la mise en place de stratégies d'attente efficaces, améliorant ainsi la rapidité et la fiabilité. De plus, la définition de délais d'attente avec page.setDefaultTimeout()
peut aider à éviter les échecs de script tout en gardant votre automatisation efficace.