Cas d'Usage

Récupération de données financières avec la gestion des CAPTCHA

Les plateformes financières telles que les filtres d'actions, SEC EDGAR et les plateformes de négociation protègent les données avec des CAPTCHA pour empêcher l'extraction automatisée. CaptchaAI gère ces défis par programmation afin que vous puissiez collecter des données de marché à grande échelle.


Où apparaissent les CAPTCHA dans la finance

Source Type de CAPTCHA Déclencheur Valeur des données
SEC EDGAR reCAPTCHA v2 Demandes à volume élevé Dépôts de l'entreprise
Yahoo Finance reCAPTCHA v2 Détection de grattage Cotations boursières, historique
Bloomberg Cloudflare Turnstile Tous les accès automatisés Données de marché
Finviz reCAPTCHA v2 Accès au filtre d'actions Résultats du dépistage
TradingView Cloudflare Challenge Limitation du débit Graphiques, indicateurs
Étoile du matin reCAPTCHA v3 Pages d'exportation de données Analyse des fonds

Grattage de tamis de stock

import requests
import time
from bs4 import BeautifulSoup
import re

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


def solve_captcha(method, sitekey, pageurl, **kwargs):
    data = {
        "key": CAPTCHAAI_KEY,
        "method": method,
        "googlekey": sitekey,
        "pageurl": pageurl,
        "json": 1,
    }
    data.update(kwargs)

    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data=data)
    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,
        })
        r = result.json()
        if r["request"] != "CAPCHA_NOT_READY":
            return r["request"]

    raise TimeoutError("Solve timeout")


class FinancialScraper:
    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",
            "Accept-Language": "en-US,en;q=0.9",
        })

    def scrape_screener(self, url):
        """Scrape stock screener, handling CAPTCHA if triggered."""
        resp = self.session.get(url, timeout=30)

        # Check for CAPTCHA
        sitekey_match = re.search(r'data-sitekey="([^"]+)"', resp.text)
        if sitekey_match:
            sitekey = sitekey_match.group(1)
            token = solve_captcha("userrecaptcha", sitekey, url)

            # Resubmit with token
            resp = self.session.post(url, data={
                "g-recaptcha-response": token,
            })

        return self._parse_stocks(resp.text)

    def _parse_stocks(self, html):
        soup = BeautifulSoup(html, "html.parser")
        stocks = []
        for row in soup.select("table.screener-table tr")[1:]:
            cols = row.select("td")
            if len(cols) >= 8:
                stocks.append({
                    "ticker": cols[1].get_text(strip=True),
                    "company": cols[2].get_text(strip=True),
                    "sector": cols[3].get_text(strip=True),
                    "price": cols[6].get_text(strip=True),
                    "change": cols[7].get_text(strip=True),
                })
        return stocks


# Usage
scraper = FinancialScraper(
    proxy="http://user:pass@residential.proxy.com:5000"
)
stocks = scraper.scrape_screener("https://screener.example.com/screener.ashx?v=111")
for stock in stocks[:5]:
    print(f"{stock['ticker']}: {stock['price']} ({stock['change']})")

Extraction de dépôt SEC EDGAR

SEC EDGAR implémente une limitation de débit et des CAPTCHA pour un accès à haut volume :

import json


class SECFilingScraper:
    BASE_URL = "https://efts.sec.gov/LATEST"

    def __init__(self, user_agent_email, proxy=None):
        self.session = requests.Session()
        if proxy:
            self.session.proxies = {"http": proxy, "https": proxy}
        # SEC requires identifying User-Agent
        self.session.headers.update({
            "User-Agent": f"CompanyName admin@{user_agent_email}",
            "Accept": "application/json",
        })

    def search_filings(self, company, filing_type="10-K"):
        """Search EDGAR for specific filing types."""
        url = f"{self.BASE_URL}/search-index"
        params = {
            "q": company,
            "dateRange": "custom",
            "forms": filing_type,
        }

        resp = self.session.get(url, params=params, timeout=30)

        # Handle CAPTCHA if triggered
        if "captcha" in resp.text.lower() or resp.status_code == 403:
            sitekey = self._extract_sitekey(resp.text)
            if sitekey:
                token = solve_captcha("userrecaptcha", sitekey, url)
                resp = self.session.post(url, data={
                    **params,
                    "g-recaptcha-response": token,
                })

        return resp.json() if resp.status_code == 200 else {}

    def download_filing(self, filing_url):
        """Download individual filing document."""
        resp = self.session.get(filing_url, timeout=60)
        if resp.status_code == 200:
            return resp.text
        return None

    def _extract_sitekey(self, html):
        match = re.search(r'data-sitekey="([^"]+)"', html)
        return match.group(1) if match else None


