← Bloga geri dön

Python için httpx'te Asenkron Proxy: Rotasyon, HTTP/2 ve Yeni Başlayanların 5 Hatası

httpx'te proxy rotasını nasıl doğru bir şekilde ayarlayacağımızı, HTTP/2'yi nasıl etkinleştireceğimizi ve başlangıçta karşılaşan %90'lık geliştirici grubunun düştüğü tuzaklara nasıl düşmeyeceğimizi ele alıyoruz.

📅17 Ekim 2026

httpx kütüphanesi, Python'da asenkron HTTP istekleri için standart haline geldi, ancak proxy ile çalışırken, üretimdeki parseleri kıran bazı nüanslar var. Asenkron proxy döngüsünü nasıl ayarlayacağımızı, HTTP/2'yi nasıl etkinleştireceğimizi ve neden her 50-100 istekte bir scriptinizin çöktüğünü inceleyelim.

Neden httpx, requests veya aiohttp değil

requests senkron bir kütüphanedir ve kutudan çıktığı gibi HTTP/2'yi desteklemez. aiohttp asenkron bir kütüphanedir, ancak proxy ayarları daha az kullanıcı dostudur ve HTTP/2 desteği yoktur. httpx her iki sorunu da çözer: senkron ve asenkron bir istemci ile tek bir API, h2 uzantısı aracılığıyla yerel HTTP/2 desteği ve taşıma düzeyinde proxy ile esnek çalışma.

Pazar yerleri (Wildberries, Ozon, Avito), sosyal medya API'lerinden veri toplama veya rakip fiyatlarını izleme gibi parselama görevleri için asenkronluk kritik öneme sahiptir — bu, ardışık isteklere göre hızda katlanarak artış sağlar. Ancak, akıllıca bir proxy döngüsü ve bağlantı yönetimi olmadan asenkronluk yeni sorunların kaynağı haline gelir: bağlantı havuzunun tükenmesi, takılı kalan korutinler, dosya tanımlayıcılarının sızıntısı.

İkinci önemli nokta — HTTP/2, bir TCP bağlantısında birden fazla isteği çoklayabilir, bu da hedef sunucu üzerindeki yükü azaltır ve bir IP'den gelen TCP el sıkışmalarının sayısına bakan bazı basit anti-bot sistemlerini aşmaya yardımcı olur.

httpx'te proxy için temel ayar

httpx 0.26+ sürümünden itibaren proxy ayarlarının sözdizimi değişti — proxies yerine proxy parametresi kullanılıyor. Eski eğitimlere bakıyorsanız, bu sıkça kafa karışıklığına neden olur.

import httpx
import asyncio

PROXY_URL = "http://user:[email protected]:8000"

async def fetch(url: str):
    async with httpx.AsyncClient(proxy=PROXY_URL, timeout=15.0) as client:
        response = await client.get(url)
        return response.status_code, response.text[:200]

asyncio.run(fetch("https://httpbin.org/ip"))

HTTP ve HTTPS trafiği için proxy'leri ayırmanız veya farklı alanlar için farklı proxy'ler ayarlamanız gerekiyorsa, httpx.Client(mounts=...) kullanın — taşıyıcılar URL şablonuna göre monte edilir:

mounts = {
    "http://": httpx.AsyncHTTPTransport(proxy="http://user:[email protected]:8000"),
    "https://": httpx.AsyncHTTPTransport(proxy="http://user:[email protected]:8000"),
}

async with httpx.AsyncClient(mounts=mounts) as client:
    response = await client.get("https://example.com")

Kullanıcı adı ve şifre ile kimlik doğrulama için http://user:pass@host:port formatı, HTTP proxy'leri için güvenilir bir şekilde çalışır. SOCKS5 için ayrıca httpx[socks] yüklemeniz gerekir, aksi takdirde çalışma zamanında ImportError alırsınız, kod yazma aşamasında değil — bu, birçok kişinin düştüğü bir tuzaktır.

Asenkron proxy döngüsü: çalışan kod

Proxy döngüsündeki en büyük hata — her istek için yeni bir AsyncClient oluşturmaktır. Bu, performansı öldürür çünkü istemci bir bağlantı havuzunu tutar ve yeniden oluşturulması, keep-alive bağlantılarının tüm avantajlarını ortadan kaldırır. Doğru yaklaşım — önceden bir proxy için bir istemci havuzu oluşturmak ve görevleri bunlar arasında dağıtmaktır.

import httpx
import asyncio
import itertools
import random

PROXIES = [
    "http://user:[email protected]:8000",
    "http://user:[email protected]:8000",
    "http://user:[email protected]:8000",
]

