Google Scholar est la référence des chercheurs, étudiants et universitaires pour trouver des articles scientifiques, des actes de conférences, des thèses et des citations dans presque toutes les disciplines. Sa page de résultats est un enregistrement bibliographique compact : chaque résultat porte un titre d'article, les auteurs, le lieu et la date de publication, le nombre de citations et un lien vers la source. Cela fait de Google Scholar un point de départ précieux pour les revues de littérature, l'analyse de citations et le suivi de l'évolution d'un domaine au fil du temps.

Ce guide vous montre comment extraire les résultats de Google Scholar avec Python de manière fiable. Vous construirez un petit script opérationnel qui récupère une page de résultats rendue via la Crawling API, analyse chaque résultat avec BeautifulSoup et exporte des enregistrements propres en JSON et CSV. L'ensemble du tutoriel se limite aux données bibliographiques publiques visibles par quiconque sur une page de résultats, et la section sur la légalité en fin d'article n'est pas un simple remplissage, alors lisez-la avant d'utiliser ce script à grande échelle.

Ce que vous allez construire

Un script Python qui prend une URL de recherche Google Scholar, récupère le HTML via la Crawling API et extrait un enregistrement structuré pour chaque résultat sur la page. Nous utiliserons la requête "Data Science" comme exemple de référence et extrairons ces champs pour chaque résultat :

  • Titre le titre de l'article ou du livre tel qu'il apparaît dans le résultat.
  • Auteurs les noms des auteurs analysés depuis la ligne de signature sous le titre.
  • Publication la revue, la conférence, l'éditeur ou la source nommée dans la ligne de signature.
  • Année l'année de publication, lorsque la ligne de signature en inclut une.
  • Citations le nombre de citations issu du lien "Cited by" sous le résultat.
  • Lien l'URL de destination vers laquelle pointe le titre du résultat.

Pourquoi une requête ordinaire échoue sur Google Scholar

Si vous envoyez une requête HTTP brute à une URL de résultats Google Scholar depuis un script, vous n'obtenez que rarement la page propre que vous voyez dans votre propre navigateur. Scholar surveille de près le trafic automatisé. Les requêtes qui ne ressemblent pas à un vrai navigateur se heurtent à un CAPTCHA, reçoivent une page de vérification ou sont limitées après quelques appels, et une seule IP de datacenter effectuant des requêtes répétées est un signal immédiat. La page s'appuie également sur les scripts par endroits, donc les récupérations statiques peuvent revenir avec du contenu manquant qu'un navigateur rendu afficherait.

Un scraper Scholar fonctionnel a donc besoin de deux choses en une seule requête : une IP que la plateforme considère comme un visiteur réel et, lorsque la page en a besoin, un navigateur qui la rend. Vous pouvez assembler cela vous-même avec un navigateur headless et un pool de proxies résidentiels rotatifs, mais maintenir ces éléments en bon état représente l'essentiel du travail. La Crawling API combine les deux en un seul appel : vous lui envoyez l'URL, elle récupère depuis une IP résidentielle de confiance et rend si nécessaire, et retourne le HTML final prêt à analyser.

Pourquoi la gestion des CAPTCHA est importante ici

Google Scholar est l'une des cibles qui commence le plus rapidement à servir des CAPTCHA dès qu'elle détecte une rafale de requêtes automatisées depuis une adresse. La Crawling API fait tourner les IPs résidentielles et absorbe ces défis côté serveur, vous n'avez donc pas à sourcer des proxies ni à résoudre vous-même des CAPTCHA. Vous pouvez démarrer avec jusqu'à 20 000 requêtes gratuites, sans carte de crédit.

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 BeautifulSoup est nouveau pour vous, notre guide d'utilisation de BeautifulSoup en Python couvre les bases de l'analyse 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.

Un compte et un token Crawlbase. Inscrivez-vous, ouvrez votre tableau de bord et copiez votre token de requête. Crawlbase propose deux types de tokens, Normal et JavaScript ; le token Normal est le bon pour Google Scholar. Vous obtenez jusqu'à 20 000 requêtes gratuites. 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 les deux bibliothèques dont le scraper a besoin.

bash
python --version

python -m venv scholar_env
source scholar_env/bin/activate

pip install requests beautifulsoup4

Sous Windows, activez l'environnement avec scholar_env\Scripts\activate à la place de la ligne source. Deux dépendances effectuent le travail : requests envoie l'appel HTTP à la Crawling API, et beautifulsoup4 analyse le HTML retourné pour extraire les champs individuels par sélecteur CSS.

Étape 1 : récupérer la page via la Crawling API

