Latenode

Déboguer des scripts Puppeteer : du mode slowMo aux techniques avancées

Maîtrisez les techniques essentielles de débogage des scripts Puppeteer, des méthodes visuelles à la gestion avancée des erreurs, afin d’améliorer leur fiabilité.

9 min de lecture
Fenêtre Chrome DevTools affichant le débogage d’un script Puppeteer

Déboguer des scripts Puppeteer peut sembler complexe, mais maîtriser quelques techniques clés peut vous faire gagner du temps et vous éviter bien des frustrations. Voici un aperçu rapide de ce que vous allez apprendre :

  • Commencez par le débogage visuel : utilisez le mode slowMo et le mode navigateur visible pour observer votre script en action.
  • Capturez les erreurs : ajoutez des blocs try-catch et automatisez les captures d’écran d’erreurs pour mieux résoudre les problèmes.
  • Exploitez les journaux de console : suivez les erreurs de page, les requêtes échouées et les messages personnalisés pour obtenir des informations plus approfondies.
  • Gérez les sélecteurs et le timing : utilisez des stratégies de sélecteurs robustes et gérez les délais d’attente pour éviter les pièges courants.
  • Organisez votre code : divisez vos scripts en modules dédiés aux actions, aux sélecteurs et aux validations afin de simplifier la maintenance.

Exemple de configuration rapide :

const browser = await puppeteer.launch({
    headless: false,
    slowMo: 100,
    devtools: true
});

Conseils de débogage :

  1. Activez la journalisation : exécutez avec DEBUG="puppeteer:*" pour obtenir des journaux détaillés.
  2. Utilisez des captures d’écran : capturez les états de la page pour voir ce qui n’a pas fonctionné.
  3. Gérez les ressources : nettoyez toujours les instances du navigateur et des pages pour éviter les plantages.

En combinant ces techniques, vous simplifierez votre processus de débogage et améliorerez la fiabilité de vos scripts Puppeteer.

Configuration de l’environnement de débogage

Paramètres de débogage de base

Configurez Puppeteer pour le débogage avec ces options de lancement :

const browser = await puppeteer.launch({
    headless: false,
    slowMo: 20,
    devtools: true
});

Pour activer une journalisation détaillée, exécutez votre script avec la commande suivante :

DEBUG="puppeteer:*" node script.js

Une fois la configuration terminée, utilisez les outils de débogage pour analyser et affiner le comportement de votre script.

Outils de débogage requis

Voici quelques outils pour vous aider à résoudre efficacement les problèmes :

OutilObjectifFonctionnalité clé
Chrome DevToolsInspecter les scriptsOutils de console et de réseau
Débogueur VS CodeGérer les points d’arrêtExécution pas à pas
Utilitaire de capture d’écranRésolution visuelle des problèmesCapture des états de page

Vous pouvez également ajouter des points de contrôle dans votre code pour améliorer la visibilité :

await page.screenshot({ path: 'before_click.png' });
await page.click('#button');
await page.screenshot({ path: 'after_click.png' });

Organisation du script

Une bonne organisation est aussi importante que les outils que vous utilisez. Divisez votre script en modules logiques et incluez une gestion des erreurs pour faciliter le débogage :

try {
    await page.waitForSelector('#target-element');
    await page.click('#target-element');
} catch (error) {
    console.error(`Navigation failed: ${error.message}`);
    await page.screenshot({ path: 'error-state.png' });
}

Pour réduire le risque de détection des bots, intégrez le plugin stealth :

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());

Enfin, assurez une bonne gestion des ressources en implémentant des procédures de nettoyage :

async function cleanup() {
    if (page) await page.close();
    if (browser) await browser.close();
}

Cette configuration fournit une base solide pour le débogage visuel et via la console dans vos projets.

Puppeteer - 3 approches à envisager pour le débogage

Méthodes de débogage visuel

Observer vos scripts en action peut révéler des problèmes que l’analyse de code traditionnelle pourrait ne pas détecter. Ces méthodes élargissent vos options de débogage au-delà des journaux de console et du suivi des erreurs.

Guide du mode SlowMo

SlowMo introduit un délai entre les actions Puppeteer, ce qui permet de suivre plus facilement ce qui se passe :

const browser = await puppeteer.launch({
    headless: false,
    slowMo: 250,
    devtools: true
});

La valeur slowMo (en millisecondes) contrôle le délai entre les actions. Ajustez-la en fonction de ce que vous testez :

Type d’opérationSlowMo recommandé (ms)Cas d’utilisation
Clics simples100–250Étapes de navigation de base
Remplissage de formulaires250–500Test de la validation des saisies
Contenu dynamique500–1000Vérification des états de chargement

