Geonode logo
Geonode Team

Geonode Team

Güncellenme: 7 Eylül 2026

Yayınlanma: 2 Eylül 2026

ChromeDP: Başlangıç Rehberi

chromedp, DevTools Protocol kullanarak Go'dan Chrome'u sürer; dış bağımlılık yoktur — driver ikilisi yok, Java yok, ayrı sunucu süreci yok. Bu tasarım dağıtımı hoş, öğrenmeyi biraz alışılmadık kılar çünkü her şey Go'nun `context` paketine ilk bakışta bariz olmayan şekillerde asılıdır. Bu rehber context modelini, gerçekten kullanacağınız actions'ı, doğru beklemeyi ve insanların takıldığı dağıtım ile vekil yapılandırmasını kapsar.

Çıkarımız: biz Geonode ve vekil satıyoruz, tarayıcı otomasyonu da bir vekil üzerinden yapabileceğiniz en bant genişliği aç şeyi. Headless bir tarayıcı her görseli, yazı tipini, betiği ve video ön yüklemesini çeker, bu yüzden ölçülü trafik üzerinden chromedp çalıştırmak aynı sayfalar için ham HTTP isteklerinden kabaca bir mertebe daha pahalıdır. Bunu kesmeye dair bir bölüm var ve içindeki teknik daha ucuz bir sağlayıcı seçmekten daha fazla tasarruf ettirir. Vekil yapılandırmasının kendisi üç satırdır ve gerçek bir tuzağı vardır; o da kapsanır.

chromedp nedir

Proje kendini "a faster, simpler way to drive browsers supporting the Chrome DevTools Protocol in Go without external dependencies" diye tanımlar.

Satış argümanı son cümledir. Selenium tarayıcı sürümüne uyan bir driver ikilisi ister; Playwright kendi çalışma zamanını gönderir. chromedp DevTools Protocol'ü doğrudan bir websocket üzerinden konuşur, dolayısıyla bir Go ikilisi artı bir Chrome kurulumu tüm dağıtımdır.

MIT lisanslıdır ve aktif bakılır — 0.15.1 sürümü Nisan 2026'da çıktı, Temmuz'a kadar commit'ler var, Eylül 2026'da kontrol edildi.

Kurulum sıradandır:

go get -u github.com/chromedp/chromedp

Üretilen protokol bağlamaları yoldaş pakette, github.com/chromedp/cdproto, durur; yüksek düzey API'nin sarmadığı bir şeye ihtiyaç duyduğunuzda oraya gidersiniz.

Context modeli

Önce anlaşılması gereken kısım, çünkü gerisi bundan gelir.

chromedp context.Context'i aynı anda iki iş için kullanır: Go'nun her zaman yaptığı iptal ve tarayıcı ile sekme tanıtıcılarını taşımak. Bu çift amaç, kurulumun böyle görünmesinin nedenidir.

ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()

var title string
err := chromedp.Run(ctx,
    chromedp.Navigate("https://example.com"),
    chromedp.Text("h1", &title, chromedp.NodeVisible),
)

İlk NewContext bir tarayıcı ayırır. Ondan türetilen sonraki context'ler aynı tarayıcıda yeni sekmeler oluşturur; tarayıcı başlatma maliyetini tekrar tekrar ödemeden birkaç sayfa böyle çalışır:

browserCtx, cancelBrowser := chromedp.NewContext(context.Background())
defer cancelBrowser()

tabCtx, cancelTab := chromedp.NewContext(browserCtx)
defer cancelTab()

İptal etmek kapatır. Bir sekme context'ini iptal etmek sekmeyi kapatır; tarayıcı context'ini iptal etmek tarayıcıyı kapatır. defer cancel() isteğe bağlı muhasebe değildir — atlamak bir Chrome sürecini sızdırır.

Zaman aşımları sıradan Go yolunda birleşir:

ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()

Projenin kendi SSS'inden iki hata önceden bilinmeye değer.

"Executing an action without Run results in 'invalid context'." SSS, "by default, a chromedp context does not have an executor, however one can be specified manually if necessary" diye açıklar. Actions kendi kendine çalışmaz — Run'ın gerçekleştirdiği değerlerdir.

"I'm seeing 'context canceled' errors." SSS bunu bağlantı kaybına bağlar: "when the connection to the browser is lost, chromedp cancels the context, and it may result in this error. This occurs, for example, if the browser is closed manually, or if the browser process has been killed or otherwise terminated." Yani bir context canceled hatası sıklıkla zaman aşımının tetiklendiği değil Chrome'un öldüğü anlamına gelir — zaman aşımını yükseltmeden önce ayırt etmeye değer.

