Recensione di chromedp: un vero browser richiede comunque le giuste condizioni di disponibilità

Ultimo aggiornamento il August 17, 2026
Recensione di chromedp: un vero browser richiede comunque le giuste condizioni di disponibilità
Riepilogo AI
chromedp è una libreria in puro Go, con licenza MIT, che controlla un vero Chrome tramite il Chrome DevTools Protocol. Legge il DOM dopo l'esecuzione del JavaScript della pagina da un programma Go, senza bisogno di un WebDriver separato o di un runtime Node. Il modulo Go si compila dentro l'applicazione, ma il sistema eseguibile richiede comunque un eseguibile Chrome esterno, la cui durata viene gestita tramite i context di Go. L'installazione per me è stata un semplice go get più un Chrome che ho dovuto fornire io: creare un allocator, derivare un context, passare a Run una lista di azioni.

chromedp è una libreria in puro Go, con licenza MIT, che controlla un vero Chrome tramite il Chrome DevTools Protocol. Legge il DOM dopo l'esecuzione del JavaScript della pagina, direttamente da un programma Go, senza bisogno di un WebDriver separato o di un runtime Node. Il modulo Go si compila dentro l'applicazione, ma il sistema eseguibile richiede comunque un eseguibile Chrome esterno, la cui durata viene gestita tramite i context di Go.

L'installazione per me è stata un semplice go get più un Chrome che ho dovuto fornire io: creare un allocator, derivare un context, passare a Run una lista di azioni. Su questo host macOS arm64, con una headless shell già presente su disco e ben avviata, un processo nuovo fino al primo risultato dello script ha registrato una mediana di 102 ms. Questo è un riferimento locale, non un'affermazione generale che l'avvio non sia mai un collo di bottiglia. Su un fixture che inserisce un link 800 millisecondi dopo il caricamento, due strategie di lettura su quattro hanno restituito il contenuto prima che il link esistesse.

Il browser era reale, il contenuto c'era, e il codice semplicemente non stava aspettando abbastanza. Quel divario è la cosa più utile che chromedp mi ha insegnato, e non è un bug: è la differenza tra "ho renderizzato la pagina" e "ho aspettato proprio l'elemento che mi serviva", una distinzione che nel folklore dei browser headless viene spesso appiattita fino a sparire. È la strategia di attesa, non il browser, a decidere se i dati arrivano. Ogni numero qui proviene da un fixture locale che controllo io, con la verità di riferimento registrata prima di ogni esecuzione, e i riepiloghi grezzi si trovano nella cartella chromedp del nostro repository di benchmark.

Cos'è davvero chromedp

Lo stack chromedp è volutamente essenziale. Niente server Selenium. Nessun livello di astrazione WebDriver. Nessun runtime Node nascosto sotto il cofano. Il tuo programma Go apre una connessione WebSocket a un'istanza di Chrome e parla direttamente con il CDP, cioè più o meno lo stesso protocollo usato da Puppeteer, ma senza JavaScript.

Quando ho controllato il 27 luglio 2026, il repository aveva 13.212 stelle e 178 issue aperte, con licenza MIT. La versione che ho testato è v0.16.0, cioè il tag più recente nel repository. Vale la pena segnalarlo per evitare confusione: la pagina Releases di GitHub mostra ancora v0.15.1 (pubblicata il 2026-04-01) come ultimo oggetto release, mentre go get github.com/chromedp/chromedp@latest risolve a v0.16.0. I Go module e gli oggetti release di GitHub qui si sono leggermente separati. Non è rotto, ma è fastidioso quando stai cercando di capire cosa stai davvero eseguendo.

Il modello mentale è tutto basato sui context di Go. Crei un context per l'allocator (che sa come avviare Chrome), ne derivi un browser context, e poi chiami chromedp.Run(ctx, actions...) con una lista di Actions. Un child context di un browser context corrisponde a una nuova scheda. Se annulli un context, ciò che rappresenta sparisce. Se hai già lavorato con la concorrenza in Go, ti sembrerà subito naturale; in caso contrario, la nostra guida per iniziare con il web scraping in Go è un ingresso molto più morbido della godoc di chromedp.

