Ho creato un sito di test per verificare l’aspetto di Colly che né il numero di pagine né la reputazione in termini di velocità riescono a raccontare: se i suoi callback estraggono i record attesi, instradano un errore HTTP, seguono un grafo limitato e rendono disponibili contenuti forniti al di fuori dell’HTML renderizzato. Non si trattava di un benchmark di throughput, ma di una verifica di correttezza e dei limiti operativi.
Nei fixture controllati ha estratto tutti i record statici attesi, ha inoltrato una risposta 500 a OnError e ha visitato 17 URL nel grafo configurato con profondità limitata. Su due pagine, i cui elementi comparivano solo dopo l’esecuzione di JavaScript, ha restituito zero elementi target. Un endpoint JSON accessibile direttamente è rimasto utilizzabile senza browser: una distinzione importante rispetto al rendering dell’interfaccia client.
Che cos’è davvero Colly

Colly si presenta come un “elegant scraper and crawler framework for Golang”, e questa definizione conta più di quanto sembri. È una libreria Go — circa 25.300 stelle su GitHub e 1.850 fork — con licenza Apache-2.0. Non è un CLI da scaricare e lanciare contro un URL. Si scrive in Go, si importa Colly, si registrano alcuni callback e si compila tutto in un unico eseguibile.
Il modello mentale è event-driven. Si agganciano handler a un Collector: OnHTML esegue la logica di estrazione per i selettori CSS corrispondenti, OnResponse fornisce il corpo grezzo della risposta e OnError gestisce i fallimenti delle richieste. Gli handler dei link chiamano Visit() sugli URL scoperti, mentre MaxDepth limita l’attraversamento. Per questi percorsi solo HTTP, la macchina target non ha bisogno di un runtime Go separato né di un browser; se l’eseguibile sia davvero completamente statico dipende dai flag di build e dall’uso di CGO, che questo test non ha registrato.
Funzionalità chiave e come funzionano sotto il cofano

Il modello a callback è l’elemento da capire, perché è ciò che fa percepire Colly in modo diverso da uno script che fa request e parsing. Tre callback hanno coperto ogni test che ho eseguito.
OnHTML(selector, handler) è il cavallo di battaglia. Lo registri su .product o article p e Colly invoca il tuo handler una volta per ogni elemento corrispondente mentre analizza il DOM. Qui vive l’estrazione strutturata: il codice resta leggibile, perché descrivi cosa prendere invece di scrivere un ciclo di parsing.
OnResponse(handler) si colloca un livello più in basso e ti consegna i byte grezzi. Quando un target restituisce JSON invece di HTML, salti del tutto il DOM e fai tu il parsing del body. È proprio questo callback singolo il motivo per cui, nei miei test, Colly ha gestito in modo pulito una API JSON senza fare alcun parsing HTML.
OnError(handler) gestisce i fallimenti delle richieste e può esporre al codice chiamante lo status della risposta. In questo test, una risposta fixture con status 500 è arrivata al callback registrato. Retry, timeout, errori DNS, reset della connessione, panic dei callback, persistenza e alerting non sono stati testati.
Sopra i callback ci sono due funzioni operative. MaxDepth limita il follow dei link secondo la semantica di profondità di Colly. Un eseguibile Go compilato evita anche un runtime linguistico installato separatamente sulla macchina target. Questa esecuzione non ha registrato flag di build né lo stato di CGO, quindi non afferma che ogni binario risultante sia completamente statico.
Setup: serve la toolchain Go
La storia delle dipendenze è breve ma reale, quindi la chiarisco prima di installare qualsiasi cosa. La macchina che ho usato non aveva Go installato, e Colly è una libreria Go: il passo zero è stato quindi installare una toolchain Go sul sistema (ho installato Go 1.26.5 tramite Homebrew). Se il tuo team non vive già in Go, questo è il vero attrito: non Colly in sé, ma l’ambiente linguistico necessario prima ancora che una sola riga compili.
Una volta installato Go, go get github.com/gocolly/colly/v2 ha risolto alla versione v2.3.0. I percorsi testati non richiedevano browser né Chrome headless.
C’è un aspetto di versione che può confondere. Il modulo Go si è risolto a v2.3.0 (pubblicato nel dicembre 2025), mentre l’ultima voce visibile nell’interfaccia Releases di GitHub era v2.2.0 (marzo 2025) al momento del controllo. La distinzione è tra versione del modulo/repository e release su GitHub, non tra modulo e tag Git. Ho testato v2.3.0.
Prova pratica: estrazione e limiti operativi

