Bloga geri dön

Scrapy Çerçevesinde Proxy Ayarları: Kod Örnekleri ile Tam Kılavuz

Scrapy'de proxy entegrasyonu için kapsamlı rehber: temel ayarlardan IP adresi döndürme için gelişmiş yöntemlere kadar, çalışır kod örnekleri ile.

📅14 Şubat 2026

Scrapy, web scraping için en güçlü Python framework'lerinden biridir, ancak doğru proxy ayarı olmadan, tarayıcılarınız birkaç dakika içinde engellenebilir. Bu kılavuzda, Scrapy'de proxy entegrasyonu için tüm yöntemleri göstereceğim: en basit ayarlardan, otomatik hata işleme ile IP adreslerinin döngüsüne kadar.

Materyal, büyük e-ticaret siteleri ve korumalı web siteleri üzerinde yapılan gerçek veri çekme deneyimlerine dayanmaktadır. Projelerinizde hemen kullanabileceğiniz hazır kod örnekleri alacaksınız.

Neden Scrapy Proxy Olmadan Engelleniyor

Modern web siteleri, veri çekmeye karşı çok katmanlı koruma kullanmaktadır. User-Agent ve istekler arasındaki gecikmeleri ayarlasanız bile, IP adresiniz birkaç belirti ile otomasyonu ortaya çıkarır:

  • İstek Sıklığı: bir IP, dakikada 100+ istek yapıyorsa - bu, bir botun açık bir işareti
  • Davranış Kalıpları: rastgele geçişler olmadan sayfaların ardışık olarak gezilmesi
  • JavaScript Eksikliği: Scrapy JS çalıştırmaz, bu kolayca tespit edilir
  • Coğrafi Konum: ev ağı yerine veri merkezinden erişim

Sonuç - birkaç saat veya gün boyunca IP banı. Özellikle agresif koruma, pazar yerleri (Amazon, Wildberries, Ozon), sosyal medya ve Cloudflare ile korunan sitelerde kullanılır. Proxy'ler, istekleri birçok IP adresi arasında dağıtarak bu sorunu çözer.

Önemli: Proxy ile bile, oran limitlerine uymak gerekir. Önerilen hız: bir IP için saniyede 1-3 istek. Yüksek hızlı veri çekimi için 50+ proxy ile bir havuz kullanın ve döngü oluşturun.

Scrapy'de Proxy Temel Ayarları

En basit yöntem, proxy'yi doğrudan örümcek ayarlarında belirtmektir. Bu yöntem, test etme veya tek bir proxy sunucusuyla küçük veri hacimlerini çekmek için uygundur.

Yöntem 1: Request'te meta ile

import scrapy

class MySpider(scrapy.Spider):
    name = 'example'
    start_urls = ['https://example.com']
    
    def start_requests(self):
        proxy = 'http://username:password@proxy.example.com:8080'
        
        for url in self.start_urls:
            yield scrapy.Request(
                url=url,
                callback=self.parse,
                meta={'proxy': proxy}
            )
    
    def parse(self, response):
        # Veri çekme mantığınız
        self.log(f'Scraped {response.url} via {response.meta["proxy"]}')

Proxy formatı, protokole ve kimlik doğrulama yöntemine bağlıdır:

  • http://proxy.example.com:8080 — kimlik doğrulama olmadan
  • http://user:pass@proxy.example.com:8080 — kullanıcı/şifre ile
  • socks5://user:pass@proxy.example.com:1080 — SOCKS5 proxy

Yöntem 2: settings.py'de Küresel Ayar

# settings.py

# Tüm istekler için HTTP proxy
HTTPPROXY_ENABLED = True
HTTPPROXY_AUTH_ENCODING = 'utf-8'

# Ortam değişkenleri ile ayarlama
HTTP_PROXY = 'http://username:password@proxy.example.com:8080'
HTTPS_PROXY = 'http://username:password@proxy.example.com:8080'

Bu yöntem hızlı testler için uygundur, ancak üretim için uygun değildir: IP döngüsü yoktur, proxy düştüğünde tüm tarayıcı durur, farklı siteler için farklı proxy'ler kullanmak mümkün değildir.

Özel Proxy Middleware Oluşturma

Üretim veri çekimi için, proxy havuzunu yönetecek, hataları işleyecek ve IP'leri otomatik olarak döndürecek özel bir middleware gerekir. İşte temel bir uygulama:

# middlewares.py

