Les décisions financières reposent sur les données. Que vous suiviez une action que vous détenez, construisiez un tableau de bord de marché ou alimentiez un modèle de recherche, les chiffres publics qui font bouger le marché (cours, niveaux des indices, bilans publiés par les entreprises) constituent la matière première. La plupart de ces données sont visibles en clair sur les sites financiers, mais les rassembler manuellement pour des dizaines de tickers est lent, et les pages dynamiques qui les affichent sont conçues pour s'afficher dans un navigateur, pas pour restituer une réponse propre à un script brut.
Ce guide vous montre comment extraire des données financières avec Python de façon fiable. Il couvre les sources publiques pertinentes, puis présente un scraper minimaliste et fonctionnel qui récupère une page de cours rendue via la Crawling API, analyse les champs principaux (prix, variation, volume et quelques données connexes) et exporte des JSON et CSV propres. Tout ici est limité aux données de marché publiques : des chiffres factuels que tout le monde peut consulter sans connexion, jamais des données personnelles ou payantes. La section sur la légalité, vers la fin, n'est pas un simple boilerplate : lisez-la avant de pointer ce script sur des volumes réels.
Quelles données financières publiques valent la peine d'être collectées
Avant d'écrire du code, il est utile de savoir quelles données sont à la fois utiles et légitimes à collecter. Les données financières publiques se répartissent en quelques grandes catégories, chacune alimentant un type d'analyse différent.
- Cours de marché. Le prix en temps réel, la variation intraday, la variation en pourcentage, le range journalier et le volume d'échanges pour une action, un ETF ou un fonds. C'est la donnée la plus couramment suivie et le sujet de l'exemple pratique ci-dessous.
- Indices. Les niveaux agrégés de benchmarks comme les indices de marché larges ou sectoriels, utiles pour mesurer une position par rapport à l'ensemble du marché.
- Bilans des sociétés cotées. Les chiffres que les entreprises cotées sont tenues de divulguer : revenus, résultats, capitalisation boursière et les ratios résumés affichés sur une page de profil d'entreprise.
- Actualités et titres du marché public. Titres éditoriaux et horodatages qui alimentent l'analyse du sentiment. Collectez le titre factuel et le lien, pas le corps complet de l'article protégé par le droit d'auteur.
Les sources généralistes comme Forbes, Reuters, Bloomberg, MarketWatch et le Financial Times sont de bonnes lectures, mais pour un flux programmatique vous voulez une page qui expose des champs de cours structurés, ce que nous ciblons ci-dessous. Pour un panorama plus large, notre sélection des meilleurs fournisseurs de données financières compare les principales sources.
Ce que vous allez construire
Un script Python qui prend une URL publique de cours pour un ticker, récupère la page rendue via la Crawling API et extrait un enregistrement structuré. Les champs ci-dessous sont des champs de marché public représentatifs ; les sélecteurs CSS exacts dépendent de la page source que vous ciblez, traitez-les donc comme un modèle à adapter.
- Symbol le ticker auquel appartient le cours.
- Price le prix actuel coté.
- Change la variation absolue du prix sur la journée.
- Change percent le mouvement du jour exprimé en pourcentage.
- Volume le nombre d'actions échangées.
- Day range le bas et le haut intraday.
- Market cap la capitalisation boursière de l'entreprise, lorsque la page l'affiche.
Pourquoi une requête simple échoue sur les pages financières
Faites une requête vers une URL de cours financier moderne avec un client HTTP brut et vous obtenez généralement un statut 200 avec presque aucun chiffre dans le corps. Deux obstacles se dressent contre vous. D'abord, la plupart des sites financiers affichent les cours côté client : le prix, la variation et le volume sont injectés par JavaScript après le chargement initial du HTML, donc la première réponse est une coquille vide, et son analyse ne capture que l'habillage de la page plutôt que les chiffres recherchés. Ensuite, les sites financiers surveillent étroitement le trafic automatisé, car les données de cours en temps réel ont de la valeur. Les adresses IP de datacenter et les schémas de requêtes non-navigateur sont soumis à des limites de débit, bloqués par IP ou mis en défi avant d'atteindre le contenu rendu.
Un scraper financier fonctionnel a donc besoin de deux choses en une seule requête : un navigateur qui rend réellement la page, et une IP que le site perçoit comme un vrai visiteur. Vous pouvez construire cela vous-même avec un navigateur headless et des proxies résidentiels rotatifs, mais maintenir cette pile en bonne santé représente l'essentiel du travail. La Crawling API regroupe les deux en un seul appel : vous envoyez l'URL avec un token JavaScript, elle rend la page derrière une IP de confiance et renvoie le HTML final à analyser. Pour en savoir plus sur pourquoi les pages client-rendues nécessitent cela, voir scraper des pages JavaScript avec Python.
Crawlbase propose deux types de tokens. Le token normal récupère le HTML statique ; le token JavaScript (JS) rend la page dans un vrai navigateur au préalable. Les pages financières remplissent leurs champs de cours côté client, vous avez donc besoin du token JS ici. Le token normal renvoie la même coquille vide qu'une simple requête, avec peu d'éléments utiles à en extraire.
Prérequis
Quelques éléments doivent être en place avant d'écrire du code. Aucun ne prend longtemps.
Python de base. Vous devez être à l'aise pour écrire et exécuter un script Python et installer des packages avec pip. Si vous débutez sur la partie analyse, le guide BeautifulSoup est un bon complément à ce tutoriel.
Python 3.8 ou version ultérieure. Confirmez votre version avec python --version. Si vous ne l'avez pas, installez-le depuis python.org ou via une distribution comme Anaconda, et assurez-vous que Python est dans votre PATH.
Un compte Crawlbase et un token JS. Inscrivez-vous, ouvrez votre tableau de bord et copiez votre token JavaScript (JS) depuis la page de documentation du compte. Crawlbase inclut jusqu'à 20 000 requêtes gratuites pour commencer, ce qui est largement suffisant pour parcourir ce guide, et vous ne payez que pour les requêtes réussies. Traitez le token comme un mot de passe : il authentifie vos requêtes, donc gardez-le hors du contrôle de version.
Configurer le projet
Créez un environnement virtuel pour que les dépendances du projet restent isolées, puis installez les bibliothèques dont le scraper a besoin.
python --version python -m venv finance_env source finance_env/bin/activate pip install crawlbase beautifulsoup4
Sous Windows, activez l'environnement avec finance_env\Scripts\activate au lieu de la ligne source. Deux dépendances font le travail : crawlbase est le client officiel pour la Crawling API, et beautifulsoup4 analyse le HTML renvoyé pour extraire les champs individuels par sélecteur CSS. Les modules json et csv sont livrés avec la bibliothèque standard, il n'y a donc rien de plus à installer pour l'étape d'export.
Étape 1 : Récupérer une page de cours rendue
Commencez par obtenir une page complète. Importez la classe CrawlingAPI, initialisez-la avec votre token JS et demandez une URL de cours public. Les pages financières diffusent leurs chiffres de façon asynchrone, passez donc ajax_wait et page_wait pour attendre le contenu dynamique avant que la page soit capturée. Vérifier le cb_status (legacy pc_status) de Crawlbase avant d'analyser maintient les échecs visibles plutôt que silencieux.
from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) OPTIONS = { "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/122.0", "ajax_wait": "true", "page_wait": 5000, } def crawl(page_url): response = api.get(page_url, OPTIONS) if response["headers"]["cb_status"] == "200": return response["body"].decode("utf-8") print(f"Request failed: {response['headers']['cb_status']}") return None if __name__ == "__main__": quote_url = "https://www.example-finance.com/quote/AAPL" html = crawl(quote_url) print(html[:500] if html else "No HTML returned")
Remplacez quote_url par la page de cours public que vous souhaitez suivre. Les deux options d'attente sont importantes pour une page financière rendue côté client : ajax_wait attend la fin du chargement du contenu asynchrone, et page_wait maintient un nombre fixe de millisecondes après le chargement pour que les chiffres diffusés tardivement apparaissent avant la capture. Cinq secondes est un bon point de départ ; augmentez si des chiffres reviennent manquants. Exécutez le script et vous devriez voir le balisage réel du cours, pas la coquille qu'une simple requête renvoie, ce qui confirme que le rendu fonctionne avant d'écrire un seul sélecteur.
Une page de cours financier nécessite une page rendue derrière une IP de confiance, en un seul appel, ce que les options ajax_wait et page_wait ci-dessus mettent en place. La Crawling API prend un token JS, exécute la page dans un vrai navigateur, fait tourner les IPs résidentielles côté serveur et vous remet le HTML final, vous évitant de gérer vous-même une flotte headless et un pool de proxies. Pointez-la d'abord vers une page de cours public sur le niveau gratuit.
Étape 2 : Analyser les champs de cours
Avec le HTML complet en main, chargez-le dans BeautifulSoup et extrayez les chiffres principaux. La plupart des pages financières marquent leurs champs clés avec des attributs data-* stables ou des noms de champs, qui sont plus durables que les noms de classes générés. Chaque lookup est protégé pour qu'un champ manquant renvoie None au lieu de faire planter l'exécution.
from bs4 import BeautifulSoup def text_of(soup, selector): el = soup.select_one(selector) return el.get_text(strip=True) if el else None def parse_quote(html, symbol, url): soup = BeautifulSoup(html, "html.parser") return { "symbol": symbol, "price": text_of(soup, '[data-field="regularMarketPrice"]'), "change": text_of(soup, '[data-field="regularMarketChange"]'), "change_percent": text_of(soup, '[data-field="regularMarketChangePercent"]'), "volume": text_of(soup, '[data-field="regularMarketVolume"]'), "day_range": text_of(soup, '[data-field="regularMarketDayRange"]'), "market_cap": text_of(soup, '[data-field="marketCap"]'), "link": url, }
L'assistant text_of interroge un élément et retourne son texte nettoyé, ou None si l'élément est absent, de sorte qu'une page de cours omettant un champ ne casse pas la boucle. Les valeurs data-field ici (regularMarketPrice, regularMarketChange, regularMarketVolume, etc.) sont typiques de la façon dont les pages financières étiquettent leurs chiffres en temps réel. Ouvrez votre page cible dans les outils de développement, trouvez l'attribut ou la classe encapsulant chaque chiffre, et remplacez par les vrais sélecteurs ; garder les lookups dans un dictionnaire unique fait de cela une modification d'une ligne par champ.
Les sites financiers modifient leur balisage sans préavis, et les noms data-field exacts varient d'une source à l'autre. Traitez les sélecteurs ici comme un modèle de départ, pas comme un contrat. Lorsqu'un champ revient à None, réinspectez la page en direct et mettez à jour le sélecteur. La maintenance périodique des sélecteurs est normale pour tout scraper en production, ce n'est pas le signe que quelque chose est cassé.
Étape 3 : Assembler le script complet
Assemblez maintenant les pièces en un script unique exécutable : parcourez une liste de tickers, récupérez et analysez chaque cours avec un petit wrapper de retry, et exportez les enregistrements en JSON et CSV.
import csv import json import time from crawlbase import CrawlingAPI from bs4 import BeautifulSoup api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) OPTIONS = { "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/122.0", "ajax_wait": "true", "page_wait": 5000, } # Map each ticker to its public quote page URL. QUOTE_BASE = "https://www.example-finance.com/quote/" SYMBOLS = ["AAPL", "MSFT", "GOOGL"] def crawl(page_url): response = api.get(page_url, OPTIONS) if response["headers"]["cb_status"] == "200": return response["body"].decode("utf-8") print(f"Request failed: {response['headers']['cb_status']}") return None def fetch_html(page_url, max_retries=2): for attempt in range(max_retries + 1): html = crawl(page_url) if html: return html if attempt < max_retries: time.sleep(1) return None def text_of(soup, selector): el = soup.select_one(selector) return el.get_text(strip=True) if el else None def parse_quote(html, symbol, url): soup = BeautifulSoup(html, "html.parser") return { "symbol": symbol, "price": text_of(soup, '[data-field="regularMarketPrice"]'), "change": text_of(soup, '[data-field="regularMarketChange"]'), "change_percent": text_of(soup, '[data-field="regularMarketChangePercent"]'), "volume": text_of(soup, '[data-field="regularMarketVolume"]'), "day_range": text_of(soup, '[data-field="regularMarketDayRange"]'), "market_cap": text_of(soup, '[data-field="marketCap"]'), "link": url, } def save_outputs(records): with open("quotes.json", "w") as f: json.dump(records, f, indent=2) if not records: return with open("quotes.csv", "w", newline="") as f: writer = csv.DictWriter(f, fieldnames=records[0].keys()) writer.writeheader() writer.writerows(records) def main(): records = [] for symbol in SYMBOLS: url = QUOTE_BASE + symbol html = fetch_html(url) if html: records.append(parse_quote(html, symbol, url)) time.sleep(2) save_outputs(records) print(f"Saved {len(records)} quotes") if __name__ == "__main__": main()
Le script parcourt SYMBOLS, construit chaque URL de cours, la récupère avec le wrapper de retry, l'analyse en un enregistrement et rythme la boucle avec une pause de deux secondes. save_outputs écrit à la fois le JSON et le CSV en utilisant les clés du premier enregistrement comme en-tête, vous avez donc les données dans le format que votre outil en aval préfère. Ajoutez des tickers à SYMBOLS et ajustez QUOTE_BASE pour correspondre à la source publique que vous ciblez.
À quoi ressemble le résultat
Exécutez le script complet et vous obtenez un enregistrement structuré propre par ticker, prêt pour l'analyse, une base de données ou un tableur. Les valeurs ci-dessous sont illustratives, pas des chiffres en temps réel.
[ { "symbol": "AAPL", "price": "225.40", "change": "+1.85", "change_percent": "+0.83%", "volume": "48,210,300", "day_range": "223.10 - 226.05", "market_cap": "3.42T", "link": "https://www.example-finance.com/quote/AAPL" }, { "symbol": "MSFT", "price": "418.20", "change": "-2.40", "change_percent": "-0.57%", "volume": "19,840,100", "day_range": "416.00 - 421.30", "market_cap": "3.11T", "link": "https://www.example-finance.com/quote/MSFT" } ]
Le CSV correspondant contient les mêmes colonnes, une ligne par ticker, qui se chargent directement dans pandas ou n'importe quel tableur pour trier par variation, filtrer par volume ou tracer les prix sur des exécutions répétées. Planifiez le script via un cron et vous disposez d'une simple série chronologique de cours publics pour les tickers que vous suivez.
Mise à l'échelle et maintien sans blocage
Suivre des centaines de symboles, ou interroger le même ensemble selon un calendrier serré, c'est là que le scraping financier se complique, car c'est exactement le trafic que ces sites surveillent. Quelques bonnes pratiques maintiennent une exécution prolongée en bonne santé.
- Rythmez vos requêtes. Interroger une liste de surveillance dans une boucle serrée est le moyen le plus rapide de se faire throttler ou mettre en défi. Les pauses de deux secondes ci-dessus sont un plancher, pas un plafond ; élargissez-les pour les grands travaux et échelonnez vos exécutions plutôt que de lancer tous les tickers en même temps.
- Appuyez-vous sur la rotation. Un pool d'IPs résidentielles répartit les requêtes sur de nombreuses adresses d'utilisateurs réels afin qu'aucune n'atteigne une limite de débit. La Crawling API gère cela côté serveur ; si vous construisez votre propre stack, c'est la partie à bien maîtriser.
-
Lisez les codes de statut. Une exécution qui commence à renvoyer des valeurs
cb_statusnon-200 vous indique que le débit actuel ou le niveau d'IP n'est plus suffisant. Traitez cela comme un signal de ralentissement, pas comme du bruit à ignorer.
Pour les grands travaux, le Crawler asynchrone met les requêtes en file d'attente et livre les résultats vers un webhook, ce qui convient à l'interrogation de nombreux symboles sans maintenir des connexions ouvertes. Pour le manuel complet, voir le scraping financier à grande échelle et notre guide général sur comment scraper sans se faire bloquer. Si votre objectif final est l'analyse concurrentielle ou de pricing, notre guide sur le web scraping pour l'intelligence prix montre comment les équipes transforment ce type de flux en décisions.
Est-il légal de scraper des données financières ?
Le fait de savoir si le scraping de données financières est autorisé dépend des conditions d'utilisation de la source, de votre juridiction et de ce que vous faites des données. Les cours de marché, les niveaux d'indices et les bilans qu'une entreprise cotée doit divulguer sont des informations factuelles et publiques, et la collecte de faits publics à des fins d'analyse est largement défendable. Mais la page qui les sert appartient à quelqu'un, et la plupart des sites financiers restreignent l'accès automatisé et la collecte en masse dans leurs conditions. Aucun code ici ne change cela ; il fait seulement fonctionner la partie technique. Lisez les conditions d'utilisation du site cible et son robots.txt, respectez tout limite de débit déclarée, et traitez ces deux éléments comme la frontière de ce que vous collectez.
Quelques lignes à suivre. Collectez uniquement des données publiques non payantes : les champs de cours, les niveaux d'indices et les bilans divulgués que tout le monde peut voir sans compte. Ne scrappez rien derrière une connexion ou un paywall, et ne contournez jamais l'authentification ou la mesure pour atteindre des données premium, ce qui fait passer de la collecte publique à l'accès non autorisé. Maintenez votre volume assez bas pour ne pas surcharger les serveurs de la source. Et rappellez-vous que même les données factuelles comportent des conditions de licence lorsque vous les redistribuez : de nombreux sites sourcent les cours auprès des bourses et des fournisseurs de données sous des accords qui restreignent la republication, donc collecter un chiffre pour votre propre analyse n'est pas la même chose qu'avoir le droit de le revendre ou de le publier. Le contenu éditorial comme le texte complet d'un article est protégé par le droit d'auteur ; prenez le titre et le lien pour l'analyse de sentiment, pas le corps.
Ce guide est limité aux données de marché public car c'est la ligne qui maintient le travail défendable. Pour tout ce qui dépasse la recherche personnelle, et surtout pour les produits en production ou commerciaux, utilisez une API officielle de données de marché ou un flux sous licence plutôt qu'un scraper plus sophistiqué. La plupart des grandes plateformes financières offrent leur propre API de données ou s'associent à des fournisseurs de données de marché établis, et les bourses concèdent sous licence des données en temps réel et historiques directement. Ces voies vous donnent un contrat stable, des champs documentés et des droits de redistribution que le scraping d'une page publique n'accorde jamais. Utilisez le scraping pour prototyper et combler les lacunes ; concédez sous licence un flux lorsque les données alimentent quelque chose de réel.
Points clés
- Sachez ce qui est légitime à collecter. Les données de marché publiques (cours, indices, bilans divulgués des entreprises, titres) sont factuelles et légitimes ; les données personnelles et payantes ne le sont pas.
- Les pages financières sont rendues côté client. Une simple requête renvoie une coquille vide avec les chiffres manquants, vous devez donc rendre la page avant de l'analyser.
-
Vous avez besoin du rendu et d'une IP de confiance ensemble. La Crawling API avec un token JS fait les deux en un appel ;
ajax_waitetpage_waitcontrôlent la durée d'attente du contenu. - Analysez, bouclez et exportez. Mappez chaque champ à un sélecteur protégé, parcourez vos tickers avec un wrapper de retry, rythmer l'exécution avec de courtes pauses, et écrivez en JSON et CSV.
- Concédez sous licence pour la production. Respectez les CGU et le robots.txt de chaque source, notez que les données de cours comportent des conditions de redistribution, et passez à une API officielle de données de marché ou un flux sous licence pour tout usage commercial.
Foire aux questions
Pourquoi une simple requête renvoie-t-elle une page financière sans chiffres ?
Parce que la plupart des sites financiers chargent leurs champs de cours côté client avec JavaScript. Le HTML initial est une coquille qui ne se remplit qu'après l'exécution des scripts de la page, donc une simple requête HTTP renvoie un statut 200 avec le prix, la variation et le volume manquants. Pour obtenir les chiffres, vous devez d'abord rendre la page, ce que le token JS de la Crawling API gère pour vous.
Ai-je besoin du token normal ou du token JS pour les pages financières ?
Le token JS. Le token normal récupère le HTML statique, qui sur une page financière rendue côté client est la même coquille vide qu'une simple requête renverrait. Le token JS rend la page dans un vrai navigateur avant de renvoyer le HTML, de sorte que les champs de cours sont présents lorsque BeautifulSoup les analyse.
Quelles données financières puis-je scraper en toute sécurité ?
Les données de marché publiques non payantes : cours en direct, niveaux d'indices, bilans qu'une entreprise cotée est tenue de divulguer, et titres factuels avec leurs liens. Restez sur des données visibles par tout visiteur sans compte, ne collectez rien derrière une connexion ou un paywall, et évitez de republier des textes d'articles protégés par le droit d'auteur ou des flux de données sous licence.
Mes sélecteurs renvoient None. Qu'est-ce qui a changé ?
Presque certainement le balisage de la source. Les sites financiers modifient leurs noms de classes générés et leurs attributs data-field sans préavis, et ces noms d'attributs diffèrent d'une source à l'autre, donc des sélecteurs qui fonctionnaient le mois dernier peuvent cesser de fonctionner. Réinspectez une page en direct dans les outils de développement de votre navigateur et mettez à jour les sélecteurs. La maintenance périodique des sélecteurs est normale pour tout scraper en production.
Dois-je scraper ou utiliser une API officielle de données de marché pour la production ?
Pour tout usage commercial ou en production, utilisez une API officielle ou un flux sous licence. Scraper une page publique est excellent pour le prototypage et pour combler les lacunes, mais les API officielles vous donnent des champs documentés, des contrats stables et des droits de redistribution qu'une page publique n'accorde jamais. La plupart des grandes plateformes financières offrent une API de données ou s'associent à des fournisseurs de données de marché établis.
Comment scraper de nombreux tickers sans se faire bloquer ?
Rythmer vos requêtes avec des pauses, échelonner les exécutions plutôt que d'interroger chaque symbole en même temps, et vous appuyer sur des IPs résidentielles rotatives afin qu'aucune adresse unique ne déclenche une limite de débit. La Crawling API fait tourner les IPs côté serveur, et le Crawler asynchrone met les grands travaux en file d'attente et envoie les résultats vers un webhook. Surveillez les codes cb_status et ralentissez dès qu'ils cessent de renvoyer 200.
Crawlez n'importe quel site à grande échelle, sans combattre l'infrastructure.
Crawlbase gère les proxies, les empreintes et les CAPTCHA afin que votre équipe livre des pipelines de données au lieu de maintenir la plomberie de crawl. 1 000 requêtes gratuites, sans carte requise.