Ho eseguito Colly su un server fixture autosufficiente (httptest di Go) più due siti demo pubblici. La directory benchmark corrente e results/colly-test-summary.json espongono gli artefatti, ma entrambi i link puntano a un branch mobile. L’articolo non fornisce un commit testato, un comando esatto, flag di build o seed del fixture, quindi non è ancora una ricetta di riproduzione immutabile.
| Test | Target | Risultato |
|---|---|---|
| Catalogo statico + paginazione | fixture locale | 12/12 prodotti attesi estratti |
| Estrazione articolo | fixture locale | titolo + 3/3 paragrafi |
| Risposta JSON diretta | fixture locale | 8/8 elementi attesi tramite OnResponse |
| Gestione HTTP 500 | fixture locale | instradato a OnError, status 500 |
Grafo di crawl (MaxDepth 2) | fixture locale | 17 pagine |
| Books to Scrape | demo pubblica | 20 prodotti |
| Pagina dinamica (senza JS) | fixture locale | 0 card (atteso) |
| Quotes JS (senza rendering) | demo pubblica | 0 (atteso) |
Sui fixture statici controllati, i selettori configurati hanno prodotto 12 record prodotto su 12 attesi e tutti e tre i paragrafi attesi dell’articolo. La risposta JSON diretta non ha mai toccato un parser HTML: OnResponse ha fornito il body e l’harness ha decodificato tutti gli otto elementi attesi. La singola fixture 500 è arrivata a OnError con lo status esposto e non ha fatto crashare quell’esecuzione; questo non dimostra affidabilità unattended. Sulla pagina pubblica Books to Scrape, il selettore ha restituito 20 prodotti, come smoke test su un sito pubblico.
Per l’attraversamento, il collector è stato configurato con MaxDepth(2) usando la convenzione seed-depth dell’harness e ha visitato 17 URL nel grafo del fixture. Il risultato riguarda la copertura del crawl, non la velocità. La traccia osservata — non una tesi generale su grafi arbitrari — si trova in results/local_crawl_graph.json.

Colly non esegue JavaScript. Il fixture renderizzato via JavaScript ha prodotto 0 card target e la pagina pubblica Quotes to Scrape JS ha prodotto 0 citazioni target. Se gli elementi esistono solo dopo l’esecuzione nel browser e non esiste un endpoint di supporto accessibile che li fornisca, il percorso HTTP-only non può vedere quegli elementi come DOM renderizzato. In quel caso bisogna affiancargli un renderer, oppure chiamare direttamente l’endpoint di supporto quando è disponibile, come dimostra il fixture JSON.
Non ho stressato il collector asincrono, la configurazione di rate limiting o politeness, la rotazione dei proxy, i retry, né i backend di coda e storage. Non sono stati misurati tempo trascorso, throughput, concorrenza, CPU, memoria, latenza del target o un baseline di confronto. Questo articolo, quindi, non rivendica né velocità né affidabilità unattended.
Come interpretare i risultati del fixture
Le tre esecuzioni di contenuto andate a buon fine esercitano contratti diversi. I casi catalogo e articolo testano la selezione CSS su HTML restituito dal server. I loro denominatori sono aspettative del fixture scritte prima dell’estrazione: dodici record prodotto e tre paragrafi dell’articolo. Presentarli come “record attesi estratti” è una scelta intenzionale. L’esecuzione non definisce fuzzy matching, gestione dei duplicati, tolleranza ai campi parziali o una metrica di recall sull’intero corpus, quindi il risultato non va promosso a misura generale di accuratezza di estrazione.
Il caso JSON bypassa la selezione del DOM. Colly riceve i byte della risposta tramite OnResponse, e l’harness esegue la decodifica JSON. Ecco perché “Colly non renderizza JavaScript” non significa che ogni sito con client non sia accessibile. Se la fonte dati usata dal client è un endpoint direttamente richiamabile e la richiesta è riproducibile fuori dal browser, il crawler HTTP può ancora essere sufficiente. Autenticazione, firme generate, stato solo browser e controlli anti-bot possono cambiare la risposta; qui nessuno di questi elementi è stato esercitato.
Il percorso 500 testa il dispatch, non il recupero. Mostra che il callback OnError registrato ha ricevuto quella risposta fixture e il relativo status. Un crawler di produzione ha comunque bisogno di una policy esplicita per codici retryable, backoff, errori terminali, persistenza e alerting. Il test non fornisce prove per queste scelte, e “il callback è scattato” non va letto come “il job è affidabile senza supervisione”.

