← Bloga geri dön

Kötü Proxylere Elenme: Hata Metrikleri ve Python ile Dönüşüm

Hangi hata metriklerinin proxy'nin parser havuzundaki bozulmayı işaret ettiğini ve otomatik bir IP elenme ve döngü sistemi nasıl kurulacağını inceliyoruz.

📅19 Ekim 2026

Eğer Wildberries veya Ozon parseliniz aniden boş sayfalar, zaman aşımı ve 403 hataları vermeye başladıysa, sorun her zaman platformda değildir. Çoğu zaman proxy havuzundaki bazı IP adresleri zaten "bozulmuş" durumda: yasaklanmış, yavaşlatılmış veya CAPTCHA'ya alınmışlardır. Çalışan bir proxy ile ölü bir proxy'yi ayırt etmek için hangi metriklerin kullanılacağını ve manuel kontrol olmadan ayıklamayı nasıl otomatikleştireceğimizi inceliyoruz.

Neden proxy havuzu zamanla bozulur

Herhangi bir proxy havuzu - güvenilir bir sağlayıcıdan satın alınmış olsa bile - zamanla çalışan adreslerin bir kısmını kaybeder. Sebepler çeşitlidir: Wildberries, Ozon ve Avito'nun anti-fraud sistemleri IP'lerde itibar etiketleri biriktirir, bazı adresler sağlayıcının diğer müşterilerinin toplu talepleri sonrasında kara listeye alınır (eğer proxy paylaşımlıysa), veri merkezi aralıkları alt ağlara göre topluca yasaklanır ve yerel IP'ler bazen sadece gerçek kullanıcı cihazını kapattığı için havuzdan çıkar.

Eğer havuzu temizlemezseniz, "ölü" proxy'lerin oranı doğrusal olmayan bir şekilde artar: önce %5, bir haftalık aktif parselikten sonra - %20-30. Parseliyici, çalışmayan IP'ler üzerinden tekrar denemeler yapmak için kaynak harcamaya başlar, bir sayfanın toplanma süresi artar ve günlüklerde gerçek sorunları maskeleyen hatalar birikir (örneğin, web sayfasının düzeninin değiştirilmesi). Ayıklama sistemi olmadan ya havuzu "yedek" olarak şişirirsiniz ya da düzenli olarak veri toplama başarısızlıkları yaşarsınız.

Görev, hatanın varlığını sadece kaydetmek değil, aynı zamanda onu sınıflandırmaktır: sunucu aşırı yüklenmesi, belirli bir IP'nin yasaklanması, bölgesel engelleme veya parseliyici tarafında bir sorun (geçersiz başlıklar, eski çerezler). Hatanın türüne bağlı olarak, proxy'yi havuzdan sonsuza dek atıp atmayacağınız, "karantinaya" alıp almayacağınız veya sadece isteği tekrarlayıp tekrarlamayacağınız belirlenir.

Ayıklama için ana hata metrikleri

Geçici bir arızayı gerçekten ölü bir proxy'den ayırmak için, her IP için birkaç metrik toplamak gerekir, tek bir HTTP durumu ile yönelmek yerine. İşte her istekte kaydedilmesi gereken temel set:

Metrik Ne sinyal veriyor Eylem
HTTP 403 / 429 IP üzerinde yasak veya rate-limit 30-60 dakika karantina, tekrarında - silme
Bağlantı zaman aşımı Proxy aşırı yüklenmiş veya ölü Arka arkaya 3 zaman aşımı - havuzdan silme
Yanıtta CAPTCHA IP, anti-bot tarafından şüpheli hale geldi İstek sıklığını azalt veya IP'yi değiştir
Yanıt süresi > 5 sn Proxy tarafında hızın bozulması Havuzda önceliği düşür
Yanıt boyutu ortalamanın altında Engelleme sayfası/placeholder verildi Kabul etmeden önce içeriği ek kontrol et
Başarılı istek oranı (success rate) IP kalitesinin toplam değerlendirmesi 50 istekte %70'in altında - silme

