Puppeteer: come usare Chrome attraverso le API per fare browser automation
In questo post scopriamo e impariamo ad usare Puppeteer, uno strumento che permette di creare delle automazioni per Chrome utili per analisi SEO e UX.
Cos'è Puppeteer?
Puppeteer è una libreria Node.JS che mette a disposizione delle API per controllare Chrome o Chromium, sia in modalità "headless" che completi.
▶️ Cosa permette di fare?
Fondamentalmente, permette di eseguire attraverso delle API, tutte le azioni che un utente potrebbe mettere in atto in un sito web attraverso il browser.
Alcuni esempi:
- generare screenshot (anche in PDF) di pagine web,
- scansionarle e creare contenuti pre-renderizzati,
- automatizzare l'invio di form, testare le interfacce, input da tastiera, ecc.,
- misurare le prestazioni e diagnosticare problemi tracciando la "timeline",
- creare un ambiente di test automatizzato e sempre aggiornato.
▶️ Installazione e primi passi
Per utilizzare Puppeteer servono fondamentalmente tre elementi: Node.JS, la libreria e un po' di esperienza di sviluppo e con la sintassi JavaScript.
Installazione di Node.Js
Puoi scaricare il codice sorgente o l'installer per il sistema operativo che utilizzi attraverso la seguente pagina web.
Nella parte finale sono presenti anche le guide per l'installazione in ogni ambiente. Si tratta, comunque, di un'operazione molto semplice.
Installazione di Puppeteer
Una volta installato Node.JS, l'installazione della libreria può avvenire attraverso un gestore di pacchetti, quindi NPM o Yarn, eseguendo il seguente comando da una console (nel mio caso PowerShell).
npm i puppeteer
# or "yarn add puppeteer"
Quello che segue è il risultato.
Come vedi, l'installazione scarica automaticamente anche Chromium, che farà da motore per le automazioni.
L'utilizzo
Dopo questi semplici passaggi è già possibile scrivere il primo script ed eseguirlo.
Il flusso di funzionamento delle operazioni segue sempre il seguente schema: specifichi che viene utilizzata la libreria "puppeteer", crei un'istanza di "Browser", apri le pagine ed esegui delle operazioni su di esse.
In particolare, le righe di codice che seguono aprono la homepage di Amazon salvando uno screenshot.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.amazon.it');
await page.screenshot({ path: 'amazon-screenshot.png' });
await browser.close();
})();
Gli script vanno inseriti all'interno di file JavaScript, quindi, ad esempio amazonss.js. Tali file, vengono successivamente eseguiti come segue (sempre dalla console, quindi da PowerShell).
node amazonss.js
Ed ecco lo screenshot che viene salvato all'interno della directory di esecuzione.
Se non viene specificata una dimensione, lo screenshot viene fatto con dimensioni 800 x 600 px. Ma la dimensione della pagina può essere specificata nello script. Vediamo come.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({
width: 1920,
height: 1080,
deviceScaleFactor: 1,
});
await page.goto('https://www.amazon.it');
await page.screenshot({ path: 'amazon-screenshot.png' });
await browser.close();
})();
In questo modo viene impostata una dimensione della pagina di 1920 x 1080 px. Vediamo il risultato.
Non solo è possibile cambiare le dimensioni della pagina, ma anche emulare un dispositivo. Lo script che segue, ad esempio, emula un iPhone 6 ed effettua uno screenshot.
const puppeteer = require('puppeteer');
const iPhone = puppeteer.devices['iPhone 6'];
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.emulate(iPhone);
await page.goto('https://www.amazon.it');
await page.screenshot({ path: 'amazon-screenshot-mobile.png' });
await browser.close();
})();
Ed ecco il risultato.
Come noti, gli screenshot includono la barra dei cookie, ed è del tutto normale poiché si tratta di una visita vera e propria al sito web.
Come possiamo evitarlo? Semplicemente creando un'azione che agisce come farebbe un utente.. ovvero andiamo a cliccare "Accetta i cookie".
Analizzando il sorgente della pagina web, è facile identificare un "selettore" del bottone, infatti l'ID dell'elemento è "sp-cc-accept".
Un piccolo trucco per individuare subito il selettore?
Se usi Chrome come browser, puoi ispezionare gli elementi con gli Strumenti per Sviluppatori. Per farlo puoi cliccare il tasto dertro sopra a qualsiasi elemento della pagina e selezionare "Ispeziona".
Contemporaneamente si aprirà un'area in cui si può visualizzare il sorgente della pagina. Dal menù del tasto destro cliccato sull'elemento nella tab "Elements" (vedi immagine seguente), selezionando Copy > Copy Selector otterrai proprio il selettore.
Facendolo sul bottone "Accetta cookie" di Amazon, ad esempio, otterrai esattamente "#sp-cc-accept".
Grazie a questo, puoi usare un evento clic per fare tap sul bottone. Quello che segue è un esempio.
const puppeteer = require('puppeteer');
const iPhone = puppeteer.devices['iPhone 6'];
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.emulate(iPhone);
await page.goto('https://www.amazon.it');
var el = await page.waitForSelector('#sp-cc-accept', { timeout: 1000 });
await page.click(el._remoteObject.description);
await page.screenshot({ path: 'amazon-screenshot-mobile-accetta-cookie.png' });
await browser.close();
})();
Ed ecco cosa si ottiene eseguendo lo script: la pagina senza la barra dei cookie.
Una ricerca completa su Amazon con lo scroll
Rendiamo l'operazione un po' più strutturata. Lo script che segue, effettua le seguenti operazioni:
- apre l'homepage di Amazon,
- clicca su "Accetta i cookie" nella barra dei cookie e fa il primo screenshot,
- scrive "smart speaker" nella barra di ricerca e fa il secondo screenshot,
- avvia la ricerca (terzo screenshot con la pagina dei risultati),
- esegue uno scroll-down e produce l'ultimo screenshot.
const puppeteer = require('puppeteer');
const iPhone = puppeteer.devices['iPhone 6'];
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.emulate(iPhone);
await page.goto('https://www.amazon.it');
var el = await page.waitForSelector('#sp-cc-accept');
await page.click(el._remoteObject.description);
await page.screenshot({ path: '1-amazon-screenshot-mobile-home.png' });
await page.type('#nav-search-keywords', 'smart', { delay: 100 });
await page.type('#nav-search-keywords', ' speaker', { delay: 300 });
await page.screenshot({ path: '2-amazon-screenshot-mobile-home-input.png' });
await page.click('#nav-search-form > div.nav-right > div > input');
await page.waitForNavigation();
await page.screenshot({ path: '3-amazon-screenshot-mobile-home-risultati.png' });
await page.evaluate(() => {
window.scrollBy(0, window.innerHeight/1.2);
});
await page.screenshot({ path: '4-amazon-screenshot-mobile-home-risultati-scroll.png' });
await browser.close();
})();
Ed ecco la sequenza delle immagini prodotte.
La seguente risorsa è la documentazione di tutte le funzioni a disposizione nella libreria.
▶️ Alcuni esempi più strutturati
Grazie a queste basi, puoi realizzare dei sistemi anche molto strutturati a supporto delle strategie SEO, UX e CRO.
Ad esempio, ho realizzato un sistema che effettua il crawling dei siti web (specificando il livello di profondità) generando l'alberatura in un file Json (che può essere utilizzato anche per generare il grafo dei link interni) e facendo lo screenshot delle pagine. Lo screenshot viene anche inserito all'interno del Json in formato Base64.
Un'altra sperimentazione molto interessante è quella che ho usato per confrontare le prestazioni dei siti web. In questo caso, andiamo ad emulare uno scenario specificando il dispositivo, la velocità di connessione, la CPU e gli URL da confrontare.
In questo caso si tratta di un test in modalità non headless: si aprono fisicamente i browser simultaneamente e si possono osservare i caricamenti.
Timeline Viewer
Con pochissime righe di codice, puoi anche salvare tutti i dati di caricamento di tutte le risorse di una pagina.
const puppeteer = require('puppeteer');
const iPhone = puppeteer.devices['iPhone 6'];
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.emulate(iPhone);
await page.tracing.start({ path: 'trace.json' });
await page.goto('https://www.google.com');
await page.tracing.stop();
await browser.close();
})();
In questo esempio viene emulata la navigazione utilizzando un iPhone 6, le informazioni vengono registrate in un file Json. Attraverso un viewer (DevTools Timeline Viewer) i dati possono essere convertiti in una dashboard come quella che segue.
▶️ Esempi di script pronti all'uso
Cliccando sul seguente link potrai visualizzare moltissimi esempi da provare semplicemente scaricando i file JavaScript.
Alcuni di questi esempi utilizzano altre librerie oltre a Puppeteer, ma l'installazione ha la stessa modalità: tutto avviene sempre attraverso NPM o Yarn.
▶️ Un ambiente di test per gli script
Se vuoi fare dei test senza configurare l'ambiente Node.JS in locale, puoi farlo attraverso Try Puppeteer, uno strumento web based per testare le funzionalità della libreria.
L'interfaccia è divisa in tre parti: l'area in cui puoi editare il codice, l'area dei risultati e quella dei log.
Tuttavia, vista la semplicità, ti consiglio di utilizzare l'installazione di Node.JS in locale, e di utilizzare questo pannello per avere qualche idea interessante.
▶️ Conclusioni
Pappeteer è uno strumento incredibilmente potente che si mette a fianco di chi si occupa di SEO, di UX, di CRO, ma anche di sviluppo per effettuare dei test "end to end".
Le idee possono essere davvero infinite.. pensa, ad esempio, a monitorare attraverso una mail di report l'evoluzione nel tempo delle SERP features per alcune query di interesse. Oppure monitorare costantemente come i competitor dispongono gli elementi all'interno delle pagine web, e le corrispettive prestazioni.
Pensa alla comodità di pianificare test periodici di invio form, di ricerche e di altre funzionalità. Puoi fare scraping, testare i siti web con qualunque dispositivo automaticamente, verificare il corretto funzionamento del "lazy load" su tutte le pagine, e molto altro!
L'unico limite è la fantasia!