Web kazıma, webden halka açık veri toplamak isteyen veri mühendisleri, araştırmacılar ve geliştiriciler için vazgeçilmez bir araçtır. Python gibi diller BeautifulSoup ve Scrapy gibi kütüphanelerle bu alanda baskın olsa da Go (Golang), öncelikli olarak performans, eşzamanlılık ve tip güvenliği önceliklendiren geliştiriciler için ikna edici bir alternatif sunar. Go'nun hafif goroutine'leri ve verimli bellek yönetimi, diğer dillerdeki iş parçacığı (threading) yükü olmadan aynı anda büyük veri hacimlerini kazıması için son derece uygundur.
Bu rehberde, Go kullanarak pratik bir web kazıyıcı oluşturacağız. HTML ayrıştırma, bağlantı çıkarma ve olay işleme işlemlerini basitleştiren Go için yüksek performanslı bir web kazıma çerçevesi olan Colly kullanımına odaklanacağız. Bu makalenin sonunda, bir kazıyıcıyı nasıl yapılandıracağınızı, asenkron istekleri nasıl yöneteceğinizi ve bir kazıma işleminin yaşam döngüsünü nasıl kontrol edeceğinizi sağlam bir şekilde anlayacaksınız.
Neden Web Kazıma İçin Go Seçilmeli?
Koda dalmadan önce, Go'nun kazıma görevleri için güçlü bir aday olmasının nedenlerini anlamak önemlidir. İlk olarak, Go tek bir ikili dosyaya derlenir; bu da dağıtımı farklı ortamlar (Linux, macOS, Windows) arasında sorunsuz hale getirir. İkinci olarak, dilin yerleşik eşzamanlılık ilkeleri, istekleri verimli bir şekilde dağıtmanıza olanak tanır. 1.000 sayfayı kazımanız gerekiyorsa, Go az miktarda bellek izi ile binlerce eşzamanlı isteği işleyebilir; oysa Python, asenkron kütüphanelerle yoğun şekilde yama yapılmadıkça, Global Yorumlayıcı Kilidi (GIL) sınırlamaları nedeniyle zorlanabilir.
Proje Kurulumu
Başlamak için sisteminizde Go'nun yüklü olduğundan emin olun. Yeni bir proje dizini oluşturup bir Go modülü başlatacağız. Ardından, kazıma mantığını tanımlamak için temiz bir API sağlayan Colly kütüphanesini yükleyeceğiz.
mkdir go-scraper
cd go-scraper
go mod init go-scraper
go get -u github.com/gocolly/colly/v2
Kazıyıcının Oluşturulması
Hedef bir web sitesini ziyaret eden, ana sayfadaki tüm makale bağlantılarını çıkaran ve ardından her bir makaleyi ziyaret ederek başlık ve içeriği çıkaran bir kazıyıcı oluşturacağız. Bu örnek, temel kavramları göstermektedir: URL'leri ziyaret etme, CSS seçicileri kullanarak veri çıkarma ve eşzamanlılığı yönetme.
package main
import (
"fmt"
"log"
"github.com/gocolly/colly/v2"
)
func main() {
// Yeni bir toplayıcı (collector) örneği oluşturun
c := colly.NewCollector(
colly.AllowedDomains("example.com"), // İzin verilen alan adlarıyla sınırlayın
colly.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64)"), // Kullanıcı aracısını ayarlayın
)
// href özelliğine sahip her bir a elementi için geri çağrıyı çağırın
c.OnHTML("a[href]", func(e *colly.HTMLElement) {
link := e.Attr("href")
// O sayfada bulunan bağlantıyı ziyaret edin
// Göreceli bağlantılar, mevcut URI kullanılarak çözümlenecektir
c.Visit(e.Request.AbsoluteURL(link))
})
// "article-title" sınıfına sahip her bağlantı için
c.OnHTML(".article-title", func(e *colly.HTMLElement) {
fmt.Printf("Makale bulundu: %s\n", e.Text)
})
// example.com'da kazımayı başlatın
if err := c.Visit("https://example.com"); err != nil {
log.Fatal(err)
}
}
Yukarıdaki kodda, belirli seçeneklerle bir Collector başlatıyoruz. AllowedDomains seçeneği güvenlik açısından kritiktir; kazıyıcımızın yanlışlıkla kötü amaçlı veya alakasız sitelere gitmesini engeller. Ayrıca, basit bot algılama mekanizmaları tarafından anında engellenmemek için gerçek bir tarayıcıyı taklit eden bir UserAgent ayarlıyoruz.
Eşzamanlılık ve Hız Sınırlama İşleme
Go'nun en önemli avantajlarından biri eşzamanlılıktır. Ancak, kazıma yaparken sunucu yüküne ve kazıma karşıtı politikalara saygı duymak hayati önem taşır. Colly, bunu yönetmek için kolay yollar sağlar.
colly.Async(true) ayarlayarak paralel ziyaretleri etkinleştirebilirsiniz, ancak hedef sunucuyu aşırı yüklememek için bir hız sınırlayıcı (rate limiter) uygulamanız gerekir. Hız sınırlayıcıyı toplayıcıya eklemenin yolu şöyledir:
import "github.com/gocolly/colly/v2"
// Saniyede 1 istek olacak şekilde bir hız sınırlayıcı ekleyin
c.Limit(&colly.LimitRule{
DomainGlob: "*",
Parallelism: 5,
Delay: 1 * time.Second,
})
Bu yapılandırma, kazıyıcımızın herhangi bir alan adı için saniyede en fazla 5 istek göndermesini ve bunlar arasında 1 saniyelik bir gecikme bırakmasını sağlar. Bu uygulama sadece etik olmakla kalmaz, aynı zamanda IP adresinizin engellenme olasılığını da azaltır.
Gelişmiş Teknikler: Hata Yönetimi ve Proxy Desteği
Üretim seviyesindeki kazıyıcılar için sağlam hata yönetimi tartışmasızdır. Colly, sorunları günlüğe kaydetmenize veya başarısız istekleri yeniden denemenize olanak tanıyan hata geri çağrıları tanımlamanıza izin verir.
c.OnError(func(r *colly.Response, err error) {
log.Printf("İstek URL'si: %s %s ile başarısız oldu\n", r.Request.URL, err)
})
Ayrıca, IP engellemeleriyle karşılaşırsanız bir proxy havuzu uygulayabilirsiniz. Proxy'leri döndürerek yükü dağıtabilir ve erişimi sürdürebilirsiniz. Tam bir proxy havuzu uygulamak bu giriş makalesinin kapsamı dışındadır, ancak entegrasyon, başlatma sırasında toplayıcıya bir proxy işlevi geçirmeyi içerir.
Sonuç
Go'da web kazıyıcıları oluşturmak, performans ve güvenilirlik arayan geliştiriciler için güçlü bir yaklaşımdır. Colly'den yararlanarak, HTTP istekleri ve HTML ayrıştırma ile ilişkili karmaşıklığın çoğunu soyutlayabilir, böylece veri çıkarma mantığına odaklanabilirsiniz. Piyasa verilerini topluyor, fiyat değişikliklerini izliyor veya akademik araştırma yapıyor olun, Go ölçeklenebilir, verimli ve sürdürülebilir kazıma çözümleri oluşturmak için gerekli araçları sağlar.
Kazıyıcınızı genişletirken, çıkarılan verileri depolamak için veritabanı entegrasyonu eklemeyi, daha karmaşık kimlik doğrulama akışları uygulamayı veya JavaScript ağırlıklı siteler için başsız tarayıcılar (headless browsers) kullanmayı düşünün. Go ve Colly tarafından atılan temel, bu sonraki adımları yönetilebilir ve verimli hale getirir.