Laténode

Exécution de JavaScript dans le contexteune page avec page.evaluate dans Puppeteer

Apprenez à utiliser efficacement la méthode page.evaluate de Puppeteer pour exécuter du JavaScript dans le contexte du navigateur pour les tâchesautomatisation web.

RaianRaian
Exécution de JavaScript dans le contexteune page avec page.evaluate dans Puppeteer

page.evaluate() est une clé Marionnettiste méthode permettantexécuter JavaScript directement dans le contexte du navigateur. Elle fait le lien Node.js et le navigateur, permettant des tâches telles que la manipulation du DOM, l'extraction de données et l'automatisation de pages web dynamiques. Voici ce que vous devez savoir :

  • Ce qu'il fait: Exécute JavaScript dans le navigateur, comme si vous utilisiez la console du navigateur.
  • Comment ça marche: Convertit une fonction en chaîne, l'envoie au navigateur, l'exécute et renvoie le résultat.
  • Utilisations clés:
    • Extraction de données à partir de sites Web (par exemple, texte, tableaux, JSON).
    • Automatisation des soumissions de formulaires et des interactions des utilisateurs.
    • Gestion de contenu dynamique comme le défilement infini ou les mises à jour AJAX.
  • Limites: Les fonctions doivent être sérialisables en JSON et les variables Node.js ne sont pas directement accessibles dans le contexte du navigateur.

Exemple rapide :

<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>);

Cela récupère le titre de la page directement à partir du navigateur.

Comparaison: Node.js vs. Contexte du navigateur

CaractéristiqueContexte de Node.jsContexte du navigateur
Objets globauxprocessus, nécessitentfenêtre, document
Emplacement du scriptMachine localePage Web cible
Accès APIAPI Node.jsAPI Web du navigateur

Utilisez le page.evaluate() pour des tâchesautomatisation précises et efficaces, en particulier lorsque vous travaillez avec des sites Web riches en JavaScript.

NodeJS : Nodejs/Marionnettiste - Comment utiliser page.evaluate

Contexte de la page expliqué

Lorsque vous travaillez avec Puppeteer pour l'automatisation Web, il est essentiel de comprendre la distinction entre Contexte Node.js et la contexte du navigateurCes deux environnements sont isolés, chacun avec ses propres règlesexécution de code etéchange de données.

Comparaison des contextes Node.js et du navigateur

Puppeteer opère dans deux environnements : le Contexte Node.js, où votre script principal s'exécute, et le contexte du navigateur, où se produisent les interactions avec la page web. Il s'agit de processus distincts, chacun disposant de sa propre machine virtuelle. [3].

Voici une comparaison rapide de leurs principales caractéristiques :

CaractéristiqueContexte de Node.jsContexte du navigateur
Objets globauxprocessus, exigence, __dirnamefenêtre, document, stockage local
Emplacement du scriptMachine localePage Web cible
Portée variablePortée du script du marionnettistePortée du contexte de la page
Accès APIAPI Node.jsAPI Web du navigateur
Espace mémoireProcessus séparéProcessus du navigateur

Comment fonctionne la communication contextuelle

L'échange de données entre ces contextes implique une sérieétapes, s'appuyant fortement sur la sérialisation :

  1. La fonction est convertie en chaîne à l'aide de Function.prototype.toString() [1].
  2. Cette chaîne est envoyée au navigateur via le Protocole Chrome DevTools [1].
  3. Le navigateur évalue la fonction dans son environnement.
  4. Les résultats sont sérialisés en JSON et renvoyés au contexte Node.js [1].

Principales limitesLes fonctions du navigateur ne peuvent pas accéder directement aux variables de la portée Node.js. Puppeteer propose des outils spécifiques pour répondre à ces défis :

  • page.evaluateHandle(): Renvoie des références aux objets dans le contexte du navigateur [1].
  • page.exposeFunction(): Permet au navigateurappeler des fonctions Node.js [1].
  • evaluateOnNewDocument(): Exécute le code avant le chargement des scripts de page [1].

