Web scraping yaparken captcha'lardan nasıl kaçınılır (kurallara uyarak)
Scraping sırasında çıkan captcha'ların çoğu, otomatik göründüğü için gelen trafiğe verilen bir tepkidir. Bunlarla başa çıkmanın en ucuz yolu, onları tetiklemeyi bırakmaktır. Bu da önce meşru bir veri kaynağına bakmak, sitenin kurallarının neye izin verdiğini öğrenmek, daha az ve daha yavaş istek göndermek ve aynı sayfayı iki kez çekmemek anlamına gelir. Captcha çözmek kaçınamadığınız durumlar için bir yedek yoldur, asıl plan değildir.
Önce resmi bir API ya da veri akışı arayın
Scrape edilen birçok site, aynı veriye captcha olmadan erişmenin bir yolunu zaten sunar: herkese açık bir API, bir veri dışa aktarımı, bir RSS ya da sitemap akışı veya bir iş ortaklığı programı. Resmi bir kaynak daha güvenilirdir, habersiz değişme olasılığı daha düşüktür ve verinin nasıl kullanılacağı konusunda site sahibinin bir sözü olur. Şunlara bakın:
- sayfa altbilgisinde bir geliştirici veya API bölümü,
- sayfa listesi için
sitemap.xml, - sayfa
<head>kısmında RSS ya da Atom bağlantıları, - toplu dışa aktarımlar için bir "veri" ya da "indir" sayfası.
İhtiyacınızı bunlardan biri karşılıyorsa onu kullanın. HTML istemeyerek çoğu captcha'dan kaçınmış olursunuz.
robots.txt'e ve istediği hıza uyun
robots.txt, otomatik istemcilerin hangi yolları çekebileceğini ve bazen istekler arasında ne kadar beklemeleri gerektiğini söyler. Python'un standart kütüphanesi bunu sizin yerinize okuyabilir:
import time
from urllib.robotparser import RobotFileParser
import requests
USER_AGENT = "ExampleBot/1.0 (+https://example.com/bot)"
parser = RobotFileParser()
parser.set_url("https://example.com/robots.txt")
parser.read()
delay = parser.crawl_delay(USER_AGENT) or 5 # muhafazakâr bir varsayılan olarak 5 saniyeye dön
urls = [
"https://example.com/products?page=1",
"https://example.com/products?page=2",
]
last_request = 0.0
for url in urls:
if not parser.can_fetch(USER_AGENT, url):
print("skipped by robots.txt:", url)
continue
wait = delay - (time.monotonic() - last_request)
if wait > 0:
time.sleep(wait)
resp = requests.get(url, headers={"User-Agent": USER_AGENT}, timeout=30)
last_request = time.monotonic()
print(url, resp.status_code)
robots.txt bir yolu yasaklıyorsa dürüst cevap o yolu bırakmak ya da site sahibine sormaktır. Bir tarayıcı kullanarak etrafından dolaşmak, sitenin istediğini değiştirmez.
Yavaşlayın ve istekleri yayın
Sabit ve mütevazı bir hız neredeyse hiç captcha tetiklemez; ani bir patlama ise neredeyse her zaman tetikler. Birkaç alışkanlık büyük fark yaratır:
- Site başına tek bir istek hızı belirleyin ve ona sadık kalın; tam hızda çalışmayın.
- Zamanlamanın tamamen düzenli olmaması için rastgele bir jitter ekleyin.
- Bir 429 ya da captcha sayfası gördüğünüzde bir süre durup geri çekilin.
- Sitenin yükü bir sorunsa işleri yoğunluk dışı saatlerde çalıştırın.
Önbelleğe alın, tekrar çekmeyin
Yapmadığınız her istek, sitenin işlemek zorunda olmadığı bir istektir. Çektiğiniz sayfaları tarihleriyle ve gövdelerinin hash'iyle saklayın; yalnızca içeriğin muhtemelen değiştiği durumlarda yeniden çekin. Destekleniyorsa If-Modified-Since ya da ETag başlıklarıyla koşullu istekler, sunucunun "değişmedi" cevabını ucuza vermesini sağlar.
Oturumları yeniden kullanın, olağan başlıklar gönderin
İstekler arasında çerezleri tutan bir oturum, her seferinde sıfırdan başlayan bir scripte göre gerçek bir ziyaretçiye daha çok benzer. Her site için requests.Session() kullanın ve bir iletişim bilgisini belirten açık, dürüst bir User-Agent gönderin. Bir kuralı aşmak için bir tarayıcıymış gibi davranmayın. Bir site içeriğini göstermek için JavaScript gerektiriyorsa o sayfalar için bir tarayıcı aracı kullanın ve aynı hız sınırlarını koruyun.
Captcha yine de çıkarsa
Bazı siteler, ne kadar dikkatli davranırsanız davranın captcha gösterecektir. Bunu kodda tespit edin ve sayfaya saldırmak yerine o işi durdurun. Tespit ve PopularCaptcha için isteğe bağlı çözme adımı, web scraping captcha'ları rehberinde ele alınmıştır.
Taramayı başlamadan planlayın
Her şeyi her gün çeken bir tarama, captcha tetiklemenin en kolay yoludur. İşi önce planlayın:
- Önceliklendirin. Hangi sayfaların sık, hangilerinin nadir değiştiğine karar verin. Sık olanları sık, diğerlerini nadiren tarayın.
- Sitemap'teki tarihleri kullanın. Birçok sitemap
lastmoddeğeri içerir. Son ziyaretinizden beri değişmemiş URL'leri atlayın. - Artımlı tarayın. Her URL için son başarılı çekimi saklayın ve bir hatadan sonra baştan değil, oradan devam edin.
- Yükü yayın. Büyük bir listeyi parçalara bölün ve hepsini aynı anda değil, gün boyunca çalıştırın.
Böyle bir plan istek sayısını düşürür; bu sahip olduğunuz en büyük kaldıraçtır.
Planı kısa bir yapılandırma dosyası ya da tablo olarak yazın: siteler, bölümler, yenileme aralığı ve her biri için günlük istek bütçesi. Bütçe tükendiğinde iş bir sonraki pencereye kadar durur. Bütçeyi bir öneri değil, sert bir sınır olarak görmek, tarayıcıyı captcha'ları tetikleyen trafik örüntüsüne kaymaktan alıkoyan şeydir. Bütçeyi birkaç haftada bir gözden geçirin; büyüyen bir site trafiğini de artırabilir ve geçen çeyrekte makul olan şey bugün makul olmayabilir.
Sorumlu scraping
- Başlamadan önce
robots.txtve kullanım koşullarını kontrol edin ve dediklerine uyun. - İstek hızını düşük tutun; site zorlandığını belirtirse durun.
- İhtiyacınız olmayan kişisel veriyi toplamayın ve artık gerekmediğinde silin.
- Telif hakkıyla korunan içeriği toplu olarak yeniden yayınlamayın. Veriyi analiz, karşılaştırma ya da kendi ürününüz için kullanın ve uygun olduğunda kaynağı belirtin.
- Daha büyük bir hacme ihtiyacınız varsa site sahibiyle iletişime geçin. Bir veri akışı sunabilirler.