Actions

Run bir actions dizisi alır ve sırayla yürütür. Yaygın olanlar işin çoğunu kapsar.

err := chromedp.Run(ctx,
    chromedp.Navigate("https://example.com/search"),
    chromedp.WaitVisible(`input[name="q"]`),
    chromedp.SendKeys(`input[name="q"]`, "golang"),
    chromedp.Click(`button[type="submit"]`, chromedp.NodeVisible),
    chromedp.WaitVisible(`.results`),
    chromedp.Text(`.results`, &results, chromedp.NodeVisible),
)

Birkaç öğeden çıkarmak Nodes veya Evaluate kullanır:

var links []string
err := chromedp.Run(ctx,
    chromedp.Navigate(url),
    chromedp.Evaluate(`[...document.querySelectorAll('a')].map(a => a.href)`, &links),
)

Evaluate sayfada JavaScript çalıştırır ve sonucu bir Go değerine çözür; birden fazla öğeyi birden içeren her şey için sıklıkla en kısa yoldur. Değer JSON serileştirilebilir olmalıdır.

Birden fazla değer döndüren actions için SSS sarmalayıcıyı verir:

chromedp.Run(ctx, chromedp.ActionFunc(func(ctx context.Context) error {
    _, err := domain.SomeAction().Do(ctx)
    return err
}))

ActionFunc ayrıca yüksek düzey API'nin kapsamadığı her şey — çerez koymak, ağ isteklerini yakalamak, cihaz öykünmek — için ham cdproto çağrılarına inme yoludur. Bu kaçış kapağı tüm DevTools Protocol için açıktır; bu geniş bir yüzeydir.

Doğru beklemek

Güvenilir bir kazıyıcı ile kırılgan biri arasındaki fark, ve hata her zaman aynıdır.

Uyuma. chromedp.Sleep(3*time.Second) vardır, caziptir ve ya çok kısadır — yavaş bir günde aralıklı başarısızlıklar — ya da çok uzundur, her çalışmada zaman harcar. Genelde ikisi de, farklı makinelerde.

Önemsediğiniz şeyi bekleyin:

chromedp.WaitVisible(`.results`, chromedp.ByQuery)
chromedp.WaitNotVisible(`.spinner`)
chromedp.WaitReady(`#content`)

WaitVisible öğenin var ve görünür olmasını bekler; WaitReady DOM'da var olmasını bekler. Etkileşimden sonra yüklenen içerik için görünür genellikle doğru koşuldur.

Hiçbir seçicinin ifade etmediği bir koşul için sayfada yoklayın:

chromedp.Poll(`document.querySelectorAll('.item').length >= 20`, nil)

Bu, "liste yüklenene kadar bekle"nin cevabıdır; öğe tabanlı hiçbir bekleme bunu ifade edemez.

Beklemeyi her zaman bir context zaman aşımıyla sınırlayın. Hiç eşleşmeyecek bir seçicide WaitVisible context dolana kadar bloklar; zaman aşımı yoksa bu sonsuza dek.

Headless çalıştırmak, ve Docker'da

Chrome varsayılan olarak headless çalışır. SSS insanların ilk sorusunu yanıtlar: "By default, Chrome is run in headless mode. See DefaultExecAllocatorOptions, and an example to override the default options."

Geliştirirken izlemek için:

opts := append(chromedp.DefaultExecAllocatorOptions[:],
    chromedp.Flag("headless", false),
)
allocCtx, cancelAlloc := chromedp.NewExecAllocator(context.Background(), opts...)
defer cancelAlloc()

ctx, cancel := chromedp.NewContext(allocCtx)
defer cancel()

NewExecAllocator Chrome'un komut satırı bayraklarını koyduğunuz yerdir ve tarayıcı context'inin üst katmanıdır.

Kapsayıcılar için projenin önerisi somuttur: "The simplest way is to run the Go program that uses chromedp inside the chromedp/headless-shell image. That image contains headless-shell, a smaller headless build of Chrome, which chromedp is able to find out of the box."

Bunu almak değer. Çalışan bir Chrome'u kapsayıcıda elle kurmak eksik paylaşılan kitaplıkları ve yazı tipi paketlerini kovalamak demektir ve sonuç amaçlı görüntüden daha büyüktür.