Un confine importante da chiarire subito: chromedp ti consegna un DOM renderizzato. Non ti consegna dati strutturati. Qualunque cosa estrai da quel DOM — campi, tabelle, prezzi — è codice che scrivi e mantieni tu. È un driver, non un framework di scraping.

La meccanica interna

In chromedp tutto è un Action, e Run esegue una slice di azioni in ordine contro un target. Navigate, Click, Evaluate, OuterHTML, WaitVisible: stessa interfaccia, componibili tra loro, tutti semplicemente comandi CDP con tipi Go addosso. Questa uniformità è la scelta progettuale migliore della libreria, perché fa convivere il livello comodo e il protocollo grezzo allo stesso piano.

Ed è importante, perché il livello comodo è volutamente sottile. chromedp si basa su cdproto, un insieme generato di binding Go tipizzati che copre l'intera superficie del DevTools Protocol, e la godoc di chromedp documenta entrambi i livelli affiancati. Quando l'azione di comodità non esiste, passi direttamente alla chiamata di dominio — network.Enable(), page.CaptureScreenshot(), runtime.Evaluate() — nello stesso Run. Non c'è un muro tra "API bella" e "API reale", e non tutte le librerie browser funzionano così.

Le azioni di attesa sono il punto in cui si gioca la partita quotidiana, e sono molte più di quelle che si usano di solito:

Azione di attesaSu cosa si blocca
WaitReady(sel)finché il nodo non è attaccato al DOM
WaitVisible(sel)finché il nodo non è davvero visibile
WaitNotPresent(sel) / WaitNotVisible(sel)l'opposto, utile per gli spinner
Poll(js, res)valuta un predicato JavaScript a intervalli finché non diventa vero

La gestione dei processi è l'altro pezzo da conoscere, perché decide se il tuo programma lascia dietro di sé un browser in esecuzione. chromedp avvia Chrome tramite exec.CommandContext di Go. Cancellare quel context termina il processo. Questo singolo dettaglio di implementazione spiega sia il comportamento corretto sia il lato spigoloso che ho incontrato nei test.

La configurazione è un binario Go più un Chrome che devi fornire tu

go get github.com/chromedp/chromedp si è risolto senza problemi a v0.16.0, e l'albero delle dipendenze non contiene import cgo. Quindi la frase "puro Go, senza dipendenze esterne" che leggerai spesso è vera — ma riguarda il modulo Go.

Non è vera per il runtime. chromedp controlla un Chrome esterno e, se sulla macchina Chrome non c'è, l'esecuzione fallisce subito. Ogni misurazione che ho fatto ha fornito l'eseguibile esatto tramite chromedp.ExecPath, puntando a una headless shell Chrome for Testing 151.0.7922.10. Non è una critica — per controllare un browser serve un browser — ma "nessuna dipendenza esterna" e "devi distribuire un Chrome da 155 MB insieme al tuo binario" sono storie di deployment molto diverse, e solo una delle due compare nel README.

Una seconda trappola di setup mi è costata tempo ed è bene conoscerla prima di scrivere codice. L'issue di chromedp #1591 segnala che il runner go test di Go 1.25+ annulla NewExecAllocator durante l'avvio; lo stesso codice, compilato come binario, funziona correttamente. Per ogni misurazione ho quindi costruito un binario di prova con go build e ho eseguito quello, invece di passare da go test. In questo caso usavo Go 1.26.5 su macOS arm64. Se la tua prima esperienza con chromedp è un file di test che muore durante l'avvio di Chrome, leggi quell'issue prima di dare la colpa al tuo codice.

Prova pratica: quattro modi per leggere la stessa pagina, due tornano vuoti

Measured results chart: Which read strategy saw each link?

