Bloga geri dön

Tıbbi Verileri Parse Etmek İçin Proxy: Engellenmeden Bilgi Nasıl Toplanır

Klinik araştırmalardan, ilaç veritabanlarından ve tıbbi dergilerden tıbbi verileri güvenli bir şekilde nasıl çekebileceğinizi öğrenin, engellenmeden.

📅9 Mart 2026
```html

Tıbbi verileri parsellemek, proxy seçimi konusunda özel bir yaklaşım gerektiren bir görevdir. Tıbbi portallar, klinik araştırma veritabanları ve ilaç kaynakları, otomatik veri toplama sistemlerine karşı gelişmiş koruma sistemleri kullanmaktadır. Bu yazıda, tıbbi bilgileri güvenli bir şekilde parsellemek için proxy'lerin nasıl doğru bir şekilde ayarlanacağı, yasaklardan nasıl kaçınılacağı ve gerekli verilerin etkili bir şekilde nasıl toplanacağı ele alınacaktır.

Tıbbi siteler neden parsellemeyi yasaklıyor

Tıbbi portallar ve veritabanları, otomatik bilgi toplama konusunda birkaç nedenle özellikle hassastır. Öncelikle, birçoğu ticari bir temele dayanmakta ve verilere ücretli abonelikler aracılığıyla erişim satmaktadır. Otomatik parselleme, kullanım şartlarını ve lisans sözleşmelerini ihlal edebilir.

İkinci olarak, tıbbi veriler genellikle yasalarla korunan gizli bilgileri içermektedir (ABD'de HIPAA, Avrupa'da GDPR). Kaynak sahipleri, bu verilere erişimi kontrol etmek ve yetkisiz dağılımını önlemekle yükümlüdür. Bu nedenle, gelişmiş koruma sistemleri kullanmaktadırlar:

  • Rate limiting — bir IP adresinden belirli bir zaman diliminde (genellikle dakikada 10-50 istek) gelen istek sayısının sınırlandırılması
  • Fingerprinting — tarayıcı özelliklerinin, HTTP başlıklarının ve kaynakların yüklenme sırasının analizi
  • CAPTCHA — şüpheli etkinlik durumunda devreye giren reCAPTCHA v3 gibi sistemler
  • IP yasakları — veri merkezlerinin IP adreslerinin geçici veya kalıcı olarak yasaklanması
  • Cloudflare ve benzerleri — CDN düzeyinde botlara karşı koruma

Üçüncü neden — sunucular üzerindeki yük. Tıbbi veritabanları genellikle milyonlarca kayıt içermekte ve toplu parselleme, altyapı üzerinde önemli bir yük oluşturabilir. Bu nedenle, yöneticiler otomatik veri toplama ile aktif olarak mücadele etmekte ve botlara özgü davranış kalıplarını izlemektedir: istekler arasındaki benzer aralıklar, sayfaların lineer olarak gezilmesi, JavaScript ve çerezlerin yokluğu.

Önemli: Tıbbi verileri parsellemeye başlamadan önce, sitenin kullanım şartlarını ve geçerli yasaları mutlaka inceleyin. Bazı veriler telif hakkı ile korunabilir veya hasta kişisel bilgilerini içerebilir. Faaliyetlerinizin yasal olduğundan ve üçüncü şahısların haklarını ihlal etmediğinden emin olun.

Tıbbi veriler için hangi proxy türü seçilmeli

Proxy türünün seçimi, tıbbi verilerin başarılı bir şekilde parselenmesi için kritik öneme sahiptir. Farklı kaynaklar, farklı yaklaşımlar gerektirmektedir. Temel proxy türlerini ve uygulanabilirliklerini inceleyelim:

Proxy Türü Avantajları Dezavantajları Ne Zaman Kullanılmalı
Veri Merkezi Proxy'leri Yüksek hız (100+ Mbps), düşük maliyet, stabil bağlantı Kolayca tespit edilebilir, genellikle korumalı sitelerde yasaklıdır Sıkı koruma olmayan açık veri tabanları (PubMed, WHO)
Konut Proxy'leri Gerçek ev kullanıcılarının IP'leri, düşük yasaklanma riski, Cloudflare'ı geçer Daha yüksek maliyet, değişken hız, kararsız olabilirler Koruma altındaki ticari veri tabanları (Elsevier, Springer), Cloudflare ile siteler
Mobil Proxy'ler Maksimum güvenilirlik (mobil operatörlerin IP'leri), neredeyse yasaklanmazlar En pahalıları, sınırlı coğrafya, daha yavaş olabilirler Özellikle korumalı kaynaklar, konut proxy'leri işe yaramadığında
ISP Proxy'leri Veri merkezi hızları + konut güvenilirliği, statik IP'ler Ortalama maliyet, sınırlı erişilebilirlik Bir IP ile uzun süreli parselleme, stabilite gerektiğinde

Çoğu tıbbi veri parselleme görevi için konut proxy'leri kullanılması önerilmektedir. Maliyet ve etkinlik arasında optimal bir denge sağlarlar. Veri merkezi proxy'leri yalnızca korumasız açık kaynaklar için uygundur. Mobil proxy'ler, diğer türlerin işe yaramadığı durumlarda kullanılmalıdır.

Belirli kaynaklar için seçim önerileri

  • PubMed, PubMed Central — veri merkezi proxy'leri yeterlidir, ancak saniyede 3 istekle sınırlıdır
  • ClinicalTrials.gov — veri merkezi proxy'leri, resmi bir API vardır
  • Elsevier, Springer, Wiley — konut proxy'leri zorunludur, gelişmiş fingerprinting kullanmaktadırlar
  • DrugBank, RxList — konut proxy'leri, parsellemeye karşı aktif koruma
  • FDA, EMA veri tabanları — veri merkezi proxy'leri uygundur, ancak parselleme hızı düşüktür

Tıbbi verilerin ana kaynakları ve koruma yöntemleri

Tıbbi veriler, her birinin kendine özgü özellikleri ve koruma seviyeleri olan birçok kaynağa dağılmıştır. Bu özelliklerin anlaşılması, parselleme stratejisinin doğru bir şekilde ayarlanmasına yardımcı olacaktır.

Açık devlet veri tabanları

PubMed/PubMed Central — en büyük tıbbi yayın veritabanı, 35 milyondan fazla kayıt içermektedir. ABD Ulusal Tıp Kütüphanesi (NLM), verilere erişim için tercih edilen yöntem olan resmi E-utilities API'sini sağlamaktadır. Web arayüzünün doğrudan parsellemesi mümkündür, ancak bir IP'den saniyede 3 istekle sınırlıdır. Limitin aşılması, 24 saatlik geçici bir yasakla sonuçlanır.

ClinicalTrials.gov — klinik araştırmalar veritabanı, 220 ülkede 400,000'den fazla araştırma hakkında bilgi içermektedir. Ayrıca programlı erişim için API sağlamaktadır. Web arayüzü, bir IP'den 5 dakikada maksimum 100 istekle sınırlı olan rate limiting ile korunmaktadır. Temel bot koruması kullanılmakta, ancak Cloudflare yoktur.

FDA İlaç Veritabanı — FDA onaylı ilaçların veritabanı. Web arayüzü ve openFDA API'si aracılığıyla açık erişim. Sınırlamalar: anonim kullanıcılar için dakikada 240 istek, API anahtarı ile dakikada 1000 istek. Yasaklamalar nadirdir, ancak agresif parselleme durumunda mümkün olabilir.

Ticari bilimsel yayıncılar

Elsevier (ScienceDirect) — bilimsel literatürün en büyük yayıncılarından biri. Çok katmanlı koruma kullanmaktadır: Cloudflare, tarayıcı fingerprinting, kullanıcı davranış analizi. Otomatik indirme kalıplarını tespit eder: makalelere ardışık erişim, JavaScript yokluğu, alışılmadık User-Agent. Parselleme tespit edildiğinde, IP'yi hesap düzeyinde yasaklar ve tüm kurumu yasaklayabilir. Tam bir tarayıcı emülasyonu ile rotasyonlu konut proxy'lerinin kullanılması zorunludur.

Springer Nature — benzer koruma, ayrıca sayfaların kaydırma hızını ve fare hareketlerini izler. Botları tespit etmek için makine öğrenimi kullanmaktadır. Bir IP'den saatte 10-15 makaleden fazla parselleme yapılması önerilir, istekler arasında rastgele gecikmeler ile.

Wiley Online Library — daha az agresif bir koruma, ancak yine de proxy kullanımı gerektirir. Bir IP'den saatte yaklaşık 50 istek yapmaya izin verir, yasaklama olmadan. Etkinliği izlemek için oturum çerezleri kullanmaktadır.

İlaç veri tabanları

DrugBank — kapsamlı bir ilaç veri tabanı. Ücretsiz sürüm, web arayüzü ile sınırlıdır, ticari sürüm API ve veri çıkışları sunmaktadır. Web versiyonu, Cloudflare ve rate limiting ile korunmaktadır — dakikada maksimum 20 istek. Otomasyonu, çerezlerin ve JavaScript'in yokluğuna göre tespit eder.

RxList, Drugs.com — tüketiciler için popüler ilaç rehberleri. Cloudflare kullanmakta ve parsellemeye karşı aktif bir şekilde mücadele etmektedir. Veri merkezi IP'lerini neredeyse anında yasaklamaktadır. Konut proxy'leri ve yavaş parselleme hızı (dakikada 5-10 sayfa) gereklidir.

Uzun vadeli parselleme için IP rotasyonu ayarlama

IP adreslerinin doğru rotasyonu, tıbbi verilerin başarılı bir şekilde parselenmesi için anahtar bir faktördür. İki ana yaklaşım vardır: istek düzeyinde rotasyon ve zaman düzeyinde rotasyon.

İstek düzeyinde rotasyon

Bu yaklaşımda, her istek yeni bir IP adresi üzerinden gönderilir. Bu, yasaklanma riskini en aza indirir, ancak çerezler aracılığıyla oturumları izleyen sitelerde sorun yaratabilir. Oturum durumunu sürdürmenin gerekmediği liste ve katalog parselleme için uygundur.

Çoğu konut proxy sağlayıcısı, özel bir endpoint aracılığıyla otomatik rotasyon sunmaktadır. Örneğin, rotasyonlu proxy endpoint'i kullanıldığında, her yeni TCP bağlantısı yeni bir IP alır. Bu, Python'daki requests gibi kütüphanelerle otomatik olarak çalışır, çünkü varsayılan olarak her istek için yeni bir bağlantı oluşturulur.

Zaman düzeyinde rotasyon (sticky sessions)

Sticky sessions, belirli bir süre boyunca (genellikle 5-30 dakika) bir IP adresinin kullanılmasına izin verir, ardından otomatik olarak değişir. Bu, kimlik doğrulama gerektiren veya çerezler aracılığıyla oturum durumunu izleyen siteler için faydalıdır. Bir IP üzerinden birkaç sayfa parselleyebilir, gerçek bir kullanıcının davranışını taklit edebilir ve ardından IP otomatik olarak değişir.

Tıbbi siteler için, 10-15 dakika süresince sticky sessions kullanılması önerilir. Bu süre zarfında 10-20 sayfa parselleyebilirsiniz (gecikmelere bağlı olarak), ardından IP değişir ve "yeni bir oturum" başlarsınız. Bu, doğal görünür ve tespit riskini azaltır.

IP havuzunun boyutu

Uzun vadeli parselleme için, mevcut IP adreslerinin havuzunun boyutu önemlidir. Eğer bir hafta boyunca aynı 100 IP setini kullanıyorsanız, site bir kalıp fark edebilir ve tüm bu adresleri yasaklayabilir. Konut proxy'leri genellikle milyonlarca IP'ye erişim sağlar, bu da aynı adresin yeniden kullanılmasını neredeyse imkansız kılar.

Veri merkezi proxy'leri kullanırken, ortalama bir hacim için (ayda 10,000-50,000 sayfa) en az 500-1000 IP havuzuna sahip olmak önerilir. Büyük ölçekli parselleme (yüz binlerce sayfa) için, büyük IP havuzlarına sahip konut proxy'leri kullanmak daha iyidir.

Farklı kaynaklar için rotasyon önerisi:

  • PubMed — rotasyon zorunlu değildir, rate limit'e uyularak 1 IP yeterlidir
  • Ticari yayıncılar — 10-15 dakika sticky sessions, her 15-20 sayfada yeni IP
  • İlaç veri tabanları — her istek için rotasyon veya 5 dakika sticky sessions
  • Siteler Cloudflare ile — sticky sessions zorunludur, istek düzeyinde rotasyon çalışmaz

Proxy ile parselleme için Python'da kod örnekleri

Tıbbi verileri parsellemek için proxy ayarlarının pratik örneklerini inceleyelim. Temel bir örnekle başlayıp, yavaş yavaş karmaşıklaştıracağız.

Requests kütüphanesi ile temel ayar

import requests
from time import sleep
import random

# Proxy ayarları (verilerinizi değiştirin)
PROXY_HOST = "proxy.example.com"
PROXY_PORT = "8080"
PROXY_USER = "username"
PROXY_PASS = "password"

proxies = {
    'http': f'http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}',
    'https': f'http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}'
}

# Gerçek bir tarayıcıyı taklit etmek için başlıklar
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': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.9',
    'Accept-Encoding': 'gzip, deflate, br',
    'DNT': '1',
    'Connection': 'keep-alive',
    'Upgrade-Insecure-Requests': '1'
}

# PubMed'e istek örneği
url = "https://pubmed.ncbi.nlm.nih.gov/?term=diabetes"

try:
    response = requests.get(url, proxies=proxies, headers=headers, timeout=30)
    print(f"Durum kodu: {response.status_code}")
    print(f"İçerik uzunluğu: {len(response.content)}")
    
    # İstekler arasında gecikme ekleyin (PubMed için zorunludur)
    sleep(random.uniform(1.0, 3.0))
    
except requests.exceptions.RequestException as e:
    print(f"Hata: {e}")

Rotasyon ve tekrar mantığı ile gelişmiş ayar

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
from time import sleep
import random

class ProxyRotator:
    def __init__(self, proxy_list):
        """
        proxy_list: proxy'lerin sözlük listesi
        [{'http': 'http://user:pass@host:port', 'https': '...'}, ...]
        """
        self.proxy_list = proxy_list
        self.current_index = 0
    
    def get_next_proxy(self):
        """Listeden bir sonraki proxy'i al"""
        proxy = self.proxy_list[self.current_index]
        self.current_index = (self.current_index + 1) % len(self.proxy_list)
        return proxy

def create_session_with_retries():
    """Hatalarda otomatik tekrarlarla bir oturum oluştur"""
    session = requests.Session()
    
    # Otomatik tekrar ayarları
    retry_strategy = Retry(
        total=3,  # maksimum 3 deneme
        backoff_factor=1,  # denemeler arasındaki gecikme: 1, 2, 4 saniye
        status_forcelist=[429, 500, 502, 503, 504],  # tekrar için kodlar
        allowed_methods=["GET", "POST"]
    )
    
    adapter = HTTPAdapter(max_retries=retry_strategy)
    session.mount("http://", adapter)
    session.mount("https://", adapter)
    
    return session

def scrape_with_rotation(urls, proxy_rotator):
    """Proxy rotasyonu ile URL listesini parselle"""
    session = create_session_with_retries()
    results = []
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'en-US,en;q=0.9',
    }
    
    for url in urls:
        # Her istek için yeni bir proxy al
        proxy = proxy_rotator.get_next_proxy()
        
        try:
            response = session.get(
                url, 
                proxies=proxy, 
                headers=headers, 
                timeout=30
            )
            
            if response.status_code == 200:
                results.append({
                    'url': url,
                    'status': 'başarılı',
                    'content_length': len(response.content)
                })
                print(f"✓ Başarılı: {url}")
            else:
                results.append({
                    'url': url,
                    'status': 'başarısız',
                    'error': f"Durum kodu: {response.status_code}"
                })
                print(f"✗ Başarısız: {url} (Durum: {response.status_code})")
        
        except requests.exceptions.RequestException as e:
            results.append({
                'url': url,
                'status': 'hata',
                'error': str(e)
            })
            print(f"✗ Hata: {url} ({e})")
        
        # İstekler arasında rastgele gecikme (önemli!)
        sleep(random.uniform(2.0, 5.0))
    
    return results

# Kullanım örneği
proxy_list = [
    {
        'http': 'http://user1:pass1@proxy1.example.com:8080',
        'https': 'http://user1:pass1@proxy1.example.com:8080'
    },
    {
        'http': 'http://user2:pass2@proxy2.example.com:8080',
        'https': 'http://user2:pass2@proxy2.example.com:8080'
    }
]

rotator = ProxyRotator(proxy_list)

urls_to_scrape = [
    "https://pubmed.ncbi.nlm.nih.gov/?term=diabetes",
    "https://pubmed.ncbi.nlm.nih.gov/?term=cancer",
    "https://pubmed.ncbi.nlm.nih.gov/?term=covid"
]

results = scrape_with_rotation(urls_to_scrape, rotator)

JavaScript içeren siteler için Selenium kullanımı

Birçok modern tıbbi site, içeriği yüklemek için JavaScript kullanmaktadır. Bu durumlarda, headless tarayıcı gereklidir:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

def create_proxy_driver(proxy_host, proxy_port, proxy_user, proxy_pass):
    """Proxy ile Chrome WebDriver oluştur"""
    
    chrome_options = Options()
    
    # Headless mod (GUI olmadan)
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('--disable-dev-shm-usage')
    
    # Proxy ayarı
    chrome_options.add_argument(f'--proxy-server=http://{proxy_host}:{proxy_port}')
    
    # Otomasyonu devre dışı bırakma (tespiti aşmak için önemlidir)
    chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
    chrome_options.add_experimental_option('useAutomationExtension', False)
    
    # User-Agent
    chrome_options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')
    
    driver = webdriver.Chrome(options=chrome_options)
    
    # Kimlik doğrulama gerektiren proxy'ler için uzantı kullanmak gerekir
    # veya capabilities aracılığıyla ayarlamak (daha karmaşık bir seçenek)
    
    return driver

def scrape_with_selenium(url, driver):
    """JavaScript yüklemesini bekleyerek sayfayı parselle"""
    
    driver.get(url)
    
    # Elemanın yüklenmesini bekleme (örneğin, arama sonuçları)
    try:
        wait = WebDriverWait(driver, 10)
        results = wait.until(
            EC.presence_of_element_located((By.CLASS_NAME, "results-article"))
        )
        
        # Verileri çıkarma
        articles = driver.find_elements(By.CLASS_NAME, "results-article")
        
        data = []
        for article in articles:
            try:
                title = article.find_element(By.CLASS_NAME, "docsum-title").text
                authors = article.find_element(By.CLASS_NAME, "docsum-authors").text
                
                data.append({
                    'title': title,
                    'authors': authors
                })
            except:
                continue
        
        return data
        
    except Exception as e:
        print(f"Elemanları beklerken hata: {e}")
        return []

# Kullanım örneği
proxy_host = "proxy.example.com"
proxy_port = "8080"
proxy_user = "username"
proxy_pass = "password"

driver = create_proxy_driver(proxy_host, proxy_port, proxy_user, proxy_pass)

try:
    url = "https://pubmed.ncbi.nlm.nih.gov/?term=diabetes"
    results = scrape_with_selenium(url, driver)
    
    for result in results:
        print(f"Başlık: {result['title']}")
        print(f"Yazarlar: {result['authors']}\n")
        
finally:
    driver.quit()

İstek hız kontrolü ve rate limiting aşma

Rate limiting, tıbbi sitelerin parsellemeye karşı uyguladığı ana koruma yöntemlerinden biridir. İstek hızının doğru bir şekilde ayarlanması, yasaklamalardan kaçınmak için kritik öneme sahiptir.

Güvenli hızın belirlenmesi

İlk adım, belirli bir sitenin limitlerini belirlemektir. Bu, istek hızını kademeli olarak artırarak 429 (Too Many Requests) hatası veya yasaklama oluşana kadar yapılabilir. Çoğu tıbbi site için güvenli değerler:

  • PubMed — maksimum 3 istek/saniye (resmi öneri)
  • ClinicalTrials.gov — dakikada 20 istek güvenlidir, 5 dakikada 100'e kadar kabul edilebilir
  • Ticari yayıncılar — bir IP'den saatte 10-15 istek
  • İlaç veri tabanları — dakikada 5-10 istek

Python'da rate limiter uygulaması

import time
from collections import deque

class RateLimiter:
    def __init__(self, max_calls, period):
        """
        max_calls: maksimum çağrı sayısı
        period: saniye cinsinden zaman aralığı
        Örneğin: RateLimiter(3, 1) = saniyede 3 istek
        """
        self.max_calls = max_calls
        self.period = period
        self.calls = deque()
    
    def __call__(self, func):
        """Fonksiyon çağrısını hız sınırlamak için dekoratör"""
        def wrapper(*args, **kwargs):
            now = time.time()
            
            # Dönem dışındaki eski çağrıları kaldır
            while self.calls and self.calls[0] < now - self.period:
                self.calls.popleft()
            
            # Limit aşılmışsa bekle
            if len(self.calls) >= self.max_calls:
                sleep_time = self.period - (now - self.calls[0])
                if sleep_time > 0:
                    print(f"Hız limiti aşıldı, {sleep_time:.2f}s bekliyorum")
                    time.sleep(sleep_time)
                    # Beklemeden sonra temizle
                    self.calls.clear()
            
            # Çağrı zamanını kaydet
            self.calls.append(time.time())
            
            # Fonksiyonu çalıştır
            return func(*args, **kwargs)
        
        return wrapper

# Kullanım örneği
@RateLimiter(max_calls=3, period=1)  # saniyede 3 istek
def fetch_pubmed_page(url):
    response = requests.get(url, headers=headers, proxies=proxies)
    return response

# Artık fonksiyon otomatik olarak hız limitine uyar
for i in range(10):
    result = fetch_pubmed_page(f"https://pubmed.ncbi.nlm.nih.gov/?term=test&page={i}")
    print(f"Sayfa {i} alındı")

Adaptif hız sınırlama

Daha gelişmiş bir yaklaşım, sunucunun yanıtlarına bağlı olarak hızın adaptif olarak değiştirilmesidir. Eğer 429 veya 503 hataları alıyorsak, otomatik olarak hızı düşürmeliyiz:

import time
import random

class AdaptiveRateLimiter:
    def __init__(self, initial_delay=1.0, max_delay=60.0):
        self.current_delay = initial_delay
        self.initial_delay = initial_delay
        self.max_delay = max_delay
        self.success_count = 0
    
    def wait(self):
        """Sonraki isteğin öncesinde bekleme"""
        # Doğallık için rastgelelik ekleyin
        actual_delay = self.current_delay * random.uniform(0.8, 1.2)
        time.sleep(actual_delay)
    
    def on_success(self):
        """Başarılı bir istek alındığında çağrılır"""
        self.success_count += 1
        
        # 10 başarılı isteğin ardından biraz hızlanırız
        if self.success_count >= 10:
            self.current_delay = max(
                self.initial_delay,
                self.current_delay * 0.9
            )
            self.success_count = 0
    
    def on_rate_limit(self):
        """429 veya benzeri hatalar alındığında çağrılır"""
        # Gecikmeyi iki katına çıkarırız, ama maksimuma ulaşmadan
        self.current_delay = min(
            self.current_delay * 2,
            self.max_delay
        )
        self.success_count = 0
        print(f"Hız limiti aşıldı! Gecikmeyi {self.current_delay:.2f}s olarak artırıyorum")
    
    def on_error(self):
        """Diğer hatalar alındığında çağrılır"""
        # Gecikmeyi biraz artırırız
        self.current_delay = min(
            self.current_delay * 1.5,
            self.max_delay
        )
        self.success_count = 0

# Kullanım örneği
limiter = AdaptiveRateLimiter(initial_delay=2.0, max_delay=30.0)

for url in urls_to_scrape:
    limiter.wait()
    
    try:
        response = requests.get(url, proxies=proxies, headers=headers)
        
        if response.status_code == 200:
            limiter.on_success()
            # Verileri işleyin
            
        elif response.status_code == 429:
            limiter.on_rate_limit()
            # Daha sonra tekrar deneyin
            
        else:
            limiter.on_error()
            
    except requests.exceptions.RequestException:
        limiter.on_error()

Tıbbi siteler için doğru başlıklar ve User-Agent

Tıbbi siteler, bot tespiti için HTTP başlıklarını analiz etmektedir. Yanlış veya eksik başlıklar, kaliteli proxy kullanılsa bile yasaklamaların yaygın bir nedenidir.

Zorunlu başlıklar

Her istekte bulunması gereken minimum başlık seti:

headers = {
    # User-Agent — güncel bir tarayıcı zorunludur
    '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 — tarayıcının kabul ettiği içerik türleri
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
    
    # Accept-Language — kullanıcının dili
    'Accept-Language': 'en-US,en;q=0.9',
    
    # Accept-Encoding — sıkıştırma desteği
    'Accept-Encoding': 'gzip, deflate, br',
    
    # Connection — bağlantının sürdürülmesi
    'Connection': 'keep-alive',
    
    # Upgrade-Insecure-Requests — otomatik HTTPS geçişi
    'Upgrade-Insecure-Requests': '1',
    
    # DNT — Do Not Track (isteğe bağlı, ama gerçekçilik katar)
    'DNT': '1',
    
    # Sec-Fetch-* başlıkları (modern tarayıcılar için önemlidir)
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Site': 'none',
    'Sec-Fetch-User': '?1',
    
    # Cache-Control
    'Cache-Control': 'max-age=0'
}

User-Agent rotasyonu

Aynı User-Agent kullanmak şüpheli olabilir. Birkaç güncel tarayıcı arasında rotasyon yapılması önerilmektedir:

import random

USER_AGENTS = [
    # Windows'ta Chrome
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    
    # Mac'te Chrome
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    
    # Windows'ta Firefox
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
    
    # Mac'te Firefox
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0',
    
    # Mac'te Safari
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15',
    
    # Windows'ta Edge
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0'
]

def get_random_headers():
    """Rastgele User-Agent ile başlıkları al"""
    return {
        'User-Agent': random.choice(USER_AGENTS),
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'en-US,en;q=0.9',
        'Accept-Encoding': 'gzip, deflate, br',
        'Connection': 'keep-alive',
        'Upgrade-Insecure-Requests': '1',
        'DNT': '1'
    }

# Kullanım
for url in urls:
    headers = get_random_headers()
    response = requests.get(url, headers=headers, proxies=proxies)

Formlar için Referer ve Origin

Arama formları ile çalışırken veya POST istekleri gönderirken, Referer ve Origin başlıklarını eklemek zorunludur:

# Arama formuna POST isteği için
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.9',
    'Accept-Encoding': 'gzip, deflate, br',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Origin': 'https://example.com',
    'Referer': 'https://example.com/search',
    'Connection': 'keep-alive'
}

# Form verileri ile POST isteği
data = {
    'query': 'diabetes',
    'page': '1'
}

response = requests.post(
    'https://example.com/search',
    headers=headers,
    data=data,
    proxies=proxies
)

Tipik sorunlar ve çözümleri

Tıbbi verileri parselleme sırasında belirli sorunlar ortaya çıkabilir. En yaygın olanları ve çözümlerini inceleyelim.

Sorun: Cloudflare tüm istekleri engelliyor

Belirtiler: "Tarayıcınızı kontrol ediyor" yazılı sayfa veya Cloudflare ile ilgili 403 Forbidden hatası alıyorsunuz.

Çözüm:

  • Veri merkezi yerine konut proxy'leri kullanın — Cloudflare, veri merkezi IP'lerini varsayılan olarak engeller
  • Selenium veya Puppeteer'e geçin — headless tarayıcılar Cloudflare kontrollerinden daha iyi geçer
  • Python için cloudscraper kütüphanesini kullanın — temel Cloudflare korumasını otomatik olarak aşar
  • Çerezleri ve JavaScript'i etkinleştirin — Cloudflare bunların varlığını kontrol eder
  • TLS fingerprinting ekleyin — gerçek bir tarayıcıyı TLS düzeyinde taklit etmek için curl_cffi kullanın

Sorun: 429 Too Many Requests hatası alıyorum

Belirtiler: Birkaç başarılı isteğin ardından sunucu 429 döndürmeye başlıyor.

Çözüm:

  • İstekler arasındaki gecikmeyi artırın — 3-5 saniye ile başlamayı deneyin
  • IP rotasyonunu etkinleştirin — her istek yeni bir IP üzerinden yapılırsa rate limiting kaldırılır
  • 429 yanıtındaki Retry-After başlığını kontrol edin — beklemeniz gereken süreyi belirtir
  • Tekrarlar için üstel gecikme kullanın — 1s, 2s, 4s, 8s vb.

Sorun: Proxy'ler yavaş çalışıyor veya sık sık kopuyor

Belirtiler: Zaman aşımı hataları, sayfaların çok uzun sürede yüklenmesi, bağlantı kopmaları.

Çözüm:

  • İsteklerdeki zaman aşımını 30-60 saniyeye çıkarın — konut proxy'leri daha yavaş olabilir
  • Coğrafi olarak yakın proxy'ler kullanın — Avrupa sitesini parselliyorsanız, Avrupa IP'leri kullanın
  • Proxy sağlayıcısının kalitesini kontrol edin — ucuz proxy'ler genellikle kararsızdır
  • Tekrar mantığı ekleyin — bağlantı hatası durumunda isteği otomatik olarak tekrar edin
  • Bağlantı havuzlaması kullanın — requests.Session() aracılığıyla TCP bağlantılarını yeniden kullanın

Sorun: Site kimlik doğrulama veya abonelik istiyor

Belirtiler: Makalelerin tam metnine erişim kısıtlı, giriş yapılması gerekiyor.

Çözüm:

  • Kurumsal erişim kullanın — birçok üniversite ve hastane aboneliklere sahiptir
  • Açık Erişim versiyonlarının mevcut olup olmadığını kontrol edin — birçok makale, arşivler aracılığıyla ücretsiz olarak erişilebilir
  • Parselleme yerine API kullanın — bazı yayıncılar araştırmacılara API sunmaktadır
  • Sadece meta verileri (başlıklar, yazarlar, özetler) parselleyin — bunlar genellikle ücretsiz olarak erişilebilir

Sorun: JavaScript içeriği yüklenmiyor

Belirtiler: HTML'de gerekli veriler yok, sadece yüklenme dönerleri veya boş konteynerler görünmekte.

Çözüm:

  • Selenium/Puppeteer'e geçin — bunlar JavaScript'i çalıştırır
  • API uç noktasını bulun — tarayıcıda DevTools'u açın, Network sekmesi, ve verilerle XHR isteklerini bulun
  • requests-html kullanın — JavaScript içeriğini yüklemek için bir kütüphane
```