class ProxyPool:
    def __init__(self, proxies: list[str]):
        self.clients = [
            httpx.AsyncClient(proxy=p, timeout=httpx.Timeout(15.0, connect=5.0))
            for p in proxies
        ]
        self._cycle = itertools.cycle(self.clients)

    def get_client(self) -> httpx.AsyncClient:
        return next(self._cycle)  # round-robin
        # rastgele seçim için: random.choice(self.clients)

    async def close_all(self):
        for client in self.clients:
            await client.aclose()

async def fetch_with_retry(pool: ProxyPool, url: str, retries: int = 3):
    for attempt in range(retries):
        client = pool.get_client()
        try:
            response = await client.get(url)
            if response.status_code == 200:
                return response.text
        except (httpx.ConnectTimeout, httpx.ProxyError, httpx.ReadTimeout):
            await asyncio.sleep(0.5 * (attempt + 1))
            continue
    return None

async def main():
    pool = ProxyPool(PROXIES)
    urls = [f"https://example.com/page/{i}" for i in range(100)]

    sem = asyncio.Semaphore(20)  # paralelliği sınırlıyoruz

    async def bound_fetch(url):
        async with sem:
            return await fetch_with_retry(pool, url)

    results = await asyncio.gather(*(bound_fetch(u) for u in urls))
    await pool.close_all()
    return results

asyncio.run(main())

Bu desen, üç sorunu aynı anda çözer: keep-alive aracılığıyla TCP bağlantılarını yeniden kullanır, proxy'ler arasında round-robin yöntemiyle yük dağıtır ve hedef sunucuyu çökertmemek ve rate-limit nedeniyle yasaklanmayı tetiklememek için paralelliği sınırlamak için bir semafor kullanır.

Wildberries, Ozon veya Instagram API'si ile çalışan üretim parselerinin, proxy havuzunun coğrafi olarak yeterince büyük ve çeşitli olması önemlidir — aksi takdirde, tek bir alt ağ içindeki döngü, engellemeyi önlemez. Burada, gerçek kullanıcıların IP'lerine sahip olan ve anti-bot sistemlerinin ASN ve IP aralığının itibarını analiz etmesi nedeniyle daha az filtreye takılan rezidans proxy'leri iyi bir seçimdir.

httpx'te HTTP/2: neden ve nasıl etkinleştirilir

Varsayılan olarak httpx HTTP/1.1 kullanır. HTTP/2'yi etkinleştirmek için uzantıyı yüklemeniz ve bayrağı açıkça iletmeniz gerekir:

# pip install httpx[http2]

async with httpx.AsyncClient(http2=True, proxy=PROXY_URL) as client:
    response = await client.get("https://example.com")
    print(response.http_version)  # "HTTP/2" bekliyoruz

Önemli bir nokta: Tüm proxy'ler HTTP/2 tünelleme desteğine sahip değildir. Bazı ucuz veri merkezi proxy'leri, son sunucu HTTP/2'yi desteklese bile yalnızca HTTP/1.1 proxy olarak çalışır — bu durumda httpx sessizce CONNECT tüneli aracılığıyla HTTP/1.1'e geri döner ve bunu açık bir kontrol olmadan her zaman fark etmeyebilirsiniz response.http_version.