Il fixture è un server locale su 127.0.0.1 che serve tre classi di contenuto, differenti solo per quando entrano nel DOM: un <a> statico nei byte serviti, un <a> creato da uno <script> inline durante il parsing iniziale, e un <a> creato da setTimeout un certo numero di millisecondi dopo l'evento di load. I marker e gli href dei due link creati dallo script vengono costruiti in JavaScript da frammenti di stringa, quindi nei byte serviti non esiste alcun letterale contiguo. Un "trovato" prova quindi che Chrome ha eseguito JavaScript, non che qualcuno abbia letto HTML.

Il recall viene calcolato in Python sulla base di marker di verità pre-registrati, non dentro il probe Go, quindi il probe non può barare conoscendo già la risposta. Ogni strategia è stata eseguita tre volte; gli insiemi dei risultati trovati erano identici in tutte e tre le esecuzioni.

Strategia di letturaLink HTML staticoInserito durante il parsingInserito 800 ms dopo il loadTempo trascorso
Navigate + lettura, senza attesatrovatotrovatoperso317 ms
WaitReady("body")trovatotrovatoperso107 ms
WaitVisible("#delayed-injected")trovatotrovatotrovato912 ms
Poll finché compare il markertrovatotrovatotrovato972 ms

Due righe restituiscono due link su tre. La lettura ingenua perde il terzo perché Navigate ritorna all'evento load e il terzo link non esiste ancora. WaitReady("body") fallisce per un motivo più sottile e, in pratica, più insidioso: body è attaccato al load, quindi l'attesa viene soddisfatta subito e sembra di aver fatto la cosa giusta. In 107 ms è tornato persino più in fretta del percorso senza attesa, ma con la stessa pagina incompleta.

Per confermare il meccanismo invece di assumerlo, ho variato il ritardo di iniezione e rilanciato entrambi gli estremi (recall-summary.json):

Ritardo di iniezione dopo il loadLa lettura senza attesa lo vedeWaitVisible lo vedeTempo di WaitVisible
0 mssì (race)109 ms
100 msno208 ms
400 msno519 ms
800 msno911 ms
1500 msno1625 ms

Il tempo di WaitVisible in questo fixture segue il ritardo di iniezione — 100 contro 208, 400 contro 519, 800 contro 911, 1500 contro 1625 — prova che si è bloccato finché il nodo non è apparso, invece di leggere troppo presto. La riga a 0 ms è il confine: setTimeout(…, 0) può scattare prima della lettura immediata, quindi il percorso senza attesa può prenderlo. Da 100 ms in su, in questo sweep, il percorso senza attesa l'ha perso in ogni esecuzione.

In produzione, lo stesso errore di timing può produrre HTML valido con zero righe estratte e uscita 0, a meno che la pipeline non controlli la cardinalità dell'output. È un possibile modo di fallire, coerente con il comportamento del fixture, anche se qui non è stato osservato in un incidente reale. Il rendering è solo metà del requisito; la lettura deve attendere una condizione a livello applicativo collegata ai dati desiderati.

WaitReady e WaitVisible non sono in competizione: rispondono a domande diverse

La formula più comune è che WaitVisible sia "più affidabile" di WaitReady. È troppo imprecisa per essere utile. Su una pagina con un nodo attaccato al DOM ma stilizzato con display: none, i due si separano chiaramente (waitsem-summary.json, tre esecuzioni identiche):

Nodo targetAzioneEsitoTempo
attaccato, display:noneWaitReadyritorna~6 ms
attaccato, display:noneWaitVisibleva in timeout, context deadline exceeded4000 ms
nodo visibileWaitVisible, query predefinitaritorna4–12 ms
nodo visibileWaitVisible, ByIDritorna1–2 ms
nodo visibileWaitVisible, ByQueryritorna1 ms

WaitReady significa attaccato. WaitVisible significa visibile. Chiedere quello sbagliato vuol dire o passare oltre contenuto che non è mai stato reso, oppure restare bloccati per tutto il timeout su un nodo che non sarebbe mai stato visibile. Il comportamento della deadline è pulito — un corretto context deadline exceeded esattamente dopo 4 s, senza hang e senza stato zombie — e non tutti i driver riescono a farlo.