Cependant, la sérialisation JSON peut supprimer certaines propriétés, en particulier avec des objets complexes comme les nœuds DOM [2]Pour éviter les problèmes, transmettez les données sous formearguments de fonction au lieu de vous fier aux variables Node.js [3].

La maîtrise de ces techniques de communication vous garantit de pouvoir utiliser page.evaluate efficacement pour les tâchesautomatisation. Nous explorerons ensuite des exemples pratiques pour mettre ces concepts en pratique.

Premiers pas avec page.evaluate

Structure et paramètres de la méthode

syntaxe:

<span class="hljs-keyword">await</span> page.<span class="hljs-title function_">evaluate</span>(pageFunction, ...args)
ParamètreTypeDescription
pageFonctionFonction ou chaîneCode JavaScript à exécuter dans le contexte du navigateur
argsParamètres facultatifsValeurs transmises de Node.js au contexte du navigateur
Valeur de retourPromesseRésout avec la valeur de retour de la fonction

Le pageFonction Il peut s'agirune fonction ouune chaîne contenant du code JavaScript. L'utilisationune fonction est généralement plus adaptée au débogage et Manuscrit Compatibilité. Voici quelques exemples pour illustrer son fonctionnement.

Exemples de code de base

Exemples :

  • Extraire le texte du premier <h1> directement depuis le 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>;
});
  • Automatisez la soumission du formulaire en passant des paramètres :
<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>);
  • Manipuler le DOM en ajoutant un nouvel élément :
<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>;
});

Notes clés pour le développement

  • Les fonctions s'exécutent de manière isolée de votre code Node.js.
  • Les arguments passés à la fonction doivent être JSON-sérialisable.
  • Les valeurs renvoyées sont automatiquement encapsulées dans un Promesse.
  • La manipulation d’objets complexes comme les nœuds DOM nécessite une attention particulière.

Conseil de débogage : Utilisez la configuration suivante pour activer le débogage pendant le développement :

<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>
});

Ensuite, nous allons plonger dans les techniques d’échange de données entre Node.js et les contextes de navigateur.

Échange de données entre contextes

Paramètresentrée

Lors du transfert de données avec page.evaluate, s'en tenir aux valeurs sérialisables JSON pour les argumentsentrée.

Voici une brève description des types de paramètres pris en charge :

Type de paramètrePrise en charge?Exemple
Primitives✓ Entièrement'texte', 42, vrai
Tableaux/Objets✓ Compatible JSON{ clé: 'valeur' ​​}, [1, 2, 3]
Les fonctions✗ Pas directementUtilisez page.exposeFunction
Éléments DOM✓ Via JSHandleUtilisez page.evaluateHandle

Voyons maintenant comment ces valeurs sont renvoyées à partir du contexte du navigateur.

Gestion des sorties

Lors de l'utilisation page.evaluateLes valeurs renvoyées sont automatiquement sérialisées au format JSON. Voici comment cela fonctionne :

<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>()
}));

« En règle générale, si la valeur de retour de la fonction donnée est plus compliquée qu'un objet JSON (par exemple, la plupart des classes), alors evaluate renverra probablement une valeur tronquée (ou {}). Cela est dû au fait que nous ne renvoyons pas la valeur de retour réelle, mais une version désérialisée résultant du transfert de la valeur de retour via un protocole vers Puppeteer. [1]

Une fois la sortie récupérée, vous pourriez rencontrer des problèmes de sérialisation. Voici comment les résoudre.

Gestion des problèmes de sérialisation

Certains scénarios courants nécessitent des solutions de contournement spécifiques :

  • Travailler avec les éléments 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>
  • Utilisation des fonctions 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>);
});
  • Réglage des paramètres du transpileur

Si vous travaillez avec TypeScript, assurez-vous que votre transpileur est correctement configuré :

<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>
    }
}