HTTP/2, üç senaryoda gerçek bir kazanç sağlar: bir alan adına çok sayıda istek yaptığınızda (bir bağlantıda çoklama gecikmeleri azaltır), anti-bot koruması için isteklerin görünürlüğünü azaltmak önemli olduğunda (bir IP'den daha az TCP el sıkışması daha doğal görünür) ve hedef site kendisi HTTP/2 talep ettiğinde ve HTTP/1.1'deki istemcilere hata veya kısıtlı içerik döndürdüğünde — bu bazen Cloudflare üzerinde bulunan sitelerde görülür.

Proxy aracılığıyla HTTP/2 bağlantılarının hızı ve istikrarı önemliyse, özel veri merkezi proxy'leri daha iyi bir seçimdir — bunlar rezidans proxy'lerinden daha hızlıdır ve genellikle modern protokollerin tünellemesini doğru bir şekilde destekler.

httpx ile proxy'de 5 yaygın hata

1. Her istek için istemciyi yeniden oluşturma

async with httpx.AsyncClient(...) as client: await client.get(url) şeklindeki kod döngü içinde bir antipattern'dır. Her istemci oluşturma, yeni bir TCP bağlantısı, yeni bir TLS el sıkışması ve bağlantı havuzunun tamamen göz ardı edilmesi anlamına gelir. 1000 istek için doğru ve yanlış yaklaşım arasındaki hız farkı 5-10 katına kadar çıkabilir.

2. Zaman aşımı yok veya varsayılan olarak çok büyük zaman aşımı

Varsayılan olarak httpx, her şey için 5 saniyelik bir zaman aşımı ayarlar — bağlantı, okuma, yazma, havuz. Dengesiz proxy'ler ile çalışırken bu, bağlantı için yetersiz, ancak proxy "takılı" kaldığında okuma için çok fazla. Zaman aşımını açıkça ayırın:

timeout = httpx.Timeout(
    connect=5.0,
    read=10.0,
    write=10.0,
    pool=5.0
)
client = httpx.AsyncClient(proxy=PROXY_URL, timeout=timeout)

3. Bağlantı havuzunun sınırlarını göz ardı etme

Çok sayıda eşzamanlı görev (500+ korutini semafor olmadan toplamak) olduğunda httpx PoolTimeout hatası vermeye başlar, çünkü havuzdaki bağlantı limiti (varsayılan olarak 100) tükenmiştir. Sınırları açıkça httpx.Limits(max_connections=200, max_keepalive_connections=50) ile ayarlayın ve her zaman paralelliği kontrol etmek için bir semafor kullanın.

4. Doğru sonuçları anlamadan doğrulamayı devre dışı bırakma

Birçok kişi, proxy ile MITM sertifikaları aracılığıyla SSL hatalarından kurtulmak için verify=False kodunu Stack Overflow'dan kopyalar. Bu, "adam ortada" saldırılarına kapı açar ve tehlikeli bir proxy aracılığıyla veri sızıntısına neden olabilir. Proxy özel bir sertifika gerektiriyorsa — bunu açıkça verify="/path/to/cert.pem" ile ekleyin, tüm kontrolü devre dışı bırakmayın.

5. Kapatılmamış istemciler ve dosya tanımlayıcılarının sızıntısı

Eğer istemci havuzunu manuel olarak oluşturuyorsanız (yukarıdaki örnekte olduğu gibi), her birinin iş bitiminde await client.aclose() çağrısını yapmayı unutmayın. Uzun süre çalışan scriptler, açık bağlantıların sayısı için işletim sisteminin (genellikle Linux'ta varsayılan olarak 1024) sınırına ulaşır ve parseler gizemli bir Too many open files hatası ile birkaç saat içinde çöker.

Hangi proxy türü parselama için seçilmeli

Proxy seçimi, yukarıdaki listedeki hataların ne kadarını göreceğinizi doğrudan etkiler — dengesiz proxy'ler zaman aşımına ve bağlantı kopmalarına neden olur, kod mükemmel yazılmış olsa bile.

Proxy Türü Hız Engellenme Riski Ne Zaman Kullanılmalı
Veri Merkezi Yüksek Korunan sitelerde yüksek Açık API, zayıf anti-bot koruması
Rezidans Orta Düşük Wildberries, Ozon, sosyal medya
Mobil Orta-düşük Minimum Instagram, TikTok API, sıkı koruma

Orta düzeyde korumaya sahip API'lere yüksek hızda istek yapmak için asenkron parselama için veri merkezi proxy'leri ekonomik bir seçenek olmaya devam ediyor — önemli olan, yükü havuzda eşit bir şekilde dağıtmaktır, yukarıdaki kodda gösterildiği gibi.

Üretim öncesi kontrol listesi

  • httpx istemcileri bir kez oluşturulur ve her istek için yeniden kullanılmaz
  • Zaman aşım süreleri bağlantı/okuma/yazma/havuz olarak ayrılmıştır, varsayılan kullanılmaz
  • Paralellik asyncio.Semaphore ile sınırlıdır
  • Bağlantı havuzunun sınırları gerçek yük altında ayarlanmıştır
  • ProxyError, ConnectTimeout, ReadTimeout ile hata işleme mantığı vardır
  • Tüm istemciler iş bitiminde açıkça aclose() ile kapatılır
  • Gerekmedikçe verify=False kullanılmaz
  • HTTP/2 bilinçli olarak etkinleştirilmiş ve response.http_version ile kontrol edilmiştir

Sonuç

httpx, proxy ve HTTP/2 ile asenkron çalışma için güçlü bir araç seti sunar, ancak istemci havuzlarının, zaman aşım sürelerinin ve bağlantı sınırlarının dikkatlice ayarlanmasını gerektirir. Üretimdeki parseler genellikle kütüphaneden değil, mimari hatalardan kaynaklanır: istemcilerin yeniden oluşturulması, paralelliğin sınırlandırılmaması ve proxy hatalarının yanlış işlenmesi.

Eğer pazar yerleri veya sosyal medya API'leri için bir parsel oluşturuyorsanız, şüpheli etkinlikleri aktif olarak izleyen, proxy altyapısının istikrarı kod kadar önemlidir. Bu tür görevler için rezidans proxy'lerine bakmak iyi bir fikir olabilir — bunlar, ucuz veri merkezi havuzlarına göre daha yüksek IP itibarına sahip oldukları için ProxyError ve ConnectTimeout hatalarının oranını azaltır.