Commencez par obtenir le HTML. Écrivez une petite fonction crawl() qui envoie votre URL cible à la Crawling API avec votre token, vérifie que la page Scholar sous-jacente est revenue avec un statut 200 et retourne le corps HTML. Vérifier le statut avant d'analyser permet de rendre les échecs visibles plutôt que silencieux.

python
import json
import requests

API_TOKEN = "YOUR_CRAWLBASE_TOKEN"  # replace with your token
API_ENDPOINT = "https://api.crawlbase.com/"

def crawl(url):
    params = {"token": API_TOKEN, "url": url}
    response = requests.get(API_ENDPOINT, params=params)
    response.raise_for_status()

    data = json.loads(response.text)
    if data["original_status"] != 200:
        raise Exception(f"Unable to crawl '{url}'")

    return data["body"]

if __name__ == "__main__":
    url = "https://scholar.google.com/scholar?q=Data+Science"
    html = crawl(url)
    print(html[:500])

L'API retourne une enveloppe JSON, vous chargez donc la réponse avec json.loads et lisez deux champs : original_status est le statut que Google Scholar lui-même a retourné, et body est le HTML de la page. La vérification sur original_status signifie qu'une page CAPTCHA ou un blocage remonte comme une exception plutôt que d'alimenter du contenu indésirable dans le parseur. Le terme de recherche est porté dans le paramètre q, qui est la manière dont Scholar transmet la requête. Exécutez le script avec python crawling.py et vous devriez voir le vrai balisage de résultats dans les 500 premiers caractères, ce qui confirme que la récupération fonctionne avant d'écrire un seul sélecteur.

Crawlbase Crawling API

La vérification original_status ne lit 200 que parce que la requête a atteint Google Scholar comme un visiteur réel dès le départ. La Crawling API récupère la page depuis une IP résidentielle rotative, absorbe les défis CAPTCHA que Scholar lance au trafic automatisé et rend lorsque la page nécessite un navigateur, puis vous remet le HTML final. Vous évitez de gérer vous-même une flotte headless et de sourcer un pool de proxies résidentiels. Commencez par une URL de résultats publique sur le niveau gratuit.

Étape 2 : inspecter la structure des résultats

Avant d'analyser, ouvrez une page de résultats Google Scholar dans votre navigateur, faites un clic droit sur un résultat et choisissez Inspecter pour voir comment chaque annonce est construite. Chaque résultat est encapsulé dans un élément div.gs_r portant un attribut data-rp indiquant sa position. À l'intérieur de cet encapsulant, le titre se trouve dans un en-tête h3.gs_rt avec le lien de destination comme ancre à l'intérieur, la ligne de signature (auteurs, publication, année) se trouve dans un élément div.gs_a, l'extrait vit dans div.gs_rs, et le nombre de citations "Cited by" apparaît dans les liens de pied de page sous div.gs_fl. Ces noms de classes sont les sélecteurs que le parseur cible.

Le champ qui nécessite un peu de travail est la ligne de signature. Google Scholar regroupe auteurs, publication et année dans une seule chaîne gs_a séparée par des tirets, par exemple H Wickham, M Çetinkaya-Rundel - 2023 - books.google.com. Nous divisons cette chaîne pour séparer les trois parties dans l'étape suivante.

Étape 3 : analyser les résultats avec BeautifulSoup

Une fois le HTML en main, chargez-le dans BeautifulSoup et extrayez chaque résultat via les sélecteurs de l'étape précédente. Le parseur de ligne de signature divise le texte gs_a sur ses séparateurs de tirets, puis scanne les segments du milieu et de fin pour trouver une année à quatre chiffres, de sorte que les auteurs, la publication et l'année atterrissent chacun dans leur propre champ.

python
import re
from bs4 import BeautifulSoup

def parse_byline(text):
    # gs_a packs "authors - publication, year - host"
    parts = [p.strip() for p in text.split(" - ")]
    authors = parts[0] if parts else ""
    publication = parts[1] if len(parts) > 1 else ""
    year = None
    match = re.search(r"\b(19|20)\d{2}\b", text)
    if match:
        year = match.group()
        publication = re.sub(r",?\s*" + year, "", publication).strip()
    return authors, publication, year

def parse_citations(result_item):
    for a in result_item.select("div.gs_fl a"):
        text = a.get_text(strip=True)
        if text.startswith("Cited by"):
            return int(text.replace("Cited by", "").strip())
    return 0

