Zurück zum Blog

Proxys für das Scraping medizinischer Daten: So sammeln Sie Informationen ohne Sperren

Erfahren Sie, wie Sie medizinische Daten aus klinischen Studien, Arzneimitteldatenbanken und medizinischen Zeitschriften sicher extrahieren, ohne gesperrt zu werden.

📅9. März 2026
```html

Das Scraping medizinischer Daten ist eine Aufgabe, die einen besonderen Ansatz bei der Auswahl von Proxys erfordert. Medizinische Portale, Datenbanken klinischer Studien und pharmazeutische Ressourcen verwenden fortschrittliche Schutzsysteme gegen automatisierte Datensammlungen. In diesem Artikel werden wir erörtern, wie man Proxys richtig konfiguriert, um medizinische Informationen sicher zu scrapen, Sperren zu vermeiden und die benötigten Daten effizient zu sammeln.

Warum medizinische Websites Scraping blockieren

Medizinische Portale und Datenbanken sind besonders empfindlich gegenüber automatisierten Informationssammlungen aus mehreren Gründen. Erstens arbeiten viele von ihnen auf kommerzieller Basis und verkaufen den Zugang zu Daten über kostenpflichtige Abonnements. Automatisiertes Scraping kann die Nutzungsbedingungen und Lizenzvereinbarungen verletzen.

Zweitens enthalten medizinische Daten häufig vertrauliche Informationen, die durch Gesetze geschützt sind (HIPAA in den USA, DSGVO in Europa). Die Eigentümer der Ressourcen sind verpflichtet, den Zugang zu solchen Daten zu kontrollieren und deren unbefugte Verbreitung zu verhindern. Daher verwenden sie fortschrittliche Schutzsysteme:

  • Rate Limiting — Begrenzung der Anzahl der Anfragen von einer IP-Adresse pro Zeiteinheit (normalerweise 10-50 Anfragen pro Minute)
  • Fingerprinting — Analyse der Merkmale des Browsers, der HTTP-Header, der Reihenfolge des Ladens von Ressourcen
  • CAPTCHA — Systeme wie reCAPTCHA v3, die bei verdächtiger Aktivität aktiviert werden
  • IP-Sperren — vorübergehende oder permanente Sperrung von IP-Adressen von Rechenzentren
  • Cloudflare und ähnliche Dienste — Schutz vor Bots auf CDN-Ebene

Der dritte Grund ist die Belastung der Server. Medizinische Datenbanken enthalten oft Millionen von Datensätzen, und massives Scraping kann eine erhebliche Belastung für die Infrastruktur darstellen. Daher kämpfen Administratoren aktiv gegen automatisierte Datensammlungen, indem sie Verhaltensmuster verfolgen, die für Bots charakteristisch sind: gleiche Intervalle zwischen Anfragen, lineares Durchblättern von Seiten, Fehlen von JavaScript und Cookies.

Wichtig: Vor dem Scraping medizinischer Daten sollten Sie unbedingt die Nutzungsbedingungen der Website und die geltenden Gesetze studieren. Einige Daten können urheberrechtlich geschützt sein oder persönliche Informationen von Patienten enthalten. Stellen Sie sicher, dass Ihre Aktivitäten legal sind und keine Rechte Dritter verletzen.

Welchen Proxy-Typ für medizinische Daten wählen

Die Wahl des Proxy-Typs ist entscheidend für das erfolgreiche Scraping medizinischer Daten. Verschiedene Quellen erfordern unterschiedliche Ansätze. Lassen Sie uns die wichtigsten Proxy-Typen und ihre Anwendbarkeit betrachten:

Proxy-Typ Vorteile Nachteile Wann verwenden
Rechenzentrums-Proxys Hohe Geschwindigkeit (100+ Mbit/s), niedrige Kosten, stabile Verbindung Leicht zu erkennen, oft auf geschützten Websites blockiert Öffentliche Datenbanken ohne strengen Schutz (PubMed, WHO)
Residential Proxys Echte IPs von Heimnutzern, geringes Risiko einer Sperrung, umgehen Cloudflare Höhere Kosten, variable Geschwindigkeit, können instabil sein Geschützte kommerzielle Datenbanken (Elsevier, Springer), Websites mit Cloudflare
Mobile Proxys Maximales Vertrauen (IPs von Mobilfunkanbietern), praktisch nicht blockiert Die teuersten, begrenzte Geografie, können langsamer sein Besonders geschützte Ressourcen, wenn Residential Proxys nicht helfen
ISP Proxys Rechenzentrums-Geschwindigkeit + Vertrauen von Residential Proxys, statische IPs Durchschnittliche Kosten, begrenzte Verfügbarkeit Langfristiges Scraping von einer IP, wenn Stabilität erforderlich ist

Für die meisten Scraping-Aufgaben medizinischer Daten wird empfohlen, Residential Proxys zu verwenden. Sie bieten das optimale Gleichgewicht zwischen Kosten und Effizienz. Rechenzentrums-Proxys eignen sich nur für offene Quellen ohne Schutz. Mobile Proxys sollten nur in extremen Fällen verwendet werden, wenn andere Typen nicht funktionieren.

Empfehlungen zur Auswahl für spezifische Quellen

  • PubMed, PubMed Central — Rechenzentrums-Proxys sind ausreichend, aber mit einer Geschwindigkeitsbegrenzung von 3 Anfragen pro Sekunde
  • ClinicalTrials.gov — Rechenzentrums-Proxys, es gibt eine offizielle API
  • Elsevier, Springer, Wiley — Residential Proxys sind erforderlich, verwenden fortschrittliches Fingerprinting
  • DrugBank, RxList — Residential Proxys, aktive Schutzmaßnahmen gegen Scraping
  • FDA, EMA-Datenbanken — Rechenzentrums-Proxys sind geeignet, aber mit langsamer Scraping-Geschwindigkeit

Hauptquellen medizinischer Daten und deren Schutz

Medizinische Daten sind über viele Quellen verteilt, von denen jede ihre eigenen Besonderheiten und Schutzstufen hat. Das Verständnis dieser Besonderheiten hilft, die Scraping-Strategie richtig einzustellen.

Öffentliche staatliche Datenbanken

PubMed/PubMed Central — die größte Datenbank medizinischer Publikationen, enthält über 35 Millionen Datensätze. Die National Library of Medicine (NLM) der USA bietet eine offizielle API E-utilities, die der bevorzugte Zugang zu den Daten ist. Direktes Scraping der Weboberfläche ist möglich, aber auf 3 Anfragen pro Sekunde von einer IP-Adresse begrenzt. Eine Überschreitung des Limits führt zu einer vorübergehenden Sperrung von 24 Stunden.

ClinicalTrials.gov — eine Datenbank klinischer Studien, enthält Informationen zu über 400.000 Studien in 220 Ländern. Bietet auch eine API für den programmgesteuerten Zugriff. Die Weboberfläche ist durch Rate Limiting geschützt — maximal 100 Anfragen in 5 Minuten von einer IP-Adresse. Es wird ein grundlegender Schutz gegen Bots verwendet, aber ohne Cloudflare.

FDA Drugs Database — eine Datenbank genehmigter Arzneimittel der FDA. Offener Zugang über die Weboberfläche und die API openFDA. Einschränkungen: 240 Anfragen pro Minute für anonyme Benutzer, 1000 Anfragen pro Minute mit API-Schlüssel. Sperrungen sind selten, aber bei aggressivem Scraping möglich.

Kommerzielle wissenschaftliche Verlage

Elsevier (ScienceDirect) — einer der größten Verlage wissenschaftlicher Literatur. Verwendet mehrstufigen Schutz: Cloudflare, Fingerprinting des Browsers, Analyse des Nutzerverhaltens. Erkennt Muster automatisierter Downloads: sequenzieller Zugriff auf Artikel, Fehlen von JavaScript, untypische User-Agent. Bei Entdeckung des Scraping werden IPs auf Kontoebene blockiert und die gesamte Institution kann gesperrt werden. Die Verwendung von Residential Proxys mit Rotation und vollständiger Browseremulation ist unbedingt erforderlich.

Springer Nature — ähnliche Schutzmaßnahmen, zusätzlich wird die Scrollgeschwindigkeit der Seiten und die Mausbewegungen überwacht. Verwendet Machine Learning zur Erkennung von Bots. Es wird empfohlen, nicht mehr als 10-15 Artikel pro Stunde von einer IP-Adresse zu scrapen, mit randomisierten Verzögerungen zwischen den Anfragen.

Wiley Online Library — weniger aggressiver Schutz, erfordert jedoch dennoch die Verwendung von Proxys. Erlaubt etwa 50 Anfragen pro Stunde von einer IP-Adresse ohne Sperrung. Verwendet Session-Cookies zur Verfolgung der Aktivität.

Pharmazeutische Datenbanken

DrugBank — umfassende Datenbank von Arzneimitteln. Die kostenlose Version ist auf die Weboberfläche beschränkt, die kommerzielle Version bietet API und Datenexporte. Die Webversion ist durch Cloudflare und Rate Limiting geschützt — maximal 20 Anfragen pro Minute. Erkennt Automatisierung durch das Fehlen von Cookies und JavaScript.

RxList, Drugs.com — beliebte Arzneimittelverzeichnisse für Verbraucher. Verwenden Cloudflare und kämpfen aktiv gegen Scraping. Blockieren IPs von Rechenzentren praktisch sofort. Es werden Residential Proxys und eine langsame Scraping-Geschwindigkeit (5-10 Seiten pro Minute) benötigt.

IP-Rotation für langfristiges Scraping einrichten

Die richtige Rotation von IP-Adressen ist ein Schlüsselfaktor für erfolgreiches Scraping medizinischer Daten. Es gibt zwei Hauptansätze: Rotation auf Anfrageebene und zeitbasierte Rotation.

Rotation auf Anfrageebene

Bei diesem Ansatz wird jede Anfrage über eine neue IP-Adresse gesendet. Dies minimiert das Risiko einer Sperrung, kann jedoch Probleme mit Websites verursachen, die Sitzungen über Cookies verfolgen. Geeignet für das Scraping von Listen und Katalogen, bei denen kein Sitzungsstatus aufrechterhalten werden muss.

Die meisten Anbieter von Residential Proxys bieten eine automatische Rotation über einen speziellen Endpunkt an. Zum Beispiel, wenn Sie einen rotating proxy endpoint verwenden, erhält jede neue TCP-Verbindung eine neue IP. Dies funktioniert automatisch mit Bibliotheken wie requests in Python, da standardmäßig für jede Anfrage eine neue Verbindung hergestellt wird.

Zeitbasierte Rotation (Sticky Sessions)

Sticky Sessions ermöglichen die Verwendung einer IP-Adresse für einen bestimmten Zeitraum (normalerweise 5-30 Minuten), nach dem eine automatische Änderung erfolgt. Dies ist nützlich für Websites, die eine Authentifizierung erfordern oder den Sitzungsstatus über Cookies verfolgen. Sie können mehrere Seiten von einer IP-Adresse scrapen und dabei das Verhalten eines echten Benutzers imitieren, bevor die IP automatisch gewechselt wird.

Für medizinische Websites wird empfohlen, Sticky Sessions mit einer Dauer von 10-15 Minuten zu verwenden. In dieser Zeit können 10-20 Seiten gescraped werden (je nach Verzögerungen), danach wird die IP gewechselt und Sie beginnen eine "neue Sitzung". Dies sieht natürlich aus und verringert das Risiko einer Erkennung.

Größe des IP-Pools

Für langfristiges Scraping ist die Größe des Pools verfügbarer IP-Adressen wichtig. Wenn Sie dieselbe Gruppe von 100 IPs über eine Woche hinweg verwenden, kann die Website ein Muster bemerken und alle diese Adressen blockieren. Residential Proxys bieten normalerweise Zugang zu Millionen von IPs, was die Wiederverwendung derselben Adresse praktisch ausschließt.

Bei der Verwendung von Rechenzentrums-Proxys wird empfohlen, einen Pool von mindestens 500-1000 IPs für das Scraping eines mittleren Volumens (10.000-50.000 Seiten pro Monat) zu haben. Für großangelegtes Scraping (Hunderte von Tausenden von Seiten) ist es besser, Residential Proxys mit ihren riesigen IP-Pools zu verwenden.

Rotationstipps für verschiedene Quellen:

  • PubMed — Rotation ist nicht erforderlich, 1 IP mit Einhaltung des Rate Limits reicht aus
  • Kommerzielle Verlage — Sticky Sessions von 10-15 Minuten, neue IP alle 15-20 Seiten
  • Pharmazeutische Datenbanken — Rotation bei jeder Anfrage oder Sticky Sessions von 5 Minuten
  • Websites mit Cloudflare — Sticky Sessions sind erforderlich, Rotation auf Anfrageebene funktioniert nicht

Python-Codebeispiele für das Scraping mit Proxys

Lassen Sie uns praktische Beispiele für die Konfiguration von Proxys für das Scraping medizinischer Daten unter Verwendung beliebter Python-Bibliotheken betrachten. Wir beginnen mit einem grundlegenden Beispiel und werden es schrittweise komplizierter gestalten.

Grundkonfiguration mit der Bibliothek requests

import requests
from time import sleep
import random

# Proxy-Konfiguration (ersetzen Sie durch Ihre Daten)
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}'
}

# Header zur Imitation eines echten Browsers
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'
}

# Beispielanfrage an PubMed
url = "https://pubmed.ncbi.nlm.nih.gov/?term=diabetes"

try:
    response = requests.get(url, proxies=proxies, headers=headers, timeout=30)
    print(f"Statuscode: {response.status_code}")
    print(f"Inhaltslänge: {len(response.content)}")
    
    # Verzögerung zwischen Anfragen hinzufügen (unbedingt für PubMed)
    sleep(random.uniform(1.0, 3.0))
    
except requests.exceptions.RequestException as e:
    print(f"Fehler: {e}")

Fortgeschrittene Konfiguration mit Rotation und Retry-Logik

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: Liste von Dictionaries mit Proxys
        [{'http': 'http://user:pass@host:port', 'https': '...'}, ...]
        """
        self.proxy_list = proxy_list
        self.current_index = 0
    
    def get_next_proxy(self):
        """Nächsten Proxy aus der Liste abrufen"""
        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():
    """Eine Sitzung mit automatischen Wiederholungen bei Fehlern erstellen"""
    session = requests.Session()
    
    # Automatische Wiederholungen einrichten
    retry_strategy = Retry(
        total=3,  # maximal 3 Versuche
        backoff_factor=1,  # Verzögerung zwischen den Versuchen: 1, 2, 4 Sekunden
        status_forcelist=[429, 500, 502, 503, 504],  # Codes für Wiederholungen
        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):
    """Scraping einer Liste von URLs mit Proxy-Rotation"""
    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:
        # Für jede Anfrage neuen Proxy abrufen
        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': 'success',
                    'content_length': len(response.content)
                })
                print(f"✓ Erfolg: {url}")
            else:
                results.append({
                    'url': url,
                    'status': 'failed',
                    'error': f"Statuscode: {response.status_code}"
                })
                print(f"✗ Fehler: {url} (Status: {response.status_code})")
        
        except requests.exceptions.RequestException as e:
            results.append({
                'url': url,
                'status': 'error',
                'error': str(e)
            })
            print(f"✗ Fehler: {url} ({e})")
        
        # Zufällige Verzögerung zwischen Anfragen (wichtig!)
        sleep(random.uniform(2.0, 5.0))
    
    return results

# Beispielverwendung
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)

Verwendung von Selenium für Websites mit JavaScript

Viele moderne medizinische Websites verwenden JavaScript zum Laden von Inhalten. In solchen Fällen ist ein Headless-Browser erforderlich:

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):
    """Erstellen Sie den Chrome WebDriver mit Proxy"""
    
    chrome_options = Options()
    
    # Headless-Modus (ohne GUI)
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('--disable-dev-shm-usage')
    
    # Proxy-Konfiguration
    chrome_options.add_argument(f'--proxy-server=http://{proxy_host}:{proxy_port}')
    
    # Automatisierung deaktivieren (wichtig zur Umgehung der Erkennung)
    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)
    
    # Für Proxys mit Authentifizierung müssen Sie eine Erweiterung verwenden
    # oder über capabilities konfigurieren (komplizierterer Ansatz)
    
    return driver

def scrape_with_selenium(url, driver):
    """Scraping einer Seite mit Warten auf das Laden von JavaScript"""
    
    driver.get(url)
    
    # Warten auf das Laden des Elements (z.B. Suchergebnisse)
    try:
        wait = WebDriverWait(driver, 10)
        results = wait.until(
            EC.presence_of_element_located((By.CLASS_NAME, "results-article"))
        )
        
        # Daten extrahieren
        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"Fehler beim Warten auf Elemente: {e}")
        return []

# Beispielverwendung
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"Titel: {result['title']}")
        print(f"Autoren: {result['authors']}\n")
        
finally:
    driver.quit()

Kontrolle der Anfragespeed und Umgehung von Rate Limiting

Rate Limiting ist eines der Hauptschutzmittel medizinischer Websites gegen Scraping. Die richtige Einstellung der Anfragespeed ist entscheidend für langfristiges Scraping ohne Sperrungen.

Bestimmung einer sicheren Geschwindigkeit

Der erste Schritt besteht darin, die Limits der jeweiligen Website zu bestimmen. Dies kann experimentell erfolgen, indem die Anfragespeed schrittweise erhöht wird, bis Fehler 429 (Too Many Requests) oder Sperrungen auftreten. Für die meisten medizinischen Websites sind sichere Werte:

  • PubMed — maximal 3 Anfragen pro Sekunde (offizielle Empfehlung)
  • ClinicalTrials.gov — 20 Anfragen pro Minute sind sicher, bis zu 100 in 5 Minuten sind zulässig
  • Kommerzielle Verlage — 10-15 Anfragen pro Stunde von einer IP
  • Pharmazeutische Datenbanken — 5-10 Anfragen pro Minute

Implementierung eines Rate Limiters in Python

import time
from collections import deque

class RateLimiter:
    def __init__(self, max_calls, period):
        """
        max_calls: maximales Anzahl an Aufrufen
        period: Zeitraum in Sekunden
        Zum Beispiel: RateLimiter(3, 1) = 3 Anfragen pro Sekunde
        """
        self.max_calls = max_calls
        self.period = period
        self.calls = deque()
    
    def __call__(self, func):
        """Dekorator zur Begrenzung der Geschwindigkeit der Funktionsaufrufe"""
        def wrapper(*args, **kwargs):
            now = time.time()
            
            # Alte Aufrufe außerhalb des Zeitraums entfernen
            while self.calls and self.calls[0] < now - self.period:
                self.calls.popleft()
            
            # Wenn das Limit erreicht ist, warten
            if len(self.calls) >= self.max_calls:
                sleep_time = self.period - (now - self.calls[0])
                if sleep_time > 0:
                    print(f"Rate Limit erreicht, warte {sleep_time:.2f}s")
                    time.sleep(sleep_time)
                    # Nach dem Warten leeren
                    self.calls.clear()
            
            # Zeit des Aufrufs aufzeichnen
            self.calls.append(time.time())
            
            # Funktion ausführen
            return func(*args, **kwargs)
        
        return wrapper

# Beispielverwendung
@RateLimiter(max_calls=3, period=1)  # 3 Anfragen pro Sekunde
def fetch_pubmed_page(url):
    response = requests.get(url, headers=headers, proxies=proxies)
    return response

# Jetzt hält die Funktion automatisch das Rate Limit ein
for i in range(10):
    result = fetch_pubmed_page(f"https://pubmed.ncbi.nlm.nih.gov/?term=test&page={i}")
    print(f"Seite {i} abgerufen")

Adaptives Rate Limiting

Ein fortgeschrittenerer Ansatz ist die adaptive Anpassung der Geschwindigkeit basierend auf den Antworten des Servers. Wenn wir Fehler 429 oder 503 erhalten, reduzieren wir automatisch die Geschwindigkeit:

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):
        """Warten vor der nächsten Anfrage"""
        # Fügen Sie Zufälligkeit für Natürlichkeit hinzu
        actual_delay = self.current_delay * random.uniform(0.8, 1.2)
        time.sleep(actual_delay)
    
    def on_success(self):
        """Wird bei erfolgreicher Anfrage aufgerufen"""
        self.success_count += 1
        
        # Nach 10 erfolgreichen Anfragen etwas schneller werden
        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):
        """Wird bei Erhalt von 429 oder ähnlichen Fehlern aufgerufen"""
        # Verdoppeln Sie die Verzögerung, aber nicht mehr als das Maximum
        self.current_delay = min(
            self.current_delay * 2,
            self.max_delay
        )
        self.success_count = 0
        print(f"Rate Limit erreicht! Verzögerung auf {self.current_delay:.2f}s erhöhen")
    
    def on_error(self):
        """Wird bei anderen Fehlern aufgerufen"""
        # Verzögerung etwas erhöhen
        self.current_delay = min(
            self.current_delay * 1.5,
            self.max_delay
        )
        self.success_count = 0

# Beispielverwendung
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()
            # Datenverarbeitung
            
        elif response.status_code == 429:
            limiter.on_rate_limit()
            # Später wiederholen
            
        else:
            limiter.on_error()
            
    except requests.exceptions.RequestException:
        limiter.on_error()

Die richtigen Header und User-Agent für medizinische Websites

Medizinische Websites analysieren die HTTP-Header zur Erkennung von Bots. Falsche oder fehlende Header sind häufige Ursachen für Sperrungen, selbst bei der Verwendung hochwertiger Proxys.

Obligatorische Header

Das minimale Set an Headern, das in jeder Anfrage vorhanden sein sollte:

headers = {
    # User-Agent — unbedingt einen aktuellen Browser
    '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 — die von dem Browser akzeptierten Inhaltstypen
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
    
    # Accept-Language — die Sprache des Benutzers
    'Accept-Language': 'en-US,en;q=0.9',
    
    # Accept-Encoding — Unterstützung für Kompression
    'Accept-Encoding': 'gzip, deflate, br',
    
    # Connection — Verbindung aufrechterhalten
    'Connection': 'keep-alive',
    
    # Upgrade-Insecure-Requests — automatischer Wechsel zu HTTPS
    'Upgrade-Insecure-Requests': '1',
    
    # DNT — Do Not Track (optional, aber erhöht die Realitätsnähe)
    'DNT': '1',
    
    # Sec-Fetch-* Header (wichtig für moderne Browser)
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Site': 'none',
    'Sec-Fetch-User': '?1',
    
    # Cache-Control
    'Cache-Control': 'max-age=0'
}

Rotation des User-Agent

Die Verwendung desselben User-Agent kann verdächtig sein. Es wird empfohlen, zwischen mehreren aktuellen Browsern zu rotieren:

import random

USER_AGENTS = [
    # Chrome unter Windows
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    
    # Chrome unter Mac
    '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',
    
    # Firefox unter Windows
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
    
    # Firefox unter Mac
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0',
    
    # Safari unter Mac
    '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',
    
    # Edge unter Windows
    '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():
    """Erhalten Sie Header mit zufälligem User-Agent"""
    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'
    }

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

Referer und Origin für Formulare

Bei der Arbeit mit Suchformularen oder beim Senden von POST-Anfragen sollten Sie unbedingt die Header Referer und Origin hinzufügen:

# Für POST-Anfragen an das Suchformular
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'
}

# POST-Anfrage mit Formulardaten
data = {
    'query': 'diabetes',
    'page': '1'
}

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

Typische Probleme und deren Lösungen

Beim Scraping medizinischer Daten treten spezifische Probleme auf. Lassen Sie uns die häufigsten betrachten und wie man sie löst.

Problem: Cloudflare blockiert alle Anfragen

Symptome: Sie erhalten eine Seite mit dem Text "Überprüfung Ihres Browsers" oder einen Fehler 403 Forbidden mit Erwähnung von Cloudflare.

Lösung:

  • Verwenden Sie Residential Proxys anstelle von Rechenzentrums-Proxys — Cloudflare blockiert standardmäßig IPs von Rechenzentren
  • Wechseln Sie zu Selenium oder Puppeteer — Headless-Browser durchlaufen Cloudflare-Überprüfungen besser
  • Verwenden Sie die Bibliothek cloudscraper für Python — sie umgeht automatisch den grundlegenden Schutz von Cloudflare
  • Aktivieren Sie Cookies und JavaScript — Cloudflare überprüft deren Vorhandensein
  • Fügen Sie TLS-Fingerprinting hinzu — verwenden Sie curl_cffi, um einen echten Browser auf TLS-Ebene zu imitieren

Problem: Ich erhalte den Fehler 429 Too Many Requests

Symptome: Nach mehreren erfolgreichen Anfragen beginnt der Server, 429 zurückzugeben.

Lösung:

  • Erhöhen Sie die Verzögerung zwischen den Anfragen — versuchen Sie, mit 3-5 Sekunden zu beginnen
  • Aktivieren Sie die IP-Rotation — jede Anfrage über eine neue IP hebt das Rate Limiting auf
  • Überprüfen Sie den Header Retry-After in der Antwort 429 — er gibt an, wie viele Sekunden gewartet werden muss
  • Verwenden Sie exponentielle Verzögerung bei Wiederholungen — 1s, 2s, 4s, 8s usw.

Problem: Proxys arbeiten langsam oder fallen häufig aus

Symptome: Timeout-Fehler, sehr lange Ladezeiten, Verbindungsabbrüche.

Lösung:

  • Erhöhen Sie den Timeout in den Anfragen auf 30-60 Sekunden — Residential Proxys können langsamer sein
  • Verwenden Sie geografisch nahe Proxys — wenn Sie eine europäische Website scrapen, verwenden Sie europäische IPs
  • Überprüfen Sie die Qualität des Proxy-Anbieters — billige Proxys sind oft instabil
  • Fügen Sie eine Retry-Logik hinzu — wiederholen Sie die Anfrage automatisch bei Verbindungsfehlern
  • Verwenden Sie Connection Pooling — wiederverwenden Sie TCP-Verbindungen über requests.Session()

Problem: Die Website erfordert Authentifizierung oder ein Abonnement

Symptome: Der Zugang zu den Volltexten der Artikel ist eingeschränkt, eine Anmeldung ist erforderlich.

Lösung:

  • Verwenden Sie institutionellen Zugang — viele Universitäten und Krankenhäuser haben Abonnements
  • Überprüfen Sie, ob Open Access-Versionen vorhanden sind — viele Artikel sind kostenlos über Repositories verfügbar
  • Verwenden Sie APIs anstelle von Scraping — einige Verlage bieten APIs für Forscher an
  • Scrapen Sie nur Metadaten (Titel, Autoren, Abstracts) — diese sind normalerweise kostenlos verfügbar

Problem: JavaScript-Inhalte werden nicht geladen

Symptome: Im HTML sind die benötigten Daten nicht vorhanden, es sind nur Lade-Spinners oder leere Container sichtbar.

Lösung:

  • Wechseln Sie zu Selenium/Puppeteer — sie führen JavaScript aus
  • Finden Sie den API-Endpunkt — öffnen Sie die DevTools im Browser, Tab Netzwerk, und suchen Sie nach XHR-Anfragen mit Daten
  • Verwenden Sie requests-html — eine Bibliothek mit...
```