Your Scrapy spider 100 test sayfasında gayet iyi giderken, 10.000 sayfada dağılıp gidiyorsa, sorun aslında bir scraping bug’ı değil; scraping bug’ı kılığına girmiş bir ağ problemidir. Herkesin başvurduğu çözüm proxy’dir ve bir tane request.meta içine koymak yaklaşık otuz saniye sürer.
Asıl mesele, o otuz saniyelik çözümde birçok temel rehberin durmasıdır. Size meta={"proxy": "http://IP:PORT"} gösterirler, belki bir middleware sınıfı eklerler ve konuyu kapatırlar. Ama proxy crawl ortasında ölürse ne olacağını, kimlik bilgilerinin Git geçmişine sızmasını, ya da bir retry’nin neden aynı başarısız proxy’yi tekrar kullanabileceğini çoğu zaman anlatmazlar. Bu rehberin ele aldığı üretim konuları bunlardır: fail-closed yapılandırma, gizli bilgi yönetimi, retry sırasında bilinçli proxy seçimi, protokol sınırları ve ölçülebilir maliyet dengeleri.
Scrapy’de Proxy Middleware Nedir?
Proxy middleware, Scrapy’nin downloader pipeline’ında yer alan ve bir isteğin dışarıya hangi IP’den çıkıyormuş gibi görünmesi gerektiğine karar veren koddur. Scrapy’nin yerleşik HttpProxyMiddleware bileşeni, request.meta içindeki proxy anahtarını okur, gerekiyorsa proxy kimlik doğrulamasını ekler ve isteği bağlantıyı gerçekten açan download handler’a iletir. Özel bir proxy middleware’i bu taşıma adımının yerine geçmez; yerleşik mekanizma devreye girmeden önce hangi proxy’nin seçileceğine karar veren bir seçicidir. Bu ayrım göründüğünden daha önemlidir ve "özel middleware’im çalışmıyor" türü hataların büyük kısmının kaynağıdır.
Proxy’ler Neden Üretim Scrapy Projelerinde Önemlidir?
Proxy, ağ rotasını ve görünen kaynak IP’yi değiştirir. Bu, meşru coğrafi testlerde işe yarayabilir, yetkili istek trafiğini dağıtabilir ve ağ kaynaklı hataları izole edebilir. Ancak otomatik olarak izin vermez, hız limitlerini ortadan kaldırmaz ya da erişim garantisi sağlamaz. Bir crawl için proxy gerekip gerekmediği; hedef sisteme, kullanım koşullarına, istek hızına ve işin güvenilirlik gereksinimlerine bağlıdır.
Tüm proxy’ler aynı değildir ve yanlış katmanı seçmek başlı başına bir üretim olayıdır:
| Proxy Türü | Güvenilirlik | Hız | Tespit Riski | Tipik Maliyet |
|---|---|---|---|---|
| Ücretsiz herkese açık proxy’ler | Çok değişken | Değişken | Genellikle yüksek | Ücret yoktur, ancak ciddi güvenlik/operasyon riski vardır |
| Veri merkezi proxy’leri | Sağlayıcıya ve hedefe bağlı | Genelde hızlı | Hedefe bağlı | Çoğunlukla GB başına veya IP başına fiyatlandırılır |
| Residential proxy’ler | Sağlayıcıya ve hedefe bağlı | Değişken | Hedefe bağlı | Genellikle GB başına fiyatlandırılır |
| ISP proxy’leri | Sağlayıcıya ve hedefe bağlı | Değişken | Hedefe bağlı | Sağlayıcıya özeldir |
Ücretsiz proxy’ler için ayrı bir uyarı gerekir; ölçülen riskler oldukça yüksektir. 30 aylık Free Proxies Unmasked çalışması 11 sağlayıcıdan 640.000’den fazla adresi izledi: %34,5’i en az bir kez aktifti ve 16.923 tanesi içerik üzerinde oynama yaptı. Bu veri seti, herkese açık listeler için güçlü bir güvenlik uyarısını destekler; mevcut her liste, ücretli havuz, hedef veya iş yükü için taşınabilir bir hata oranı değildir.
Proxy’ler modern bot tespitini de sihirli biçimde alt etmez. Cloudflare gibi servisler istekleri onlarca sinyalle puanlar — TLS parmak izleri, header tutarlılığı, JavaScript çalıştırma, davranış kalıpları — ve IP adresiniz bunlardan sadece biridir. Uyumlu olmayan header’lara ve cookie jar olmayan temiz bir residential proxy bile işaretlenebilir. "Sadece IP’yi döndürürüz" yaklaşımıyla tüm mimariyi kurmadan önce beklentiyi gerçekçi tutun.
Başlamadan Önce
- Zorluk: Orta
- Gerekli Süre: Tam üretim kurulumu için yaklaşık 30–45 dakika, hızlı test için yaklaşık 5 dakika
- İhtiyacınız Olanlar: Python 3.9+, Scrapy kurulu olmalı (bu rehber Scrapy 2.17.0 ile test edilmiştir, Temmuz 2026 sürümü),
scrapy startprojectile oluşturulmuş çalışan bir spider ve en az bir proxy uç noktası (test için herhangi bir veri merkezi proxy sağlayıcısının ücretsiz denemesi yeterlidir)
1. Adım: Request Meta Parametresi ile Proxy Test Edin
Bir proxy’nin çalıştığını doğrulamanın en hızlı yolu, tüm middleware mimarisini bir kenara bırakıp doğrudan denemektir.
Scrapy’nin yerleşik HttpProxyMiddleware bileşeni request.meta içinden doğrudan proxy anahtarını okur ve isteği oradan yönlendirir. Ayar değişikliği yok, middleware sınıfı yok — sadece tek bir anahtar-değer çifti.
import scrapy
class ProxyTestSpider(scrapy.Spider):
name = "proxy_test"
start_urls = ["https://httpbin.org/ip"]
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(
url,
meta={"proxy": "http://203.0.113.10:8080"},
callback=self.parse,
)
def parse(self, response):
self.logger.info(response.text)
scrapy runspider proxy_test.py ile çalıştırın. Proxy çalışıyorsa httpbin.org/ip, sizin IP’niz yerine proxy’nin IP adresini döndürür — doğrulama budur. Yanıt takılır ve sonunda TCP connection timed out hatası verirse, proxy ölüdür ya da ulaşılamıyordur; ne yazık ki proxy sağlayıcılarının kabul etmek istediğinden daha sık olur.
Bu yöntem tek seferlik spider’lar veya hızlı testler için uygundur. Birden fazla spider olduğunda işe yaramaz; çünkü aynı proxy dizesini beş farklı dosyada elle yazmanız gerekir.
2. Adım: Özel Bir Proxy Middleware Oluşturun
Tek bir spider’ın ötesine geçtiğinizde, proxy mantığını tek bir yerde merkezileştirmek istersiniz. Projenizin middlewares.py dosyasında bir ProxyMiddleware sınıfı oluşturun:
from scrapy.exceptions import NotConfigured
class ProxyMiddleware:
def __init__(self, proxy_url):
self.proxy_url = proxy_url
@classmethod
def from_crawler(cls, crawler):
proxy_url = crawler.settings.get("PROXY_URL")
if not proxy_url:
raise NotConfigured("PROXY_URL is required; refusing silent direct fallback")
return cls(proxy_url=proxy_url)
def process_request(self, request, spider):
if "proxy" not in request.meta:
request.meta["proxy"] = self.proxy_url
Ve bunu settings.py içinde kaydedin:
import os
PROXY_URL = os.environ.get("PROXY_URL")
DOWNLOADER_MIDDLEWARES = {
"myproject.middlewares.ProxyMiddleware": 350,
}
Burada düz __init__ yerine from_crawler classmethod’ine dikkat edin. Scrapy’nin ayar okumak için gerçekten önerdiği desen budur ve gizli bilgilerden bahsederken 4. Adım’da tekrar kullanacağımız hook da budur. Buradaki avantaj basittir: tek bir ayarı değiştirirsiniz, projedeki tüm spider’lar yeni proxy’yi alır. Artık ölü bir IP’yi değiştirmek için beş dosyada arama yapmanız gerekmez.
3. Adım: Middleware Çalışma Sırasını Anlayın (Aksi Halde Proxy’niz Sessizce Hiçbir Şey Yapmaz)
Çoğu rehberin üzerinde atladığı kısım tam da burasıdır; "sadece önceliği 350 yapın, bana güvenin" demekle geçiştirirler. Scrapy’de downloader middleware belirli ve öngörülebilir bir sırayla çalışır; bunu anlamazsanız proxy kurulumunuz proxy ile ilgisi olmayan sorunlar üretebilir.
İstek tarafı hook’ları (process_request) artan öncelik sırasıyla çalışır — en küçük sayı önce. Yanıt tarafı hook’ları (process_response, process_exception) azalan sırayla çalışır — en büyük sayı önce ve zincir aşağı doğru çözülür.
İstek akışı (artan):
Spider → [100] RobotsTxt → [300] HttpAuth → [350] SİZİN PROXY MIDDLEWARE’INIZ
→ [500] UserAgent → [550] Retry → [700] Cookies → [750] HttpProxy
→ Downloader
Yanıt akışı (azalan):
Downloader → [750] HttpProxy → [700] Cookies → [550] Retry
→ [500] UserAgent → [350] SİZİN PROXY MIDDLEWARE’INIZ → [300] HttpAuth
→ [100] RobotsTxt → Spider
Aşağıda Scrapy’nin yerleşik middleware’leri için güncel ve gerçek varsayılan öncelik tablosu var (2.17.0’a göre doğrulanmıştır):
| Middleware | Varsayılan Öncelik |
|---|---|
| RobotsTxtMiddleware | 100 |
| HttpAuthMiddleware | 300 |
| DownloadTimeoutMiddleware | 350 |
| DefaultHeadersMiddleware | 400 |
| UserAgentMiddleware | 500 |
| RetryMiddleware | 550 |
| RedirectMiddleware | 600 |
| CookiesMiddleware | 700 |
| HttpProxyMiddleware | 750 |
| DownloaderStats | 850 |
| HttpCacheMiddleware | 900 |
RetryMiddleware bir yeniden deneme planladığında, başarısız isteği — metadata’sı dahil — kopyalar ve yeni istek downloader middleware zincirine tekrar girer. Seçicinin 550 önceliğiyle sayısal ilişkisi, otomatik olarak rotasyon anlamına gelmez. Rotasyon ancak seçici kodu retry durumunu fark edip kopyalanan meta["proxy"] değerini bilinçli biçimde değiştirirse gerçekleşir. 350, seçici için kullanışlı bir konumdur çünkü 750’deki yerleşik taşıma adımından önce çalışır; fakat tek başına bir rotasyon mekanizması değildir.