Une fois SlowMo configuré, associez-le au mode d’affichage du navigateur pour surveiller le comportement de l’interface utilisateur pendant l’exécution du script.

Mode d’affichage du navigateur

Le mode d’affichage du navigateur vous permet de voir votre script s’exécuter dans une fenêtre de navigateur visible. Il est particulièrement utile pour déboguer du contenu dynamique et des interactions complexes.

const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: { width: 1700, height: 800 },
    args: ['--start-maximized']
});

Par exemple, l’équipe QA de Acme Corp a utilisé ce mode en juin 2024 pour résoudre des problèmes dans un script de web scraping. Elle a repéré des sélecteurs incorrects et les a corrigés, réduisant le temps de débogage de 40 %.

Pour compléter cette approche, capturez des captures d’écran des états visuels importants afin de les analyser plus en détail.

Enregistrement visuel

Les captures d’écran et les vidéos peuvent créer un historique clair de l’exécution de votre script, ce qui facilite le débogage :

// Screenshot of a specific element
await page.screenshot({
    path: 'element-state.png',
    clip: {
        x: 0,
        y: 0,
        width: 500,
        height: 300
    }
});

// Full-page screenshot
await page.screenshot({
    path: 'full-page.png',
    fullPage: true
});

Commencez par activer le mode d’affichage du navigateur, utilisez SlowMo pour un suivi détaillé et documentez les moments clés avec des captures d’écran. Ensemble, ces étapes créent un processus complet de débogage visuel.

Méthodes de débogage via la console

Les méthodes de console offrent un moyen direct d’obtenir des informations textuelles sur le comportement de vos scripts. Ces sorties complètent le débogage visuel en vous donnant des détails précis sur l’exécution des scripts.

Suivi des messages de console

Puppeteer permet de capturer facilement les messages du navigateur avec des gestionnaires d’événements comme ceux-ci :

page.on('console', msg => {
    console.log('PAGE LOG:', msg.text());
});

page.on('pageerror', err => {
    console.error('PAGE ERROR:', err.message);
});

page.on('requestfailed', request => {
    console.error('REQUEST FAILED:', request.url());
});

Cette configuration crée un système de journalisation qui suit les messages de console, les erreurs de page et les requêtes échouées. Pour améliorer la clarté, vous pouvez classer les messages par type :

Type de messageObjectifExemple de sortie
JournalInformations généralesFlux d’exécution standard
ErreurProblèmes majeursOpérations échouées
AvertissementPoints d’attention potentielsRalentissements des performances
InformationMises à jour de statutAchèvement d’une tâche

Bonnes pratiques pour Console.log

Utiliser console.log de manière judicieuse peut faciliter considérablement le débogage. Placez les journaux de façon stratégique pour suivre la progression et identifier les problèmes :

// Log before attempting to find an element
console.log(`Looking for element: ${selector}`);
const element = await page.$(selector);
// Log after confirming the element exists
console.log(`Element found: ${!!element}`);

// Log form data before filling it out
console.log(`Form data: ${JSON.stringify(formData)}`);
await page.type('#email', formData.email);

Méthodes de journalisation étendues

Pour les problèmes plus complexes, les techniques de journalisation avancées peuvent tout changer :

// Enable detailed debugging for Puppeteer
process.env.DEBUG = 'puppeteer:*';
process.env.DEBUG_MAX_STRING_LENGTH = null;

// Monitor pending protocol calls
const browser = await puppeteer.launch({
    dumpio: true
});
console.log(browser.debugInfo.pendingProtocolErrors);

Une équipe a constaté une baisse de 40 % des échecs de tests après avoir adopté une journalisation détaillée du protocole.

// Filter out specific network domain messages
// Command: DEBUG="puppeteer:*" DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'

Ces méthodes ajoutent une couche textuelle à votre processus de débogage, vous aidant à détecter et résoudre les problèmes plus efficacement.

sbb-itb-23997f1

Méthodes de débogage avancées

Le débogage de scripts Puppeteer complexes implique d’utiliser des stratégies efficaces de gestion des erreurs et des techniques avancées afin d’assurer une exécution fluide des scripts.

Try-Catch pour la gestion des erreurs

Utilisez des blocs try-catch pour gérer efficacement les erreurs et maintenir l’exécution de votre script :

