Les Pages Jaunes font partie des annuaires professionnels les plus anciens du web, et constituent toujours une source dense de données sur les entreprises locales : nom, numéro de téléphone public, adresse postale, catégories dans lesquelles une entreprise est répertoriée et lien vers son propre site. Pour la prospection commerciale, la cartographie de marché ou la constitution d'un jeu de données régional de prestataires de services, ces annonces publiques sont exactement le renseignement structuré dont vous avez besoin. La difficulté est opérationnelle, pas conceptuelle : les Pages Jaunes surveillent le trafic ayant la forme d'un scraper et ralentiront ou défieront rapidement une boucle naïve.
Ce guide vous montre comment scraper les Pages Jaunes avec Python de manière fiable. Vous récupérez les pages de résultats de recherche rendues via la Crawling API, analysez chaque résultat avec BeautifulSoup pour extraire le nom, le téléphone, l'adresse, la catégorie et le site web, puis parcourez la pagination pour couvrir un jeu de résultats complet. Tout ce qui suit se limite aux données de répertoire d'entreprises publiques, et la section sur la légalité en fin d'article n'est pas du remplissage, lisez-la avant de pointer cet outil sur un volume réel.
Ce que vous allez construire
Un petit scraper Python qui prend une requête de recherche et une localisation, récupère la page de résultats de recherche rendue des Pages Jaunes via la Crawling API et extrait un enregistrement structuré pour chaque entreprise sur la page. L'exemple fil rouge concerne les entreprises "Information Technology" à "Los Angeles, CA", et pour chaque annonce nous extrayons ces champs :
- Nom de l'entreprise l'identifiant principal de l'annonce.
- Téléphone le numéro de contact public affiché sur la fiche.
- Adresse l'adresse postale publique, utilisée pour toute analyse géographique.
- Catégorie les catégories professionnelles dans lesquelles l'annonce est répertoriée.
- Site web le lien vers le propre site de l'entreprise, lorsqu'il est indiqué.
Comment les pages de recherche des Pages Jaunes sont structurées
Une recherche sur les Pages Jaunes est pilotée par deux paramètres URL : search_terms pour la requête et geo_location_terms pour la localisation. Soumettez une recherche et vous arrivez sur une page de résultats où chaque entreprise est une fiche autonome. La fiche porte le nom comme lien d'en-tête, le téléphone et l'adresse dans leurs propres blocs, les catégories sous forme de liste, et, pour les entreprises qui ont payé ou revendiqué l'annonce, un lien sortant vers le site web.
Les résultats s'étendent sur plusieurs pages. Les Pages Jaunes utilisent un paramètre URL page pour se déplacer entre elles, ce qui fait de la pagination une simple question d'incrémentation d'un entier plutôt que de chasser un comportement dynamique "charger plus". Cette prévisibilité permet au même analyseur de fonctionner sur chaque page sans modification une fois qu'il fonctionne sur l'une d'elles.
Pourquoi une simple récupération échoue
Vous pouvez frapper une URL de recherche des Pages Jaunes avec la bibliothèque requests et, les bons jours, obtenir du HTML en retour. Le problème apparaît au volume. Les Pages Jaunes déploient des défenses anti-scraping : elles limitent le débit par IP, servent des CAPTCHA au trafic qui semble automatisé et bloquent les adresses de datacenter qui demandent des pages dans un schéma machine serré. Une seule requête depuis votre ordinateur peut réussir ; quelques centaines depuis la même IP ne le peuvent pas.
Un scraper qui achève réellement le travail a donc besoin de requêtes qui semblent être celles d'un vrai visiteur venant d'une IP de confiance. Vous pouvez construire cela vous-même avec un pool de proxies résidentiels rotatifs et la plomberie pour les maintenir en bonne santé, mais maintenir cette pile représente la majeure partie du travail. La Crawling API regroupe tout en un seul appel : vous lui envoyez l'URL, elle achemine la requête via des IP résidentielles côté serveur et gère la couche anti-bot, et elle retourne le HTML à analyser.
Crawlbase propose deux types de tokens. Le token normal récupère le HTML statique ; le token JavaScript (JS) rend d'abord la page dans un vrai navigateur. Les Pages Jaunes servent leurs données d'annonces dans le HTML initial, donc le token normal est le bon choix ici et rend chaque requête moins coûteuse. N'utilisez le token JS que si une cible commence à rendre les annonces côté client.
Prérequis
Quelques éléments à mettre en place au préalable. Aucun ne prend beaucoup de temps.
Python de base. Vous devez être à l'aise pour exécuter un script et installer des packages avec pip. Si les sélecteurs sont nouveaux pour vous, le guide sur l'utilisation de BeautifulSoup en Python couvre en détail la partie analyse.
Python 3.8 ou version ultérieure. Vérifiez avec python --version. Si vous ne l'avez pas, installez-le depuis python.org ou via une distribution comme Anaconda.
Un compte Crawlbase et un token. Inscrivez-vous, ouvrez votre tableau de bord et copiez votre token normal depuis la page de documentation du compte. Les 1 000 premières requêtes sont gratuites et aucune carte n'est requise. Traitez le token comme un mot de passe et gardez-le en dehors du contrôle de version.
Configurer le projet
Créez un environnement virtuel pour que les dépendances restent isolées, puis installez les deux bibliothèques dont le scraper a besoin.
python --version python -m venv yellowpages_env source yellowpages_env/bin/activate pip install crawlbase beautifulsoup4
Sous Windows, activez l'environnement avec yellowpages_env\Scripts\activate à la place de la ligne source. Deux dépendances font le travail : crawlbase est le client officiel de la Crawling API, et beautifulsoup4 analyse le HTML retourné pour que vous puissiez extraire chaque champ par sélecteur CSS.
Étape 1 : Récupérer une page de recherche rendue
Commencez par obtenir une page de résultats en retour. Construisez l'URL de recherche depuis votre requête et localisation, importez la classe CrawlingAPI, initialisez-la avec votre token et demandez l'URL. Vérifier le statut avant d'analyser garde les échecs visibles plutôt que silencieux.
from urllib.parse import urlencode from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) def build_url(query, location, page=1): base = "https://www.yellowpages.com/search?" params = {"search_terms": query, "geo_location_terms": location, "page": page} return base + urlencode(params) def crawl(page_url): response = api.get(page_url) if response["headers"]["pc_status"] == "200": return response["body"].decode("utf-8") print(f"Request failed: {response['headers']['pc_status']}") return None if __name__ == "__main__": url = build_url("Information Technology", "Los Angeles, CA") html = crawl(url) print(html[:500] if html else "No HTML returned")
Notez que la vérification de statut lit pc_status depuis les en-têtes de réponse, qui est le statut Crawlbase pour la requête, distinct du code HTTP amont. Exécutez le script avec python scraper.py et vous devriez voir un vrai balisage de résultats plutôt qu'une page de défi. Cela confirme que le chemin de récupération fonctionne avant d'écrire le moindre sélecteur.
Les Pages Jaunes limitent le débit par IP et défient le trafic ayant la forme d'un scraper. La Crawling API achemine chaque requête via des IP résidentielles rotatives côté serveur, gère les CAPTCHA et les blocages, et retourne du HTML prêt à analyser, ce qui vous évite de gérer vous-même un pool de proxies et une couche de nouvelles tentatives. Pointez-la sur une page de recherche publique avec le niveau gratuit d'abord.
Étape 2 : Analyser les annonces avec BeautifulSoup
Une fois la page de résultats en main, chargez-la dans BeautifulSoup et parcourez les fiches de résultats. Chaque fiche se trouve sous un conteneur prévisible, et à l'intérieur de celui-ci le nom, le téléphone, l'adresse, les catégories et le site web correspondent à leurs propres sélecteurs. Lire chaque champ de manière défensive, en retournant None quand un élément est manquant, empêche une valeur absente de faire planter l'exécution.
from bs4 import BeautifulSoup def text_of(node): return node.get_text(strip=True) if node else None def extract_listings(html): soup = BeautifulSoup(html, "html.parser") cards = soup.select("div.search-results.organic div.result") listings = [] for card in cards: name = card.select_one("a.business-name") phone = card.select_one("div.phone") address = card.select_one("div.adr") category = card.select_one("div.categories") website = card.select_one("a.track-visit-website") listings.append({ "name": text_of(name), "phone": text_of(phone), "address": text_of(address), "category": text_of(category), "website": website["href"] if website else None, }) return listings
L'assistant text_of interroge un nœud et retourne None lorsqu'il est absent, au lieu de lever une exception sur un appel .get_text() sur rien. Cela rend l'extraction résiliente : toutes les annonces n'ont pas un lien de site web ou un bloc téléphonique propre, et un champ manquant doit laisser un None dans l'enregistrement plutôt que d'arrêter la boucle. Le site web est lu depuis le href de l'ancre plutôt que depuis son texte, il est donc géré séparément.
Les noms de classes ci-dessus (result, business-name, adr, categories, track-visit-website) reflètent le balisage actuel des Pages Jaunes, et ce balisage change sans préavis. Traitez les sélecteurs comme un modèle de départ, pas comme un contrat. Quand un champ revient à None pour chaque annonce, réinspectez une page de résultats en direct dans les outils de développement de votre navigateur et mettez le sélecteur à jour. Une maintenance périodique des sélecteurs est normale pour tout scraper en production.
Étape 3 : Tout assembler
Reliez maintenant la récupération et l'analyse en un seul script exécutable pour une seule page. Construisez l'URL, récupérez le HTML, passez-le à l'analyseur et affichez les enregistrements structurés.
import json from urllib.parse import urlencode from crawlbase import CrawlingAPI from bs4 import BeautifulSoup api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) def build_url(query, location, page=1): base = "https://www.yellowpages.com/search?" params = {"search_terms": query, "geo_location_terms": location, "page": page} return base + urlencode(params) def crawl(page_url): response = api.get(page_url) if response["headers"]["pc_status"] == "200": return response["body"].decode("utf-8") print(f"Request failed: {response['headers']['pc_status']}") return None def text_of(node): return node.get_text(strip=True) if node else None def extract_listings(html): soup = BeautifulSoup(html, "html.parser") cards = soup.select("div.search-results.organic div.result") listings = [] for card in cards: website = card.select_one("a.track-visit-website") listings.append({ "name": text_of(card.select_one("a.business-name")), "phone": text_of(card.select_one("div.phone")), "address": text_of(card.select_one("div.adr")), "category": text_of(card.select_one("div.categories")), "website": website["href"] if website else None, }) return listings def main(): url = build_url("Information Technology", "Los Angeles, CA") html = crawl(url) if not html: return data = extract_listings(html) print(json.dumps(data, indent=2)) if __name__ == "__main__": main()
À quoi ressemble la sortie
Exécutez le script complet avec python scraper.py et vous obtenez une liste propre d'enregistrements structurés, prête à écrire en JSON, CSV ou dans une base de données.
[ { "name": "L. A. Computer Works", "phone": "(310) 277-9799", "address": "2355 Westwood Blvd, Los Angeles, CA 90064", "category": "Computer Technical Assistance and Support Services", "website": "http://lacomputerworks.com" }, { "name": "Desktop Conquest", "phone": "(213) 321-1869", "address": "Los Angeles, CA 90057", "category": "Computer System Designers and Consultants", "website": null } ]
Les annonces sans site web revendiqué reviennent avec "website": null, ce qui est attendu et c'est exactement pourquoi l'analyseur lit chaque champ de manière défensive plutôt qu'en supposant que chaque clé est présente.
Étape 4 : Gérer la pagination sur plusieurs pages de résultats
Une page est une démonstration ; un vrai travail couvre le jeu de résultats complet. Comme les Pages Jaunes exposent la page de résultats via le paramètre URL page, parcourir les pages est une boucle sur une plage d'entiers. Les mêmes fonctions build_url et extract_listings restent inchangées, donc la pagination est simplement une boucle externe qui se cadence entre les requêtes.
import time def scrape_all_pages(query, location, max_pages): all_listings = [] for page in range(1, max_pages + 1): url = build_url(query, location, page) html = crawl(url) if not html: print(f"Stopping at page {page}: no HTML") break listings = extract_listings(html) if not listings: print(f"No results on page {page}; reached the end") break all_listings.extend(listings) print(f"Page {page}: {len(listings)} listings") time.sleep(2) return all_listings if __name__ == "__main__": rows = scrape_all_pages("Information Technology", "Los Angeles, CA", max_pages=5) with open("yellow_pages.json", "w") as f: json.dump(rows, f, indent=2) print(f"Saved {len(rows)} listings")
Deux détails rendent cette boucle utilisable en production. Elle s'arrête tôt lorsqu'une page ne retourne aucune annonce, ce qui évite de gaspiller des requêtes au-delà de la dernière vraie page, et elle attend deux secondes entre les requêtes pour que l'exécution n'arrive pas comme une seule rafale serrée. Ajustez max_pages et le délai en fonction de votre volume ; plus vous allez lentement, moins vous attirez l'attention.
Rester non bloqué
Même avec la Crawling API gérant la rotation des IP et la couche anti-bot, quelques habitudes maintiennent une exécution en bonne santé, et elles s'appliquent à toute cible de répertoire.
- Cadencez vos requêtes. Le délai ci-dessus n'est pas cosmétique. Une boucle serrée est le moyen le plus rapide de se faire ralentir ; espacer les requêtes ressemble bien plus à du trafic normal.
- Misez sur la rotation. Un pool d'IP résidentielles répartit les requêtes sur de nombreuses adresses d'utilisateurs réels pour qu'aucune seule ne déclenche une limite de débit. La Crawling API fait cela pour vous ; si vous construisez votre propre pile, c'est la partie à bien maîtriser. Le contexte approfondi se trouve dans le guide sur la rotation des adresses IP.
- Lisez les codes de statut. Une exécution qui commence à retourner des défis ou des erreurs vous signale que le débit actuel est trop agressif. Traitez cela comme un signal pour ralentir, pas comme du bruit à ignorer.
Pour le guide complet, consultez comment scraper des sites web sans être bloqué et l'analyse approfondie sur comment contourner les CAPTCHA lors du scraping web. Lorsque vous passez cela à l'échelle sur de nombreuses requêtes et localisations, les schémas dans le scraping web à grande échelle couvrent la mise en file d'attente et le stockage. Si vous préférez router votre propre trafic via un pool rotatif plutôt que d'utiliser l'API gérée, le Smart AI Proxy vous offre la même rotation résidentielle comme point de terminaison proxy intégré.
Est-il légal de scraper les Pages Jaunes ?
La légitimité du scraping des Pages Jaunes dépend des conditions d'utilisation du site, de votre juridiction et de ce que vous faites avec les données. Aucun code ici ne change cela ; il fait seulement fonctionner la partie technique. Lisez les Conditions d'utilisation des Pages Jaunes et son robots.txt, et traitez les deux comme la limite de ce que vous collectez et à quelle vitesse.
Quelques lignes à respecter. Collectez uniquement les données de répertoire d'entreprises publiques : le nom de l'entreprise, le numéro de téléphone public, l'adresse publique et la catégorie que tout le monde peut voir sans se connecter. Respectez les attentes de débit déclarées du site et gardez votre volume de requêtes raisonnable pour ne pas solliciter ses serveurs. Ce guide se limite délibérément à cette surface publique car c'est la ligne qui rend le travail défendable.
Ce que cette approche ne couvre pas est tout aussi important. Elle ne touche rien derrière une connexion, et elle ne contourne pas l'authentification ou tout contrôle d'accès pour atteindre du contenu restreint ; c'est hors de portée ici et va à l'encontre des conditions du site. Et notez que l'agrégation de données de contact d'entreprises peut engendrer des obligations légales distinctes selon votre juridiction, même si chaque champ est individuellement public, donc si vous prévoyez de stocker, d'enrichir ou de réutiliser commercialement un jeu de données de contacts, vérifiez les règles qui s'appliquent à vous plutôt que de supposer que public signifie sans restriction.
Points clés
-
Les Pages Jaunes sont un répertoire structuré. Chaque résultat de recherche est une fiche avec un nom, un téléphone public, une adresse publique, une catégorie et un site web optionnel, piloté par les paramètres URL
search_termsetgeo_location_terms. - Une simple récupération échoue au volume. Les limites de débit, les CAPTCHA et les blocages IP arrêtent une boucle naïve ; la Crawling API route via des IP résidentielles et retourne du HTML prêt à analyser en un seul appel.
- BeautifulSoup fait l'extraction. Associez nom, téléphone, adresse, catégorie et site web aux sélecteurs actuels, lisez chaque champ de manière défensive et attendez-vous à ce que ces sélecteurs évoluent.
-
La pagination est une boucle sur le paramètre
page. Réutilisez le même analyseur sur toutes les pages, arrêtez-vous tôt sur une page vide et attendez entre les requêtes pour cadencer l'exécution. - Restez sur les données publiques. Respectez les CGU et le robots.txt, ne touchez jamais au contenu derrière une connexion et souvenez-vous que l'agrégation de données de contact peut engendrer ses propres obligations selon la juridiction.
Foire aux questions
Ai-je besoin du token normal ou du token JS pour les Pages Jaunes ?
Le token normal. Les Pages Jaunes servent leurs données d'annonces dans le HTML initial, donc une récupération avec le token normal retourne un balisage analysable et rend chaque requête moins coûteuse. Le token JS rend d'abord la page dans un vrai navigateur, ce dont vous n'avez besoin que lorsqu'une cible charge ses annonces côté client après l'arrivée de la page. Commencez avec le token normal et ne changez que si les champs reviennent vides partout.
Comment gérer la pagination sur les Pages Jaunes ?
Les Pages Jaunes exposent la page de résultats via un paramètre URL page, donc vous bouclez sur une plage d'entiers, construisez une URL par page et exécutez le même analyseur sur chacune. Arrêtez-vous quand une page retourne zéro annonce, ce qui marque la fin du jeu de résultats, et attendez quelques secondes entre les requêtes pour que l'exécution n'arrive pas comme une seule rafale.
Mes sélecteurs retournent None. Qu'est-ce qui a changé ?
Presque certainement le balisage des Pages Jaunes. Les noms de classes comme result, business-name et track-visit-website changent sans préavis, de sorte que les sélecteurs qui fonctionnaient le mois dernier peuvent ne plus marcher. Réinspectez une page de résultats en direct dans les outils de développement de votre navigateur et mettez les sélecteurs à jour. Une maintenance périodique des sélecteurs est normale pour tout scraper en production, ce n'est pas le signe que quelque chose est cassé.
Pourquoi certaines annonces n'ont-elles pas de site web ?
Toutes les entreprises ne revendiquent pas ou ne lient pas leur propre site sur les Pages Jaunes, donc l'ancre du site web est simplement absente sur ces fiches. L'analyseur lit le champ de manière défensive et stocke None plutôt que de lever une exception, donc un site web manquant laisse un null propre dans l'enregistrement et la boucle continue vers l'annonce suivante.
Comment éviter d'être bloqué en scrapant les Pages Jaunes ?
Gardez un faible taux de requêtes par IP, cadencez les requêtes avec un délai et routez via des IP résidentielles rotatives pour qu'aucune seule adresse ne déclenche une limite de débit. La Crawling API gère la rotation et la couche anti-bot pour vous ; si vous construisez votre propre pile, c'est la partie dans laquelle investir. Surveillez les codes de statut et ralentissez dès que vous commencez à voir des défis.
Puis-je exporter les données scrapées vers Excel ?
Oui. Le scraper produit une liste de dictionnaires, que pandas transforme en tableur en deux lignes : pd.DataFrame(rows).to_excel("yellow_pages.xlsx", index=False). Comme chaque enregistrement partage les mêmes clés, les colonnes s'alignent proprement, et la même structure s'exporte tout aussi facilement en CSV ou dans une table de base de données.
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.