Una trappola segnalata non si è ripresentata. L'issue #440 riporta WaitVisible("#id") bloccato con la query predefinita, ma su v0.16.0 non si è riprodotto: query predefinita, ByID e ByQuery hanno tutte restituito il nodo visibile in ogni esecuzione. Non riprodotto non significa risolto: si tratta di una sola forma di selettore su una sola pagina, quindi non basta a chiudere la questione.

Il defer cancel() che hai saltato regge il tetto

Conteggi di processi, non valori di ritorno. Ogni prova di lifecycle ha usato un --user-data-dir unico e ha contato i processi browser reali di Chrome con pgrep, escludendo i renderer figli. Ogni percorso è stato eseguito tre volte (lifecycle-summary.json).

Percorso di uscita (macOS, 3 esecuzioni ciascuno)Che fine ha fatto il chrome-headless-shell avviatoTempo
Annullare il context e l'allocatoreliminato13, 13 e 12 millisecondi
Uscire dal processo Go senza annullaresopravvive al tuo programma — zero processi browser prima, uno dopo l'uscita del probe; orfano in tre esecuzioni su tre

Annullare è pulito, veloce, esattamente ciò che promette exec.CommandContext. (Ogni processo orfano è stato poi terminato forzatamente dall'harness; l'host è stato ripulito.)

Si tratta di un comportamento noto, documentato e limitato alla piattaforma — la misurazione è mia, la scoperta no. Il tracker di chromedp ne parla da più angolazioni: #774 descrive lo stesso mancato termine su FreeBSD, #752 segnala processi Chromium bloccati su macOS, e #562 insieme a #1566 spiegano il meccanismo. Quello che ho aggiunto è il conteggio dei processi e la tempistica su entrambi i lati del confronto, che quei report qualitativi non forniscono.

Il meccanismo stesso dipende dai build tag, e vale la pena conoscerlo. Nel codice sorgente v0.16.0, allocate_linux.go imposta Pdeathsig = SIGKILL sul processo figlio, quindi Linux ottiene un segnale di morte del padre a livello kernel. allocate_other.go, che è ciò che viene compilato su macOS, rende quella chiamata un no-op. Su darwin non esiste un segnale equivalente, quindi nulla uccide Chrome quando il tuo programma termina. Nel frattempo, la godoc sembra promettere qualcosa di generale — il comando predefinito "invia SIGKILL a qualsiasi browser aperto quando il programma Go termina" — ma la parte limitata a Linux vive solo nel sorgente protetto da build tag, che devi andare a leggere. Dire che la documentazione promette troppo è corretto; dire che è un bug di chromedp no.

La conseguenza pratica però resta la stessa: su macOS, defer cancel() è un pezzo portante. Se lo salti, ogni esecuzione lascia dietro di sé un processo browser. Non ho testato Linux, quindi non sto generalizzando lì il risultato sugli orfani: il sorgente suggerisce un comportamento diverso su Linux, e un suggerimento non è una misurazione.

Cold start, concorrenza e le cose noiose che decidono il deploy

Measured results chart: Cold start and two concurrency shapes

102 ms è stata la mediana da processo nuovo, allocator, context, navigazione localhost e prima Evaluate su cinque processi, con valori tra 98 e 111 ms (coldstart-summary.json). Su questo fixture macOS arm64 con headless shell già calda su disco, l'avvio era piccolo rispetto all'attesa del contenuto ritardato. Non ho misurato container, filesystem freddi, CI, ambienti serverless o navigazioni in produzione.

Sul fronte della concorrenza, chromedp ti dà due forme: un solo browser con vari child context (schede), oppure più browser indipendenti. Quattro navigazioni, tre esecuzioni ciascuna (concurrency-summary.json):

ModalitàTempo totale (p50)IntervalloPicco di processi browser Chrome
Browser condiviso, 4 child context214 ms209–2191
4 browser separati264 ms261–2784