async function navigateAndScreenshot(url, selector) {
    try {
        await page.goto(url, { waitUntil: 'networkidle0' });
        const element = await page.waitForSelector(selector, { timeout: 5000 });
        await element.screenshot({ path: 'element.png' });
    } catch (error) {
        if (error instanceof TimeoutError) {
            console.error(`Element ${selector} not found within timeout`);
            // Add recovery logic if needed
            await page.reload();
        } else {
            console.error(`Navigation failed: ${error.message}`);
            throw error; // Re-throw unexpected errors
        }
    }
}

Vous pouvez renforcer la gestion des erreurs en combinant les blocs try-catch avec des classes d’erreurs personnalisées pour améliorer la catégorisation et la réponse.

Classes d’erreurs personnalisées

La création de classes d’erreurs personnalisées vous aide à identifier et classer les problèmes plus efficacement :

class PuppeteerScriptError extends Error {
    constructor(message, details = {}) {
        super(message);
        this.name = 'PuppeteerScriptError';
        this.details = details;
        this.timestamp = new Date().toISOString();
    }
}

class SelectorError extends PuppeteerScriptError {
    constructor(selector, context) {
        super(`Failed to find selector: ${selector}`, {
            selector,
            context,
            type: 'SELECTOR_ERROR'
        });
        this.name = 'SelectorError';
    }
}

Ces classes vous permettent de suivre et de déboguer les opérations asynchrones avec davantage de clarté.

Débogage du code asynchrone

Le code asynchrone introduit souvent des problèmes de timing et des promesses non résolues. Traitez ces problèmes avec les techniques suivantes :

// Enable detailed debugging for protocol calls
const browser = await puppeteer.launch({
    dumpio: true
});

// Monitor unresolved promises periodically
setInterval(() => {
    const pending = browser.debugInfo.pendingProtocolErrors;
    if (pending.length > 0) {
        console.log('Pending protocol calls:', pending);
    }
}, 5000);

// Handle async errors with a timeout mechanism
async function safeExecute(promiseFn) {
    try {
        return await Promise.race([
            promiseFn(),
            new Promise((_, reject) => 
                setTimeout(() => reject(new Error('Operation timed out')), 30000)
            )
        ]);
    } catch (error) {
        console.error(`Operation failed: ${error.message}`);
        throw new PuppeteerScriptError('Execution timeout', {
            originalError: error,
            operation: promiseFn.name
        });
    }
}

En utilisant l’interface debugInfo, vous pouvez surveiller les rappels en attente et identifier les promesses non résolues lors de la communication avec le protocole du navigateur.

Niveau de débogageObjectifImplémentation
BasiqueGérer les erreurs courantesBlocs try-catch standard
IntermédiaireClasser les erreursHiérarchie de classes d’erreurs personnalisées
AvancéSuivre les problèmes de protocoleSurveillance de l’interface de débogage

Solutions aux problèmes courants

Cette section aborde les difficultés fréquentes avec Puppeteer et propose des correctifs clairs pour assurer le bon fonctionnement de vos scripts d’automatisation.

Problèmes de sélecteurs

Les problèmes de sélecteurs peuvent souvent perturber l’exécution du script. Voici comment les gérer efficacement :

async function findElement(page) {
  try {
    const element = await page.waitForSelector('[data-testid="target"]', {
      timeout: 5000
    });
    return element;
  } catch {
    return page.waitForSelector('.target-class', {
      timeout: 5000
    });
  }
}

Pour les éléments à l’intérieur d’iframes ou du Shadow DOM, utilisez les approches suivantes :

// Access iframe content
const frame = await page.frames().find(f => f.name() === 'content-frame');
const button = await frame.$('button[data-hook="create"]');

// Handle Shadow DOM elements
await page.evaluateHandle(selector => {
  const element = document.querySelector('parent-element')
    .shadowRoot
    .querySelector(selector);
  return element;
}, 'target-selector');

Une gestion correcte des sélecteurs garantit que vos scripts localisent les éléments de manière fiable.

Problèmes de timing

Une fois les sélecteurs stabilisés, la gestion du timing devient essentielle pour une exécution fluide :

await page.setDefaultNavigationTimeout(30000);
await page.setDefaultTimeout(10000);

async function waitForContent(page) {
  await Promise.all([
    page.waitForNavigation({ waitUntil: 'networkidle0' }),
    page.click('#load-more-button')
  ]);
}

Voici une référence rapide des contrôles de timing :

Problème de timingSolutionImplémentation
Chargement de pagewaitForNavigationAttendre l’inactivité réseau
Contenu dynamiquewaitForSelectorUtiliser avec un délai d’attente approprié
Mises à jour AJAXwaitForResponseSurveiller les requêtes réseau spécifiques

