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.

Puppeteer: come usare Chrome attraverso le API per fare browser automation

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.

Download | Node.js
Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript engine.

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.

L'installazione di Puppeteer attraverso NPM su PowerShell
L'installazione di Puppeteer attraverso NPM su PowerShell

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.

Uno screenshot dell'homepage di Amazon fatto attraverso Puppeteer
Uno screenshot dell'homepage di Amazon fatto attraverso Puppeteer

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.

Uno screenshot dell'homepage di Amazon fatto attraverso Puppeteer usando setViewport
Uno screenshot dell'homepage di Amazon fatto attraverso Puppeteer usando setViewport

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.

Uno screenshot dell'homepage di Amazon fatto attraverso Puppeteer emulando un iPhone 6
Uno screenshot dell'homepage di Amazon fatto attraverso Puppeteer emulando un iPhone 6

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

Come estrarre il selettore di un elemento della pagina web usando Chrome
Come estrarre il selettore di un elemento della pagina web usando Chrome

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.

Uno screenshot dell'homepage di Amazon con un'automazione che accetta i cookie
Uno screenshot dell'homepage di Amazon con un'automazione che accetta i cookie

Una ricerca completa su Amazon con lo scroll

Rendiamo l'operazione un po' più strutturata. Lo script che segue, effettua le seguenti operazioni:

  1. apre l'homepage di Amazon,
  2. clicca su "Accetta i cookie" nella barra dei cookie e fa il primo screenshot,
  3. scrive "smart speaker" nella barra di ricerca e fa il secondo screenshot,
  4. avvia la ricerca (terzo screenshot con la pagina dei risultati),
  5. 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.

Una ricerca completa di prodotti su Amazon con gli screenshot nelle diverse fasi e scroll finale
Una ricerca completa di prodotti su Amazon con gli screenshot nelle diverse fasi e scroll finale

La seguente risorsa è la documentazione di tutte le funzioni a disposizione nella libreria.

puppeteer/puppeteer
Headless Chrome Node.js API. Contribute to puppeteer/puppeteer development by creating an account on GitHub.

▶️ 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 esempio del crawling di un sito web che genera alberatura in Json e screenshot delle pagine il file distinti
Un esempio del crawling di un sito web che genera alberatura in Json e screenshot delle pagine il file distinti

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.

Un esempio di confronto tra le prestazioni di alcuni siti web con l'emulazione di un device e di una velocità di connessione
Un esempio di confronto tra le prestazioni di alcuni siti web con l'emulazione di un device e di una velocità di connessione

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.

Un esempio di timeline con il caricamento di tutte le risorse della pagina web generato con Puppeteer in modalità headless
Un esempio di timeline con il caricamento di tutte le risorse della pagina web generato con Puppeteer in modalità headless

▶️ Esempi di script pronti all'uso

Cliccando sul seguente link potrai visualizzare moltissimi esempi da provare semplicemente scaricando i file JavaScript.

Examples | Tools for Web Developers | Google Developers
Puppeteer examples

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.

Try Puppeteer
Official playground for Google’s Puppeteer Node library. Try/run scripts in the cloud.

L'interfaccia è divisa in tre parti: l'area in cui puoi editare il codice, l'area dei risultati e quella dei log.

Try Puppeteer: un tool per testare gli script per la browser automation attraverso un'interfaccia web based
Try Puppeteer: un tool per testare gli script per la browser automation attraverso un'interfaccia web based

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!

Per approfondire

Puppeteer | Tools for Web Developers | Google Developers
Overview of Puppeteer