def parse_google_scholar(html):
    soup = BeautifulSoup(html, "html.parser")
    results = []

    for item in soup.select("div.gs_r[data-rp]"):
        heading = item.find("h3", class_="gs_rt")
        link = item.select_one("h3.gs_rt > a")
        byline = item.find("div", class_="gs_a")
        if not heading:
            continue

        authors, publication, year = "", "", None
        if byline:
            authors, publication, year = parse_byline(byline.get_text(strip=True))

        results.append({
            "position": int(item["data-rp"]),
            "title": heading.get_text(strip=True),
            "authors": authors,
            "publication": publication,
            "year": year,
            "citations": parse_citations(item),
            "link": link["href"] if link else None,
        })

    return results

Le sélecteur div.gs_r[data-rp] correspond à chaque encapsulant de résultat et ignore les blocs de mise en page sans position. Pour chacun, h3.gs_rt donne le titre et l'ancre à l'intérieur donne le lien, div.gs_a alimente le parseur de ligne de signature, et parse_citations parcourt les liens de pied de page dans div.gs_fl pour l'entrée "Cited by", retournant 0 quand un article n'en a aucune. Lire la position directement depuis data-rp correspond au rang que Scholar lui-même attribue. La garde if not heading: continue exclut le balisage parasite de votre sortie.

Les sélecteurs peuvent évoluer

Google change parfois le balisage de Scholar. Les noms de classes comme gs_rt, gs_a et gs_fl sont stables depuis longtemps, mais considérez-les comme un modèle de départ, non comme un contrat. Si un champ revient vide pour chaque résultat, réinspectez une page en direct dans les outils de développement de votre navigateur et mettez à jour le sélecteur. La maintenance périodique des sélecteurs est normale pour tout scraper en production.

Étape 4 : tout assembler et exporter en JSON et CSV

Maintenant, combinez la récupération et l'analyse en un seul script opérationnel, puis écrivez la sortie structurée en JSON et CSV. Le JSON conserve la forme imbriquée pour un usage programmatique, et le CSV s'importe directement dans un tableur ou un dataframe pandas pour une revue de littérature. Régler ensure_ascii=False garde les noms d'auteurs avec des caractères accentués lisibles dans le fichier.

python
import csv
import json
import requests
from bs4 import BeautifulSoup
from scholar_parser import parse_google_scholar  # the parser from step 3

API_TOKEN = "YOUR_CRAWLBASE_TOKEN"
API_ENDPOINT = "https://api.crawlbase.com/"
FIELDS = ["position", "title", "authors", "publication", "year", "citations", "link"]

def crawl(url):
    params = {"token": API_TOKEN, "url": url}
    response = requests.get(API_ENDPOINT, params=params)
    response.raise_for_status()
    data = json.loads(response.text)
    if data["original_status"] != 200:
        raise Exception(f"Unable to crawl '{url}'")
    return data["body"]

def save_json(results, path="scholar_results.json"):
    with open(path, "w", encoding="utf-8") as f:
        json.dump(results, f, ensure_ascii=False, indent=2)

def save_csv(results, path="scholar_results.csv"):
    with open(path, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=FIELDS)
        writer.writeheader()
        writer.writerows(results)

def main():
    query = "Data Science"
    url = f"https://scholar.google.com/scholar?q={query.replace(' ', '+')}"
    html = crawl(url)
    results = parse_google_scholar(html)
    save_json(results)
    save_csv(results)
    print(f"Saved {len(results)} results to JSON and CSV")

if __name__ == "__main__":
    main()

Exécutez le script complet avec python main.py. Il récupère la page de résultats pour "Data Science", extrait un enregistrement pour chaque résultat et écrit à la fois scholar_results.json et scholar_results.csv. Les mêmes fonctions suffisent : changez la requête et le parseur gère ce qui revient.

À quoi ressemble la sortie

Vous obtenez une liste ordonnée d'objets résultats, chacun avec le titre analysé, les auteurs, la publication, l'année, le nombre de citations et le lien, prêt à écrire en JSON, CSV ou dans une base de données.

json
[
  {
    "position": 0,
    "title": "[BOOK][B] R for data science",
    "authors": "H Wickham, M Çetinkaya-Rundel, G Grolemund",
    "publication": "books.google.com",
    "year": "2023",
    "citations": 8421,
    "link": "https://books.google.com/books?id=TiLEEAAAQBAJ"
  },
  {
    "position": 1,
    "title": "Data science and its relationship to big data and data-driven decision making",
    "authors": "F Provost, T Fawcett",
    "publication": "Big data",
    "year": "2013",
    "citations": 2510,
    "link": "https://www.liebertpub.com/doi/abs/10.1089/big.2013.1508"
  }
]