Ces stratégies permettent d’aligner le timing de votre script sur le comportement de la page.

Correctifs pour les plantages du navigateur

Même avec des stratégies solides de sélecteurs et de timing, des plantages du navigateur peuvent toujours se produire. Voici comment les réduire et vous en remettre :

const browser = await puppeteer.launch({
  args: [
    '--disable-dev-shm-usage',
    '--enable-gpu',
    '--no-first-run',
    '--disable-extensions'
  ]
});

Pour la récupération après un plantage :

let browser;
try {
  browser = await puppeteer.launch();
  const page = await browser.newPage();

  page.on('error', err => {
    console.error('Page crashed:', err);
  });

  await page.goto('https://example.com');
} catch (error) {
  console.error('Browser error:', error);
} finally {
  if (browser) {
    await browser.close();
  }
}

Si vous travaillez sous Linux, vérifiez les dépendances manquantes :

ldd chrome | grep not

Pour optimiser l’utilisation des ressources, ajustez les indicateurs du navigateur :

const browser = await puppeteer.launch({
  args: [
    '--disable-dev-shm-usage',
    '--disable-accelerated-2d-canvas',
    '--disable-gpu'
  ]
});

Configurez une récupération automatique pour renforcer la résilience :

async function checkAndRecoverPage(page) {
  if (!page.isClosed()) {
    try {
      await page.reload();
    } catch {
      page = await browser.newPage();
    }
  }
  return page;
}

Optimisation du débogage des scripts

Améliorez vos scripts pour faciliter leur maintenance et accélérer la résolution des erreurs en vous appuyant sur des techniques de débogage éprouvées.

Clarté du code

Gardez votre code lisible en regroupant les configurations et en utilisant des noms clairs et descriptifs :

// Group related configurations
const browserConfig = {
  headless: false,
  defaultViewport: { width: 1920, height: 1080 },
  args: ['--no-sandbox', '--disable-setuid-sandbox']
};

// Use descriptive function names
async function validatePageContent(page) {
  const pageTitle = await page.title();
  console.log(`Validating content for page: ${pageTitle}`);

  const contentExists = await page.evaluate(() => {
    const mainContent = document.querySelector('.main-content');
    return {
      hasHeader: !!document.querySelector('header'),
      hasContent: !!mainContent,
      contentLength: mainContent?.textContent.length || 0
    };
  });

  return contentExists;
}

Organisation des modules

Divisez vos scripts en modules distincts afin de simplifier le débogage. Cette approche isole les sélecteurs, les actions et les validations, ce qui facilite la localisation et la correction des erreurs.

// selectors.js
export const SELECTORS = {
  loginForm: '#login-form',
  submitButton: '[data-testid="submit-btn"]',
  errorMessage: '.error-notification'
};

// actions.js
export async function performLogin(page, credentials) {
  await page.type(SELECTORS.loginForm + ' input[name="username"]', credentials.username);
  await page.type(SELECTORS.loginForm + ' input[name="password"]', credentials.password);
  await Promise.all([
    page.waitForNavigation(),
    page.click(SELECTORS.submitButton)
  ]);
}

// validators.js
export async function checkLoginStatus(page) {
  const errorElement = await page.$(SELECTORS.errorMessage);
  if (errorElement) {
    throw new Error('Login failed: ' + await page.evaluate(el => el.textContent, errorElement));
  }
}

Cette structure modulaire organise non seulement votre code, mais simplifie également le suivi des erreurs.

Configuration du suivi des erreurs

Configurez un suivi des erreurs pour identifier rapidement les problèmes et fournir un contexte détaillé pour le débogage :

class PuppeteerError extends Error {
  constructor(message, action, selector) {
    super(message);
    this.name = 'PuppeteerError';
    this.action = action;
    this.selector = selector;
    this.timestamp = new Date().toISOString();
  }
}

async function executeWithTracking(page, action, description) {
  try {
    await action();
  } catch (error) {
    const screenshot = await page.screenshot({
      path: `error-${Date.now()}.png`,
      fullPage: true
    });

    throw new PuppeteerError(
      `Failed to ${description}`,
      error.message,
      error.selector
    );
  }
}

Vous pouvez également automatiser la journalisation des erreurs et avertissements de console :

page.on('console', message => {
  const type = message.type();
  const text = message.text();

  if (type === 'error' || type === 'warning') {
    console.log(`[${type.toUpperCase()}] ${text}`);

    // Log to external service or file
    logger.log({
      level: type,
      message: text,
      timestamp: new Date().toISOString(),
      url: page.url()
    });
  }
});