# Usage
sec = SECFilingScraper(
    user_agent_email="example.com",
    proxy="http://user:pass@proxy.example.com:5000",
)
filings = sec.search_filings("Apple Inc", "10-K")

Données de marché protégées par tourniquet

def scrape_turnstile_market_data(url, sitekey):
    """Handle Cloudflare Turnstile on financial data sites."""
    token = solve_captcha("turnstile", sitekey, url)

    session = requests.Session()
    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",
    })

    resp = session.post(url, data={
        "cf-turnstile-response": token,
    }, timeout=30)

    return resp.json() if resp.status_code == 200 else None

Collecte de données programmée

import csv
from datetime import datetime


def daily_market_snapshot(tickers, output_dir="data"):
    """Collect daily stock data, handling CAPTCHAs automatically."""
    scraper = FinancialScraper(
        proxy="http://user:pass@residential.proxy.com:5000"
    )

    date_str = datetime.now().strftime("%Y-%m-%d")
    results = []

    for ticker in tickers:
        url = f"https://screener.example.com/quote.ashx?t={ticker}"
        try:
            data = scraper.scrape_screener(url)
            if data:
                results.extend(data)
            time.sleep(2)  # Rate limit
        except Exception as e:
            print(f"Error on {ticker}: {e}")

    # Save to CSV
    filepath = f"{output_dir}/market_{date_str}.csv"
    with open(filepath, "w", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=["ticker", "company", "sector", "price", "change"])
        writer.writeheader()
        writer.writerows(results)

    print(f"Saved {len(results)} records to {filepath}")
    return results


# Run daily
tickers = ["AAPL", "GOOGL", "MSFT", "AMZN", "TSLA"]
daily_market_snapshot(tickers)

Meilleures pratiques de limitation de débit

Les sites financiers sont plus stricts en matière d’accès automatisé :

Pratique Recommandation
Retard de demande 2 à 5 secondes entre les pages
Connexions simultanées Max 3-5 par domaine
Type de mandataire Résidentiel ou FAI
Durée de la séance Séances collantes de 5 à 10 minutes
Agent utilisateur Réaliste, cohérent par session
SEC EDGAR Inclure l'adresse e-mail de contact dans UA (obligatoire)
Horaires du marché Grattez pendant les heures creuses lorsque cela est possible

Dépannage

Problème Parce que Corriger
403 sur SEC EDGAR Agent utilisateur manquant avec e-mail Ajouter l'en-tête CompanyName email@domain
CAPTCHA à chaque demande Limite de débit dépassée Ajouter des délais de 3 à 5 secondes entre les demandes
Données de prix obsolètes Réponse en cache Ajouter un paramètre de requête de suppression de cache
Erreur d'analyse JSON Page CAPTCHA renvoyée à la place Vérifiez le CAPTCHA avant d'analyser
IP bloquée Trop de requêtes depuis la même IP Passer au proxy résidentiel rotatif

FAQ

La récupération de données financières est-elle légale ?

Les données financières publiques (dépôts auprès de la SEC, cotations boursières) sont généralement autorisées. Respectez toujours les conditions de service et les limites de tarifs. SEC EDGAR fournit explicitement un accès EDGAR à des fins de recherche.

Pourquoi les sites financiers utilisent-ils des CAPTCHA ?

Pour empêcher une extraction automatisée de gros volumes qui pourrait permettre une manipulation du marché, une collecte de veille concurrentielle ou une charge excessive du serveur.

À quelle fréquence dois-je extraire les données du marché ?

Pour les cours de bourse : une fois par minute pendant les heures de bourse maximum. Pour les dépôts : une fois par jour est typique. Le grattage excessif déclenche les CAPTCHA plus rapidement.


Guides connexes


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