Il risultato misurato importante è il numero di processi: un processo browser Chrome contro quattro per queste quattro navigazioni locali banali. Gli intervalli di tempo non si sovrapponevano, ma restano indicativi più che un benchmark di throughput. Non ho misurato RSS o PSS, quindi questo test non dimostra un risparmio di memoria.

La piccola prova sul percorso di errore non è abbastanza dettagliata da sostenere un'affermazione di robustezza: la bozza non identifica se a esporre ogni condizione sia stato lo stato HTTP, un errore di navigazione, un evento o la logica dell'harness. Considera la gestione di 500/link morti come non riportata finché non vengono pubblicati l'esito esatto dell'API e l'artefatto grezzo.

Non testato, e quindi fuori da ciò che questi numeri coprono: il comportamento di lifecycle su Linux, la concorrenza oltre N=4 o con lavoro reale per pagina, le differenze di memoria (ho contato processi, non RSS), l'intercettazione di rete e la cattura delle richieste, e i report aperti di timeout di WaitReady in #168 e #1593 — descrivono timeout intermittenti, mentre ciò che ho misurato è la semantica delle attese, che è un'altra domanda. Una macchina, una build di Chrome.

chromedp non è l'unico driver CDP in Go su questo banco: rod è stato testato con lo stesso fixture, lo stesso harness, lo stesso host e la stessa build di Chrome nella stessa sessione, e ha una sua analisi dedicata.

Pro e contro

Pro:

  • Accesso CDP autentico — le azioni di comodità e le chiamate grezze di cdproto si combinano nello stesso Run, quindi non incontri mai un limite dell'API.
  • Baseline locale di cold cycle pari a 102 ms p50, con variazione 98–111 ms sul fixture macOS testato.
  • cancel elimina Chrome in circa 13 ms, in modo costante, in ogni esecuzione.
  • I child context condividono un solo processo browser per N schede (1 processo contro 4 per browser separati).
  • Deterministico nei test — insiemi di recall, semantica delle attese ed esiti del lifecycle identici in tre ripetizioni ciascuno.
  • Gestione pulita delle deadline: WaitVisible su una condizione irraggiungibile è terminato correttamente con context deadline exceeded esattamente dopo 4 s, senza bloccarsi.
  • Modulo puro Go (senza cgo), licenza MIT; a runtime serve comunque un eseguibile Chrome esterno.