Anche il grafo da 17 URL è ristretto. Conferma il set visitato prodotto da questo fixture, da questa convenzione seed e da MaxDepth(2). Non stabilisce pagine al secondo, equità tra host, crescita della memoria, né comportamento su cicli e forme duplicate di URL. Per questo servono test separati di workload e di coda.
Una checklist di selezione basata su questa esecuzione
Parti da ciò che Colly riceve davvero nella risposta. Se i campi richiesti sono presenti nell’HTML restituito dal server, usa OnHTML e valida il numero di campi o le chiavi obbligatorie prima di accettare un record. Se la risposta è JSON, gestisci il body con OnResponse e valida lo schema. Se l’HTML è solo una shell dell’applicazione, verifica se una richiesta di supporto accessibile contiene i dati prima di aggiungere un browser.
| Cosa contiene la risposta | Percorso Colly | Verifica di accettazione |
|---|---|---|
| Campi richiesti in HTML restituito dal server | selettori OnHTML | Chiavi richieste e numero atteso di record |
| Payload JSON richiamabile direttamente | OnResponse + decodifica JSON | Validazione dello schema e dei campi richiesti |
| Shell HTML supportata da una richiesta riproducibile | richiedi l’endpoint di supporto | Status della risposta, schema e completezza |
| Dati creati solo dopo l’esecuzione nel browser | aggiungi un renderer o scegli un crawler browser-based | Prontezza e completezza specifiche del target |
Quando l’esecuzione nel browser è necessaria, trattala come un componente in più invece di aspettarti un flag di Colly che abiliti il rendering. Il browser deve determinare la prontezza, esporre il contenuto renderizzato o le risposte di supporto e passare i dati al resto della pipeline. Questa review non ha testato un’integrazione del genere.
Per il deployment, registra versione di Go, versione del modulo, flag di build, stato di CGO, comando esatto, seed del fixture e commit del repository. Questi dettagli mancano nei link di pubblicazione attuali e fanno la differenza tra artefatti ispezionabili e una riproduzione duratura. Sul piano operativo, aggiungi una matrice dei guasti e misura il workload che ti interessa davvero prima di definire il sistema veloce o affidabile.
Pro e contro
Pro:
- Estratti 12/12 prodotti attesi del catalogo e 3/3 paragrafi attesi dell’articolo tramite
OnHTML. - Gestione JSON pulita tramite
OnResponse, senza parsing del DOM — 8/8 elementi API. - La risposta 500 testata è arrivata a
OnErrorcon lo status esposto. - Un crawl con profondità limitata ha raggiunto 17 pagine da un singolo collector.
- Compila in un eseguibile Go; per i percorsi testati il target non necessita di un runtime Go installato separatamente.
- Licenza permissiva Apache-2.0.
Contro:
- Nessuna esecuzione JavaScript — i contenuti renderizzati lato client restituiscono 0, senza eccezioni.
- Richiede una toolchain Go; i team non-Go pagano questo costo di setup prima di scrivere qualsiasi scraper.
- Il modulo testato (
v2.3.0) è più avanti dell’ultima release GitHub osservata (v2.2.0). - L’output è il tuo codice: Colly ti fornisce callback, non un dataset o un exporter nativo come Scrapy.
- I backend asincroni, di rate limiting, proxy e coda esistono ma qui non sono stati testati; throughput e scala restano non misurati.
Per chi è adatto — e chi dovrebbe evitarlo