import random
from scrapy import signals
from scrapy.exceptions import NotConfigured

class RandomProxyMiddleware:
    def __init__(self, proxy_list):
        self.proxy_list = proxy_list
    
    @classmethod
    def from_crawler(cls, crawler):
        # Ayarlardan proxy listesini yükle
        proxy_list = crawler.settings.getlist('PROXY_LIST')
        
        if not proxy_list:
            raise NotConfigured('PROXY_LIST not configured')
        
        return cls(proxy_list)
    
    def process_request(self, request, spider):
        # Havuzdan rastgele bir proxy seç
        proxy = random.choice(self.proxy_list)
        request.meta['proxy'] = proxy
        
        spider.logger.info(f'Using proxy: {proxy}')
    
    def process_exception(self, request, exception, spider):
        # Hata durumunda başka bir proxy deneyin
        proxy = random.choice(self.proxy_list)
        request.meta['proxy'] = proxy
        
        spider.logger.warning(
            f'Proxy error, switching to: {proxy}'
        )
        
        return request

Şimdi settings.py dosyasında middleware kullanımını ayarlayalım:

# settings.py

# Proxy listesi (dosyadan veya API'den yüklenebilir)
PROXY_LIST = [
    'http://user1:pass1@proxy1.example.com:8080',
    'http://user2:pass2@proxy2.example.com:8080',
    'http://user3:pass3@proxy3.example.com:8080',
    # ... etkili döngü için 50+ proxy ekleyin
]

# Middleware'i bağlayın
DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.RandomProxyMiddleware': 350,
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 400,
}

# Hatalarda tekrar denemeler
RETRY_TIMES = 3
RETRY_HTTP_CODES = [500, 502, 503, 504, 408, 429]

Proxy Döngüsü: Üç Çalışan Yöntem

Proxy'lerin rastgele seçimi (yukarıdaki örnekte olduğu gibi) en basit yöntemdir, ancak en etkili değildir. Farklı senaryolar için üç döngü stratejisini inceleyelim.

Yöntem 1: Round-robin (sıralı döngü)

Proxy'ler dairesel olarak seçilir. Yükü eşit dağıtmak için uygundur:

class RoundRobinProxyMiddleware:
    def __init__(self, proxy_list):
        self.proxy_list = proxy_list
        self.current_index = 0
    
    @classmethod
    def from_crawler(cls, crawler):
        proxy_list = crawler.settings.getlist('PROXY_LIST')
        return cls(proxy_list)
    
    def process_request(self, request, spider):
        # Dairesel olarak bir sonraki proxy'yi al
        proxy = self.proxy_list[self.current_index]
        self.current_index = (self.current_index + 1) % len(self.proxy_list)
        
        request.meta['proxy'] = proxy

Yöntem 2: Akıllı döngü ile blacklist

Sorunlu proxy'leri izleyip geçici olarak döngüden çıkarıyoruz:

import time
from collections import defaultdict

class SmartProxyMiddleware:
    def __init__(self, proxy_list):
        self.proxy_list = proxy_list
        self.proxy_errors = defaultdict(int)
        self.blacklist = set()
        self.blacklist_timeout = 300  # 5 dakika
        self.blacklist_time = {}
    
    @classmethod
    def from_crawler(cls, crawler):
        proxy_list = crawler.settings.getlist('PROXY_LIST')
        return cls(proxy_list)
    
    def get_working_proxies(self):
        # Blacklist'ten zaman aşımına uğramış proxy'leri çıkar
        current_time = time.time()
        expired = [
            proxy for proxy, ban_time in self.blacklist_time.items()
            if current_time - ban_time > self.blacklist_timeout
        ]
        
        for proxy in expired:
            self.blacklist.discard(proxy)
            self.proxy_errors[proxy] = 0
        
        # Çalışan proxy'leri döndür
        return [p for p in self.proxy_list if p not in self.blacklist]
    
    def process_request(self, request, spider):
        working_proxies = self.get_working_proxies()
        
        if not working_proxies:
            spider.logger.error('Tüm proxy'ler blacklist'te!')
            return
        
        proxy = random.choice(working_proxies)
        request.meta['proxy'] = proxy
    
    def process_response(self, request, response, spider):
        # Eğer bir engelleme aldıysak - blacklist'e ekle
        if response.status in [403, 429, 503]:
            proxy = request.meta.get('proxy')
            self.proxy_errors[proxy] += 1
            
            if self.proxy_errors[proxy] >= 3:
                self.blacklist.add(proxy)
                self.blacklist_time[proxy] = time.time()
                spider.logger.warning(
                    f'Proxy {proxy} {self.blacklist_timeout}s süreyle blacklist'e alındı'
                )
        
        return response