Le miroir CSV porte les mêmes colonnes, une ligne par résultat, avec une ligne d'en-tête position,title,authors,publication,year,citations,link. Ce format est celui que la plupart des flux de travail de revue de littérature veulent, puisque vous pouvez trier par nombre de citations ou filtrer par année directement dans un tableur.

Gérer la pagination

Une requête sur une page est une démonstration ; un vrai travail va plus loin dans les résultats. Google Scholar pagine avec le paramètre de requête start, qui est un offset par multiples de 10 : start=10 donne la deuxième page, start=20 la troisième, et ainsi de suite, avec dix résultats par page. La structure reste la même : construisez chaque URL, récupérez-la via la Crawling API et analysez-la avec la même fonction. Rythmez l'exécution avec une pause entre les requêtes plutôt que de les envoyer en rafale.

python
import time

def fetch_paginated_results(base_url, max_pages=5):
    all_results = []
    for page in range(max_pages):
        start = page * 10  # 10 results per page
        url = f"{base_url}&start={start}"
        html = crawl(url)
        all_results.extend(parse_google_scholar(html))
        time.sleep(3)
    return all_results

base_url = "https://scholar.google.com/scholar?q=Data+Science"
results = fetch_paginated_results(base_url, max_pages=5)
print(f"Collected {len(results)} results across 5 pages")

Toute réponse 5XX de la Crawling API est gratuite, donc réessayer une URL bloquée ou indisponible ne vous coûte rien. Si vous préférez acheminer votre propre trafic via un pool rotatif au lieu d'utiliser l'API gérée, le Smart AI Proxy vous offre la même rotation d'IP résidentielles comme point d'entrée proxy intégrable. Pour stocker plus que les résultats d'une seule exécution, écrivez les enregistrements de chaque page dans une base de données comme SQLite au fur et à mesure, indexée par titre et lien, plutôt que de tout conserver en mémoire.

Rester non bloqué

Même avec une IP de confiance gérée, Google Scholar surveille le trafic à l'allure d'un scraper, et il recourt aux CAPTCHA plus rapidement que la plupart des cibles de recherche. Quelques habitudes maintiennent un cycle d'exécution en bonne santé.

  • Rythmez vos requêtes. Bombarder les pages de résultats en rafale est le moyen le plus rapide d'être mis au défi. Espacez les requêtes et variez vos requêtes au lieu de parcourir un terme à toute vitesse.
  • Misez sur la rotation. Un pool d'IPs résidentielles répartit les requêtes sur de nombreuses adresses d'utilisateurs réels pour qu'aucune ne dépasse une limite. La Crawling API gère cela pour vous ; si vous construisez votre propre pile, c'est la partie à soigner.
  • Lisez les codes de statut. Une exécution qui commence à retourner des pages CAPTCHA ou de vérification vous indique que le taux ou le niveau IP actuel n'est plus suffisant. Traitez cela comme un signal de ralentissement, pas comme du bruit à ignorer.
  • Réinspectez quand des champs deviennent vides. Scholar change parfois son balisage. Si les résultats ne s'analysent plus, ouvrez une page en direct dans les outils de développement et mettez à jour les sélecteurs.

Pour le guide de pratiques plus large, consultez comment extraire des sites web sans être bloqué. Si vous extrayez aussi l'index Google principal, notre guide sur comment extraire les pages de recherche Google couvre la structure SERP ordinaire, et le guide général d'extraction Python présente les fondamentaux sur lesquels ce tutoriel s'appuie.

Est-il légal d'extraire Google Scholar ?

La possibilité d'extraire Google Scholar dépend des conditions d'utilisation de Google, de votre juridiction et de ce que vous faites des données. Les conditions de Google Scholar limitent l'accès automatisé et découragent explicitement le scraping à des fins commerciales, donc une collecte automatisée 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 Scholar et son robots.txt, et traitez les deux comme la frontière de ce que vous collectez.

Quelques lignes à respecter. Collectez uniquement les données bibliographiques publiques : les titres, auteurs, détails de publication, années, nombres de citations et liens que tout le monde peut voir sur une page de résultats sans compte. Maintenez votre volume de requêtes suffisamment bas pour ne pas surcharger les serveurs de Scholar, et rythmez votre exploration plutôt que de la lancer à pleine vitesse. Essentiellement, les résultats sont des métadonnées sur des articles, pas les articles eux-mêmes. N'utilisez pas un scraper pour récupérer ou redistribuer le texte intégral d'articles qui se trouvent derrière un paywall ou une licence d'éditeur ; c'est une question distincte de la lecture de métadonnées de citations publiques, et elle n'est pas couverte ici.

