Python'daki scriptiniz 403 hatası, CAPTCHA veya IP yasaklaması alıyorsa, hedef site sizi fark etmiştir. requests kütüphanesine proxy bağlamak bu sorunu çözer: IP adresinizi değiştirir, coğrafi kısıtlamaları aşar ve yükü birden fazla adres arasında dağıtırsınız. Bu kılavuzda, temel bağlantıdan gelişmiş döndürmeye kadar gerçek kod örnekleri ile her şey mevcut.
Python scriptlerinde proxy neden gereklidir
Çoğu web sitesi ve API, gelen isteklerin IP adreslerini izler. Eğer bir adres dakikada 100'den fazla istek yapıyorsa, bu adres engellenir. Bu, Wildberries, Ozon, Avito, Google, Instagram ve yüzlerce diğer platformun kullandığı standart bir bot koruma yöntemidir. Proxy, isteği başka bir IP adresi ile bir ara sunucu üzerinden yönlendirmenizi sağlar, böylece koruma sistemleri için görünmez olursunuz.
İşte Python'da proxy'nin kritik olduğu ana görevler:
- Pazar yerlerini veri çekme — Wildberries, Ozon, Yandex.Market'ten IP engellemeleri olmadan fiyat toplama
- Rakipleri izleme — rakip sitelere her 5-15 dakikada bir düzenli istekler
- Sınırları olan API'lerle çalışma — istekleri birden fazla IP arasında dağıtarak rate limit'i aşmamak
- Coğrafi test — sitenin farklı ülkelerden ve bölgelerden nasıl göründüğünü kontrol etme
- Form ve kayıt otomasyonu — farklı IP'lerden hesap oluşturma veya formları doldurma
- SEO izleme — Rusya ve diğer ülkelerden pozisyonları takip etme
Proxy olmadan, iyi yazılmış bir veri çekme aracı bile birkaç saat içinde engellenir. Doğru yapılandırılmış bir IP döndürme ile aynı script haftalarca duraksamadan çalışır.
requests'ta proxy temel ayarları
requests kütüphanesi, proxy'yi yerel olarak destekler — ek paketlere gerek yoktur. Proxy, isteğin parametrelerinde proxies sözlüğü aracılığıyla iletilir.
En basit örnek — tek bir istek için HTTP proxy:
import requests
proxies = {
"http": "http://123.45.67.89:8080",
"https": "http://123.45.67.89:8080",
}
response = requests.get("https://httpbin.org/ip", proxies=proxies)
print(response.json())
# {'origin': '123.45.67.89'}
Dikkat: proxies sözlüğünde her iki anahtarın da belirtilmesi gerekir — http ve https. Sadece birini belirtirseniz, diğer protokol için istekler doğrudan proxy olmadan gidecektir. Bu, gerçek IP'nin sızmasına neden olan yeni başlayanların sık yaptığı bir hatadır.
Proxy'nin çalıştığından emin olmak için httpbin.org/ip servisini kullanın — bu, isteğin geldiği IP adresini döndürür. Eğer yanıtınızda proxy sunucusunun IP'sini görüyorsanız, her şey doğru ayarlanmıştır.
HTTP, HTTPS ve SOCKS5 proxy: farklar ve örnekler
Proxy'ler farklı türlerde gelir ve her biri kendi görevleri için uygundur. Python requests bağlamında, üç ana protokol arasındaki farkı anlamak önemlidir:
| Tür | URL'deki Protokol | Hız | UDP Desteği | En İyi Senaryo |
|---|---|---|---|---|
| HTTP | http:// |
Yüksek | Hayır | HTTP sitelerini veri çekme |
| HTTPS | https:// |
Yüksek | Hayır | Korunan siteleri veri çekme |
| SOCKS5 | socks5:// |
Orta | Evet | Tam anonimlik, her türlü protokol |
SOCKS5 ile Python'da çalışmak için ek bir paket yüklemeniz gerekir:
pip install requests[socks] # veya ayrı olarak: pip install PySocks
Kurulumdan sonra SOCKS5 proxy bağlantısı şöyle görünür:
import requests
# SOCKS5 proxy
proxies = {
"http": "socks5://123.45.67.89:1080",
"https": "socks5://123.45.67.89:1080",
}
response = requests.get("https://httpbin.org/ip", proxies=proxies)
print(response.json())
SOCKS5, anonimlik açısından önemli görevler için tercih edilen protokoldür. HTTP proxy'lerin aksine, SOCKS5 X-Forwarded-For başlıklarını eklemez, bu da gerçek IP'nizi açığa çıkarabilir.
Kullanıcı adı ve şifre ile kimlik doğrulamalı proxy
Çoğu ücretli proxy hizmeti, kullanıcı adı ve şifre ile kimlik doğrulaması kullanır. Bu standart bir uygulamadır — kimlik doğrulaması olmadan proxy, isteğinizi geçmeyecektir. requests kütüphanesinde kimlik doğrulama verileri doğrudan proxy URL'sine iletilir.
import requests # Format: protokol://kullanıcı_adı:şifre@host:port proxy_url = "http://myuser:[email protected]:8080" proxies = { "http": proxy_url, "https": proxy_url, } response = requests.get("https://httpbin.org/ip", proxies=proxies) print(response.status_code) print(response.json())
Eğer şifre veya kullanıcı adında özel karakterler (örneğin, @, #, %) varsa, bunları URL kodlaması yapmalısınız. Bunun için urllib.parse modülünü kullanın:
import requests
from urllib.parse import quote
username = "myuser"
password = "p@ss#word!" # Özel karakterler
# Kullanıcı adı ve şifreyi URL kodlayın
encoded_user = quote(username, safe="")
encoded_pass = quote(password, safe="")
proxy_url = f"http://{encoded_user}:{encoded_pass}@123.45.67.89:8080"
proxies = {
"http": proxy_url,
"https": proxy_url,
}
response = requests.get("https://httpbin.org/ip", proxies=proxies)
print(response.json())
💡 Güvenlik İpucu
Asla kullanıcı adı ve şifreyi doğrudan script koduna sabitlemeyin. Çevresel değişkenler veya .env dosyası kullanarak python-dotenv kütüphanesi ile saklayın. Böylece kodunuzu GitHub'da yayınlarken kimlik bilgilerinin yanlışlıkla sızmasını önlersiniz.
Proxy döndürme: otomatik IP değişimi
Tek bir proxy, hâlâ tek bir IP adresidir ve bu adres engellenebilir. Gerçek yasaklamalardan korunmanın yolu döndürmedir: her istek (veya her N istekte) yeni bir IP ile gönderilir. Aşağıda döndürme uygulaması için birkaç yaklaşım bulunmaktadır.
Yöntem 1: Listeden rastgele seçim
import requests
import random
# Proxy listesi
proxy_list = [
"http://user:[email protected]:8080",
"http://user:[email protected]:8080",
"http://user:[email protected]:8080",
"http://user:[email protected]:8080",
]
def get_random_proxy():
proxy = random.choice(proxy_list)
return {"http": proxy, "https": proxy}
# IP döndürme ile 10 sayfa veri çekme
urls = [f"https://example.com/page/{i}" for i in range(1, 11)]
for url in urls:
proxies = get_random_proxy()
try:
response = requests.get(url, proxies=proxies, timeout=10)
print(f"URL: {url} | IP: {proxies['http'].split('@')[1]} | Durum: {response.status_code}")
except requests.RequestException as e:
print(f"Hata: {e}")
Yöntem 2: itertools ile döngüsel döndürme
import requests
import itertools
proxy_list = [
"http://user:[email protected]:8080",
"http://user:[email protected]:8080",
"http://user:[email protected]:8080",
]
# Proxy listesi üzerinde sonsuz döngü oluşturma
proxy_cycle = itertools.cycle(proxy_list)
def get_next_proxy():
proxy = next(proxy_cycle)
return {"http": proxy, "https": proxy}
# Her istek, sırayla bir sonraki proxy kullanır
for i in range(9):
proxies = get_next_proxy()
response = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10)
print(f"İstek {i+1}: {response.json()['origin']}")
Saatte binlerce istek içeren endüstriyel görevler için rezidans proxy'leri kullanmanız önerilir; sağlayıcı, her istek için IP'yi tek bir uç nokta üzerinden otomatik olarak değiştirir ve adres listesini manuel olarak yönetmenize gerek kalmaz.
Session üzerinden proxy: sürekli bağlantılar ve çerezler
Bir oturum içinde birden fazla istek yapmanız gerektiğinde (örneğin, giriş yapıp ardından istekler yapmak), requests.Session() nesnesini kullanın. Bu, çerezleri, başlıkları ve proxy ayarlarını istekler arasında saklar — her çağrıda proxy'yi ayrı ayrı iletmenize gerek kalmaz.
import requests
# Proxy ile oturum oluşturma
session = requests.Session()
session.proxies = {
"http": "http://user:[email protected]:8080",
"https": "http://user:[email protected]:8080",
}
# Tarayıcıyı taklit etmek için başlık ekleme
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Accept-Language": "ru-RU,ru;q=0.9",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
})
# Adım 1: Kimlik doğrulama
login_data = {"username": "myuser", "password": "mypass"}
session.post("https://example.com/login", data=login_data)
# Adım 2: Artık çerezlerle ve proxy üzerinden istekler
response = session.get("https://example.com/dashboard")
print(response.status_code)
# Adım 3: Oturumu kapatma
session.close()
Session kullanımı, performans açısından da daha etkilidir: TCP bağlantısı yeniden kullanılır, her istek için yeniden açılmaz. 1000'den fazla sayfa veri çekerken bu, belirgin bir hız artışı sağlar.
Hata, zaman aşımı ve otomatik tekrar işleme
Proxy sunucuları erişilemez olabilir, yavaş yanıt verebilir veya bağlantı hataları döndürebilir. Güvenilir bir veri çekme scripti, bu durumları işleyebilmelidir ve bir hata durumunda otomatik olarak başka bir proxy'ye geçebilmelidir.
import requests
import random
import time
proxy_list = [
"http://user:[email protected]:8080",
"http://user:[email protected]:8080",
"http://user:[email protected]:8080",
]
def fetch_with_retry(url, max_retries=3, timeout=10):
"""
Hata durumunda otomatik proxy değişimi ile istek yapar.
Response nesnesini döndürür veya deneme sayısı dolduğunda None döner.
"""
available_proxies = proxy_list.copy()
random.shuffle(available_proxies)
for attempt, proxy_url in enumerate(available_proxies[:max_retries], 1):
proxies = {"http": proxy_url, "https": proxy_url}
try:
response = requests.get(
url,
proxies=proxies,
timeout=timeout,
headers={"User-Agent": "Mozilla/5.0"}
)
response.raise_for_status() # 4xx/5xx durumunda istisna fırlatır
print(f"✓ {attempt}. denemede başarı")
return response
except requests.exceptions.ProxyError:
print(f"✗ {attempt}. deneme: proxy erişilemez — {proxy_url}")
except requests.exceptions.Timeout:
print(f"✗ {attempt}. deneme: zaman aşımı — {proxy_url}")
except requests.exceptions.HTTPError as e:
print(f"✗ {attempt}. deneme: HTTP hatası {e.response.status_code}")
if e.response.status_code == 403:
print(" → Yasak alındı, bir sonraki proxy'yi deniyoruz...")
except requests.exceptions.RequestException as e:
print(f"✗ {attempt}. deneme: genel hata — {e}")
time.sleep(1) # Denemeler arasında bekleme
print(f"✗ {url} için tüm {max_retries} deneme doldu")
return None
# Kullanım
result = fetch_with_retry("https://httpbin.org/ip")
if result:
print(result.json())
raise_for_status() metoduna dikkat edin — bu metod, otomatik olarak 4xx ve 5xx HTTP durumlarında istisna fırlatır. Bunu yapmazsanız, scriptiniz 403 (yasak) veya 429 (istek limiti aşıldı) kodu ile gelen yanıtları bile başarılı olarak sayacaktır.
Çevresel değişkenler üzerinden proxy: güvenli veri saklama
requests kütüphanesi, HTTP_PROXY ve HTTPS_PROXY çevresel değişkenlerini otomatik olarak okur. Bu, kimlik bilgilerini kodda saklamadan proxy'ler arasında kolayca geçiş yapmanıza olanak tanır.
Terminalde değişkenleri ayarlama (Linux/macOS):
export HTTP_PROXY="http://user:[email protected]:8080" export HTTPS_PROXY="http://user:[email protected]:8080" export NO_PROXY="localhost,127.0.0.1"
Veya .env dosyası ile python-dotenv kütüphanesini kullanarak:
# .env dosyası (gitignore'a ekleyin!) HTTP_PROXY=http://user:[email protected]:8080 HTTPS_PROXY=http://user:[email protected]:8080
# Python scripti
from dotenv import load_dotenv
import requests
import os
load_dotenv() # .env'den değişkenleri yükle
# requests otomatik olarak HTTP_PROXY ve HTTPS_PROXY kullanır
response = requests.get("https://httpbin.org/ip")
print(response.json())
# Veya çevresel değişkenlerden açıkça:
proxies = {
"http": os.getenv("HTTP_PROXY"),
"https": os.getenv("HTTPS_PROXY"),
}
response = requests.get("https://httpbin.org/ip", proxies=proxies)
print(response.json())
⚠️ Önemli: NO_PROXY değişkeni
NO_PROXY değişkeni, belirli adresleri proxy dışı bırakmanıza olanak tanır. localhost ve 127.0.0.1'yi eklemeyi unutmayın, böylece yerel istekler proxy üzerinden geçmez.
Gerçek senaryolar: pazar yerlerini veri çekme, API ile çalışma ve otomasyon
Geliştiricilerin en sık karşılaştığı üç pratik senaryoyu inceleyelim.
Senaryo 1: Pazar yerinden fiyat çekme
Wildberries veya Ozon'da fiyatları izlerken, gerçek bir kullanıcının davranışını taklit etmek önemlidir: doğru tarayıcı başlıklarını iletmek, istekler arasında gecikmeler eklemek ve IP'leri döndürmek. Bu görev için data center proxy'leri iyi bir seçimdir — büyük veri hacimleri ile çalışırken hızlı ve ucuzdur.
import requests
import time
import random
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept": "application/json, text/plain, */*",
"Accept-Language": "ru-RU,ru;q=0.9",
"Referer": "https://www.wildberries.ru/",
}
PROXIES = [
{"http": "http://user:[email protected]:8080",
"https": "http://user:[email protected]:8080"},
{"http": "http://user:[email protected]:8080",
"https": "http://user:[email protected]:8080"},
]
def get_product_price(article_id: int) -> dict:
"""Wildberries'den makale numarasına göre ürün fiyatını alır."""
url = f"https://card.wb.ru/cards/v1/detail?appType=1&curr=rub&nm={article_id}"
proxies = random.choice(PROXIES)
try:
resp = requests.get(url, headers=HEADERS, proxies=proxies, timeout=15)
resp.raise_for_status()
data = resp.json()
product = data["data"]["products"][0]
return {
"id": product["id"],
"name": product["name"],
"price": product["salePriceU"] / 100, # fiyat kuruş cinsindendir
}
except (requests.RequestException, KeyError, IndexError) as e:
return {"error": str(e)}
# Gecikme ile birkaç makale çekme
articles = [12345678, 87654321, 11223344]
for article in articles:
result = get_product_price(article)
print(result)
time.sleep(random.uniform(1.5, 3.0)) # 1.5-3 saniye arasında rastgele gecikme
Senaryo 2: API ile proxy üzerinden çalışma
Bazı API'ler, bir IP'den gelen istek sayısını sınırlar (rate limiting). İstekleri birden fazla proxy arasında dağıtmak, bu sınırlamayı aşmanıza olanak tanır:
import requests
import itertools
from typing import Optional
class ProxyAPIClient:
"""Proxy döndürme ile API ile çalışma için istemci."""
def __init__(self, api_key: str, proxy_list: list):
self.api_key = api_key
self.proxy_cycle = itertools.cycle(proxy_list)
self.session = requests.Session()
self.session.headers.update({
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
})
def _get_proxy(self) -> dict:
proxy = next(self.proxy_cycle)
return {"http": proxy, "https": proxy}
def get(self, url: str, **kwargs) -> Optional[dict]:
proxies = self._get_proxy()
try:
resp = self.session.get(url, proxies=proxies, timeout=10, **kwargs)
resp.raise_for_status()
return resp.json()
except requests.RequestException as e:
print(f"API isteği başarısız oldu: {e}")
return None
# Kullanım
proxy_list = [
"http://user:[email protected]:8080",
"http://user:[email protected]:8080",
]
client = ProxyAPIClient(api_key="your_api_key", proxy_list=proxy_list)
data = client.get("https://api.example.com/products")
Senaryo 3: Coğrafi test
Pazarlamacılar ve SEO uzmanları, bir sitenin farklı bölgelerden nasıl göründüğünü sıkça kontrol eder. İstenilen lokasyonlardan proxy kullanarak bu süreci otomatikleştirebilirsiniz:
import requests
# Farklı bölgelerden proxy'ler
regional_proxies = {
"Moskova": "http://user:[email protected]:8080",
"Saint Petersburg": "http://user:[email protected]:8080",
"Novosibirsk": "http://user:[email protected]:8080",
"ABD": "http://user:[email protected]:8080",
}
url = "https://example.com/prices"
for region, proxy_url in regional_proxies.items():
proxies = {"http": proxy_url, "https": proxy_url}
try:
resp = requests.get(url, proxies=proxies, timeout=15)
print(f"[{region}] Durum: {resp.status_code} | "
f"Büyüklük: {len(resp.content)} bayt")
except requests.RequestException as e:
print(f"[{region}] Hata: {e}")
Göreviniz için hangi proxy türünü seçmelisiniz
Proxy türünün seçimi, projenizin başarısını doğrudan etkiler. Ucuz bir data center proxy, bazı görevler için mükemmel çalışabilirken, diğerleri için tamamen başarısız olabilir. İşte seçim için pratik bir rehber:
| Görev | Proxy Türü | Neden |
|---|---|---|
| Pazar yerlerini veri çekme (Wildberries, Ozon) | Rezidans | Normal kullanıcılar gibi görünür, daha az yasaklanır |
| Açık verileri, haberleri çekme | Data center | Hızlı, ucuz, yeterince anonim |
| Facebook API, Instagram ile çalışma | Mobil | Sosyal medya, mobil IP'lere en fazla güveniyor |
| Coğrafi test | Hedefleme ile rezidans | Kesin coğrafi konum, gerekli bölgeden gerçek IP'ler |
| Yüksek hacimli veri çekme (10k+ istek/saat) | Data center (havuz) | Büyük hacimlerde hız ve maliyet |
| Kimlik doğrulama ve hesaplarla çalışma | Rezidans veya mobil | Anti-fraud sistemlerinin tetikleyicileri daha azdır |
Güvenli sitelerle çalışırken maksimum güvenilirlik ve minimum yasaklama riski için geliştiriciler genellikle mobil proxy'leri tercih eder — bunlar, gerçek mobil operatörlerin (MTS, Beeline, MegaFon) IP adreslerini kullanır ve çok nadir olarak yasak listelerine girer.
Proxy kullanmadan önce kontrol listesi
- ✅ IP'nizi
httpbin.org/ipüzerinden kontrol edin — gerçek adresiniz görünür mü? - ✅ Hızı kontrol edin — yanıt süresi 2-3 saniyeyi geçmemelidir
- ✅ Proxy'nin yasak listelerinde olmadığından emin olun
blocklist.deveyaipqualityscore.comüzerinden - ✅ Coğrafi konumu
ipinfo.ioüzerinden kontrol edin — beklenen bölgeyle örtüşüyor mu? - ✅ Tam scripti çalıştırmadan önce hedef sitede tek bir istekle test edin
- ✅ HTTPS trafiğinin de proxy üzerinden geçtiğinden emin olun (sözlükte her iki anahtar da olmalı)
Sonuç
Python requests'ta proxy ayarlamak zor değildir, ancak detaylara dikkat gerektirir. Hatırlanması gereken ana ilkeler: her zaman proxy sözlüğünde her iki anahtarı (http ve https) belirtin, çok aşamalı senaryolar için Session kullanın, hataları ve zaman aşımını mutlaka işleyin ve kimlik bilgilerini kodda değil, çevresel değişkenlerde saklayın.
Günde binlerce istekle endüstriyel veri çekme için manuel bir proxy listesi yeterli değildir — döndürme gerekir. Eğer Wildberries veya Ozon gibi korunan pazar yerlerini çekiyorsanız, sosyal medya ile çalışıyorsanız veya coğrafi test yapıyorsanız, rezidans proxy'lerini denemenizi öneririz — bunlar, anti-bot sistemleri tarafından yüksek güvenilirlik sağlar ve IP'yi otomatik olarak döndürme desteği sunar, bu da scriptinizin kodunu önemli ölçüde basitleştirir.