Web sitesinin hata kodlarını ağ hatalarıyla karıştırmamak önemlidir. Örneğin, 404 - proxy'nin değil, Wildberries'teki bir ürünün eksik olduğunu gösterir. Ancak aynı IP sürekli olarak 403 alıyorsa, diğer IP'ler 200 alıyorsa, bu belirli bir adresin yasaklandığının açık bir işaretidir.

Proxy skorlama algoritması

İki durumlu "çalışan / çalışmayan" yerine, her IP için 0 ile 100 arasında bir skor hesaplamak daha uygundur; bu skor hatalarla yavaşça düşer ve başarılı isteklerle geri yükselir. Bu, bir rastgele arıza sonrası proxy'yi atmamayı sağlar (pazar yeri sunucusu sadece bir saniye boyunca donmuş olabilir), ancak sistematik olarak çöp döken IP'leri hızlıca kaldırmayı sağlar.

Mantık basit: geçerli içeriğe sahip 200 kodlu başarılı bir istek skora +2 ekler (ama 100'ün üzerine çıkamaz). Zaman aşımı -15. 403/429 kodu -25. Yanıtta CAPTCHA -20. Eğer skor belirli bir eşiğin (örneğin, 30) altına düşerse, proxy sabit bir süre için karantinaya alınır ve eğer karantinadan döndükten sonra skor tekrar 10'un altına düşerse - IP kalıcı olarak havuzdan silinir ve analiz için kaydedilir.

Bu yaklaşım, Dolphin Anty veya AdsPower gibi anti-detect tarayıcılarında hesapların aktiviteye bağlı olarak "sağlık" durumuna sahip olduğu itibar sistemine benzer. Aynı mekanizma, parseliklerde IP adresleri için de mükemmel çalışır.

Kod: Python'da otomatik ayıklama ile ProxyPool

Aşağıda, hata metriklerini dikkate alarak proxy havuzunu yönetmek için çalışan bir sınıf iskeleti bulunmaktadır. Bu, herhangi bir parselik için requests, httpx veya Scrapy ile bağlanabilir, proxy alma mantığını pool.get_proxy() çağrısı ile değiştirebilirsiniz.

import time
import random
from dataclasses import dataclass, field
from typing import Optional

@dataclass
class ProxyStats:
    address: str
    score: int = 100
    quarantine_until: float = 0.0
    total_requests: int = 0
    total_success: int = 0
    consecutive_timeouts: int = 0
    is_dead: bool = False

    @property
    def success_rate(self) -> float:
        if self.total_requests == 0:
            return 1.0
        return self.total_success / self.total_requests


class ProxyPool:
    def __init__(self, proxies: list[str],
                 min_score: int = 30,
                 dead_score: int = 10,
                 quarantine_seconds: int = 1800):
        self.stats = {p: ProxyStats(address=p) for p in proxies}
        self.min_score = min_score
        self.dead_score = dead_score
        self.quarantine_seconds = quarantine_seconds

    def _is_available(self, stats: ProxyStats) -> bool:
        if stats.is_dead:
            return False
        if stats.quarantine_until > time.time():
            return False
        return True

    def get_proxy(self) -> Optional[str]:
        available = [s for s in self.stats.values() if self._is_available(s)]
        if not available:
            return None
        # skora göre sıralıyoruz, en üst %30'dan rastgele alıyoruz, böylece bir IP'yi aşırı yüklemiyoruz
        available.sort(key=lambda s: s.score, reverse=True)
        top_pool = available[:max(1, len(available) // 3)]
        return random.choice(top_pool).address

    def report_success(self, proxy: str):
        s = self.stats[proxy]
        s.total_requests += 1
        s.total_success += 1
        s.consecutive_timeouts = 0
        s.score = min(100, s.score + 2)

    def report_timeout(self, proxy: str):
        s = self.stats[proxy]
        s.total_requests += 1
        s.consecutive_timeouts += 1
        s.score -= 15
        if s.consecutive_timeouts >= 3:
            self._quarantine(s)
        self._check_dead(s)

    def report_blocked(self, proxy: str, captcha: bool = False):
        s = self.stats[proxy]
        s.total_requests += 1
        s.score -= 20 if captcha else 25
        self._quarantine(s)
        self._check_dead(s)

    def _quarantine(self, s: ProxyStats):
        if s.score < self.min_score:
            s.quarantine_until = time.time() + self.quarantine_seconds

    def _check_dead(self, s: ProxyStats):
        if s.score <= self.dead_score:
            s.is_dead = True

    def stats_report(self) -> list[dict]:
        return [
            {
                "proxy": s.address,
                "score": s.score,
                "success_rate": round(s.success_rate, 2),
                "dead": s.is_dead,
            }
            for s in self.stats.values()
        ]

Gerçek bir parselik içinde report_success, report_timeout ve report_blocked çağrıları, her HTTP isteğinden sonra yanıt işleyicisine doğrudan yerleştirilir. requests ile entegrasyon örneği:

import requests

def fetch(url: str, pool: ProxyPool):
    proxy = pool.get_proxy()
    if not proxy:
        raise RuntimeError("Havuzda mevcut proxy yok")

    proxies = {"http": proxy, "https": proxy}
    try:
        resp = requests.get(url, proxies=proxies, timeout=8)
    except requests.exceptions.Timeout:
        pool.report_timeout(proxy)
        return None

    if resp.status_code in (403, 429):
        pool.report_blocked(proxy)
        return None

    if "captcha" in resp.text.lower():
        pool.report_blocked(proxy, captcha=True)
        return None

    pool.report_success(proxy)
    return resp

Bu yaklaşım, manuel izleme yükünü azaltır: bir kez eşikleri ayarlarsınız ve ardından havuz kendiliğinden "iyileşir", ölü adresleri dışarı atar ve geçici olarak askıya alınanları karantinadan geri alır.

IP yasaklama için eşik değerleri

Evrensel sayılar yoktur - eşikler platforma ve anti-botun agresifliğine bağlıdır. Ancak, Wildberries, Ozon ve Avito parseliklerinde pratikte iyi çalışan bazı referanslar vardır:

  • Başarı oranı %70'in altında 30-50 istekte - mevcut skor hala kritik olmasa bile IP'yi silmek için bir neden.
  • Arka arkaya 3 zaman aşımı - neredeyse her zaman proxy'nin fiziksel olarak erişilemez veya aşırı yüklü olduğunu gösterir, aktif havuzda tutmanın anlamı yoktur.
  • 20 istekte 1'den fazla CAPTCHA - IP zaten anti-bot tarafından şüpheli hale geldi, istek sıklığını azaltmak veya adresi değiştirmek daha iyidir.
  • Yanıt süresi havuz medyanesinin 2 katı - bozulma sinyali, kritik değil ama seçimde önceliği düşürmek için bir neden.

30-60 dakika karantina genellikle veri merkezi ve yerel proxy'ler için yeterlidir, böylece anti-bot geçici şüpheli aktiviteyi "unutur". Mobil proxy'lerde durum farklıdır: burada IP, operatör tarafından hücre değiştiğinde değişir, bu nedenle karantina süresi daha kısa olabilir - 10-15 dakika, çünkü rotasyondan sonra bu fiziksel olarak farklı bir adres olur.

Healthcheck ve arka planda rotasyon

Reaktif ayıklamanın (parselik akışındaki hata olaylarına dayalı) yanı sıra, arka planda bir healthcheck çalıştırmak da faydalıdır - birkaç dakikada bir proxy'yi hafif isteklerle nötr bir URL'ye (örneğin, httpbin.org/ip) kontrol eden ayrı bir süreç ve proxy, Wildberries veya Ozon'a gerçek bir istekte bulunmadan önce havuzun istatistiklerini günceller.

import threading

def healthcheck_loop(pool: ProxyPool, interval: int = 300):
    while True:
        for proxy in list(pool.stats.keys()):
            try:
                r = requests.get(
                    "https://httpbin.org/ip",
                    proxies={"http": proxy, "https": proxy},
                    timeout=5
                )
                if r.status_code == 200:
                    pool.report_success(proxy)
                else:
                    pool.report_blocked(proxy)
            except requests.exceptions.RequestException:
                pool.report_timeout(proxy)
        time.sleep(interval)

threading.Thread(target=healthcheck_loop, args=(pool,), daemon=True).start()

Bu arka plan süreci özellikle önemlidir, eğer havuz büyükse (yüzlerce IP) ve parselik sürekli değil, partiler halinde yapılıyorsa - healthcheck olmadan bazı proxy'ler "bozulmayı" bekleyebilir ve parseli başlatmanın ilk dakikaları canlı ayıklama için harcanır, bunun yerine hemen kontrol edilen adreslerle çalışmak yerine.

Pazar yerleri için hangi proxy türünü seçmeli

Proxy türünün seçimi, ayıklama sıklığını ve eşiklerin ne kadar agresif olacağını doğrudan etkiler. Wildberries ve Ozon'da kararlı parselik için, anti-bot davranış kalıplarını ve alt ağın itibarını analiz ettiğinden, en iyi performansı yerel proxy'ler gösterir - bunların IP'leri gerçek ev interneti sağlayıcılarına aittir ve anti-bot bunları alt ağlar üzerinden topluca yasaklama olasılığı çok daha düşüktür.

Daha basit ve daha az korumalı kaynaklar (örneğin, Avito'dan kamu verilerini toplama veya basit vitrinlerde fiyat izleme) için genellikle veri merkezi proxy'leri yeterlidir - bunlar daha hızlı ve daha ucuzdur, bu da büyük istek hacimlerinde kritik öneme sahiptir, ancak biraz daha sık yasaklanırlar, bu nedenle ayıklama eşiklerini daha katı yapmak gerekir.

Proxy Türü Ayıklama Hızı Ne Zaman Kullanılmalı
Veri Merkezi Yüksek, alt ağlar topluca yasaklanır Basit vitrinler, büyük hacimler, düşük koruma
Yerel Orta, IP'ler noktasal olarak yasaklanır Wildberries, Ozon, anti-bot olan siteler
Mobil Düşük, IP otomatik olarak operatör tarafından değişir Sıkı korumalı kaynaklar, yüksek frekanslı parselik

Pratikte birçok ekip hibrit bir havuz kullanır: isteklerin ana kısmı yerel IP'ler üzerinden yapılır ve kitlesel yasaklamalarda mobil proxy'ler "acil" yedek olarak devreye alınır, çünkü IP değişimi hücresel ağ rotasyonu ile doğal olarak gerçekleşir ve manuel müdahale gerektirmez.

Sonuç

Ayıklama sistemi olmayan bir proxy havuzu kaçınılmaz olarak bozulur ve ne kadar uzun süre temizlenmeden çalışırsa, parselik o kadar çok kaynağı ölü IP'ler üzerinde israf eder. HTTP kodları, zaman aşımı, CAPTCHA ve başarı oranını dikkate alan bir skorlama modeli, sorunlu adresleri otomatik olarak tespit etmeyi ve havuzu manuel kontrol olmadan çalışır durumda tutmayı sağlar. Bu makaledeki kod, herhangi bir yığın için uyarlanabilir - requests, httpx, Scrapy veya kendi asenkron parseliğiniz için.

Eğer pazar yerleri için bir havuz oluşturuyorsanız ve yasaklama sıklığını başlangıçta azaltmak istiyorsanız, yerel proxy'lere göz atmanızı öneririz - bunlar, normal veri merkezi adreslerine kıyasla Wildberries ve Ozon gibi korumalı platformlarda belirgin şekilde daha yüksek bir başarı oranı sağlar.