Ces stratégies vous aideront à gérer efficacement l’échange de données dans divers contextes.

sbb-itb-23997f1

Exemples pratiques

Voici comment vous pouvez utiliser page.evaluate dans des scénarios réels, accompagnésextraits de code pratiques.

Extraction de données

Exemple : Récupération des détails du produit

Ce script collecte des détails tels que le titre, le prix, la note et l'état du stock à partir des fiches produits sur une page 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>)
  }));
});

Exemple : Extraction de données de table

Cette approche récupère les donnéesune table en parcourant ses lignes et ses colonnes :

<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>);
  });
});

Automatisation des formulaires

Automatisation de base des formulaires

Voici comment remplir les champs du formulaire, déclencher des événements et soumettre le formulaire :

<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>();
});

Gestion de formulaires complexes

Pour des tâches telles que la sélectionoptions déroulantes ou la vérification de boutons radio :

<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> }));
});

Gestion des éléments dynamiques

Exemple : défilement infini

Ce script fait défiler une page jusqu'à ce qu'il collecte au moins 100 éléments :

<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);
});

Exemple : gestion du contenu AJAX

Pour charger plus de contenu de manière dynamique, ce script clique sur un bouton « Charger plus » et attend que de nouveaux éléments apparaissent :

<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>
    });
  });
});

Ces exemples illustrent la gestion de divers scénarios tels que le scraping, l'automatisation des formulaires et le contenu dynamique. Des ajustements peuvent être apportés en fonction de la structure et du comportement spécifiques de la page web utilisée.

Utilisation de page.evaluate dans Laténode

Latenode intègre les fonctionnalités principales de Puppeteer à ses workflowsautomatisation, facilitant ainsi l'exécution de JavaScript directement dans le navigateur. page.evaluateLes utilisateurs peuvent manipuler le DOM et extraire efficacement les données. Cette approche permet une intégration transparente de la gestion avancée des données et des opérations DOM dans l'environnementautomatisation de Latenode.

Scripts de navigateur dans Latenode

Le moduleautomatisation du navigateur de Latenode utilise page.evaluate Pour gérer toutes les tâches, des tâches DOM simples aux exécutions JavaScript plus complexes. Voici son fonctionnement dans différents scénarios :

<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;
});

Latenode conserve également un journal de l'historiqueexécution, ce qui facilite le débogage des scripts.

Exemplesautomatisation

Latenode est parfaitement équipé pour gérer le contenu dynamique et les tâchesautomatisation complexes. Voici un exemple de traitement de contenu dynamique sur une page :

<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>
    }));
});

Pour des opérations plus avancées, page.exposeFunction permet une interaction transparente entre Node.js et le navigateur :

<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);
});

Pour conserver les références aux éléments DOM à travers les étapes, Latenode utilise 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);

Ces techniques permettent à Latenode de gérer efficacement le contenu dynamique tout en maintenant des performances fiables. Pour les utilisateurs de l'offre Prime, la plateforme prend en charge jusqu'à 1.5 millionexécutions de scénarios par mois, offrant ainsi des capacitésautomatisation étendues.

Guide de résolution des erreurs

Lorsque vous travaillez avec page.evaluate L'automatisation des navigateurs peut engendrer divers problèmes. Voici des solutions pratiques pour les résoudre et garantir une exécution plus fluide.

Correction des erreurs de contexte

Configurez correctement vos paramètres TypeScript pour éviter les problèmes liés à la transpilation. Par exemple :

<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>);

Évitez de renvoyer des éléments DOM directement depuis page.evaluate. Au lieu de cela, utilisez ElementHandle pour une meilleure maniabilité :

<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>);
});

Résoudre les problèmes de synchronisation

Les scripts peuvent s'exécuter avant le chargement complet de la page, ce qui peut entraîner des erreurs de synchronisation. Utilisez les stratégies suivantes pour gérer ces situations :

<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> });

Pour les sites Web dynamiques, adoptez des mécanismesattente plus ciblés :