Ce guide est délibérément limité aux pages de résultats publics car c'est la ligne qui rend le travail défendable. Google ne publie pas d'API Scholar officielle largement disponible pour ce type d'accès, donc il n'existe pas de point d'accès agréé à grand volume vers lequel se replier, ce qui est une raison supplémentaire de rester modeste dans l'échelle et respectueux des règles du site. Si votre projet nécessite plus que des métadonnées publiques à faible volume, un jeu de données bibliographiques sous licence ou une API officielle d'éditeur est la bonne voie, pas un scraper plus astucieux.

Récapitulatif

Points clés

  • Scholar bloque le trafic à allure de scraper rapidement. Il sert des CAPTCHA rapidement dès qu'il détecte des requêtes automatisées depuis une IP, vous avez donc besoin d'une adresse résidentielle de confiance pour voir les vrais résultats.
  • La Crawling API récupère derrière une vraie IP. Envoyez-lui l'URL, elle fait tourner les IPs résidentielles et absorbe les CAPTCHA côté serveur, puis retourne le HTML final prêt à analyser.
  • BeautifulSoup effectue l'extraction. Sélectionnez chaque div.gs_r[data-rp], puis lisez le titre, le lien et la ligne de signature gs_a, et divisez cette ligne en auteurs, publication et année.
  • Les citations et la pagination sont simples. Lisez le nombre "Cited by" depuis div.gs_fl, et progressez en profondeur avec l'offset start par multiples de 10, en faisant une pause entre les pages.
  • Restez sur les métadonnées publiques. Respectez les CGU de Scholar et robots.txt, maintenez un volume faible, et ne jamais récupérer de texte intégral payant ni de données personnelles.

Foire aux questions

Pourquoi une requête ordinaire échoue-t-elle ou retourne-t-elle un CAPTCHA sur Google Scholar ?

Scholar signale le trafic qui ne ressemble pas à un vrai navigateur et limite rapidement les requêtes répétées depuis une seule IP de datacenter, donc un script brut a tendance à se heurter à un CAPTCHA ou à une page de vérification au lieu des résultats que vous voyez dans votre propre navigateur. Récupérer via la Crawling API, qui utilise des IPs résidentielles rotatives et gère les défis CAPTCHA côté serveur, fait ressembler la requête à un visiteur ordinaire pour obtenir la vraie page de résultats.

Comment puis-je extraire des données Google Scholar avec Python ?

Utilisez la bibliothèque requests pour envoyer votre URL de recherche à la Crawling API, puis analysez le HTML retourné avec BeautifulSoup. Sélectionnez chaque résultat div.gs_r[data-rp] et lisez le titre depuis h3.gs_rt, la ligne de signature depuis div.gs_a et le nombre de citations depuis div.gs_fl. Pour les fondamentaux de l'analyse, consultez notre guide BeautifulSoup.

Quels champs puis-je extraire d'un résultat Google Scholar ?

Ce tutoriel extrait le titre, les auteurs, la publication, l'année, le nombre de citations et le lien pour chaque résultat, plus la position depuis l'attribut data-rp. Les auteurs, la publication et l'année proviennent tous de la ligne de signature gs_a unique, que le parseur divise. Restez dans les métadonnées bibliographiques publiques et évitez de récupérer le texte intégral payant.

Comment obtenir le nombre de citations pour chaque article ?

Le pied de page de chaque résultat, le bloc div.gs_fl, contient un lien "Cited by N" quand l'article a des citations. Le parseur parcourt ces liens, trouve celui qui commence par "Cited by" et lit le nombre à la fin, retournant 0 pour les articles sans citations encore.

Comment paginer à travers davantage de résultats Google Scholar ?

Utilisez le paramètre de requête start, qui est un offset par multiples de 10 : start=10 est la deuxième page, start=20 la troisième, et ainsi de suite, avec dix résultats par page. Construisez chaque URL de page avec l'offset, récupérez-la via la Crawling API, analysez-la avec la même fonction, et faites une pause de quelques secondes entre les requêtes pour rythmez l'exploration plutôt que de la bombarder.

Puis-je analyser les données Google Scholar extraites par la suite ?

Oui. Exportez les résultats en CSV ou JSON, puis chargez-les dans un outil comme pandas pour l'analyse. Comme les enregistrements portent les nombres de citations et les années, vous pouvez trier par impact, filtrer par récence ou tracer comment la production d'un sujet augmente au fil du temps, ce qui est exactement ce dont une revue de littérature a besoin.

Commencer à construire

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.

En libre-service · Sans appel commercial requis · Volumes de crawl entreprise disponibles