Google traite des milliards de recherches par jour, et la page de résultats derrière chaque requête est un instantané structuré de ce qui se classe pour un terme : les titres organiques, les liens vers lesquels ils pointent et le texte d'extrait sous chacun. Cela fait du SERP public de Google un signal utile pour la recherche de mots-clés, le suivi de positions et l'analyse concurrentielle. Les données sont visibles en clair sur la page de résultats ; le travail consiste à y accéder de manière fiable.
Il s'agit de la version ciblée et opérationnelle de ce travail. Vous configurerez Python, récupérerez une page de résultats Google rendue via la Crawling API, analyserez chaque résultat organique en un titre, un lien et un extrait, parcourrez des résultats plus profonds et exporterez en JSON et CSV. Le tutoriel se limite aux données de résultats de recherche publiques visibles par quiconque sans compte. Pour la visite complète de la structure SERP, les approches multiples et la mise à l'échelle, lisez le pilier plus large, comment extraire les pages de recherche Google ; cet article garde la tête baissée et produit un scraper fonctionnel.
Ce que vous allez construire
Un script Python qui prend une requête de recherche, récupère la page de résultats Google rendue via la Crawling API et retourne un enregistrement propre pour chaque résultat organique sur la page. Nous utiliserons un exemple de requête comme fil conducteur et extrairons ces champs pour chaque résultat :
- Position le rang du résultat sur la page, compté depuis le haut.
- Titre le texte du titre du résultat, tel qu'il apparaît dans le résultat.
- Lien l'URL de destination vers laquelle pointe le résultat.
- Extrait la description ou le résumé affiché sous le titre.
- Recherches associées les requêtes de suivi suggérées que Google liste en bas de la page.
Pourquoi une requête ordinaire échoue sur Google
Envoyez une requête HTTP brute à google.com/search depuis un script et vous n'obtenez presque jamais la page que vous voyez dans votre propre navigateur. Deux choses travaillent contre vous. Premièrement, Google s'appuie désormais sur JavaScript pour rendre la page de résultats : à partir de 2025, le SERP nécessite l'activation des scripts, donc une simple récupération qui n'exécute pas JavaScript revient avec une coquille vide au lieu des résultats. Deuxièmement, Google surveille le trafic automatisé. Trop de requêtes depuis une IP, des requêtes trop rapides, ou des requêtes qui ne ressemblent pas à un vrai navigateur se heurtent à un CAPTCHA, une limitation ou un blocage.
Un scraper Google fonctionnel a donc besoin de deux choses en une seule requête : une IP que le moteur de recherche considère comme un visiteur ordinaire, et un navigateur qui rend la page. Vous pouvez assembler cela vous-même avec un navigateur headless et un pool de proxies résidentiels rotatifs, mais maintenir cette flotte en bon état représente l'essentiel du travail. La Crawling API combine les deux en un seul appel. Elle intègre aussi un scraper google-serp intégré qui récupère la page rendue depuis une IP rotative de confiance et retourne les résultats organiques déjà analysés en JSON, vous évitant ainsi d'écrire des sélecteurs fragiles contre le balisage fréquemment changeant de Google.
Prérequis
Vous avez besoin de quelques éléments 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 paquets avec pip. Si vous êtes plus novice en scraping en général, notre guide d'extraction de sites web avec Python couvre les bases que ce tutoriel suppose acquises.
Python 3.8 ou supérieur. Confirmez votre version avec python --version. Si vous ne l'avez pas, installez-le depuis python.org ou via une distribution comme Anaconda. N'importe quel éditeur convient ; VS Code, PyCharm et Jupyter sont tous adaptés à cela.
Un compte et un token Crawlbase. Inscrivez-vous, ouvrez votre tableau de bord et copiez votre token de requête. Vous obtenez jusqu'à 20 000 requêtes gratuites, sans carte de crédit requise, et le scraper google-serp intégré fonctionne avec le token normal. Traitez le token comme un mot de passe : il authentifie vos requêtes, ne le mettez donc pas sous contrôle de version.
Configurer le projet
Créez un environnement virtuel pour isoler les dépendances du projet, puis installez la bibliothèque Python Crawlbase, qui encapsule la Crawling API dans un petit client.
python --version python -m venv google_env source google_env/bin/activate pip install crawlbase
Sous Windows, activez l'environnement avec google_env\Scripts\activate à la place de la ligne source. Le paquet crawlbase vous donne un client CrawlingAPI pour ne pas avoir à construire l'URL de requête à la main. Comme le scraper google-serp retourne du JSON analysé, vous n'avez même pas besoin d'une bibliothèque d'analyse HTML pour les résultats organiques dans ce tutoriel.
Étape 1 : récupérer le SERP rendu via la Crawling API
Commencez par obtenir les données. Écrivez une petite fonction scrape_google_results() qui construit l'URL de recherche, l'envoie à la Crawling API avec le scraper google-serp activé, vérifie le statut et retourne le corps analysé. Google pagine par ensembles de 10, donc la fonction prend un numéro de page et le traduit en offset start que Google attend dans l'URL.
import json from urllib.parse import quote_plus from crawlbase import CrawlingAPI # Replace with your token from the Crawlbase dashboard crawling_api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) def scrape_google_results(query, page=0): encoded = quote_plus(query) url = f"https://www.google.com/search?q={encoded}&start={page * 10}" options = {"scraper": "google-serp"} response = crawling_api.get(url, options) if response["headers"]["cb_status"] == "200": data = json.loads(response["body"].decode("latin1")) return data.get("body", {}) print(f"Failed to fetch results for '{query}' (page {page}).") return {} if __name__ == "__main__": results = scrape_google_results("web scraping tools", page=0) print(json.dumps(results.get("searchResults", [])[:2], indent=2))
Le dictionnaire options est toute l'astuce : passer {"scraper": "google-serp"} indique à la Crawling API de rendre la page, de contourner les vérifications anti-bot et de retourner le SERP déjà analysé. Le client vous retourne une réponse dont le headers["cb_status"] est le statut propre de Crawlbase pour l'exploration, donc vérifier sur "200" avant d'analyser maintient un blocage ou un rendu raté visible plutôt que d'alimenter du contenu indésirable en aval. Le corps revient sous forme d'octets, que vous décodez avec latin1 et chargez en JSON, puis lisez le SERP analysé depuis sa clé body. Exécutez le script et vous devriez voir les deux premiers résultats organiques s'afficher en JSON, ce qui confirme que la récupération et l'analyse fonctionnent avant de construire quoi que ce soit par-dessus.
Ce cb_status (legacy pc_status) lit 200 parce que la requête a atteint Google comme un visiteur réel, avec la page rendue et les vérifications anti-bot gérées, avant que le scraper google-serp ne la convertisse en JSON que vous venez d'afficher. La Crawling API effectue le rendu JavaScript et fait tourner les IPs résidentielles côté serveur, vous évitant ainsi de gérer vous-même une flotte de navigateurs headless et de sourcer un pool de proxies. Commencez sur le niveau gratuit et pointez-la vers une URL de résultats publique d'abord.
Étape 2 : analyser les résultats organiques en enregistrements propres
Le scraper google-serp retourne le SERP déjà structuré, donc l'analyse consiste à lire les champs souhaités plutôt qu'à écrire des sélecteurs CSS. Les résultats organiques se trouvent sous la clé searchResults, chacun portant sa position, son title, son url et sa description. La page vous donne aussi relatedSearches, et le scraper expose ads, peopleAlsoAsk et un snackPack local quand la requête les déclenche. Écrivez une petite fonction qui extrait les champs qui vous intéressent et normalise le nom du champ d'extrait.
def parse_results(serp): organic = [] for item in serp.get("searchResults", []): organic.append({ "position": item.get("position"), "title": item.get("title"), "link": item.get("url"), "snippet": item.get("description"), }) related = [r.get("title") for r in serp.get("relatedSearches", [])] return {"organic": organic, "relatedSearches": related}
Cela conserve les quatre champs dont la plupart des travaux de suivi de positions et de recherche ont besoin : la position directement de Google, le title, le link de destination (lu depuis le champ url du résultat), et le snippet (lu depuis description). Extraire relatedSearches en parallèle vous donne les requêtes de suivi suggérées gratuitement, ce qui est utile pour l'expansion de mots-clés. Comme le scraper effectue l'extraction des champs, vous êtes isolé des changements de balisage de Google ; vous ne touchez jamais que ces clés JSON stables.
Vous pourriez récupérer le HTML rendu brut et l'analyser avec BeautifulSoup, mais les noms de classes des conteneurs de résultats de Google sont obfusqués et changent souvent, donc les sélecteurs écrits à la main se cassent régulièrement. Le scraper google-serp retourne des clés JSON stables comme searchResults, position et relatedSearches à la place, ce qui est bien moins de maintenance. Si vous voulez l'approche par sélecteurs pour d'autres sites, notre guide sur XPath et les sélecteurs CSS la couvre.
Étape 3 : gérer la pagination
Une page est une démonstration ; un vrai travail va plus loin dans les résultats. Google pagine par ensembles de 10 via le paramètre start, donc la page deux est start=10, la page trois est start=20, et ainsi de suite, ce que le calcul page-vers-offset dans scrape_google_results gère déjà. Bouclez sur une plage de pages, arrêtez tôt quand une page revient vide, et collectez chaque enregistrement organique dans une liste. Rythmez la boucle avec un court sleep pour maintenir un cycle d'exécution long en bonne santé.
import time def scrape_all_pages(query, max_pages=3): all_organic = [] for page in range(max_pages): print(f"Scraping page {page + 1}...") serp = scrape_google_results(query, page) parsed = parse_results(serp) if not parsed["organic"]: print("No more results, stopping.") break all_organic.extend(parsed["organic"]) time.sleep(2) return all_organic
La boucle s'exécute de la page 0 jusqu'à max_pages, récupère chaque page, l'analyse et étend la liste courante. La garde if not parsed["organic"]: break s'arrête dès qu'une page n'a plus de résultats organiques, pour ne pas continuer à payer pour des pages vides au-delà de la fin des résultats. Le time.sleep(2) entre les pages répartit les requêtes au lieu de les envoyer en rafale, ce qui est la meilleure habitude unique pour rester non bloqué sur un cycle d'exécution long.
Étape 4 : assembler le script complet et exporter
Maintenant, combinez la récupération, l'analyse et la pagination en un seul script opérationnel, et écrivez la sortie en JSON et CSV. Le JSON conserve la forme imbriquée complète ; le CSV vous donne un tableau plat que vous pouvez ouvrir dans un tableur pour des vérifications rapides de positions.
import csv import json import time from urllib.parse import quote_plus from crawlbase import CrawlingAPI crawling_api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) def scrape_google_results(query, page=0): encoded = quote_plus(query) url = f"https://www.google.com/search?q={encoded}&start={page * 10}" options = {"scraper": "google-serp"} response = crawling_api.get(url, options) if response["headers"]["cb_status"] == "200": data = json.loads(response["body"].decode("latin1")) return data.get("body", {}) print(f"Failed to fetch results for '{query}' (page {page}).") return {} def parse_results(serp): organic = [] for item in serp.get("searchResults", []): organic.append({ "position": item.get("position"), "title": item.get("title"), "link": item.get("url"), "snippet": item.get("description"), }) return organic def scrape_all_pages(query, max_pages=3): all_organic = [] for page in range(max_pages): print(f"Scraping page {page + 1}...") organic = parse_results(scrape_google_results(query, page)) if not organic: print("No more results, stopping.") break all_organic.extend(organic) time.sleep(2) return all_organic def save_json(rows, filename): with open(filename, "w", encoding="utf-8") as f: json.dump(rows, f, ensure_ascii=False, indent=2) def save_csv(rows, filename): fields = ["position", "title", "link", "snippet"] with open(filename, "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=fields) writer.writeheader() writer.writerows(rows) if __name__ == "__main__": query = "web scraping tools" rows = scrape_all_pages(query, max_pages=2) save_json(rows, "google_results.json") save_csv(rows, "google_results.csv") print(f"Saved {len(rows)} results to JSON and CSV")
Exécutez avec python main.py. Il extrait deux pages pour "web scraping tools", aplatit chaque résultat organique en une seule liste et écrit google_results.json et google_results.csv. Pour extraire un terme différent, changez la chaîne query ; pour aller plus loin, augmentez max_pages. Régler ensure_ascii=False garde les titres non-Latin lisibles dans le fichier JSON plutôt que de les encoder en séquences \u.
À quoi ressemble la sortie
Le fichier JSON est une liste ordonnée d'enregistrements organiques, chacun avec sa position, son titre, son lien et son extrait, prêt à déposer dans une base de données ou une feuille de suivi de positions.
[ { "position": 1, "title": "Web Scraper - The #1 web scraping extension", "link": "https://webscraper.io/", "snippet": "The most popular web scraping extension. Start scraping in minutes." }, { "position": 2, "title": "ParseHub | Free web scraping - The most powerful web scraper", "link": "https://www.parsehub.com/", "snippet": "ParseHub is a free web scraping tool. Turn any site into a spreadsheet or API." } ]
Le CSV contient les mêmes enregistrements sous forme de tableau plat avec une ligne par résultat et les colonnes position, title, link et snippet, ce qui est le format que la plupart des suivis de positions basés sur des tableurs attendent.
Mise à l'échelle sur plusieurs requêtes et rester non bloqué
Le script ci-dessus extrait une requête sur quelques pages. Un travail en production exécute généralement de nombreuses requêtes et peut les suivre dans le temps, mais la structure ne change pas : bouclez sur votre liste de requêtes, appelez scrape_all_pages pour chacune, et taguez chaque enregistrement avec la requête dont il provient avant de sauvegarder. La Crawling API gère le rendu et la rotation des IPs par requête, donc la mise à l'échelle concerne principalement votre rythme et le suivi du statut. Quelques habitudes maintiennent un cycle d'exécution long en bonne santé.
- Rythmez vos requêtes. Maintenez le sleep entre les pages et les requêtes plutôt que de les envoyer en rafale. Répartir le trafic est la meilleure défense unique contre les défis.
-
Lisez le statut. Surveillez le
cb_statussur chaque réponse. Une exécution qui commence à échouer vous indique de ralentir, ce n'est pas du bruit à ignorer. - Réessayez sur les échecs transitoires. Tout 5XX de l'API est gratuit, donc réessayer une exploration ratée ne vous coûte rien ; un court backoff avant la nouvelle tentative suffit généralement à régler le problème.
- Misez sur la rotation. La rotation résidentielle intégrée répartit les requêtes sur de nombreuses adresses d'utilisateurs réels. Si vous préférez acheminer votre propre trafic, le Smart AI Proxy vous offre la même rotation comme point d'entrée intégrable.
Pour le guide de pratiques plus large, consultez comment extraire des sites web sans être bloqué. Si vous souhaitez aussi extraire les encadrés de questions que Google affiche en milieu de page, notre guide ciblé sur l'extraction du People Also Ask de Google couvre ce bloc spécifiquement.
Est-il légal d'extraire les résultats de recherche Google ?
La possibilité d'extraire Google dépend des conditions d'utilisation de Google, de votre juridiction et de ce que vous faites des données. Les conditions de Google limitent l'accès automatisé, donc le scraping peut aller à l'encontre de ces conditions, quelle que soit la prudence de vos outils. Aucun des codes ici ne change cela ; il rend simplement la partie technique fonctionnelle. Lisez les conditions de Google et son robots.txt, et traitez les deux comme la frontière de ce que vous collectez.
Quelques lignes méritent d'être respectées. Collectez uniquement les données publiques de résultats de recherche : les titres, liens, extraits et positions que quiconque peut voir sur une page de résultats sans compte. Maintenez votre volume de requêtes modeste pour ne pas surcharger les serveurs de Google, et rythmez votre exploration plutôt que de la lancer à pleine vitesse. Ne collectez pas de données personnelles, ne récupérez pas de contenu derrière une connexion et ne redistribuez pas de médias protégés par droit d'auteur auxquels vous accédez via les liens des résultats. Ce sont les lignes qui rendent le travail défendable.
Si votre projet nécessite un accès agréé à grand volume, Google propose des produits officiels pour cela, notamment la Custom Search JSON API et la recherche programmatique via Google Cloud, qui est la bonne voie à cette échelle plutôt qu'un scraper plus astucieux. Ce guide est délibérément limité aux pages SERP publiques car c'est la ligne qui maintient le travail propre. Pour en savoir plus sur les obstacles spécifiques que Google place devant les scrapers et comment les gérer de manière responsable, consultez notre article sur les défis de l'extraction des résultats Google.
Points clés
- Une requête ordinaire échoue sur Google. Le SERP 2025 nécessite JavaScript pour se rendre et Google bloque le trafic à allure de scraper, vous avez donc besoin du rendu plus une IP de confiance en une seule requête.
-
Le scraper google-serp fait le gros du travail. Passez
{"scraper": "google-serp"}et la Crawling API rend la page, gère les vérifications anti-bot et retourne le SERP en JSON analysé. -
Lisez des clés JSON stables, pas des sélecteurs. Extrayez
position,title,urletdescriptiondepuissearchResults, ce qui vous isole des changements de balisage de Google. -
Paginez avec l'offset start. Augmentez
startpar multiples de 10 pour aller plus loin, arrêtez quand une page revient sans résultats organiques, et dormez entre les pages. - Restez sur les données publiques. Respectez les CGU de Google et robots.txt, maintenez un volume modeste, préférez la Custom Search API officielle pour les grands volumes, et ne touchez jamais aux données personnelles ou nécessitant une connexion.
Foire aux questions
Pourquoi une requête ordinaire retourne-t-elle une page vide de Google ?
À partir de 2025, la page de résultats de Google nécessite JavaScript pour se rendre, donc une requête HTTP brute qui n'exécute pas les scripts revient comme une coquille vide ou squelettique. Google bloque aussi le trafic qui semble automatisé. Récupérer via la Crawling API avec le scraper google-serp rend la page depuis une IP rotative de confiance et retourne les résultats en JSON analysé, vous obtenez donc de vrais résultats au lieu d'une page vide.
Puis-je extraire les résultats de recherche Google avec Python ?
Oui. Avec la bibliothèque Python Crawlbase, vous appelez la Crawling API, activez le scraper google-serp intégré et lisez les titres, liens, extraits et positions directement depuis le JSON retourné. L'API agit comme le pont qui achemine votre requête vers Google depuis une IP de confiance avec la page rendue, pour que les requêtes soient traitées sans blocage. Pour une vue plus large du SERP et d'autres approches, consultez le guide plus large sur l'extraction des pages de recherche Google.
En quoi cela diffère-t-il du guide plus large sur l'extraction de Google ?
Cet article est le tutoriel Python ciblé et opérationnel : configuration, récupération, analyse des résultats organiques, pagination et export, avec du code prêt à copier-coller. Le pilier plus large, comment extraire les pages de recherche Google, couvre la structure SERP complète (annonces, People Also Ask, panneau de connaissances, pack local), les approches multiples et la stratégie de mise à l'échelle. Commencez ici si vous voulez du code maintenant ; lisez le pilier pour la carte plus large.
Comment paginer à travers davantage de résultats Google ?
Google pagine par ensembles de 10 via le paramètre de requête start : la page deux est start=10, la page trois est start=20, et ainsi de suite. La fonction scrape_google_results convertit un numéro de page en cet offset, et scrape_all_pages boucle sur une plage de pages, s'arrêtant quand une page ne retourne aucun résultat organique. Maintenez un court sleep entre les pages pour rythmez l'exploration.
Dois-je gérer JavaScript moi-même lors de l'extraction de Google ?
Non. Le SERP de Google nécessite JavaScript pour se rendre, mais le scraper google-serp rend la page pour vous côté serveur, vous ne gérez donc pas de navigateur headless ni de flotte de rendu. Vous envoyez l'URL de recherche avec le scraper activé et recevez en retour des résultats rendus et analysés.
Comment stocker les résultats Google extraits ?
N'importe quel format structuré fonctionne. Le script complet dans ce guide écrit à la fois un fichier JSON, qui conserve la forme imbriquée, et un fichier CSV, qui vous donne un tableau plat de position, titre, lien et extrait pour les tableurs. De là, vous pouvez charger les enregistrements dans une base de données ou un pipeline de suivi de positions. Restez dans les données publiques de résultats de recherche et évitez tout ce qui nécessite une connexion.
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.