Yaygın Middleware Sıralama Hataları
- Middleware’inizi
HttpProxyMiddlewareile aynı önceliğe (750) koymak: Bu, Scrapy’nin sözlük sırasının (sizin mantığınızın değil) isteği önce hangi middleware’in işleyeceğine karar verdiği bir yarış durumu yaratır. Belirti: aralıklı, açıklanamayan proxy davranışı. - Döner bir seçicide
setdefault()veyaif "proxy" not in request.metakullanmak: kopyalanan retry, eski proxy’yi taşımaya devam eder. Belirti: her retry aynı başarısız rotayı tekrarlar. Çözüm: retry’yi tespit edin (örneğinretry_times > 0) ve seçiciye ait proxy değerini açıkça değiştirin. HttpProxyMiddleware’i tamamen devre dışı bırakmak: Bazı rehberler, "özel middleware bunu hallediyor" diye"scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": Noneayarlamanızı söyler. Halletmez — özel middleware’iniz bir seçicidir, taşıma katmanı değil. Yerleşik bileşeni kapatmak, proxy kimlik doğrulama header’larının eklenmemesine yol açar ve istekleriniz sessizce kimlik doğrulamasız gider (ya da hiç gitmez).
4. Adım: Proxy Kimlik Bilgilerini Koda Gömeyin
İncelediğim neredeyse tüm üst sıralardaki Scrapy proxy rehberleri, http://username:password@proxy.example.com:8080 biçimini doğrudan Python dosyasına yazıyor. Bu, Git geçmişinizde sonsuza kadar kalacak bir kimlik bilgisidir; her clone’da, her fork’ta ve biri print() ile dikkatsiz davranırsa her log dökümünde görünür.
Bunu yapmanın gerçekten üç seviyesi vardır:
| Yöntem | Güvenlik | Esneklik | En Uygun Olduğu Durum |
|---|---|---|---|
| Spider/settings.py içinde sabit yazmak | Kötü — sırlar repoda yaşar | Düşük | Yalnızca hızlı yerel test |
http_proxy environment variable (Scrapy yerel desteği) | Daha iyi — kod dışında | Düşük (tek proxy) | CI/CD pipeline’ları, Docker |
.env dosyası + python-dotenv + from_crawler | En iyi — kod dışında, ortama göre ayrılmış | Yüksek (birden fazla proxy, rotasyon) | Üretim scraper’ları |
Üçüncü seçenek düzgün kurulmaya değer. python-dotenv paketini kurun, bir .env dosyası oluşturun ve hemen .gitignore’a ekleyin — ciddiyim, bunu şimdi yapın:
PROXY_USER=myuser
PROXY_PASSWORD=my$ecret!Pass
PROXY_HOST=proxy.example.com
PROXY_PORT=8080
Bunu settings.py dosyasının başında yükleyin:
from dotenv import load_dotenv
import os
load_dotenv()
PROXY_USER = os.getenv("PROXY_USER")
PROXY_PASSWORD = os.getenv("PROXY_PASSWORD")
PROXY_HOST = os.getenv("PROXY_HOST")
PROXY_PORT = os.getenv("PROXY_PORT")
Sonra bunu middleware içinde from_crawler ile güvenli biçimde okuyun — forumlarda insanların "kimlik bilgileri her çalıştırmada değişiyorsa scrapy crawl öncesi bunu nasıl ayarlayacağım?" diye sormasına neden olan kafa karışıklığını tam olarak çözen desen budur:
import os
from urllib.parse import quote
class SecureProxyMiddleware:
def __init__(self, user, password, host, port):
self.user = quote(user, safe="")
self.password = quote(password, safe="")
self.host = host
self.port = port
@classmethod
def from_crawler(cls, crawler):
settings = crawler.settings
return cls(
user=settings.get("PROXY_USER"),
password=settings.get("PROXY_PASSWORD"),
host=settings.get("PROXY_HOST"),
port=settings.get("PROXY_PORT"),
)
def process_request(self, request, spider):
proxy_url = f"http://{self.user}:{self.password}@{self.host}:{self.port}"
request.meta["proxy"] = proxy_url
Kimlik bilgileri etrafındaki urllib.parse.quote() çağrısına dikkat edin. Şifrenizde @, : veya / varsa (ve parola üreticileri bunları sık sık ekler), önce yüzde kodlaması yapılmazsa URL ayrıştırması bozulur. Bu tek satırlık düzeltme, proxy’nizin aslında bozuk olmadığı halde "invalid proxy URL" hatalarını ayıklarken utandırıcı bir saat kaybını önler.
Kimlik bilgilerini loglardan uzak tutun ve temsilî ama sahte değerlerle yüzde kodlamayı test edin. HTTPS tunneling, SOCKS5 ve Latin olmayan kimlik bilgileri handler’a özgü sınırlara sahiptir; aynı kimlik doğrulama deseninin tümünde çalıştığını varsaymayın, sabitlenmiş bir entegrasyon testiyle doğrulayın.

