Come appassionato di ultramaratona, mi trovo spesso di fronte a una sfida comune: come posso stimare il mio tempo di arrivo per gare più lunghe che non ho ancora affrontato? Parlando di questo con il mio allenatore, mi ha suggerito un approccio pratico – guardare ai corridori che hanno completato sia una gara che ho fatto che la gara che sto mirando. Questa correlazione potrebbe fornire preziosi spunti sui tempi di arrivo potenziali. Ma cercare manualmente nei risultati delle gare sarebbe incredibilmente dispendioso in termini di tempo.
Ciò mi ha portato a creare Race Time Insights, uno strumento che confronta automaticamente i risultati delle gare trovando atleti che hanno completato entrambi gli eventi. L’applicazione estrae i risultati delle gare da piattaforme come UltraSignup e Pacific Multisports, consentendo ai corridori di inserire due URL delle gare e vedere come si sono comportati gli altri atleti in entrambi gli eventi.
Creare questo strumento mi ha mostrato quanto potesse essere potente l’App Platform di DigitalOcean. Utilizzando Puppeteer con Chrome headless in contenitori Docker, sono riuscito a concentrarmi sulla risoluzione del problema per i corridori mentre App Platform gestiva tutta la complessità dell’infrastruttura. Il risultato è stata una soluzione robusta e scalabile che aiuta la comunità di corridori a prendere decisioni basate sui dati sui loro obiettivi di gara.
Dopo aver creato Race Time Insights, ho voluto creare una guida che mostri ad altri sviluppatori come sfruttare queste stesse tecnologie – Puppeteer, contenitori Docker e DigitalOcean App Platform. Naturalmente, quando si lavora con dati esterni, è necessario fare attenzione a cose come il limite di velocità e i termini di servizio.
Entra in Project Gutenberg. Con la sua vasta collezione di libri di pubblico dominio e chiari termini di servizio, è un candidato ideale per dimostrare queste tecnologie. In questo post, esploreremo come costruire un’applicazione di ricerca di libri utilizzando Puppeteer in un contenitore Docker, implementato su Piattaforma App, seguendo nel contempo le migliori pratiche per l’accesso a dati esterni.
Ricerca Libri Project Gutenberg
Ho sviluppato e condiviso un’applicazione web che recupera responsabilmente informazioni sui libri da Project Gutenberg. L’applicazione, che puoi trovare in questo repository GitHub, consente agli utenti di cercare tra migliaia di libri di pubblico dominio, visualizzare informazioni dettagliate su ciascun libro e accedere a vari formati di download. Ciò che rende tutto ciò particolarmente interessante è come dimostra pratiche responsabili di web scraping offrendo allo stesso tempo un valore autentico agli utenti.
Essere un Buon Cittadino Digitale
Quando si costruisce uno scraper web, è cruciale seguire buone pratiche e rispettare i confini tecnici e legali. Project Gutenberg è un ottimo esempio per apprendere questi principi perché:
- Ha chiari termini di servizio
- Fornisce linee guida per robots.txt
- Il suo contenuto è esplicitamente di dominio pubblico
- Beneficia di un aumento dell’accessibilità alle sue risorse
La nostra implementazione include diverse best practices:
Limitazione della velocità
Per scopi dimostrativi, implementiamo un semplice limitatore di velocità che garantisce almeno 1 secondo tra le richieste:
Questa implementazione è intenzionalmente semplificata per l’esempio. Presuppone un’unica istanza dell’applicazione e memorizza lo stato in memoria, il che non sarebbe adatto per un utilizzo in produzione. Soluzioni più robuste potrebbero utilizzare Redis per la limitazione della velocità distribuita o implementare sistemi basati su code per una migliore scalabilità.
Questo limitatore di velocità viene utilizzato prima di ogni richiesta a Project Gutenberg:
Identificazione chiara dei bot
Un User-Agent personalizzato aiuta gli amministratori del sito web a capire chi sta accedendo al loro sito e perché. Questa trasparenza permette loro di:
- Contattarti in caso di problemi
- Monitorare e analizzare il traffico dei bot separatamente dagli utenti umani
- Eventualmente fornire un migliore accesso o supporto per scraper legittimi
Gestione efficiente delle risorse
Chrome può essere intensivo in termini di memoria, specialmente quando si eseguono più istanze. Chiudere correttamente le pagine del browser dopo l’uso previene perdite di memoria e garantisce che la tua applicazione funzioni in modo efficiente, anche quando gestisce molte richieste:
Seguendo queste pratiche, creiamo uno scraper che sia efficace e rispettoso delle risorse a cui accede. Questo è particolarmente importante quando si lavora con risorse pubbliche preziose come Project Gutenberg.
Web Scraping nel Cloud
L’applicazione sfrutta l’architettura cloud moderna e la containerizzazione attraverso App Platform di DigitalOcean. Questo approccio fornisce un perfetto equilibrio tra semplicità nello sviluppo e affidabilità in produzione.
Il Potere di App Platform
App Platform semplifica il processo di distribuzione gestendo:
- Configurazione del server web
- Gestione dei certificati SSL
- Aggiornamenti di sicurezza
- Bilanciamento del carico
- Monitoraggio delle risorse
Questo ci permette di concentrarci sul codice dell’applicazione mentre App Platform gestisce l’infrastruttura.
Chrome Headless in un Container
Il nucleo della nostra funzionalità di scraping utilizza Puppeteer, che fornisce un’API di alto livello per controllare Chrome in modo programmato. Ecco come configuriamo e utilizziamo Puppeteer nella nostra applicazione:
Questa configurazione ci consente di:
- Eseguire Chrome in modalità headless (senza GUI necessaria)
- Eseguire JavaScript nel contesto delle pagine web
- Gestire in modo sicuro le risorse del browser
- Lavorare in modo affidabile in un ambiente containerizzato
La configurazione include anche diverse importanti impostazioni per l’esecuzione in un ambiente containerizzato:
- Argomenti Chrome Appropriati: Flag essenziali come
--no-sandbox
e--disable-dev-shm-usage
per l’esecuzione in container - Percorso Consapevole dell’Ambiente: Utilizza il percorso binario corretto di Chrome dalle variabili d’ambiente
- Gestione delle Risorse: Imposta la dimensione della viewport e disabilita le funzionalità non necessarie
- Identità del Bot Professionale: User agent chiaro e header HTTP che identificano il nostro scraper
- Gestione degli errori: Pulizia corretta delle pagine del browser per prevenire memory leaks
Anche se Puppeteer facilita il controllo di Chrome in modo programmato, eseguirlo in un container richiede delle dipendenze di sistema e una configurazione adeguata. Vediamo come impostare tutto ciò nel nostro ambiente Docker.
Docker: Garantire Ambienti Coerenti
Una delle sfide più grandi nel rilascio di web scraper è assicurarsi che funzionino allo stesso modo in sviluppo e produzione. Il tuo scraper potrebbe funzionare perfettamente sul tuo computer locale ma fallire in cloud a causa di dipendenze mancanti o configurazioni di sistema diverse. Docker risolve questo problema impacchettando tutto ciò di cui l’applicazione ha bisogno – da Node.js a Chrome stesso – in un singolo container che si esegue in modo identico ovunque.
Il nostro Dockerfile imposta questo ambiente coerente:
FROM node:18-alpine
# Installa Chromium e le dipendenze
RUN apk add --no-cache \
chromium \
nss \
freetype \
harfbuzz \
ca-certificates \
ttf-freefont \
dumb-init
# Imposta le variabili d'ambiente
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser \
PUPPETEER_DISABLE_DEV_SHM_USAGE=true
L’immagine basata su Alpine mantiene leggero il nostro container includendo tutte le dipendenze necessarie. Quando esegui questo container, sia sul tuo laptop che su App Platform di DigitalOcean, ottieni lo stesso ambiente esatto con tutte le versioni e configurazioni corrette per eseguire Chrome headless.
Sviluppo al Rilascio
Seguiamo il processo per avviare questo progetto:
1. Sviluppo Locale
Per prima cosa, effettua il fork del repository di esempio sul tuo account GitHub. Questo ti fornisce una tua copia con cui lavorare e da cui eseguire il deploy. Quindi clona il tuo fork in locale:
# Clona il tuo fork
git clone https://github.com/YOUR-USERNAME/doappplat-puppeteer-sample.git
cd doappplat-puppeteer-sample
# Compila ed esegui con Docker
docker build -t gutenberg-scraper .
docker run -p 8080:8080 gutenberg-scraper
2. Comprensione del Codice
L’applicazione è strutturata attorno a tre componenti principali:
-
Servizio di prenotazione: Gestisce lo scraping web ed l’estrazione di dati
-
Server Express: Gestisce le rotte e rende i template
-
Visualizzazioni Frontend: UI pulita e reattiva usando Bootstrap
<div class="card book-card h-100"> <div class="card-body"> <span class="badge bg-secondary downloads-badge"> <%= book.downloads.toLocaleString() %> download </span> <h5 class="card-title"><%= book.title %></h5> <!-- ... altri elementi UI ... --> </div> </div>
3. Distribuzione su DigitalOcean
Ora che hai il tuo fork del repository, la distribuzione su DigitalOcean App Platform è semplice:
- Crea una nuova applicazione App Platform
- Collegati al tuo repository forkato
- In risorse, elimina la seconda risorsa (che non è un Dockerfile); questa viene generata automaticamente da App Platform e non è necessaria
- Esegui il deploy cliccando su Crea Risorse
L’applicazione verrà automaticamente costruita e distribuita, con App Platform che gestisce tutti i dettagli dell’infrastruttura.
Conclusione
Questo scraper di Project Gutenberg dimostra come costruire un’applicazione web pratica utilizzando tecnologie cloud moderne. Combinando Puppeteer per lo scraping web, Docker per la containerizzazione e la piattaforma App di DigitalOcean per il deployment, abbiamo creato una soluzione robusta e facile da mantenere.
Il progetto funge da modello per le tue applicazioni di web scraping, mostrando come gestire l’automazione del browser, gestire efficientemente le risorse e distribuire nel cloud. Che tu stia costruendo uno strumento di raccolta dati o stia solo imparando sulle applicazioni containerizzate, questo esempio fornisce una solida base su cui costruire.
Scopri il progetto su GitHub per saperne di più e distribuire la tua istanza!