Fiyat Sınırları Ne Atıyor?
Puan sınırları, web sitelerinin herhangi bir müşterinin istekleri ne kadar hızlı kontrol etmek için inşa ettiği görünmez duvarlardır. Bir siteyi çok agresif bir şekilde kazıdığınızda, bu duvarları vurdunız - ve sonuçları geçici yavaşlamalardan kalıcı IP yasaklarına kadar. Hız sınırlarının nasıl çalıştığını anlamak, sizi nasıl algıladıkları ve onların altında kalmak, verileri güvenilir bir şekilde teslim eden hurdaları inşa etmek için temeldir.
Bu kılavuz, ölçüm sinyalleri web sitelerinin kısıtlanmasının ardındaki mekanikleri ve satın almalarını sağlayan adaptif bir throttling için pratik stratejileri açıklıyor.
Daha geniş bir tanıtım için, referanslarla kazıma, bizi gör Web'e komple rehber ProxiesGenel olarak bloklardan kaçınmak için, okuyun Blokedilmeden Web Siteleri Nasıl Çıkarılır.
How Rate Limiting Works
Web siteleri birden çok katmanda, her biri farklı algılama granularity:
Katman 1: IP-Based Rate Limits
En yaygın yaklaşım. Sunucu, IP adresi bir süre içinde talep eder. Eşliği genişletin ve HTTP 429 (Too Many Requests) veya 503 yanıt alırsınız.
# Typical rate limit behavior
Request 1-50: HTTP 200 (normal)
Request 51: HTTP 429 (rate limited)
Wait 60 seconds...
Request 52: HTTP 200 (reset)Katman 2: Oturum/Cookie-Based Limits
Tracks istek frekansı seans veya tarayıcı kurabiye için. IP'leri döndürseniz bile, aynı seans sunucuyu hızlı vurmak limitleri tetikleyecek.
Katman 3: Hesap Tabanlı Limitler
Giriş gerektiren siteler için, sınırlar IP'ye bakılmaksızın kullanıcı hesabına bağlıdır. API'ler ve SaaS platformları üzerinde ortak.
Katman 4: Davranış Analizi
Cloudflare, PerimeterX ve Akamai gibi gelişmiş sistemler: istek zamanlaması, navigasyon akışı, fare hareketleri ( tarayıcı bağlamları). Bu katman atlamak en zor çünkü basit karşılara güvenmiyor.
Common Rate Limit Tespit Signals
Web siteleri otomatik kazı tespit etmek için aynı anda birden fazla sinyal kullanır:
| Signal Signal | Hangileri tespit eder | Evade |
|---|---|---|
| Dakikada IP'ye İstekler | Raw hız | Kolay (görüler) |
| IP'ye saatte / günlük istekler | Sustained volume | Medium (rotate IPs) |
| Sıklık isteği | Machine-like intervals | Medium (add jitter) |
| Eksik /wrong başlıkları | Olmayan müşteriler | Kolay (doğru başlıklar) |
| Senaryo kalıpları | Sistematik tarama | Medium (rando Feedback order) |
| TLS parmak izi | Kütüphane vs tarayıcı | Hard (gerçek tarayıcılar kullanın) |
| JavaScript execution JavaScript execution JavaScript execution | Headless browser | Hard (advanced configure) |
| Mouse /keyboard olaylar | Bot davranışı | Çok zor |
Rehberimizde algılama mekanizmaları hakkında daha fazla bilgi edinin Anti-Bot Systems Proxies nasıl tespit edilir.
HTTP Response Kodlarını Limiting
Hangi HTTP kodlarının uygun yeniden deneme mantığı oluşturmanıza yardımcı olduğunu bilmek:
| Kod Kodu | Anlam | Eylem |
|---|---|---|
| 200 (CAPTCHA ile) | Yumuşak blok - meydan okuma sayfası servis | Rotate IP, yavaş aşağı |
| 403 Yasak | IP veya oturum bloke edildi | Rotate IP hemen |
| 429 Çok Fazla İstek | Explicit oranı limit hit | Wait and retry with backoff |
| 503 Hizmet Un available | Server aşırı yükleme veya blok | Backoff, bloke edilirse kontrol edin |
| 302/307 - CAPTCHA URL | Challenge yönlendirme | Rotate IP, hız azalt |
Strateji 1: Saygılı Throttling
En basit yaklaşım - Hedefin izin verdiğinin altında talep oranını iyi tut. Bu daha az başarısızlık, daha az boşanmış bant genişliği ve daha sürdürülebilir kazı anlamına gelir.
import requests
import time
import random
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
def respectful_scrape(urls: list[str], rpm_limit: int = 10) -> list[str]:
"""Scrape URLs while respecting a requests-per-minute limit."""
delay = 60.0 / rpm_limit
results = []
for url in urls:
try:
resp = requests.get(
url,
proxies={"http": PROXY, "https": PROXY},
timeout=30
)
results.append(resp.text if resp.status_code == 200 else None)
except requests.RequestException:
results.append(None)
# Add delay with random jitter (±30%) to look less robotic
jitter = delay * random.uniform(0.7, 1.3)
time.sleep(jitter)
return resultsStrateji 2: Adaptasyon Throttling
Sabit bir oran yerine, dinamik olarak aldığınız cevaplara dayanarak hızınızı ayarlayın. Her şeyin çalıştığı zaman hızlanır, uyarı işaretleri gördüğünüzde yavaşlayın.
Python Uygulaması
import requests
import time
import random
from dataclasses import dataclass, field
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
@dataclass
class AdaptiveThrottle:
"""Automatically adjusts request rate based on server responses."""
base_delay: float = 2.0 # seconds between requests
min_delay: float = 0.5
max_delay: float = 30.0
current_delay: float = 2.0
success_streak: int = 0
warning_codes: set = field(default_factory=lambda: {429, 403, 503})
def on_success(self):
self.success_streak += 1
# Speed up after 10 consecutive successes
if self.success_streak >= 10:
self.current_delay = max(self.current_delay * 0.85, self.min_delay)
self.success_streak = 0
def on_rate_limit(self):
self.success_streak = 0
# Double the delay on rate limit
self.current_delay = min(self.current_delay * 2.0, self.max_delay)
def on_block(self):
self.success_streak = 0
# Aggressive backoff on block
self.current_delay = min(self.current_delay * 3.0, self.max_delay)
def wait(self):
jitter = self.current_delay * random.uniform(0.7, 1.3)
time.sleep(jitter)
def scrape_adaptive(urls: list[str]) -> list[dict]:
throttle = AdaptiveThrottle()
results = []
for url in urls:
try:
resp = requests.get(
url,
proxies={"http": PROXY, "https": PROXY},
timeout=30
)
if resp.status_code == 200:
throttle.on_success()
results.append({"url": url, "status": 200, "body": resp.text})
elif resp.status_code == 429:
throttle.on_rate_limit()
# Check Retry-After header
retry_after = int(resp.headers.get("Retry-After", 0))
if retry_after:
time.sleep(retry_after)
results.append({"url": url, "status": 429, "body": None})
elif resp.status_code == 403:
throttle.on_block()
results.append({"url": url, "status": 403, "body": None})
else:
results.append({"url": url, "status": resp.status_code, "body": resp.text})
except requests.RequestException as e:
throttle.on_block()
results.append({"url": url, "status": 0, "error": str(e)})
throttle.wait()
print(f"Current delay: {throttle.current_delay:.1f}s")
return resultsNode.js Uygulama
const HttpsProxyAgent = require('https-proxy-agent');
const fetch = require('node-fetch');
class AdaptiveThrottle {
constructor() {
this.currentDelay = 2000; // ms
this.minDelay = 500;
this.maxDelay = 30000;
this.successStreak = 0;
}
onSuccess() {
this.successStreak++;
if (this.successStreak >= 10) {
this.currentDelay = Math.max(this.currentDelay * 0.85, this.minDelay);
this.successStreak = 0;
}
}
onRateLimit() {
this.successStreak = 0;
this.currentDelay = Math.min(this.currentDelay * 2, this.maxDelay);
}
onBlock() {
this.successStreak = 0;
this.currentDelay = Math.min(this.currentDelay * 3, this.maxDelay);
}
async wait() {
const jitter = this.currentDelay * (0.7 + Math.random() * 0.6);
return new Promise(resolve => setTimeout(resolve, jitter));
}
}
async function scrapeAdaptive(urls) {
const throttle = new AdaptiveThrottle();
const agent = new HttpsProxyAgent('http://USERNAME:PASSWORD@gate.proxyhat.com:8080');
const results = [];
for (const url of urls) {
try {
const res = await fetch(url, { agent, timeout: 30000 });
if (res.ok) {
throttle.onSuccess();
results.push({ url, status: res.status, body: await res.text() });
} else if (res.status === 429) {
throttle.onRateLimit();
const retryAfter = parseInt(res.headers.get('retry-after') || '0');
if (retryAfter) await new Promise(r => setTimeout(r, retryAfter * 1000));
results.push({ url, status: 429, body: null });
} else if (res.status === 403) {
throttle.onBlock();
results.push({ url, status: 403, body: null });
}
} catch (err) {
throttle.onBlock();
results.push({ url, status: 0, error: err.message });
}
await throttle.wait();
console.log(`Current delay: ${throttle.currentDelay.toFixed(0)}ms`);
}
return results;
}Strateji 3: Dağıtılmış Oran Limiting
Paralel olarak birden çok hurda örneği çalışırken, tüm işçiler arasındaki oranı sınırlayın. Koordinasyon olmadan, her işçi kendi sınırına saygı duyar, ancak birleşik trafik hala hedefin üzerindedir.
import requests
import time
import threading
class DistributedRateLimiter:
"""Thread-safe rate limiter for multiple scraper workers."""
def __init__(self, max_rpm: int):
self.min_interval = 60.0 / max_rpm
self.lock = threading.Lock()
self.last_request_time = 0.0
def acquire(self):
"""Block until it is safe to make the next request."""
with self.lock:
now = time.time()
elapsed = now - self.last_request_time
if elapsed < self.min_interval:
time.sleep(self.min_interval - elapsed)
self.last_request_time = time.time()
# Shared limiter across all threads
limiter = DistributedRateLimiter(max_rpm=30)
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
def worker(urls: list[str], results: list):
for url in urls:
limiter.acquire()
try:
resp = requests.get(
url,
proxies={"http": PROXY, "https": PROXY},
timeout=30
)
results.append({"url": url, "status": resp.status_code})
except Exception as e:
results.append({"url": url, "error": str(e)})Strateji 4: Öncekilik ile Queue
Karmaşık kazı projeleri için, hedef alan başına oranı limitlerini yöneten öncelikli bir kuyruk kullanın:
import requests
import time
import heapq
import threading
from collections import defaultdict
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
class DomainRateLimiter:
"""Per-domain rate limiting with priority queue."""
def __init__(self, default_rpm: int = 10):
self.default_rpm = default_rpm
self.domain_limits = {} # domain -> max RPM
self.domain_last = defaultdict(float) # domain -> last request time
self.lock = threading.Lock()
def set_limit(self, domain: str, rpm: int):
self.domain_limits[domain] = rpm
def wait_for_domain(self, domain: str):
rpm = self.domain_limits.get(domain, self.default_rpm)
min_interval = 60.0 / rpm
with self.lock:
now = time.time()
elapsed = now - self.domain_last[domain]
if elapsed < min_interval:
time.sleep(min_interval - elapsed)
self.domain_last[domain] = time.time()
# Configure per-domain limits
limiter = DomainRateLimiter(default_rpm=10)
limiter.set_limit("amazon.com", 3) # Very conservative for Amazon
limiter.set_limit("example.com", 30) # Lenient for simple sites
limiter.set_limit("google.com", 5) # Moderate for GoogleRobotlar.txt for Rate Hints
Birçok site, robotlarda tarama tercihlerini yayınlar.txt. The The The The The The The The Crawl-delay yönerge size istekler arasında en az saniye söyler:
import requests
from urllib.parse import urlparse
from urllib.robotparser import RobotFileParser
def get_crawl_delay(base_url: str, user_agent: str = "*") -> float | None:
"""Extract Crawl-delay from robots.txt."""
parsed = urlparse(base_url)
robots_url = f"{parsed.scheme}://{parsed.netloc}/robots.txt"
try:
resp = requests.get(robots_url, timeout=10)
if resp.status_code != 200:
return None
rp = RobotFileParser()
rp.parse(resp.text.splitlines())
delay = rp.crawl_delay(user_agent)
return delay
except Exception:
return None
# Check before scraping
delay = get_crawl_delay("https://example.com")
if delay:
print(f"Site requests {delay}s between requests")
else:
print("No crawl-delay specified")Common Rate Limit Hatalar
- 429 cevabı görmezden gelin. Birçok scrapers aynı yanıtların tamamını tedavi eder. A 429 size tam olarak ne olduğunu söyler - Retry- Afterhead ve back off.
- jitter olmadan sabit gecikmeler. Her 2.000 saniyede bir istek robotik görünüyor. Belirsizlerinize rastgele varyasyon (jitter) ekleyin.
- Paralel işçileri koordine etme. Her biri 10 RPM toplam 50 RPM eşittir. Paylaşılan bir fiyat limiti kullanın.
- Yavaşlamadan IP'leri Rotating IPs without slowing. IP rotasyonu sizi zaman alır, ancak her yeni IP hemen siteyi çekiçse, gelişmiş algılama sizi yakalar. Doğru throttling ile rotasyonu birleştirin.
- Top saatleri boyunca avlamak. Siteler yüksek-traffic dönemler sırasında sınırlanan oranla daha agresiftir. Hedefin zaman bölgesi için kapalı saatler boyunca ağır taramalar.
Oran sınırlı kazınızı desteklemek için kaç temsilciye ihtiyacınız olduğunu hesaplamak için, bakınız Kaç Proxies Kaçmak İçin İhtiyacınız Var?.For proxy rotasyon stratejileri that complete rate limit, read Proxy Rotation Strategies for Large-Scale Haping.
Doğru oran sınırlı kazılarla başlayın ProxyHat Python SDK veya keşfedin Fiyatlandırma planları Projeniz için.
Sık Sorulan Sorular
Bir oranı sınırı aşıyorsam ne olur?
Cevap siteye bağlıdır. Çoğu geri dönüş HTTP 429, bir Retry- Afterhead ile. Bazıları CAPTCHAs'a hizmet eder. Aggressive siteleri IP'yi 403 yanıtla hemen engeller. En kötü durumda, tekrarlanan ihlaller kalıcı IP yasağına yol açıyor.
Bir sitenin oranı sınırı nasıl bulurum?
Yavaş başlayın ve yanıt kodlarını takip ederken yavaşlayın. Crawl-delay yönergeleri için robotlar.txt. X-RateLimit-Limit ve X-RateLimit-Remaining alanları için kafaları takip edin. Bazı API'ler, belgelerinde sınırlarını yayınlar.
Yönleri kullanmak oran sınırları aşıyor mu?
Proxies, birden fazla IP üzerinden istekleri dağıtır, bu yüzden her IP per-IP sınırı altında kalır. Bununla birlikte, sofistike siteler de seansları, parmak izlerini ve davranışsal kalıpları takip eder. Proxies gereklidir ancak yeterli değildir - onları doğru throttling ve gerçekçi istek kalıpları ile birleştirir.
Yıkım için en güvenli istek oranı nedir?
Evrensel bir cevap yoktur. Google veya Amazon gibi agresif hedefler için, IP başına dakika başına 1-5 talep güvenlidir. Işıklı korumalı siteler için, IP başına 20-60 RPM çalışabilir. Her zaman gözlemlenen başarı oranlarına dayanan muhafazakar ve artış başlar.