5. Adım: Proxy Rotasyonu Ekleyin
Tek bir proxy — iyi olsa bile — aynı siteye 5.000 istek attığında sonunda işaretlenir. Bir havuza ihtiyacınız var.
Seçenek A — kendiniz oluşturun. Bu gerçekten basittir:
import random
class RotatingProxyMiddleware:
def __init__(self, proxy_pool):
self.proxy_pool = proxy_pool
@classmethod
def from_crawler(cls, crawler):
return cls(proxy_pool=crawler.settings.getlist("PROXY_POOL"))
def process_request(self, request, spider):
request.meta["proxy"] = random.choice(self.proxy_pool)
Bu temel kullanım için çalışır, ancak hangi proxy’lerin gerçekten ayakta olduğuna dair hiçbir farkındalığı yoktur. Her istekte zar atıyorsunuz.
Seçenek B — scrapy-rotating-proxies kullanın. Bu üçüncü taraf paket, yerleşik ban tespiti ve otomatik geri çekilme mekanizması ekler:
pip install scrapy-rotating-proxies
Burada dürüst olayım: PyPI’daki en güncel sürüm 0.6.2, tarihi 2019 ve proje Alpha etiketi taşıyor. Modern Scrapy’de mutlaka bozuk olduğu anlamına gelmez, ancak "2019’dan beri aktif olarak bakımı yapılmıyor" ifadesi, "2026 üretim trafiğinde denenmiş ve onaylanmış" anlamına gelmez. Sürümü sabitleyin, gerçek hedef sitelerinizde test edin ve kimlik doğrulamalı proxy uç noktalarını ele aldığını varsaymayın — büyük ölçüde ele almıyor.
6. Adım: Hata Toleranslı Bir Proxy Middleware Oluşturun (Ölü Proxy Tespiti)
Rakip rehberlerin tamamen atladığı bölüm burasıdır ve demo ile 6 saatlik bir crawl’ı sorunsuz atlatan sistem arasındaki fark tam da budur.
| Senaryo | Çoğu rehberin gösterdiği şey | Bu middleware’in eklediği şey |
|---|---|---|
| Proxy 407 döndürür | Ele alınmaz | Proxy kimlik doğrulama hatası olarak işler |
| Hedef 403/429 döndürür | Sıklıkla birlikte ele alınır | Politika/hız geri bildirimini proxy sağlığından ayrı tutar |
| Proxy zaman aşımına uğrar | Ele alınmaz | Ayarlanabilir zaman aşımı eşiği, sağlık puanı düşüşü |
| Tüm proxy’ler ölür | Ele alınmaz | Kibar geri dönüş veya kayıtlı uyarı ile crawl duraklatma |
| Proxy dalgalanır (aralıklı olarak düşer) | Ele alınmaz | Havuzda yeniden eklemeden önce bekleme süresi |
import time
import random
from scrapy.exceptions import IgnoreRequest
class FaultTolerantProxyMiddleware:
MAX_FAILURES = 3
COOLDOWN_SECONDS = 300
def __init__(self, proxy_pool):
self.pool = {p: {"failures": 0, "banned_until": 0} for p in proxy_pool}
@classmethod
def from_crawler(cls, crawler):
return cls(proxy_pool=crawler.settings.getlist("PROXY_POOL"))
def _healthy_proxies(self):
now = time.time()
return [p for p, s in self.pool.items() if s["banned_until"] < now]
def process_request(self, request, spider):
healthy = self._healthy_proxies()
if not healthy:
spider.logger.warning("All proxies unhealthy — pausing crawl")
raise IgnoreRequest("No healthy proxies available")
request.meta["proxy"] = random.choice(healthy)
def process_response(self, request, response, spider):
proxy = request.meta.get("proxy")
if proxy and response.status == 407:
self._mark_failure(proxy)
return response
def process_exception(self, request, exception, spider):
proxy = request.meta.get("proxy")
if proxy:
self._mark_failure(proxy)
def _mark_failure(self, proxy):
state = self.pool[proxy]
state["failures"] += 1
if state["failures"] >= self.MAX_FAILURES:
state["banned_until"] = time.time() + self.COOLDOWN_SECONDS
state["failures"] = 0
Gerçekten bunu kurarken edindiğim birkaç not: her 403’ü proxy’nin öldüğünün kanıtı saymayın — RFC 9110 403’ü "sunucu anladı ama reddediyor" şeklinde tanımlar; bu, proxy’den bağımsız olarak header’larınızın veya oturumunuzun şüpheli görünmesi kadar kolay bir nedenle de olabilir. Buna karşılık 407, proxy’nin özellikle kimlik doğrulamanızı reddettiği anlamına gelir — bu daha güçlü ve daha özel bir sinyaldir. Bu sinyalleri tek bir kovada toplamak, insanların sağlam proxy’leri boş yere yakmasına yol açar.
Üretimde Scrapy’nin geçici retry varsayılanlarını açıkça bırakın ki gözden geçirenler politikayı görebilsin:
RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408, 429]
RETRY_TIMES = 2
Bunlar Scrapy 2.17’nin varsayılanlarıdır. Bunlara körlemesine 403 veya 407 eklemeyin: 403, hedefin reddetmesidir ve birçok olası nedeni vardır; 407 ise genel istek retry’sinin düzeltemeyeceği bir proxy kimlik doğrulama problemidir. Belirli bir hedef sözleşmesi başka bir durumu retry etmeyi haklı çıkarıyorsa, nedeni belgeleyin ve ayrı test edin.

