← Retour au blog

Écrire votre premier script g.*

· 5 min de lecture ·
tutorial

Vous avez installé Guida, cliqué dans quelques pages, peut-être regardé les paramètres. Et maintenant ? Cet article vous guide dans l’écriture de votre premier vrai script : un script qui navigue vers une page, en extrait des données et les enregistre quelque part d’utile.

Aucune expérience préalable en scripting n’est requise. Si vous avez déjà écrit un peu de JavaScript, vous serez à l’aise. Sinon, l’API est assez petite pour être apprise en avançant.

Ouvrir l’éditeur de scripts

Appuyez sur Ctrl+N ou allez dans File > New Script. Vous obtenez un onglet d’éditeur vide avec IntelliSense déjà branché. Tapez g. et vous verrez toute la surface API : plus de 160 méthodes organisées en espaces de noms comme g.store, g.queue, g.search et d’autres.

Tous les scripts Guida ont la même forme :

async function main() {
// your code here
}

Le mot-clé async compte : la plupart des méthodes g.* sont asynchrones parce qu’elles parlent à un navigateur vivant. Le runtime appelle main() pour vous ; définissez-la puis appuyez sur F5 pour exécuter.

Commençons simplement. Nous allons ouvrir Hacker News et attendre le chargement :

async function main() {
await g.nav.navigateToUrl("https://news.ycombinator.com");
await g.dom.waitForDomStable();
}

g.nav.navigateToUrl() demande à l’onglet actif de charger une URL. g.dom.waitForDomStable() attend que le DOM cesse de changer : plus d’éléments qui apparaissent, plus de spinners, plus de contenu lazy-loaded en cours d’arrivée. Ensemble, ce sont les bases de tout script d’automatisation.

Exécutez avec F5. L’onglet navigateur navigue vers Hacker News. Le panneau Console en bas affiche un message de succès.

Comment fonctionnent les méthodes g.*

Avant d’aller plus loin, une convention est importante. Chaque méthode g.* renvoie son résultat directement et lève une exception en cas d’erreur.

await g.nav.navigateToUrl("https://example.com");

Si l’opération réussit, la valeur de retour contient le résultat. Si elle échoue, une exception est levée. Utilisez try/catch pour gérer les erreurs :

try {
const elements = await g.dom.getElements(".item", ["innerText"]);
g.log("Found " + elements.length + " items");
} catch (e) {
g.log("Couldn't find items: " + e.message);
return;
}

g.log() écrit un message dans le panneau Console.

Extraire des données de la page

Faisons maintenant quelque chose d’utile. Nous allons récupérer les titres et liens de Hacker News :

async function main() {
await g.nav.navigateToUrl("https://news.ycombinator.com");
await g.dom.waitForDomStable();
const items = await g.dom.getElements(
".titleline > a",
["innerText", "href"]
);
g.log("Found " + items.length + " stories");
for (const item of items) {
g.log(item.innerText);
}
}

g.dom.getElements(selector, attributes) interroge le DOM et renvoie un tableau d’objets, chacun contenant les attributs demandés. C’est comme document.querySelectorAll(), mais avec des données structurées plutôt que des nœuds DOM.

Exécutez ce script et vous verrez 30 titres journalisés dans la console.

Stocker les résultats dans un espace de travail

Journaliser suffit pour le débogage, mais que faire si vous voulez garder les données ? Les espaces de travail et g.store sont faits pour cela.

Ouvrez d’abord un espace de travail : File > Open Workspace, puis choisissez ou créez un dossier. Cela donne à vos scripts un dossier racine et active le stockage persistant.

Mettez ensuite le script à jour pour enregistrer chaque histoire :

async function main() {
await g.nav.navigateToUrl("https://news.ycombinator.com");
await g.dom.waitForDomStable();
const items = await g.dom.getElements(
".titleline > a",
["innerText", "href"]
);
for (const item of items) {
const key = item.innerText.substring(0, 80);
g.store.put("stories", key, {
title: item.innerText,
url: item.href,
scrapedAt: new Date().toISOString()
});
}
const count = g.store.count("stories");
g.log("Stored " + count + " stories");
}

g.store.put(collection, key, data) enregistre un document JSON dans une collection nommée. La clé est unique dans la collection : si vous relancez le script, les histoires existantes sont mises à jour au lieu d’être dupliquées. Les données sont stockées dans un fichier store.db du dossier d’espace de travail.

Après exécution, ouvrez le panneau Store pour parcourir les histoires enregistrées. Vous pouvez aussi les interroger depuis un autre script :

const results = g.store.search("stories", "rust");

Traiter la file avec des processus

Et si vous voulez visiter l’URL de chaque histoire et extraire davantage de données ? Commencez par mettre les URL en file :

async function main() {
const stories = g.store.list("stories");
for (const doc of stories) {
g.queue.enqueue("to-visit", {
url: doc.data.url,
title: doc.data.title
});
}
const count = g.queue.count("to-visit");
g.log("Queued " + count + " URLs to visit");
}

Au lieu d’écrire une boucle de dépilage manuelle, utilisez des processus de travail. Ils ouvrent plusieurs onglets navigateur et traitent les éléments de file en parallèle, chaque onglet exécutant votre script indépendamment.

Créez un script par élément dans votre espace de travail à scripts/visit-story.js :

async function main() {
const ctx = g.worker.getContext();
await g.nav.navigateToUrl(ctx.item.data.url);
await g.dom.waitForDomStable();
const title = await g.dom.extractContent("h1");
g.log("Visited: " + (title || ctx.item.data.title));
g.queue.commit(ctx.item.id);
}

g.worker.getContext() donne à chaque processus son élément de file courant et son ID d’onglet. Le script navigue, extrait et appelle commit() pour marquer l’élément comme terminé. Si le script échoue avant commit(), l’élément retourne automatiquement dans la file.

Lancez ensuite les processus depuis n’importe quel script ou depuis la console :

async function main() {
g.workers.start({
queue: "to-visit",
script: "scripts/visit-story.js",
concurrency: 3,
layout: "horizontal"
});
}

C’est tout. Guida ouvre 3 onglets côte à côte, et chacun traite les éléments de la file indépendamment. Le panneau Workers montre la progression en direct : éléments traités, erreurs, profondeur de file, et permet de suspendre ou arrêter le pool sans toucher au code.

Et ensuite

Vous avez maintenant vu le flux central : naviguer, extraire, stocker, mettre en file, traiter avec des processus. Vous pouvez ensuite explorer :

L’éditeur de scripts a IntelliSense complet : tapez g. n’importe où et laissez l’autocomplétion vous guider.