SSS'ten Linux'a özgü bir davranış, Chrome'u ayrı çalıştıranları şaşırtır: "On Linux, chromedp is configured to avoid leaking resources by force-killing any started Chrome child processes. If you need to launch a long-running Chrome instance, manually start Chrome and connect using RemoteAllocator."

RemoteAllocator zaten çalışan bir tarayıcıya websocket uç noktası üzerinden bağlanır; paylaşılan tarayıcı havuzu veya ayrı bir kapsayıcıdaki tarayıcı kalıbıdır.

Vekil kullanmak

Üç satır ve bir tuzak.

opts := append(chromedp.DefaultExecAllocatorOptions[:],
    chromedp.ProxyServer("http://proxy.example.com:9000"),
)
allocCtx, cancelAlloc := chromedp.NewExecAllocator(context.Background(), opts...)
defer cancelAlloc()

ctx, cancel := chromedp.NewContext(allocCtx)
defer cancel()

ProxyServer Chrome'un --proxy-server bayrağını koyar.

Tuzak kimlik doğrulamadır. Chrome'un --proxy-server bayrağı kimlik bilgisi almaz — kullanıcı adı ve parola içeren bir URL kimlik doğrulamaz. Chrome bir vekil meydan okumasına diyalog göstererek yanıt verir ve headless bir tarayıcının dolduracak kimsesi yoktur.

İki çıkış, tercih sırasıyla.

IP izin listesi kullanın. Kaynak adresiniz stabitse sağlayıcıya kaydedin ve kimlik bilgilerini tamamen bırakın. En temiz cevaptır ve sorunu dolanmak yerine kaldırır.

Kimlik doğrulama olayını işleyin. chromedp, handleAuthRequests ile fetch.Enable üzerinden DevTools Protocol'ün kimlik doğrulama isteğine programatik kimlik bilgisi vererek yanıt verebilir. Daha çok koddur ve adres sabit değilse yoldur.

Sonra işe yaradığını doğrulayın, çünkü tarayıcıda yanlış yapılandırılmış bir vekil sessizdir:

var ip string
err := chromedp.Run(ctx,
    chromedp.Navigate("https://api.ipify.org"),
    chromedp.Text("body", &ip, chromedp.NodeVisible),
)

Vekil seçeneğiyle ve onsuz çalıştırın. Adres değişmezse Chrome kullanmıyordur — ve size söyleyen olmamıştır. Coğrafi hedefli iş için daha ileri gidin ve bölgesel olarak farklı içeriğin gerçekten farklı olduğunu doğrulayın; adres kolay kısımdır. Bu, vekilleri test etmenin neden önemli olduğu yazısında anlattığımız sessiz başarısızlık kalıbıdır.

Locale'i çıkış ülkesine eşleyin madem buradasınız. en-US dil başlığı ve Londra saat dilimi olan bir Alman çıkışı gerçek bir ziyaretçinin üretmediği bir kombinasyondur ve birçok site locale'i adresten bağımsız kullanır:

chromedp.Flag("lang", "de-DE"),

Bant genişliğini kesmek

En çok para kazandıran bölüm ve her tarayıcı otomasyonuna uygulanır.

200 KB HTML olan bir sayfa her görsel, yazı tipi, izleme betiği ve video ön yüklemesi çekildiğinde 4 MB olabilir. GB başına 0,79 $ konut tarifelerinde — rakamlarımız, Eylül 2026'da fiyat sayfasına karşı kontrol edildi — bu fark tüm bütçedir.

İhtiyacınız olmayan kaynak türlerini engelleyin. fetch.Enable ve bir request-paused dinleyicisiyle görsel, medya ve yazı tipi isteklerini iptal edin:

chromedp.ListenTarget(ctx, func(ev interface{}) {
    if e, ok := ev.(*fetch.EventRequestPaused); ok {
        go func() {
            c := chromedp.FromContext(ctx)
            execCtx := cdp.WithExecutor(ctx, c.Target)
            switch e.ResourceType {
            case network.ResourceTypeImage, network.ResourceTypeMedia, network.ResourceTypeFont:
                _ = fetch.FailRequest(e.RequestID, network.ErrorReasonBlockedByClient).Do(execCtx)
            default:
                _ = fetch.ContinueRequest(e.RequestID).Do(execCtx)
            }
        }()
    }
})

Bu rutin olarak trafiğin çoğunu keser ve yan etki olarak çalışmaları hızlandırır.

Tarayıcıyı yeniden kullanın, sekmeler oluşturun. Tarayıcı başlatmak pahalıdır; sekme ucuzdur. Birçok sayfa üzerinde bir çalışma için bir kez ayırın ve sekme context'leri türetin.

