Dopo aver introdotto Puppeteer nella lezione precedente, ora ci addentriamo nel suo utilizzo pratico per controllare il browser in modo programmatico. Grazie a Puppeteer, possiamo automatizzare numerose operazioni che altrimenti dovremmo eseguire manualmente, come l'apertura di pagine web, l'interazione con gli elementi della pagina e persino la simulazione del comportamento dell'utente.
Questo strumento basato su Node.JS si rivela particolarmente utile in diversi contesti, tra cui il web scraping, il testing automatizzato di applicazioni web e la generazione di screenshot o PDF di pagine web. Inoltre, grazie alla sua integrazione con il motore di rendering di Chrome, Puppeteer permette di eseguire operazioni avanzate, come il caricamento dinamico dei contenuti, l'analisi delle performance di una pagina e la gestione delle richieste di rete. Approfondiremo quindi come sfruttare al meglio le sue API per realizzare script efficienti e personalizzati, in grado di adattarsi a diversi scenari di utilizzo.
Configurazione delle opzioni di lancio
Puppeteer ci offre diverse opzioni di configurazione quando lanciamo il browser. Ad esempio, possiamo avviarlo in modalità headless (senza interfaccia grafica) oppure con una finestra visibile per il debugging.
const browser = await puppeteer.launch({ headless: false, slowMo: 50 });
L'opzione slowMo
rallenta le operazioni di Puppeteer per aiutarci a visualizzare meglio cosa sta accadendo. Un'altra opzione utile è args
, che ci permette di passare parametri aggiuntivi al browser:
const browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] });
Queste opzioni sono particolarmente utili quando eseguiamo Puppeteer su server remoti.
Controllare la navigazione con Puppeteer
Uno degli aspetti fondamentali del controllo del browser è la gestione della navigazione tra le pagine. Possiamo navigare verso un URL specifico con il metodo goto()
:
await page.goto('https://example.com');
Possiamo anche gestire il caricamento delle pagine in base a diversi criteri:
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
L'opzione waitUntil
specifica quando considerare la pagina completamente caricata. I valori possibili sono load
, domcontentloaded
, networkidle0
e networkidle2
. Nel dettaglio:
- load: attende che l'evento
load
della pagina sia stato completamente attivato, ovvero quando tutte le risorse (immagini, script, fogli di stile) sono state caricate. - domcontentloaded: attende che l'evento
DOMContentLoaded
sia stato attivato, cioè quando l'HTML è stato completamente caricato e analizzato. Senza aspettare il caricamento di immagini e fogli di stile. networkidle0
: attende che non ci siano più richieste di rete in sospeso per almeno 500 ms. Questo è utile quando la pagina carica molte risorse dinamiche.networkidle2
: attende che ci siano al massimo 2 richieste di rete in corso per almeno 500 ms. È un buon compromesso tra attesa completa e velocità.
Navigare tra più pagine
Possiamo aprire nuove schede nel browser e passare da una all'altra:
const page2 = await browser.newPage();
await page2.goto('https://example.com/second-page');
Possiamo anche chiudere una pagina specifica:
await page2.close();
Interagire con gli elementi della pagina con Puppeteer
Uno degli aspetti più potenti di Puppeteer è la possibilità di interagire con gli elementi della pagina come farebbe un utente umano. Possiamo simulare clic, digitazione e altre azioni.
Simulare un clic
Per simulare un clic su un pulsante o un link, possiamo utilizzare il metodo click()
su un elemento selezionato:
await page.click('button#submit');
Dove button#submit
è il selettore CSS dell'elemento su cui vogliamo fare clic.
L'uso di await
indica che page.click(...)
è un'operazione asincrona, il che significa che Puppeteer attenderà che il clic venga eseguito prima di passare alla successiva istruzione del codice. Senza await
, lo script potrebbe proseguire l'esecuzione senza assicurarsi che il clic sia stato effettivamente eseguito.
Il metodo click()
appartiene all'oggetto page
che rappresenta una pagina aperta nel browser controllato da Puppeteer. Se l'elemento button#submit
non è ancora presente nel DOM o non è visibile, Puppeteer potrebbe generare un errore. Per evitare problemi, è possibile attendere che l'elemento sia disponibile prima di cliccare, ad esempio con:
await page.waitForSelector('button#submit'); // Attende che l'elemento sia presente nel DOM
await page.click('button#submit'); // Clicca sul pulsante
Inserire testo in un campo di input
Per compilare un modulo, possiamo usare type()
per inserire testo in un campo di input:
await page.type('input[name="username"]', 'mioUsername');
Possiamo anche simulare la pressione di un tasto:
await page.keyboard.press('Enter');
Eseguire il login a un sito web
Vediamo un esempio pratico in cui effettuiamo il login a un sito web:
await page.goto('https://example.com/login');
await page.type('#username', 'mioUsername');
await page.type('#password', 'miaPassword');
await page.click('#login-button');
await page.waitForNavigation();
Dopo aver compilato il form e fatto clic sul pulsante di login, usiamo waitForNavigation()
per attendere che la nuova pagina si carichi completamente.
Scattare screenshot e salvare pagine con Puppeteer
Puppeteer ci permette anche di scattare screenshot delle pagine o di salvarle come file HTML/PDF.
Screenshot
await page.screenshot({ path: 'screenshot.png', fullPage: true });
Questo comando salva uno screenshot dell'intera pagina corrente.
Salvare una pagina come PDF
await page.pdf({ path: 'pagina.pdf', format: 'A4' });
Questo ci permette di generare un PDF della pagina visualizzata, utile per report automatici.
Gestire i timeout e i ritardi con Puppeteer
A volte una pagina impiega più tempo del previsto a caricarsi, quindi dobbiamo gestire i timeout. Puppeteer offre diverse strategie per questo.
Attendere un elemento specifico
await page.waitForSelector('#contenuto');
Questo comando attende che un elemento con id contenuto
sia disponibile nella pagina.
Attendere un certo tempo
await page.waitForTimeout(5000); // attende 5 secondi
Questa soluzione non è sempre ottimale, ma utile in alcuni scenari.
Simulare diverse dimensioni dello schermo
Per testare un sito su diversi dispositivi, possiamo impostare una dimensione di viewport specifica:
await page.setViewport({ width: 1280, height: 800 });
Possiamo anche simulare un dispositivo mobile:
const iPhone = puppeteer.devices['iPhone X'];
await page.emulate(iPhone);
Debugging e gestione degli errori con Puppeteer
Quando lavoriamo con Puppeteer, potremmo incontrare errori durante l'esecuzione degli script. Un metodo utile per il debugging è abilitare il logging della console del browser:
page.on('console', msg => console.log('LOG:', msg.text()));
Possiamo anche usare evaluate()
per eseguire codice direttamente nella console del browser:
const titolo = await page.evaluate(() => document.title);
console.log('Titolo della pagina:', titolo);
Infine, possiamo gestire eventuali errori con un blocco try...catch
:
try {
await page.goto('https://example.com');
} catch (error) {
console.error('Errore durante il caricamento della pagina:', error);
}
Conclusioni
Abbiamo esplorato le basi del controllo del browser con Puppeteer, coprendo operazioni fondamentali come la navigazione, l'interazione con gli elementi, la gestione dei timeout e il debugging. Queste competenze ci permettono di creare script di automazione potenti e versatili, in grado di simulare il comportamento umano all'interno del browser.
Con questi strumenti, possiamo automatizzare compiti ripetitivi, testare applicazioni web e raccogliere dati in modo più efficiente. Nella prossima lezione vedremo come sfruttare Puppeteer per il web scraping, permettendoci di estrarre informazioni dalle pagine web in modo automatico e scalabile.