<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>
});

Gestion des références DOM

Pour éviter les fuites de mémoire, gérez soigneusement les références DOM. Voici comment :

<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>

Lorsque vous travaillez avec plusieurs éléments, transmettez les données en toute sécurité entre les contextes :

<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);

Pour les écouteursévénements, assurez-vousun nettoyage approprié pour éviter les gestionnaires persistants :

<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);
  });
});

Directives de mise en œuvre

Pour obtenir les meilleurs résultats avec page.evaluate, vous devez vous concentrer sur l'amélioration des performances, la réduction des changements de contexte inutiles et la sécurité. Voici comment affiner les workflowsautomatisation de votre navigateur.

Optimisation des performances

Exécuter efficacement du code dans le contexte de la page permet de gagner du temps etéconomiser des ressources système. Voici quelques techniques pour accélérer vos scripts :

<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;
});

Le choix des bons sélecteurs joue également un rôle important dans la performance :

Type de sélecteurSpeedExemple
IDRésultats des tests#contenu principal
ClasseRapide.produit-article
JourModéréediv > span
XPath complexeLe plus lent//div[@class='wrapper']//span

Gestion du changement de contexte

Le changement de contexte entre Node.js et l'environnement du navigateur peut ralentir l'exécution. Voici comment le minimiser :

<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);

Si vous devez traiter des données dans Node.js et les renvoyer au navigateur, exposez des fonctions au lieu de changer de contexte à plusieurs reprises :

<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>
});

Consignes de sécurité

Une fois les performances et le changement de contexte optimisés, concentrez-vous sur la sécurité de vos scripts. Voici quelques bonnes pratiques :

<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);
}

Pour les workflows Latenode, tenez compte de ces conseils supplémentaires :

  • Utilisez le userDataDir pour mettre en cache les ressources et améliorer les performances entre les sessions.
  • Fermez les pages inutilisées et les instances de navigateur pour économiser de la mémoire.
  • Gérez les capturesécran avec des tampons au lieu de vous fier aux opérations du système de fichiers.
  • Mettez en œuvre une gestion des erreurs robuste et des contrôles de sécurité approfondis.

Résumé

Examen des points clés

Le page.evaluate La méthode connecte Node.js et les contextes du navigateur en envoyant une fonction JavaScript transformée en chaîne à exécuter dans le navigateur. Cette fonction fonctionne indépendamment de l'environnement Node.js ; le transfert de données doit donc être géré avec précaution.

Voici un exemple courant d’extraction de données :

<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>()
  }));
});

Les choses à garder à l'esprit:

  • Les arguments doivent être sérialisables en JSON.
  • Les valeurs de retour sont automatiquement désérialisées.
  • Les API du navigateur ne sont disponibles que dans le evaluate contexte
  • Les variables Node.js ne sont pas accessibles dans le contexte du navigateur.

Ces bases constituent les basesune utilisation efficace de Puppeteer. Des outils supplémentaires peuvent encore optimiser vos tâchesautomatisation.

Outils supplémentaires pour marionnettistes

Puppeteer propose plusieurs outils pour étendre les capacités de page.evaluate:

OutilInteretMeilleur casutilisation
page.évaluerHandleRenvoie les référencesobjetInteragir directement avec les éléments DOM
page.exposerFonctionRend les fonctions Node.js utilisables dans le navigateurGestionune logique complexe côté serveur
page.evaluateOnNewDocumentExécute des scripts avant le chargementune pagePréparation préalable de l'environnement du navigateur

Par exemple, l'exposition des fonctions Node.js au navigateur peut simplifier le traitement avancé des données dans les workflows comme ceux de Latenode. page.evaluate fonctionne bien pour gérer les types primitifs et les objets sérialisables JSON, page.evaluateHandle est essentiel pour traiter des objets de navigateur complexes qui ne peuvent pas être sérialisés.

articles similaires

Raian

Chercheur, expert Nocode

Détails de l'auteur →