Ve bir tarayıcıya ihtiyaç olup olmadığını sorun. İçerik ilk HTML'deyse düz bir HTTP isteği kesir kadar tutar ve çok daha hızlı çalışır. Otomasyona uzanmadan önce sayfa kaynağına bakın — her şeyi işleterek gösterme refleksi bu alandaki gereksiz maliyetin en yaygın kaynağıdır.

Hiçbir şey çalışmazken hata ayıklama

Tarayıcı otomasyonu opak başarısız olur — hiç eşleşmeyen bir seçici ve hiç yüklenmeyen bir sayfa aynı zaman aşımını üretir. Sabit bir dizi çoğunu çözer.

Tarayıcıyı açın ve bakın. En hızlı tanı, ve insanların sona bıraktığı:

opts := append(chromedp.DefaultExecAllocatorOptions[:],
    chromedp.Flag("headless", false),
)

Yarı zaman cevap hemen görünür — düğmeyi örten bir çerez bandı, oturum açma sayfasına yönlendirme, bir meydan okuma ekranı veya test ettiğinizden farklı bir yerleşim.

Bir çalışma başarısız olduğunda sayfayı yakalayın. Headless bir ortamda bu bakmanın yerini alır:

var buf []byte
_ = chromedp.Run(ctx, chromedp.FullScreenshot(&buf, 90))
_ = os.WriteFile("failure.png", buf, 0644)

HTML ile eşleyin; ekran görüntüsü neyin işlendiğini, kaynak neyin geldiğini gösterir:

var html string
_ = chromedp.Run(ctx, chromedp.OuterHTML("html", &html, chromedp.ByQuery))

Zamanlama sorunu varsaymadan önce seçicinin çözüldüğünü kontrol edin:

var count int
_ = chromedp.Run(ctx, chromedp.Evaluate(`document.querySelectorAll('.item').length`, &count))

Sıfır seçici sorunudur ve hiçbir bekleme onu düzeltmez.

Sayfanın kendisinin hata verdiğinden şüpheleniyorsanız tarayıcı günlüğünü açın:

opts := append(chromedp.DefaultExecAllocatorOptions[:],
    chromedp.Flag("enable-logging", true),
    chromedp.Flag("v", "1"),
)

Konsol iletilerini ve başarısız istekleri dinleyin; bunlar sıklıkla boş işlenen bir sayfayı açıklar:

chromedp.ListenTarget(ctx, func(ev interface{}) {
    switch e := ev.(type) {
    case *runtime.EventConsoleAPICalled:
        log.Printf("console.%s", e.Type)
    case *network.EventLoadingFailed:
        log.Printf("failed: %s %s", e.Type, e.ErrorText)
    }
})

API çağrılarının hepsinin başarısız olduğu bir sayfa, seçicileri değişmiş bir sayfayla aynı görünür; onları yalnızca ağ olayları ayırır.

Ve son çare olarak chromedp-proxy kullanın. Programınızla tarayıcı arasında oturur ve DevTools Protocol trafiğini iki yönde günlüğe yazar. Davranış hiç anlam ifade etmediğinde gerçek protokol alışverişini görmek genellikle bir okumada açıklar.

chromedp ne zaman doğru seçim

Kullanın, eğer zaten Go yazıyorsanız ve dağıtılacak driver olmadan tek bir durağan ikili istiyorsanız, veya daha yüksek düzey araçların açmadığı doğrudan DevTools Protocol erişimine ihtiyacınız varsa.

Playwright'i düşünün, eğer tarayıcılar arası destek, her action'a gömülü otomatik bekleme, başarısızlıkta izleme ve ekran görüntüleri veya daha büyük bir belgelendirme ve örnek gövdesi istiyorsanız. Go bağlantı noktası vardır ama ekosistem JavaScript ve Python merkezlidir.

Düz HTTP'yi düşünün, eğer içerik ilk yanıtta duruyorsa. Daha hızlı, daha ucuz, daha basit ve web'in söylemin ima ettiğinden daha fazlası yararlı HTML sunar.

SSS'in kendi kaynak listesi sonraki adım için iyi bir haritadır: karmaşık actions ve tam sayfa ekran görüntüleri için examples deposu, üretilen protokol API'si için cdproto başvurusu ve programınızla tarayıcının birbirine tam olarak ne söylediğini görmek için bir CDP günlük vekili olan chromedp-proxy — son çare hata ayıklama aracı ve gerçekten iyi bir tanesi.