Yöntem 3: Sağlayıcının API'si ile döngü

Birçok proxy sağlayıcısı (dahil olmak üzere rezidans proxy'leri) döngüsel uç nokta sağlar - her istekte otomatik olarak IP'yi değiştiren tek bir URL:

# settings.py

# Otomatik döngü ile tek uç nokta
ROTATING_PROXY = 'http://username:password@rotating.proxy.com:8080'

# Basit middleware
class RotatingProxyMiddleware:
    def __init__(self, proxy):
        self.proxy = proxy
    
    @classmethod
    def from_crawler(cls, crawler):
        proxy = crawler.settings.get('ROTATING_PROXY')
        return cls(proxy)
    
    def process_request(self, request, spider):
        # Tek URL, ancak her istek yeni bir IP ile
        request.meta['proxy'] = self.proxy

Bu, üretim için en uygun yöntemdir: proxy havuzunu yönetmek zorunda kalmazsınız, sağlayıcı IP kalitesini izler ve sorunlu olanları değiştirir. Özellikle rezidans proxy'leri ile etkili çalışır, burada IP havuzu milyonlarca adrese ulaşabilir.

Kimlik Doğrulama: Kullanıcı/Şifre vs IP Beyaz Listesi

Proxy sağlayıcıları iki kimlik doğrulama yöntemi sunar. Seçim, bağlantı hızını ve ayarların kolaylığını etkiler.

Kullanıcı:Şifre Kimlik Doğrulaması

Kullanıcı adı ve şifre, proxy URL'sinde iletilir. Scrapy, bunları otomatik olarak Proxy-Authorization HTTP başlığına dönüştürür:

proxy = 'http://username:password@proxy.example.com:8080'
request.meta['proxy'] = proxy

# Scrapy otomatik olarak başlığı ekleyecek:
# Proxy-Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Artılar: her IP'den çalışır, kodda proxy'leri kolayca değiştirmek mümkündür.
Eksiler: her istekte küçük bir gecikme (~50-100ms), açık metin olarak kodda kimlik bilgileri.

IP Beyaz Listesi Kimlik Doğrulaması

Sunucunuzun IP'sini sağlayıcının beyaz listesine ekliyorsunuz, kimlik doğrulama gerekmez:

proxy = 'http://proxy.example.com:8080'  # kullanıcı/şifre olmadan
request.meta['proxy'] = proxy

Artılar: 50-100ms daha hızlı, daha güvenli (kodda kimlik bilgileri yok).
Eksiler: sadece belirli IP'lerden çalışır, sunucu değiştiğinde beyaz listeyi güncellemek gerekir.

Üretim için öneri:

Özel sunuculardan (AWS, Google Cloud, Hetzner) veri çekmek için IP beyaz listesini kullanın. Geliştirme ve test için yerel makineden - kullanıcı:şifre kimlik doğrulamasını kullanın.

Hata İşleme ve Otomatik IP Değiştirme

Kaliteli proxy'lerle bile hatalar olacaktır: zaman aşımı, bağlantı reddi, engellemeler. Hataların doğru bir şekilde işlenmesi, tarayıcının stabil çalışması için kritik öneme sahiptir.

HTTP Statülerinin İşlenmesi

class ProxyMiddleware:
    def process_response(self, request, response, spider):
        # Proxy'yi değiştirmek ve tekrar denemek için gereken kodlar
        ban_codes = [403, 407, 429, 503]
        
        if response.status in ban_codes:
            proxy = request.meta.get('proxy')
            spider.logger.warning(
                f'{proxy} ile {response.status} alındı, tekrar deniyoruz...'
            )
            
            # Yeni proxy ile tekrar denemek için işaretle
            request.meta['dont_retry'] = False
            request.meta['proxy'] = self.get_new_proxy()
            
            return request
        
        return response

Ağ Hatalarının İşlenmesi

from twisted.internet.error import TimeoutError, ConnectionRefusedError
from scrapy.exceptions import IgnoreRequest

class ProxyMiddleware:
    def process_exception(self, request, exception, spider):
        # Proxy bağlantı hataları
        proxy_errors = (
            TimeoutError,
            ConnectionRefusedError,
            ConnectionLost,
        )
        
        if isinstance(exception, proxy_errors):
            proxy = request.meta.get('proxy')
            spider.logger.error(
                f'Proxy {proxy} bağlantısı başarısız: {exception}'
            )
            
            # Proxy'yi değiştir ve tekrar dene
            request.meta['proxy'] = self.get_new_proxy()
            return request
        
        # Diğer hatalar için standart işleme kullan
        return None

İçerik Üzerinden Engellemelerin Tespiti

Bazı siteler HTTP 200 döndürür, ancak CAPTCHA veya engelleme sayfası gösterir:

class ProxyMiddleware:
    def process_response(self, request, response, spider):
        # İçerikteki engelleme belirtileri
        ban_indicators = [
            'captcha',
            'access denied',
            'blocked',
            'unusual traffic',
            'robot check',
        ]
        
        body_text = response.text.lower()
        
        if any(indicator in body_text for indicator in ban_indicators):
            spider.logger.warning(
                f'{request.meta.get("proxy")} üzerinden engelleme sayfası tespit edildi'
            )
            
            # Proxy'yi değiştir ve tekrar dene
            request.meta['proxy'] = self.get_new_proxy()
            return request
        
        return response

Scrapy için Hangi Proxy Türünü Seçmelisiniz

Proxy türünün seçimi, hedef siteye, bütçeye ve gerekli veri çekme hızına bağlıdır. İşte ana seçeneklerin karşılaştırması:

Proxy Türü Hız Maliyet Ne Zaman Kullanmalı
Veri Merkezi Proxy Yüksek (50-200ms) Düşük ($1-3/IP) Koruması olmayan basit siteler, API'ler, iç araçlar
Rezidans Proxy Orta (300-800ms) Orta ($5-15/GB) E-ticaret, sosyal medya, Cloudflare ile korunan siteler, coğrafi hedefleme
Mobil Proxy Düşük (500-1500ms) Yüksek ($50-150/IP) Mobil uygulamalar, Instagram, TikTok, maksimum koruma

Seçim Önerileri

Pazar yerlerini çekmek için (Amazon, Wildberries, Ozon, AliExpress) - sadece rezidans proxy'leri kullanın. Bu siteler veri merkezlerini agresif bir şekilde engeller. Döngü ve coğrafi hedefleme gereklidir (örneğin, Wildberries için Rus IP'leri).