7. Adım: Ölçülü Bir Retry Sırasında Proxy Kullanım Deseni
Yetkili bazı hedefler geçerli içeriği doğrudan döndürebilir ve proxy’yi yalnızca belgelenmiş geçici bir yanıttan sonra gerektirebilir. Bu, proxied byte miktarını azaltabilir; ancak savunulabilir evrensel bir tasarruf yüzdesi ya da taşınabilir bir doğrudan istek başarı oranı yoktur. Deseni benimsemeden önce kendi iş yükünüzü ölçün.
Scrapy’nin herkese açık get_retry_request() yardımcı fonksiyonunu kullanın ve yükseltmeyi, açıkça sınıflandırdığınız hedefe özgü durumlarla sınırlandırın. Bu örnek 429 ve 503’ü retry edilebilir baskı sinyalleri olarak ele alır; 403 ve 407’yi özellikle dışarıda bırakır.
from scrapy.downloadermiddlewares.retry import get_retry_request
class CostAwareEscalationMiddleware:
def process_response(self, request, response, spider):
if response.status not in {429, 503}:
return response
retry = get_retry_request(
request,
spider=spider,
reason=f"proxy_escalation_{response.status}",
max_retry_times=2,
)
if retry is None:
return response
current_tier = request.meta.get("proxy_tier", "direct")
if current_tier == "direct":
retry.meta["proxy"] = spider.settings["DATACENTER_PROXY"]
retry.meta["proxy_tier"] = "datacenter"
elif current_tier == "datacenter":
retry.meta["proxy"] = spider.settings["RESIDENTIAL_PROXY"]
retry.meta["proxy_tier"] = "residential"
else:
return response
return retry
Doğrudan geçerli içerik oranını, proxy üzerinden gelen geçerli içerik oranını, başarılı kayıt başına byte miktarını, başarı başına retry sayısını ve ek gecikmeyi loglayın. Direct-first tasarım yalnızca doğrudan erişim yetkiliyse ve sistem proxy gerektiğinde fail-closed davranıyorsa kabul edilebilir. Tasarruf, proxy trafiğindeki ölçülen azalmadır — varsayılan bir yüzde değil.
DIY Proxy Yönetimi Ne Zaman Buna Değmez?
Bu noktada sanki yazının geri kalanı gereksizmiş gibi davranmak istemiyorum: yukarıdakilerin hepsi gerçek ve faydalı mühendisliktir; yüksek hacimli crawl’lar, özel pipeline’lar ve istek planlaması üzerinde tam kontrol gerektiren projeler için çoğu zaman doğru seçimdir.
Ama gerçek hedefiniz "proxy altyapısı işletmek" değil de "bu sayfadan yapılandırılmış veri almak" ise, extraction API daha uygun bir sınır olabilir. Thunderbit’in güncel POST /extract dokümantasyonu bir sayfa URL’si ve isteğe bağlı bir JSON Schema kabul eder; schema verilmezse servis bunu sayfa içeriğinden üretebilir. Uç nokta ayrıca none, basic ve full render modlarını, timeout ve yükleme sonrası bekleme kontrollerini sunar. Sadece prompt’a dayalı extraction mevcut desteklenen istek yüzeyinin parçası değildir; bu nedenle üretim entegrasyonlarını belgelenmiş schema sözleşmesi etrafında kurun. Bu, extraction arayüzünü tek bir isteğin arkasına taşır; ancak bunu tüm anti-bot veya CAPTCHA hedefleri için evrensel bir çözüm olarak okumayın.
| Faktör | DIY Scrapy + Proxy’ler | API tabanlı extraction (ör. Thunderbit) | |---|---|---|---| | Kurulum çabası | Yüksek — middleware, rotasyon, retry mantığı | Düşük — schema ile tek API çağrısı | | Ağ/render davranışı | Handler’ları, proxy’leri, header’ları ve gecikmeleri siz ayarlarsınız | Belgelenmiş API seçenekleriyle kontrol edilir | | Bakım | Selector’lar, havuz sağlığı ve hedef değişimlerinden siz sorumlusunuz | Schema kalitesi, doğrulama ve entegrasyon davranışından siz sorumlusunuz | | Maliyet modeli | Proxy ücretleri + compute + mühendislik zamanı | Güncel dokümanlar sayfa başına 20 unit listeliyor (2026-08-10 kontrol edildi) | | Kontrol | Tam — özel pipeline’lar, middleware zinciri | API kabiliyetleriyle sınırlı | | En iyi kullanım | Karmaşık crawl’lar, yüksek hacim, özel mantık | Hedefli extraction, prototipleme, zenginleştirme |
Çoğunlukla lead listeleri, ürün verileri veya araştırma için yapılandırılmış sayfalar çıkarıyorsanız, Thunderbit Chrome Extension veya API ile temsili bir pilot çalıştırın ve geçerli kayıtları, gecikmeyi, unit’leri ve bakım süresini karşılaştırın. Projeniz özel crawl grafikleri ve pipeline kontrolü gerektiriyorsa, Scrapy hâlâ daha güçlü seçenektir.
Daha Fazla Bilgi
İpuçları ve Yaygın Hatalar
- İpucu: Proxy’leri gerçek bir hedefe yönlendirmeden önce
httpbin.org/ipüzerinde test edin. Karmaşıklık eklemeden önce yönlendirmenin çalıştığını doğrulamanın en hızlı yoludur. - Hata: Proxy’yi
request.headersiçine koymak yerinerequest.metaiçine koymak. Bu gerçekten çok sık görülen, yazım hatasına yakın bir bug’dır —HttpProxyMiddlewareyalnızcameta["proxy"]okur ve header üzerinden yapılan deneme sessizce başarısız olur. - Hata: HTTP ve HTTPS proxy’lerin aynı şekilde yapılandırıldığını varsaymak. HTTP proxy URL’sinin HTTPS hedefe yönlenmesi, uyumlu bir handler altında genellikle CONNECT tünellemesiyle çalışır; ancak proxy uç noktasının kendisi için
https://şeması kullanmak farklı ve daha az desteklenen bir konfigürasyondur — ikisini karıştırmayın. - İpucu: SOCKS5 desteğine ihtiyacınız varsa, önce Scrapy sürümünüzün download handler yeteneklerini kontrol edin. Scrapy 2.17’nin deneysel Httpx handler’ı
httpx[socks]ile SOCKS5 desteği ekledi, fakat hâlâ deneysel olarak etiketli — bunu üretim bağımlılığı yapmadan önce kendi testinizi yapın.
Alternatif Yöntemler
scrapy-rotating-proxies dışında bazı ekipler tüm proxy mantığını bir sağlayıcı gateway üzerinden yürütür — sağlayıcının arka planda rotasyon, session stickiness ve coğrafi hedefleme işini yaptığı tek bir proxy URL’si. Bu yaklaşım, biraz kontrol karşılığında çok daha az middleware kodu sağlar ve sıfırdan sistem kurmadan önce kendi yönettiğiniz bir havuzla fiyat açısından kıyaslamaya değerdir.
Sonuç
Scrapy’de proxy ayarlamak bir satırlık iştir. Bu kurulumu gerçek bir üretim crawl’ında ayakta tutmak için ise açık hata politikası, korumalı kimlik bilgileri, test edilmiş handler sınırları ve retry sırasında kopyalanan proxy metadata’sını bilinçli biçimde değiştiren seçici kod gerekir. Buradan iki alışkanlıkla ayrılın: proxy gerektiğinde fail-closed davranın ve bir proxy şifresini asla bir Python dosyasına commit etmeyin.
SSS
Kimlik doğrulamalı özel bir proxy’yi Scrapy’de nasıl kurarım?
protocol://username:password@host:port URL biçimini kullanın, ancak özel karakterler içeriyorsa önce kullanıcı adı ve şifreyi urllib.parse.quote() ile yüzde kodlayın. Üretimde bu kimlik bilgilerini sabit yazmak yerine, ortam değişkenlerinden çeken bir from_crawler classmethod’i üzerinden okuyun.
Scrapy’de özel proxy middleware’im için hangi öncelik numarasını kullanmalıyım?
350, yaygın bir seçici önceliğidir çünkü HttpProxyMiddleware’den önce (750) çalışır. Ancak rotasyonu garanti etmez. Bir retry ancak seçici kopyalanmış retry isteğini tanıyıp önceki meta["proxy"] değerini üzerine yazarsa yeni proxy alır.
Scrapy’de ölü proxy’leri otomatik olarak nasıl yönetirim?
process_response ve process_exception içinde proxy başına başarısızlık sayısını izleyen, eşik aşıldığında proxy’leri aktif havuzdan çıkaran ve kalıcı yasak yerine bir bekleme süresinden sonra yeniden ekleyen bir middleware oluşturun.
Scrapy ile SOCKS5 proxy kullanabilir miyim?
Scrapy 2.17’nin deneysel HttpxDownloadHandler bileşeni, httpx[socks] kuruluysa SOCKS5 desteğini belgeliyor. Varsayılan HTTP/1.1 handler SOCKS proxy’lerini desteklemez. Bu yolu üretime hazır kabul etmeden önce handler/sürüm sabitleyin ve entegrasyon testi çalıştırın.
Proxy-on-retry yaklaşımı proxy maliyetlerinde gerçekte ne kadar tasarruf sağlar? Taşınabilir bir yüzde yoktur. Yetkili isteklerin ne kadarının doğrudan geçerli içerik döndürdüğünü, her proxy katmanından geçen byte miktarını, başarılı kayıt başına retry sayısını ve ek gecikmeyi ölçün. Proxy üzerinden gönderilen trafikte gözlenen azalma sizin tasarrufunuzdur; doğrudan erişim yetkili değilse ya da geçerli değilse bu yaklaşımı kullanmayın.