Contro:

  • Richiede un Chrome esterno a runtime; la reputazione di "nessuna dipendenza" riguarda solo il modulo Go.
  • WaitReady("body") è una trappola che sembra corretta e perde silenziosamente contenuti che arrivano dopo il load: nel mio test è tornato in 107 ms con una pagina incompleta.
  • Il percorso ingenuo Navigate + lettura perde tutto ciò che viene iniettato a partire da circa 100 ms dopo il load, in modo deterministico e senza errori.
  • Su macOS, uscire senza cancel() rende orfano il browser (3/3 esecuzioni). È un comportamento noto e limitato alla piattaforma, ma facile in cui inciampare.
  • La formulazione della godoc sul SIGKILL all'uscita sembra universale, ma il meccanismo è nel codice con build tag solo per Linux.
  • go test su Go 1.25+ può annullare l'avvio dell'allocator (#1591); conviene compilare un binario.
  • Restituisce un DOM, non dati strutturati: ogni campo va parsato con codice che scrivi e mantieni tu.
  • L'ultimo tag (v0.16.0) è più avanti dell'ultimo oggetto GitHub Release (v0.15.1), cosa che rende per un attimo confuso il controllo della versione.

Per chi è chromedp e chi dovrebbe evitarlo

Se il tuo servizio è già scritto in Go e ti serve un browser vero al suo interno, chromedp è quasi la scelta ovvia. Nessun processo Node da supervisionare, nessun server WebDriver da mantenere attivo, un solo binario compilato più un Chrome che distribuisci o installi. Il modello a context si allinea così bene con le primitive di concorrenza di Go che la durata del browser finisce per essere governata dalla stessa disciplina di defer del resto del codice. E se ti serve qualcosa che l'API di comodità non copre — eventi CDP di rete, hook precisi sul ciclo di vita della pagina, trucchi a livello di protocollo — puoi scendere in cdproto senza uscire dalla libreria.

È anche una buona soluzione quando vuoi un controllo esplicito sulle attese. Le azioni di wait sono primitive, non euristiche: fanno esattamente ciò che dichiarano, ed è un vantaggio una volta accettato che scegliere quella giusta è ormai responsabilità tua.

Evitalo se il tuo team non scrive Go: il vero costo è il linguaggio, non la libreria. Evitalo se vuoi un comportamento di auto-wait che indovini al posto tuo, perché chromedp non indovina; fa esattamente ciò che gli chiedi e ti restituisce lo stato della pagina in quell'istante. Evitalo, o prevedi un investimento serio, se ciò che ti serve sono record strutturati e non un DOM: ogni campo diventa un selettore che scrivi, testi e ripari quando il sito cambia. E se il requisito è semplicemente "dammi i dati da questi 500 URL", mettere in piedi l'orchestrazione di un browser in Go è molta meccanica per un'esigenza così semplice. La nostra guida all'automazione del browser spiega quando questa meccanica vale il costo e quando no.

Alternative, incluso dove si colloca il nostro stack

Nella categoria dei driver browser, rod è un altro driver CDP in Go, mentre Playwright e Puppeteer sono opzioni lato Node trattate nella nostra analisi Playwright contro Puppeteer. I loro contratti di attesa non sono intercambiabili. Playwright esegue l'auto-wait dell'azione prima di molte operazioni; questo però non gli dice quando i dati dell'applicazione hanno finito di arrivare dopo l'azione. chromedp ti offre primitive di wait di livello più basso e lascia al chiamante sia l'actionability sia le condizioni di readiness dell'applicazione. Se stai esplorando il campo più ampio, il nostro riepilogo degli scraper open source che abbiamo testato copre crawler statici e librerie di estrazione sull'altro lato di questa linea.

Recensione correlata: recensione di Browserless.

Un servizio di estrazione gestito è una categoria diversa. Scambia controllo sul browser e sui selettori con rendering e modellazione dello schema esternalizzati. Può essere utile quando il risultato finale sono record strutturati e non un DOM, mentre chromedp è più adatto quando il browser deve restare sotto il controllo del tuo servizio Go. Noi costruiamo Thunderbit, uno di questi servizi, ma non lo abbiamo eseguito su questo fixture; questo test quindi non supporta alcun confronto di equivalenza, latenza, qualità di estrazione o costo con chromedp.

Prova Thunderbit per l'estrazione di dati web

Verdetto

Vale la pena usare chromedp? Sì, se scrivi in Go e vuoi un browser vero sotto il tuo controllo. Su questo fixture locale ha raggiunto il primo risultato dello script in 102 ms p50, ha eliminato Chrome in circa 13 ms dopo la cancellazione e ha usato un solo processo browser per quattro schede concorrenti. Si tratta di osservazioni delimitate, non di promesse prestazionali universali; il vero valore duraturo è l'accesso diretto al CDP da Go quando il livello di comodità non basta più.

Bisogna però dimensionare bene le affermazioni, perché la reputazione tende a vendere troppo due cose. "Puro Go, senza dipendenze" descrive il modulo; a runtime stai comunque distribuendo e gestendo un binario Chrome. E "usa un browser headless e otterrai il contenuto dinamico" è vero solo quando l'attesa è agganciata al nodo giusto: una lettura ingenua e WaitReady("body") mi hanno entrambi restituito una pagina priva del contenuto inserito 800 ms dopo il load, in silenzio, ogni singola volta. Su macOS, defer cancel() non è una preferenza stilistica: se lo togli, lasci in giro un browser per ogni esecuzione, comportamento noto della piattaforma ma comunque un tuo problema da gestire. Se metti a posto queste tre cose, chromedp è uno dei driver browser più prevedibili che abbia misurato. Se le sbagli, fallisce in silenzio, che è il peggior modo in cui uno scraper possa fallire.

Prova Thunderbit per l'estrazione di dati web Get Started Free

FAQ

chromedp vede davvero i contenuti renderizzati in JavaScript? Sì, ma solo con un'attesa legata al nodo che ti serve. Su un fixture in cui un link veniva inserito 800 ms dopo l'evento load, Navigate più lettura l'ha perso e anche WaitReady("body") l'ha perso, mentre WaitVisible su quel nodo e un poll JavaScript l'hanno recuperato, in tre esecuzioni su tre. Variando il ritardo, la lettura senza attesa ha perso il nodo a ogni valore da 100 ms in su. Il rendering è necessario; aspettare nel modo giusto è ciò che lo rende sufficiente.

Qual è la differenza tra WaitReady e WaitVisible? WaitReady si blocca finché il nodo non è attaccato al DOM. WaitVisible si blocca finché non è davvero visibile. Su un nodo attaccato ma stilizzato con display: none, WaitReady è tornato in circa 6 ms, mentre WaitVisible è rimasto in attesa fino alla deadline del context di 4 secondi, restituendo un pulito context deadline exceeded. Nessuno dei due è "più affidabile": rispondono a domande diverse, e scegliere quello sbagliato è la vera trappola.

Mi serve davvero defer cancel() con chromedp? Su macOS, sì. Annullare il context e l'allocator ha terminato Chrome avviato in 12–13 ms in ogni esecuzione; uscire dal processo Go senza annullare ha lasciato un processo browser orfano in tutte e tre le prove. È un comportamento noto e limitato alla piattaforma: il tracker di chromedp documenta lo stesso pattern di mancata terminazione su altri sistemi non Linux, e il kill tramite parent-death che lo gestisce vive in codice protetto da build tag solo per Linux. Non ho testato Linux, quindi considera il risultato sugli orfani come limitato a macOS.

chromedp richiede Chrome installato separatamente? Sì. Il modulo Go in sé è puro Go, senza cgo, ma controlla un browser esterno e senza uno Chrome fallisce subito. Ho fornito esplicitamente una headless shell Chrome for Testing 151.0.7922.10 tramite chromedp.ExecPath. Il lato positivo è che il costo di avvio è piccolo: un ciclo completo a freddo fino al primo risultato dello script ha avuto una mediana di 102 ms su cinque processi nuovi, con valori tra 98 e 111 ms.

Meglio condividere un browser tra più schede o avviare browser separati? Se il tuo obiettivo è ridurre il numero di processi browser, conviene usare child context. Quattro navigazioni localhost attraverso un solo browser hanno usato 1 processo browser Chrome; quattro browser separati ne hanno usati 4. Anche il tempo totale ha favorito la configurazione condivisa (214 ms contro 264 ms mediani), ma quattro pagine locali banali non sono un benchmark di throughput. La memoria non è stata misurata. Browser separati possono comunque essere la scelta giusta se ti servono isolamento più forte della sessione, proxy diversi o un raggio d'impatto più piccolo in caso di crash; questi compromessi erano fuori da questo test.

Ke
Ke
CTO di Thunderbit | Senior Data Scientist ed esperto di ML Con quasi un decennio di esperienza nel machine learning e nella data science, Ke Shen è un ex studente della Columbia University ed ex Senior Data Scientist presso Walmart Labs. Grazie a una profonda competenza, riconosciuta dai suoi pari, in Python, R, Java e statistica, condivide insight collaudati sul passaggio di algoritmi AI complessi dalla teoria a un'architettura pronta per la produzione.
Indice
Thunderbit · Agente AI per dati web

Estrai dati da qualsiasi pagina in 1 clic

Scelto da oltre 250.000 utenti
piano gratuito disponibile
Dalla pagina web al foglio di calcolo
Descrivi ciò che ti serve — l'agente AI di Thunderbit lo estrae ed esporta in Excel, Google Sheets, Airtable o Notion. Puoi iniziare gratis.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week