Haber siteleri, bloglar, forumlar için - veri merkezi proxy'leri uygundur. Koruma minimumdur, hız ve düşük trafik maliyeti önemlidir.

Cloudflare ile korunan siteleri çekmek için - rezidans proxy'leri zorunludur. Cloudflare, veri merkezlerini neredeyse anında tespit eder. JS zorluklarını aşmak için Scrapy'ye cloudscraper kütüphanesini ekleyin.

Google Arama, SEO araçlarını çekmek için - coğrafi hedefleme ile rezidans proxy'leri kullanın. Google, farklı ülkeler ve şehirler için farklı sonuçlar gösterir.

Tavsiye: Test için 10 rezidans proxy havuzuyla başlayın. Engellemeler alıyorsanız - havuzu 50-100 IP'ye çıkarın. Yüksek hızlı veri çekimi (dakikada 1000+ istek) için 10,000+ IP havuzuyla döngüsel uç nokta kullanın.

Gelişmiş Teknikler: Oturumlar ve Sticky IP

Bazı siteleri çekerken, oturum boyunca tek bir IP'yi korumak gerekir (kimlik doğrulama, alışveriş sepeti, çok aşamalı formlar). İşte Scrapy'de sticky oturumları nasıl uygulayacağınız:

Tek bir alan adı için Sticky IP

from urllib.parse import urlparse

class StickyProxyMiddleware:
    def __init__(self, proxy_list):
        self.proxy_list = proxy_list
        # Sözlük: alan adı -> proxy
        self.domain_proxy_map = {}
    
    @classmethod
    def from_crawler(cls, crawler):
        proxy_list = crawler.settings.getlist('PROXY_LIST')
        return cls(proxy_list)
    
    def process_request(self, request, spider):
        # URL'den alan adını çıkar
        domain = urlparse(request.url).netloc
        
        # Bu alan adı için zaten bir proxy varsa - onu kullan
        if domain in self.domain_proxy_map:
            proxy = self.domain_proxy_map[domain]
        else:
            # Aksi takdirde yeni bir proxy seç ve kaydet
            proxy = random.choice(self.proxy_list)
            self.domain_proxy_map[domain] = proxy
            spider.logger.info(f'{domain} için {proxy} atandı')
        
        request.meta['proxy'] = proxy

