Cas d'Usage

Collecte de données de santé derrière les murs CAPTCHA

Les portails de données de santé (annuaires de prestataires, bases de données sur les prix des médicaments et registres d'essais cliniques) utilisent des CAPTCHA pour empêcher la collecte automatisée de données. Les chercheurs et les plateformes de technologies de la santé ont besoin de ces données à des fins d’analyse, de conformité et de prise de décision éclairée.


Où apparaissent les CAPTCHA

Source Type de CAPTCHA Données Cas d'utilisation
Annuaires de fournisseurs (NPI) Image CAPTCHA Recherche Doctor/facility Adéquation du réseau
Portails de tarification des médicaments reCAPTCHA v2 Prix des médicaments Transparence des prix
Registres d'essais cliniques reCAPTCHA v2 Données d'essai, résultats Analyse de la recherche
Formulaires d'assurance reCAPTCHA v2 Listes de couverture des médicaments Comparaison du formulaire
Commissions des licences d'État Image CAPTCHA Vérification de licence Vérifications des informations d'identification
Évaluations de la qualité des hôpitaux Cloudflare Turnstile Indicateurs de qualité Analyse des performances

Scraper d'annuaire de fournisseurs

import requests
import time
import re
import base64
from bs4 import BeautifulSoup
import csv

CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"


def solve_recaptcha(sitekey, pageurl):
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY, "method": "userrecaptcha",
        "googlekey": sitekey, "pageurl": pageurl, "json": 1,
    })
    task_id = resp.json()["request"]
    for _ in range(60):
        time.sleep(5)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        data = result.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]
    raise TimeoutError("Timeout")


def solve_image_captcha(image_bytes):
    img_b64 = base64.b64encode(image_bytes).decode()
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY, "method": "base64",
        "body": img_b64, "json": 1,
    })
    task_id = resp.json()["request"]
    for _ in range(20):
        time.sleep(3)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        data = result.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]
    raise TimeoutError("Timeout")


class HealthcareDataCollector:
    def __init__(self, proxy=None):
        self.session = requests.Session()
        if proxy:
            self.session.proxies = {"http": proxy, "https": proxy}
        self.session.headers.update({
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
        })

    def search_providers(self, portal_url, specialty, location, sitekey=None):
        """Search provider directory with CAPTCHA handling."""
        resp = self.session.get(portal_url, timeout=30)

        data = {"specialty": specialty, "location": location}

        # Handle CAPTCHA
        if sitekey:
            token = solve_recaptcha(sitekey, portal_url)
            data["g-recaptcha-response"] = token
        else:
            captcha_img = re.search(r'src="(/captcha[^"]+)"', resp.text)
            if captcha_img:
                img_url = portal_url.rstrip("/") + captcha_img.group(1)
                img = self.session.get(img_url)
                data["captcha"] = solve_image_captcha(img.content)

        resp = self.session.post(portal_url, data=data)
        return self._parse_providers(resp.text)

    def lookup_drug_prices(self, pricing_url, drug_name, zip_code, sitekey):
        """Look up drug prices with CAPTCHA solving."""
        # Load search page
        self.session.get(pricing_url)

        # Solve CAPTCHA
        token = solve_recaptcha(sitekey, pricing_url)

        resp = self.session.post(pricing_url, data={
            "drug": drug_name,
            "zip": zip_code,
            "g-recaptcha-response": token,
        })

        if resp.status_code == 200:
            return self._parse_prices(resp.text)
        return []

    def batch_provider_lookup(self, portal_url, specialties, locations, output_file):
        """Batch search across specialties and locations."""
        all_providers = []

        for specialty in specialties:
            for location in locations:
                try:
                    providers = self.search_providers(
                        portal_url, specialty, location,
                    )
                    for p in providers:
                        p["specialty_search"] = specialty
                        p["location_search"] = location
                    all_providers.extend(providers)
                    print(f"{specialty} / {location}: {len(providers)} providers")
                    time.sleep(5)
                except Exception as e:
                    print(f"Error: {specialty} / {location}: {e}")

        # Export
        if all_providers:
            keys = all_providers[0].keys()
            with open(output_file, "w", newline="", encoding="utf-8") as f:
                writer = csv.DictWriter(f, fieldnames=keys)
                writer.writeheader()
                writer.writerows(all_providers)

        return all_providers

    def _parse_providers(self, html):
        soup = BeautifulSoup(html, "html.parser")
        providers = []
        for card in soup.select(".provider-card, .doctor-result, tr.provider"):
            providers.append({
                "name": self._text(card, ".name, .provider-name"),
                "specialty": self._text(card, ".specialty"),
                "address": self._text(card, ".address"),
                "phone": self._text(card, ".phone"),
                "accepting": self._text(card, ".accepting-patients"),
            })
        return providers

    def _parse_prices(self, html):
        soup = BeautifulSoup(html, "html.parser")
        prices = []
        for row in soup.select(".pharmacy-row, .price-result"):
            prices.append({
                "pharmacy": self._text(row, ".pharmacy-name"),
                "price": self._text(row, ".price, .drug-price"),
                "quantity": self._text(row, ".quantity"),
            })
        return prices

    def _text(self, el, selector):
        found = el.select_one(selector)
        return found.get_text(strip=True) if found else ""