Colly è adatto se già scrivi in Go e punti a HTML renderizzato dal server o a JSON direttamente accessibile. Il modello a callback separa corrispondenze strutturate, payload grezzi e fallimenti delle richieste. Un eseguibile compilato evita anche un ambiente linguistico installato separatamente sulla macchina target, anche se qui non è stata verificata la linkatura completamente statica.
Aggiungi un renderer quando gli elementi target compaiono solo dopo l’esecuzione nel browser e non esiste un endpoint di supporto utilizzabile. Un endpoint JSON diretto può comunque essere richiesto senza rendering. Colly è anche meno adatto ai team che non vogliono una toolchain Go o che desiderano un servizio di estrazione che si occupi della modellazione dello schema e della manutenzione dei selettori.
Alternative, incluso dove si colloca Thunderbit
Colly è software open-source che esegui in autonomia. Non ha un costo di licenza del vendor, ma computazione, banda, proxy, storage, osservabilità e lavoro di engineering restano a tuo carico. Sei tu a gestire il comportamento delle richieste, i callback di parsing, la logica di crawl e l’integrazione con un browser se il target richiede rendering.
Un servizio di estrazione gestito sposta parte di queste responsabilità su un vendor. Noi costruiamo Thunderbit, ma non lo abbiamo testato su questi fixture; quindi questo articolo non fa alcun confronto su rendering, anti-bot, qualità, latenza o costo. La distinzione rilevante è la proprietà: Colly espone risposte HTTP e callback nel tuo processo Go; un servizio gestito può occuparsi di acquisizione e shaping dello schema in cambio di un costo per chiamata.
Recensioni benchmark correlate: il confronto completo degli scraper open-source, la review del crawler Python Scrapy e la review del selettore adattivo Scrapling.
Prova Thunderbit per l’estrazione di dati web
Verdetto
Colly è un’ottima opzione per i team Go che puntano a HTML renderizzato dal server o JSON diretto e sono disposti a gestire il proprio codice di estrazione. I fixture supportano l’estrazione dei record attesi, una traccia di crawl limitata e una risposta 500 osservata — non la velocità, la scala o l’affidabilità unattended. Il DOM renderizzato dal browser richiede un altro percorso, a meno che l’endpoint dati sottostante non sia richiamabile direttamente.
Prova Thunderbit per l’estrazione di dati web Get Started Free
FAQ
Questa review ha misurato la velocità di Colly? No. Ha misurato l’estrazione dei record attesi, la gestione diretta del JSON, un callback di errore e la copertura di un grafo di crawl fixture. Non ha misurato tempo trascorso, throughput, concorrenza, CPU, memoria o un baseline di confronto.
Colly può estrarre pagine renderizzate in JavaScript? Colly non esegue il JavaScript della pagina. Il percorso HTTP testato quindi non ha trovato elementi target comparsi solo nel DOM renderizzato. Può comunque richiamare direttamente un endpoint JSON di supporto accessibile, come mostra il fixture JSON. Usa un renderer quando l’esecuzione è necessaria e nessuna richiesta di supporto riproducibile fornisce i dati.
Devo conoscere Go per usare Colly?
Sì. Colly è una libreria Go, non un CLI autonomo: la importi, registri callback (OnHTML, OnResponse, OnError) e compili. La macchina che ho testato non aveva Go, quindi il setup è iniziato installando una toolchain Go (1.26.5). Se il tuo team non è già in Go, quell’ambiente è il vero costo di setup.
Perché la versione che installo non coincide con l’ultima release GitHub di Colly?
Il modulo Go si è risolto a v2.3.0 (dicembre 2025), mentre l’ultima voce GitHub Releases osservata era v2.2.0 (marzo 2025). Ho testato v2.3.0; è una distinzione tra superfici di versione, non una prova di installazione rotta.
Colly è gratuito per uso commerciale? Sì, è Apache-2.0, quindi permissivo e adatto anche a uso commerciale. Come sempre, verifica la licenza corrente nel repo prima di basare un prodotto su di essa.
Prima dell’adozione in produzione, aggiungi test che riflettano il rischio operativo invece di estendere per analogia il risultato del fixture. Misura crawl ripetuti su target rappresentativi, registra CPU e memoria di picco, esercita fallimenti retryable e terminali e verifica il comportamento corretto sotto concorrenza. Se la persistenza conta, interrompi e riprendi un crawl controllando la gestione dei duplicati e lo stato della coda. Se conta la semplicità di deployment, registra la configurazione esatta del compilatore e del linker e ispeziona le dipendenze runtime dell’eseguibile prodotto. Nessuno di questi controlli cambia ciò che il fixture corrente ha dimostrato; stabiliscono soltanto se la stessa configurazione della libreria è adatta a un determinato lavoro in produzione.