Oturum Zaman Aşımı ile Sticky IP

Daha gelişmiş bir seçenek: proxy, belirli bir süre (örneğin, 10 dakika) için alan adına bağlanır, ardından değişir:

import time
from urllib.parse import urlparse

class SessionProxyMiddleware:
    def __init__(self, proxy_list, session_timeout=600):
        self.proxy_list = proxy_list
        self.session_timeout = session_timeout  # 10 dakika
        # Sözlük: alan adı -> (proxy, oluşturma zamanı)
        self.sessions = {}
    
    @classmethod
    def from_crawler(cls, crawler):
        proxy_list = crawler.settings.getlist('PROXY_LIST')
        timeout = crawler.settings.getint('PROXY_SESSION_TIMEOUT', 600)
        return cls(proxy_list, timeout)
    
    def get_proxy_for_domain(self, domain):
        current_time = time.time()
        
        # Aktif bir oturum var mı kontrol et
        if domain in self.sessions:
            proxy, created_at = self.sessions[domain]
            
            # Eğer oturum süresi dolmadıysa - aynı proxy'yi kullan
            if current_time - created_at < self.session_timeout:
                return proxy
        
        # Yeni bir oturum oluştur ve yeni bir proxy ile
        new_proxy = random.choice(self.proxy_list)
        self.sessions[domain] = (new_proxy, current_time)
        
        return new_proxy
    
    def process_request(self, request, spider):
        domain = urlparse(request.url).netloc
        proxy = self.get_proxy_for_domain(domain)
        request.meta['proxy'] = proxy

Cookie Middleware ile Entegrasyon

Tam oturumlar için proxy ve çerezleri senkronize etmek gerekir. Scrapy, çerezleri her alan adı için ayrı saklar, ancak proxy değiştiğinde çerezleri temizlemek gerekir:

# settings.py

# Çerez middleware'ini etkinleştir
COOKIES_ENABLED = True
COOKIES_DEBUG = False

# Proxy ve çerezlerin senkronizasyonu için middleware
class ProxyCookieMiddleware:
    def process_request(self, request, spider):
        # Mevcut proxy'yi al
        current_proxy = request.meta.get('proxy')
        
        # Eğer proxy değiştiyse - çerezleri temizle
        previous_proxy = request.meta.get('previous_proxy')
        
        if previous_proxy and previous_proxy != current_proxy:
            # Bu alan adı için çerezleri temizle
            jar = spider.crawler.engine.downloader.middleware.middlewares[0].jars
            domain = urlparse(request.url).netloc
            
            if domain in jar:
                jar[domain].clear()
                spider.logger.info(f'{domain} için çerezler temizlendi')
        
        request.meta['previous_proxy'] = current_proxy

Sonuç

Scrapy'de proxy ayarlarının doğru bir şekilde yapılması, engellenmeden stabil veri çekiminin temelidir. Temel entegrasyondan, gelişmiş döngü ve oturum yönetimi tekniklerine kadar tüm ana noktaları inceledik.

Ana çıkarımlar:

  • Üretim için akıllı döngü ve sorunlu IP'lerin blacklist'ini kullanan özel middleware kullanın
  • Tüm hata türlerini işleyin: HTTP statüleri, ağ istisnaları, içerik üzerinden engellemeler
  • Görev için uygun proxy türünü seçin: basit siteler için veri merkezleri, korumalı siteler için rezidans
  • Kimlik doğrulama gerektiren siteler için proxy'yi alan adına bağlayarak sticky oturumlar kullanın
  • 10-50 proxy ile başlayın, yük arttıkça ölçeklendirin

Koruma altındaki siteleri (pazar yerleri, sosyal medya, Cloudflare ile korunan siteler) çekmeyi planlıyorsanız, rezidans proxy'leri kullanmanızı öneririm - maksimum anonimlik ve minimum engel riski sağlarlar. Yüksek hızlı veri çekimi için döngüsel uç nokta ve 10,000 IP'den oluşan bir havuz seçin.

Bu makalede yer alan tüm kod örnekleri Scrapy 2.x üzerinde test edilmiştir ve üretimde kullanılmaya hazırdır. Kendi ihtiyaçlarınıza göre uyarlayın ve projenizin büyümesiyle ölçeklendirin.