# Usage
collector = HealthcareDataCollector(
    proxy="http://user:pass@residential.proxy.com:5000"
)

# Provider search
providers = collector.search_providers(
    portal_url="https://provider-directory.example.com/search",
    specialty="Cardiology",
    location="New York, NY",
)

# Drug pricing
prices = collector.lookup_drug_prices(
    pricing_url="https://drug-prices.example.com/compare",
    drug_name="atorvastatin",
    zip_code="10001",
    sitekey="6Lc_xxxxxxx",
)

Collecte de données d'essais cliniques

def collect_clinical_trials(search_url, condition, sitekey):
    """Collect clinical trial data for a medical condition."""
    collector = HealthcareDataCollector(
        proxy="http://user:pass@residential.proxy.com:5000"
    )

    token = solve_recaptcha(sitekey, search_url)
    resp = collector.session.post(search_url, data={
        "condition": condition,
        "status": "recruiting",
        "g-recaptcha-response": token,
    })

    if resp.status_code != 200:
        return []

    soup = BeautifulSoup(resp.text, "html.parser")
    trials = []
    for item in soup.select(".trial-item, .study-result"):
        trials.append({
            "title": collector._text(item, ".title, h3"),
            "status": collector._text(item, ".status"),
            "sponsor": collector._text(item, ".sponsor"),
            "phase": collector._text(item, ".phase"),
            "enrollment": collector._text(item, ".enrollment"),
            "location": collector._text(item, ".location"),
        })

    return trials

Considérations sur la confidentialité des données

Type de données Sensibilité Recommandation
Annuaires de fournisseurs Faible (information publique) Généralement sûr à collecter
Prix des médicaments Faible (tarif public) Autorisé pour des raisons de transparence
Métadonnées des essais cliniques Faible (registres publics) Utilisation appropriée pour la recherche
Commentaires des patients Moyen Anonymiser avant analyse
Détails du régime d'assurance Faible (tarifs publiés) Autorisé pour comparaison

Important : N'essayez jamais de collecter des informations de santé protégées (PHI). Concentrez-vous uniquement sur les données accessibles au public et non spécifiques au patient.


Dépannage

Problème Parce que Corriger
Image CAPTCHA illisible Image de mauvaise qualité Réessayer : nouvelle image générée
La recherche de fournisseur renvoie un résultat vide CAPTCHA a bloqué la recherche Résolvez CAPTCHA avant de soumettre
Le prix des médicaments varie selon l'emplacement Tarification géo-basée Faire correspondre l'emplacement du proxy au code postal
La session expire sur plusieurs pages Expiration du délai du portail Effectuez rapidement des recherches
Tarif limité sur les recherches par lots Trop de demandes Ajouter des délais de 5 à 10 secondes

FAQ

La collecte de données sur les tarifs des soins de santé est-elle autorisée ?

La transparence des prix des médicaments est encouragée par la réglementation (CMS Price Transparency Rule). Les données de l’annuaire des fournisseurs publics sont généralement accessibles.

Puis-je comparer les prix des médicaments dans les pharmacies ?

Oui. Des services comme GoodRx le font à grande échelle. CaptchaAI gère les CAPTCHA que les portails de tarification utilisent pour limiter l'accès automatisé.

Comment puis-je gérer la loi HIPAA lors du scraping des sites de soins de santé ?

HIPAA s'applique aux informations de santé protégées (PHI). Les données publiques telles que les répertoires de prestataires, les prix des médicaments et les registres d’essais cliniques ne constituent pas des PHI. Ne supprimez jamais les dossiers individuels des patients.


Guides connexes

  • Automatisation du portail gouvernemental
  • Grattage de la recherche universitaire
  • Rotation des procurations résidentielles

Les commentaires sont désactivés pour cet article.