Validation des opérations critiques

Ajoutez des contrôles de validation pour garantir que les opérations critiques sont correctement exécutées :

async function validateOperation(page, action) {
  const beforeState = await page.evaluate(() => ({
    url: window.location.href,
    elements: document.querySelectorAll('*').length
  }));

  await action();

  const afterState = await page.evaluate(() => ({
    url: window.location.href,
    elements: document.querySelectorAll('*').length
  }));

  return {
    urlChanged: beforeState.url !== afterState.url,
    elementsDelta: afterState.elements - beforeState.elements
  };
}

Ces techniques, associées aux méthodes de débogage précédentes, vous aident à identifier et résoudre rapidement les problèmes tout en maintenant vos scripts facile à maintenir.

Conclusion

Techniques de débogage clés

Le débogage visuel en mode navigateur visible avec slowMo permet d’obtenir un retour immédiat sur les scripts et d’ajuster précisément le timing. Pour des cas plus détaillés, le protocole DevTools offre un débogage pas à pas et un accès aux journaux de processus pour obtenir des informations plus approfondies.

const browser = await puppeteer.launch({
    headless: false,
    slowMo: 100,
    devtools: true,
    dumpio: true
});

Pour améliorer votre workflow, envisagez d’intégrer des pratiques de surveillance continue et de gestion des ressources en complément de ces méthodes de débogage.

Prochaines étapes

Maintenant que vous disposez d’une base solide en techniques de débogage, voici comment optimiser et maintenir vos scripts Puppeteer :

  • Surveillance des performances : utilisez une journalisation détaillée pour suivre les temps d’exécution et l’utilisation des ressources. Cela aide à identifier les goulots d’étranglement et rend le débogage plus efficace.
  • Prévention des erreurs : ajoutez le plugin puppeteer-extra-plugin-stealth pour réduire la détection de l’automatisation et limiter les échecs de scripts.
  • Gestion des ressources : privilégiez une utilisation efficace de la mémoire et mettez en place des routines de nettoyage pour maintenir le bon fonctionnement de vos scripts.

Voici un exemple de fonction de nettoyage pour gérer efficacement les ressources :

async function cleanupResources(page) {
    await page.evaluate(() => {
        if (window.performance.memory) {
            console.log(`Heap size limit: ${(window.performance.memory.jsHeapSizeLimit / 1024 / 1024).toFixed(2)} MB`);
        }
    });
    await page.close();
}

Gardez une longueur d’avance en consultant régulièrement le dépôt GitHub de Puppeteer pour découvrir les mises à jour, les nouvelles fonctionnalités et les bonnes pratiques. Maintenir votre boîte à outils à jour garantit que vos scripts restent efficaces et adaptables à mesure que les technologies web évoluent.

FAQ

Frequently Asked Questions

Lancez Puppeteer avec headless: false, slowMo (généralement 100 à 250 ms pour les clics, jusqu’à 500 à 1 000 ms pour le contenu dynamique) et devtools: true. Vous pouvez ainsi observer chaque action dans une fenêtre de navigateur visible et inspecter les éléments dans Chrome DevTools pendant l’exécution du script.

Cela vous a aidé ? Partagez-le →

Écrit par

Vasiliy Datsenko

Responsable du support client

Vasiliy Datsenko est responsable du support client chez Latenode et un rédacteur en automatisation axé sur les produits. Son travail relie les conversations clients, la recherche sur l'automatisation des flux de travail, les cas d'utilisation de l'IA et la formation pratique sur les produits pour les équipes cherchant à automatiser des processus métier réels.

Profil de l'auteur →

Vérifié par

Oleg Zankov

PDG de Latenode, expert en no-code

Avec une philosophie ancrée dans l'innovation, la résolution de problèmes et l'expérience utilisateur, je me consacre à donner aux équipes les moyens de créer des intégrations sur mesure et d'automatiser les workflows avec facilité et efficacité. Fort d'une riche expérience en développement commercial, entrepreneurship technologique et développement logiciel, j'ai reconnu le besoin d'une solution d'intégration plus accessible, évolutive et adaptable. Ainsi est né Latenode.com. Grâce à notre plateforme, les entreprises peuvent exploiter la puissance de la technologie sans nécessiter de compétences approfondies en codage. Passionné par la création d'un avenir où la technologie nous sert, et non l'inverse, ma mission est de simplifier les processus complexes. Je crois en la démocratisation de la technologie et en dotant les équipes des outils nécessaires pour innover, croître et réussir dans un monde de plus en plus numérique.

Profil de l'auteur →

Continuer la lecture