Sık sorulanlar

chromedp nedir?

Chrome DevTools Protocol konuşan tarayıcıları dış bağımlılık olmadan süren bir Go paketi. Selenium'dan farklı olarak driver ikilisine ihtiyaç duymaz, Playwright'ten farklı olarak çalışma zamanı göndermez — bir Go ikilisi artı bir Chrome kurulumu tüm dağıtımdır.

chromedp'de neden "invalid context" alıyorum?

Çünkü bir action'ı Run olmadan yürüttünüz. SSS, bir chromedp context'inin varsayılan olarak yürütücüsü olmadığını açıklar. Actions chromedp.Run'ın gerçekleştirdiği değerlerdir; birini doğrudan çağırmanın çalıştıracak bir şeyi yoktur.

chromedp'de "context canceled" ne anlama gelir?

Genelde tarayıcı bağlantısının kaybolduğu. SSS bunu tarayıcının elle kapatılmasına veya sürecin öldürülmesine bağlar. Zaman aşımından ayırt etmeye değer, çünkü düzeltme farklıdır — çöken bir Chrome daha uzun bekleyerek çözülmez.

chromedp'yi görünür tarayıcıyla nasıl çalıştırırım?

Chrome varsayılan olarak headless çalışır. chromedp.Flag("headless", false)'u DefaultExecAllocatorOptions'a ekleyip NewExecAllocator'a verin, sonra context'inizi o ayırıcıdan türetin.

chromedp ile vekili nasıl kullanırım?

Ayırıcı seçeneklerine chromedp.ProxyServer("http://host:port") ekleyin. URL'deki kimlik bilgileri işe yaramaz çünkü Chrome'un --proxy-server bayrağı onları kabul etmez — adresiniz stabitse IP izin listesi kullanın veya kimlik doğrulama isteğini DevTools Protocol üzerinden işleyin.

chromedp'yi Docker'da nasıl çalıştırırım?

Go programınızı projenin açıkça önerdiği chromedp/headless-shell görüntüsü içinde çalıştırın. chromedp'nin yapılandırma olmadan bulduğu daha küçük bir headless Chrome derlemesi içerir ve tarayıcı ortamını elle kurmayı önler.

chromedp'de bir öğeyi nasıl beklerim?

Bir seçiciyle WaitVisible, WaitReady veya WaitNotVisible kullanın; hiçbir seçicinin ifade etmediği koşullar için JavaScript ifadesiyle Poll. Sleep'ten kaçının — ya çok kısa ve kırılgan ya da çok uzun ve savurgan, genelde makineye göre ikisi de.

chromedp kullanırken bant genişliğini nasıl azaltırım?

İstek yakalamayı etkinleştirip görsel, yazı tipi ve medya kaynak türlerini başarısız kılarak engelleyin; bu tipik olarak trafiğin çoğunu kaldırır. Bir tarayıcıyı yeniden kullanın ve tekrar tekrar ayırmak yerine sekmeler oluşturun. Ve içeriğin ilk HTML'de olup olmadığına bakın; öyleyse tarayıcıyı tamamen atlayın.

Kapanış

chromedp'nin öğrenme eğrisi neredeyse tamamen context modelidir. Bir context'in tarayıcıyı veya sekmeyi taşıdığını, birini iptal etmenin onu kapattığını ve actions'ın Run onları gerçekleştirene kadar hiçbir şey yapmadığını içselleştirdiğinizde API'nin gerisi doğrudandır.

Önemli alışkanlıklar herhangi bir tarayıcı otomasyonundakiyle aynıdır. Uyumak yerine koşulları bekleyin, her beklemeyi bir context zaman aşımıyla sınırlayın ve başlatma maliyetini tekrar tekrar ödemek yerine bir tarayıcıyı birçok sekmede yeniden kullanın.

Akılda tutulacak iki Go'ya özgü nokta. Her context'te defer cancel(), yoksa Chrome süreçleri sızdırırsınız — ve Linux'ta chromedp başlattığı Chrome çocuklarını zorla öldürür, bu yüzden uzun süren bir tarayıcının ayrı başlatılıp RemoteAllocator ile ulaşılması gerekir.

Ve ölçülü bir vekil üzerinden çalışıyorsanız, başka bir şey yapmadan önce ihtiyacınız olmayan kaynak türlerini engelleyin. İşlenmiş bir sayfa içerdiği HTML'den bir mertebe daha pahalıdır ve bunun çoğu hiç bakmayacağınız görsellerdir.