← Torna al blog

Scrivere il tuo primo script g.*

· 5 min di lettura ·
tutorial

Hai installato Guida, hai cliccato qualche pagina, magari hai dato un’occhiata alle impostazioni. E adesso? Questo post ti accompagna nella scrittura del tuo primo script reale: uno script che naviga a una pagina, ne estrae dati e li salva in un posto utile.

Non serve esperienza precedente di scripting. Se hai già scritto JavaScript, ti sentirai subito a casa. In caso contrario, l’API è abbastanza piccola da impararla mentre procediamo.

Aprire l’editor degli script

Premi Ctrl+N o vai su File > Nuovo script (File > New Script). Otterrai una scheda editor vuota con IntelliSense già collegato. Digita g. e vedrai l’intero insieme delle API: oltre 160 metodi organizzati in spazi dei nomi come g.store, g.queue, g.search e altri.

Ogni script in Guida ha la stessa forma:

async function main() {
// il tuo codice qui
}

La parola chiave async conta: la maggior parte dei metodi g.* è asincrona perché comunica con un browser attivo. L’ambiente di esecuzione chiama main() per te; devi solo definirla e premere F5 per eseguire.

Iniziamo in modo semplice. Andremo su Hacker News e attenderemo il caricamento della pagina:

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

g.nav.navigateToUrl() dice alla scheda del browser attiva di caricare un URL. g.dom.waitForDomStable() attende che il DOM smetta di cambiare: niente altri elementi che appaiono, niente spinner, niente contenuto lazy-loaded ancora in arrivo. Insieme sono la base di qualsiasi script di automazione.

Eseguilo con F5. Vedrai la scheda del browser navigare verso Hacker News. Il pannello Console in basso mostrerà un messaggio di successo.

Come funzionano i metodi g.*

Prima di andare oltre, c’è una convenzione da conoscere. Ogni metodo g.* restituisce direttamente il risultato e genera un’eccezione in caso di errore.

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

Se l’operazione riesce, il valore restituito contiene il risultato. Se fallisce, viene generata un’eccezione. Usa try/catch per gestire gli errori:

try {
const elements = await g.dom.getElements(".item", ["innerText"]);
g.log("Trovati " + elements.length + " elementi");
} catch (e) {
g.log("Impossibile trovare elementi: " + e.message);
return;
}

g.log() scrive un messaggio nel pannello Console.

Estrarre dati dalla pagina

Ora facciamo qualcosa di utile. Prenderemo titoli e link da 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("Trovate " + items.length + " storie");
for (const item of items) {
g.log(item.innerText);
}
}

g.dom.getElements(selector, attributes) interroga il DOM e restituisce un array di oggetti, ciascuno con gli attributi richiesti. È simile a document.querySelectorAll(), ma restituisce dati strutturati invece di nodi DOM.

Eseguilo e vedrai 30 titoli di storie registrati nella console.

Salvare i risultati in uno spazio di lavoro

I log vanno bene per il debug, ma cosa succede se vuoi conservare i dati? È qui che servono spazi di lavoro e g.store.

Prima apri uno spazio di lavoro: File > Apri spazio di lavoro (File > Open Workspace), poi scegli o crea una cartella. Questo dà agli script una cartella di lavoro e abilita l’archiviazione persistente.

Ora aggiorna lo script per salvare ogni storia:

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("Salvate " + count + " storie");
}

g.store.put(collection, key, data) salva un documento JSON in una raccolta nominata. La chiave è univoca dentro la raccolta: se esegui di nuovo lo script, le storie esistenti vengono aggiornate invece di essere duplicate. I dati vengono salvati in un file store.db nella cartella dello spazio di lavoro.

Dopo l’esecuzione, apri il pannello Archiviazione (Store) per sfogliare le storie salvate. Puoi anche interrogarle da un altro script:

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

Elaborare la coda con processi di lavoro

E se volessi visitare l’URL di ogni storia ed estrarre altri dati? Prima metti in coda gli URL:

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("Messi in coda " + count + " URL da visitare");
}

Ora, invece di scrivere un ciclo manuale di dequeue, usa i processi di lavoro. I processi aprono più schede del browser ed elaborano elementi di coda in parallelo: ogni scheda esegue il tuo script in modo indipendente.

Crea uno script per singolo elemento nello spazio di lavoro in 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("Visitato: " + (title || ctx.item.data.title));
g.queue.commit(ctx.item.id);
}

g.worker.getContext() dà a ogni processo di lavoro l’elemento di coda corrente e l’ID scheda. Lo script naviga, estrae e chiama commit() per segnare l’elemento come completato. Se lo script fallisce prima del commit, l’elemento torna automaticamente in coda.

Poi avvia i processi da qualsiasi script (o dalla console):

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

Fatto. Guida apre 3 schede affiancate, e ciascuna elabora elementi dalla coda in modo indipendente. Il pannello Processi di lavoro (Workers) mostra l’avanzamento in tempo reale: elementi elaborati, errori, profondità della coda, e permette di mettere in pausa o fermare il pool senza toccare codice.

Cosa fare dopo

Hai visto il flusso di lavoro principale: navigare, estrarre, salvare, mettere in coda, usare processi di lavoro. Da qui puoi esplorare:

L’editor degli script ha IntelliSense completo: digita g. ovunque e lascia che l’autocomplete ti guidi. Buon scripting.