Yandex est le moteur de recherche vers lequel la plupart des internautes en Russie se tournent en premier, et il exerce une attraction similaire dans plusieurs pays voisins. Selon la plupart des estimations, il détient plus de la moitié du marché de la recherche russe, ce qui rend ses résultats publics utiles pour quiconque suit la demande en langue russe, les classements régionaux ou la façon dont une marque se positionne sur un marché où Google ne domine pas. La page de résultats expose les mêmes données structurées qu'un outil SERP cherche partout : titres, liens, extraits et l'ordre dans lequel ils apparaissent.
Ce guide vous montre comment scraper les résultats de recherche Yandex avec Python de manière fiable. Vous construisez un petit scraper exécutable qui récupère une page de résultats rendue via la Crawling API, analyse chaque résultat organique avec BeautifulSoup et exporte les données en JSON et CSV. L'ensemble du tutoriel se limite aux données de résultats de recherche publiques que tout le monde peut voir sans compte, 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 script Python qui prend une URL de recherche Yandex publique, récupère le HTML via la Crawling API et extrait un enregistrement structuré pour chaque résultat organique de la page. Nous utilisons la requête "Winter Jackets" comme exemple fil rouge et extrayons ces champs de chaque résultat :
- Titre le texte du titre du résultat, tel qu'affiché dans l'annonce.
- URL le lien de destination vers lequel pointe le résultat.
- Description l'extrait affiché sous le titre.
- Position le rang du résultat sur la page, compté depuis le haut.
Pourquoi une requête ordinaire échoue sur Yandex
Si vous envoyez une requête HTTP brute à une URL de résultats Yandex depuis un script, vous obtenez rarement la page propre que vous voyez dans votre navigateur. Yandex surveille de près le trafic automatisé. Les requêtes qui ne ressemblent pas à un vrai navigateur, ou qui arrivent trop rapidement depuis une seule adresse, sont confrontées à une page de vérification (l'interstitiel "Êtes-vous un robot ?") ou bloquées purement et simplement avant d'atteindre les annonces. Répéter la même IP sur de nombreuses requêtes déclenche ces vérifications rapidement.
Un scraper Yandex fonctionnel a donc besoin de deux choses dans une seule requête : une IP que la plateforme lit comme un vrai visiteur, et, lorsque la page s'appuie sur des scripts, un navigateur qui la rend. Vous pouvez assembler cela vous-même avec un navigateur sans tête et un pool de proxies résidentiels rotatifs, mais maintenir ces éléments en bonne santé représente la majeure partie du travail. La Crawling API regroupe les deux en un seul appel : vous lui envoyez l'URL, elle récupère depuis une IP de confiance et rend si nécessaire, et elle retourne le HTML final à analyser.
Les vérifications anti-bot de Yandex s'appuient fortement sur le taux de requêtes par adresse. Une poignée de requêtes rapides depuis une seule IP suffit à déclencher son interstitiel de vérification. La Crawling API fait tourner de nombreuses adresses côté serveur, de sorte que les requêtes se répartissent sur celles-ci et qu'aucune seule ne dépasse une limite. Vous pouvez commencer avec jusqu'à 20 000 requêtes gratuites, sans carte de crédit requise.
Prérequis
Quelques éléments à mettre en place avant d'écrire le moindre code. Aucun ne prend beaucoup de temps.
Python de base. Vous devez être à l'aise pour écrire et exécuter un script Python et installer des packages avec pip. Si BeautifulSoup est nouveau pour vous, notre guide sur l'utilisation de BeautifulSoup en Python couvre les bases de l'analyse que ce tutoriel suppose acquises.
Python 3.8 ou version ultérieure. Vérifiez votre version 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 de requête depuis la page de documentation du compte. Crawlbase émet deux types de tokens : un token Normal pour les pages statiques et un token JavaScript pour les pages à fort usage de scripts. Les résultats organiques de Yandex sont disponibles dans le HTML initial, donc le token Normal est le bon choix ici. Vous obtenez jusqu'à 20 000 requêtes gratuites. Traitez le token comme un mot de passe : il authentifie vos requêtes, donc gardez-le en dehors 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 trois bibliothèques dont le scraper a besoin.
python --version python -m venv yandex_env source yandex_env/bin/activate pip install crawlbase beautifulsoup4 pandas
Sous Windows, activez l'environnement avec yandex_env\Scripts\activate à la place de la ligne source. Trois dépendances font le travail : crawlbase est le client officiel qui envoie votre requête à la Crawling API, beautifulsoup4 analyse le HTML retourné pour que vous puissiez extraire les champs par sélecteur CSS, et pandas gère l'export en CSV à la fin.
Étape 1 : Récupérer la page via la Crawling API
Commencez par obtenir le HTML. Une URL de recherche Yandex est le domaine principal plus la requête dans le paramètre text, donc https://yandex.com/search/?text=Winter%20Jackets recherche "Winter Jackets". Encodez la requête avec urllib.parse.quote pour que les espaces et les caractères spéciaux survivent au transit. Écrivez une petite fonction fetch_page_html() qui passe l'URL à la Crawling API avec votre token, vérifie que Yandex lui-même a retourné un statut 200, et renvoie le corps HTML décodé. Vérifier le statut avant d'analyser garde les échecs visibles plutôt que silencieux.
from crawlbase import CrawlingAPI from urllib.parse import quote API_TOKEN = "YOUR_CRAWLBASE_TOKEN" # replace with your Normal token crawling_api = CrawlingAPI({"token": API_TOKEN}) def fetch_page_html(url): response = crawling_api.get(url) if response["headers"]["cb_status"] == "200": return response["body"].decode("utf-8") print(f"Request failed with Crawlbase status {response['headers']['cb_status']}") return None if __name__ == "__main__": url = f"https://yandex.com/search/?text={quote('Winter Jackets')}" html = fetch_page_html(url) if html: print(html[:500])
L'appel crawling_api.get(url) retourne une réponse dont headers["cb_status"] est le statut que Yandex lui-même a retourné et dont body sont les octets bruts de la page. Vérifier cb_status == "200" signifie qu'un blocage ou une page de vérification apparaît comme un échec propre plutôt que d'alimenter des données parasites dans l'analyseur. Décoder le corps en UTF-8 est ce qui rend lisibles les titres et descriptions en cyrillique. Enregistrez le fichier sous yandex_scraper.py, exécutez-le avec python yandex_scraper.py, et vous devriez voir un vrai balisage de résultats dans les 500 premiers caractères, ce qui confirme que la récupération fonctionne avant d'écrire le moindre sélecteur.
Cette vérification cb_status (legacy pc_status) ne lit 200 que parce que la requête a atteint Yandex en ressemblant à un vrai visiteur dès le départ, contournant l'interstitiel "Êtes-vous un robot ?". La Crawling API récupère la page depuis une IP tournante, la rend quand la page a besoin d'un navigateur, et vous remet le HTML final, ce qui vous évite de gérer vous-même une flotte sans tête et de sourcer un pool de proxies résidentiels. Pointez-la sur une URL de résultats publique avec le niveau gratuit d'abord.
Étape 2 : Analyser les résultats avec BeautifulSoup
Une fois le HTML en main, chargez-le dans BeautifulSoup et extrayez chaque résultat par son sélecteur. Yandex encapsule chaque résultat organique dans un conteneur .serp-item ; à l'intérieur, le titre se trouve dans h2.organic__url-text, le lien de destination dans a.organic__url, et l'extrait dans div.organic__content-wrapper. Pour confirmer ces sélecteurs sur une page en direct, ouvrez l'URL des résultats Yandex dans votre navigateur, faites un clic droit sur un résultat, choisissez Inspecter et lisez les noms de classes sur l'élément ; les sélecteurs ci-dessous correspondent à la mise en page au moment de la rédaction.
from bs4 import BeautifulSoup def scrape_yandex_search(html_content): soup = BeautifulSoup(html_content, "html.parser") search_results = [] for position, result in enumerate(soup.select(".serp-item"), start=1): title_element = result.select_one("h2.organic__url-text") url_element = result.select_one("a.organic__url") description_element = result.select_one("div.organic__content-wrapper") if not title_element or not url_element: continue search_results.append({ "position": position, "title": title_element.get_text(strip=True), "url": url_element["href"], "description": description_element.get_text(strip=True) if description_element else None, }) return search_results
Sélectionner .serp-item vous donne un élément par résultat, et enumerate(..., start=1) vous donne la position gratuitement pendant la boucle, de sorte que le rang provient de l'ordre sur la page plutôt que d'un attribut fragile. Lire l'URL depuis le href de a.organic__url conserve la destination séparée du texte du titre. La vérification if not title_element or not url_element: continue ignore tout ce qui n'est pas un vrai résultat organique, ce qui exclut les blocs publicitaires et le balisage parasite de votre sortie. La description revient à None lorsque son conteneur est absent.
Yandex révise périodiquement le balisage de son interface, et les noms de classes comme organic__url-text peuvent changer lors d'un redéploiement. Traitez les sélecteurs ci-dessus comme un modèle de départ, pas comme un contrat. Quand 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 le sélecteur à 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é.
Étape 3 : Tout assembler
Reliez maintenant la récupération et l'analyse en un seul script exécutable. Crawlez la page de résultats rendue, passez le HTML à l'analyseur et affichez la sortie structurée en JSON. Définir ensure_ascii=False garde les caractères cyrilliques lisibles dans la sortie au lieu de les échapper en séquences \u.
from crawlbase import CrawlingAPI from bs4 import BeautifulSoup from urllib.parse import quote import json API_TOKEN = "YOUR_CRAWLBASE_TOKEN" crawling_api = CrawlingAPI({"token": API_TOKEN}) def fetch_page_html(url): response = crawling_api.get(url) if response["headers"]["cb_status"] == "200": return response["body"].decode("utf-8") print(f"Request failed with Crawlbase status {response['headers']['cb_status']}") return None def scrape_yandex_search(html_content): soup = BeautifulSoup(html_content, "html.parser") search_results = [] for position, result in enumerate(soup.select(".serp-item"), start=1): title_element = result.select_one("h2.organic__url-text") url_element = result.select_one("a.organic__url") description_element = result.select_one("div.organic__content-wrapper") if not title_element or not url_element: continue search_results.append({ "position": position, "title": title_element.get_text(strip=True), "url": url_element["href"], "description": description_element.get_text(strip=True) if description_element else None, }) return search_results def main(): search_query = "Winter Jackets" url = f"https://yandex.com/search/?text={quote(search_query)}" html_content = fetch_page_html(url) if html_content: search_results = scrape_yandex_search(html_content) print(json.dumps(search_results, ensure_ascii=False, indent=2)) if __name__ == "__main__": main()
Exécutez le script complet avec python yandex_scraper.py. Il récupère la page de résultats pour "Winter Jackets", extrait un enregistrement pour chaque annonce organique et affiche la liste en JSON formaté. Les deux mêmes fonctions sont tout ce dont vous avez besoin : changez la requête dans main() et l'analyseur gère ce qui revient.
À quoi ressemble la sortie
Vous obtenez une liste ordonnée propre d'objets de résultats, chacun avec sa position, son titre, son URL et sa description, prêt à écrire en JSON, CSV ou dans une base de données. Comme la requête exemple mélange des boutiques en anglais et en russe, vous pouvez voir la force régionale de Yandex dans les résultats eux-mêmes.
[ { "position": 1, "title": "Best Winter Jackets of 2024 | Switchback Travel", "url": "https://www.switchbacktravel.com/best-winter-jackets", "description": "Patagonia Tres 3-in-1 parka. Category: Casual. Fill: 4.2 oz. of 700-fill-power down." }, { "position": 2, "title": "Winter jacket: купить по низкой цене на Яндекс Маркете", "url": "https://market.yandex.ru/search?text=winter%20jacket", "description": "Купить winter jacket: 97 предложений, низкие цены, быстрая доставка." }, { "position": 3, "title": "Amazon.com: Winter Jackets", "url": "https://www.amazon.com/Winter-Jackets/s?k=Winter+Jackets", "description": "CAMEL CROWN Men's Mountain Snow Waterproof Ski Jacket, Detachable Hood, Fleece Parka." } ]
Un point à surveiller dans la sortie réelle : le titre cyrillique en position 2 conserve ses caractères d'origine grâce au décodage UTF-8 et à ensure_ascii=False. Si vous voyez des séquences d'échappement \u à la place, l'une de ces deux étapes est manquante.
Passage à l'échelle sur plusieurs pages et requêtes
Une requête sur une page est une démonstration ; un vrai travail couvre plusieurs recherches et va plus loin dans les résultats. Yandex pagine avec le paramètre de requête p, qui est un index de page basé sur zéro : p=0 est la première page, p=1 la deuxième, et ainsi de suite. La structure reste la même : construisez chaque URL avec le numéro de page suivant, récupérez-la via la Crawling API et analysez-la avec la même fonction. Une petite modification maintient les positions continues entre les pages au lieu de recommencer à 1 sur chaque page, et un court délai entre les requêtes cadence le crawl.
import time from urllib.parse import quote def scrape_all_pages(query, max_pages=5): base_url = f"https://yandex.com/search/?text={quote(query)}&p=" all_results = [] position = 1 for page in range(max_pages): html_content = fetch_page_html(base_url + str(page)) if not html_content: break page_results = scrape_yandex_search(html_content) for result in page_results: result["position"] = position position += 1 all_results.extend(page_results) time.sleep(2) # pace requests to respect the server return all_results
La boucle parcourt cinq pages par défaut, récupère chacune via la Crawling API et réaffecte une position croissante pour que les rangs restent continus de la page un à la page cinq. Le time.sleep de deux secondes entre les requêtes vous évite de marteler Yandex dans une boucle serrée. N'augmentez max_pages que jusqu'à ce dont vous avez réellement besoin ; les résultats plus profonds sont généralement moins pertinents de toute façon. 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 d'IP comme point de terminaison proxy intégré.
Export en CSV
Le JSON est pratique dans un terminal, mais un CSV s'ouvre directement dans un tableur, ce que la plupart des analystes veulent réellement. pandas transforme la liste de dictionnaires de résultats en CSV en deux lignes.
import pandas as pd def save_to_csv(results, filename="yandex_search_results.csv"): df = pd.DataFrame(results) df.to_csv(filename, index=False, encoding="utf-8-sig") print(f"Saved {len(results)} results to {filename}") if __name__ == "__main__": results = scrape_all_pages("Winter Jackets", max_pages=3) save_to_csv(results)
Construire le DataFrame à partir de la liste de dictionnaires vous donne une colonne par champ (position, title, url, description) et une ligne par résultat. Passer index=False supprime l'index de ligne propre à pandas du fichier, et encoding="utf-8-sig" écrit une marque d'ordre d'octets pour que les descriptions cyrilliques s'ouvrent correctement dans Excel plutôt que de se transformer en caractères incompréhensibles. À partir de là, vous pouvez étendre le même schéma pour écrire dans une base de données comme SQLite si vous préférez un stockage compatible avec les requêtes.
Rester non bloqué
Même avec une IP de confiance gérée pour vous, Yandex surveille le trafic ayant la forme d'un scraper, et ses vérifications anti-bot sont plus strictes que de nombreuses cibles occidentales. Quelques habitudes maintiennent une exécution en bonne santé.
- Cadencez vos requêtes. Marteler les pages de résultats dans une boucle serrée est le moyen le plus rapide de déclencher l'interstitiel de vérification. Espacez les requêtes et variez vos requêtes au lieu de paginer un terme à pleine vitesse.
- Misez sur la rotation. Un pool d'adresses IP répartit les requêtes pour qu'aucune seule ne déclenche les vérifications de taux par adresse de Yandex. La Crawling API gère cela pour vous ; si vous construisez votre propre pile, c'est la partie à bien maîtriser.
- Lisez les codes de statut. Une exécution qui commence à retourner des défis ou des statuts autres que 200 vous signale que le débit ou le niveau d'IP actuels ne sont plus suffisants. Traitez cela comme un signal pour ralentir, pas comme du bruit à ignorer.
- Réinspectez quand les champs sont vides. Yandex modifie son balisage périodiquement. Si les résultats cessent d'être analysés, ouvrez une page en direct dans les outils de développement et mettez les sélecteurs à jour.
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. La même approche s'applique à d'autres moteurs : nos guides sur le scraping des résultats de recherche Bing et le scraping des pages de recherche Google utilisent la même structure de récupération puis d'analyse avec des sélecteurs différents.
Est-il légal de scraper Yandex ?
La légitimité du scraping de Yandex dépend des conditions d'utilisation de Yandex, de votre juridiction et de ce que vous faites avec les données. Comme la plupart des moteurs de recherche, Yandex impose des limites à l'accès automatisé dans ses conditions, donc le scraping peut aller à l'encontre de ces conditions quelle que soit la précision de vos outils. Aucun code ici ne change cela ; il fait seulement fonctionner la partie technique. Lisez les conditions de Yandex et son robots.txt, et traitez les deux comme la limite de ce que vous collectez.
Quelques lignes à respecter. Collectez uniquement les données de résultats de recherche publiques : les titres, liens, descriptions et positions que tout le monde peut voir sur une page de résultats sans compte. Gardez votre volume de requêtes suffisamment bas pour ne pas solliciter les serveurs de Yandex, et cadencez votre crawl plutôt que de l'exécuter à fond. Yandex publie des produits officiels pour certaines données structurées, comme les API Yandex Maps et Yandex Market, donc là où un point de terminaison approuvé existe pour ce dont vous avez besoin, c'est une meilleure voie que le scraping de la SERP.
Ce guide se limite délibérément aux pages de résultats de recherche publiques car c'est la ligne qui rend le travail défendable. Il ne couvre rien derrière une connexion, les données de compte ou personnelles, ni les médias protégés par le droit d'auteur extraits des destinations liées. Données SERP publiques uniquement. Si votre projet a besoin de plus que cela, un accord officiel sur les données est la bonne voie, et non un scraper plus malin.
Points clés
- Yandex est fort dans sa région. Il domine la recherche en langue russe et régionale, donc ses résultats publics sont un signal utile là où Google ne domine pas.
- La Crawling API récupère depuis une IP de confiance. Envoyez-lui l'URL, elle fait tourner les adresses côté serveur et rend si nécessaire, et retourne le HTML final, contournant l'interstitiel "Êtes-vous un robot ?".
-
BeautifulSoup fait l'extraction. Sélectionnez chaque
.serp-item, puis lisez le titre, l'URL, la description et la position depuis celui-ci, et attendez-vous à ce que les noms de classes évoluent avec le temps. -
Paginez avec l'index p. Incrémentez
pd'une unité par page pour aller plus loin dans les résultats, maintenez les positions continues et cadencez les requêtes avec un délai entre les pages. - Restez sur les données publiques. Respectez les CGU et le robots.txt de Yandex, gardez le volume bas, préférez les API officielles comme Yandex Market là où elles conviennent, et ne touchez jamais aux comptes ou données personnelles.
Foire aux questions
Qu'est-ce que Yandex et pourquoi le scraper ?
Yandex est le moteur de recherche leader en Russie, souvent appelé le "Google de la Russie", et il propose également des cartes, une messagerie, un marché et des services cloud. Les gens scrapent ses résultats publics pour suivre les classements en langue russe et régionaux, étudier les tendances de recherche, surveiller comment les marques se positionnent sur ce marché et collecter des données pour des recherches que les outils centrés sur Google ne couvrent pas.
Puis-je scraper les résultats de recherche Yandex avec Python ?
Oui. Avec le client crawlbase et BeautifulSoup, vous pouvez récupérer une page de résultats et extraire les titres, URL, descriptions et positions. La Crawling API sert de pont qui achemine votre requête vers Yandex depuis une IP de confiance, de sorte que les requêtes sont traitées normalement au lieu de déclencher l'interstitiel de vérification. Pour un guide Python plus large, consultez notre article sur le scraping de sites web avec Python.
Pourquoi une requête ordinaire est-elle bloquée sur Yandex ?
Yandex signale le trafic qui ne ressemble pas à un vrai navigateur, et il surveille de près le taux de requêtes par IP. Quelques requêtes rapides depuis une adresse déclenchent sa page de vérification "Êtes-vous un robot ?" ou un blocage pur et simple. Récupérer via la Crawling API, qui fait tourner les IP et rend si nécessaire, fait paraître chaque requête comme un visiteur ordinaire, ce qui vous donne la vraie page de résultats.
Comment paginer à travers plus de résultats Yandex ?
Utilisez le paramètre de requête p, qui est un index de page basé sur zéro : p=0 est la première page, p=1 la deuxième, et ainsi de suite. Construisez chaque URL de page avec l'index suivant, récupérez-la via la Crawling API, analysez-la avec la même fonction, réaffectez une position croissante pour que les rangs restent continus, et marquez une pause de quelques secondes entre les requêtes pour cadencer le crawl plutôt que de le marteler.
Comment gérer les résultats en langue russe et le texte cyrillique ?
Décodez le corps de la réponse en UTF-8 lorsque vous le lisez, et lors de l'export, écrivez le JSON avec ensure_ascii=False ou le CSV avec encoding="utf-8-sig". Ces deux étapes gardent les titres et descriptions cyrilliques lisibles au lieu de les transformer en échappements \u ou en caractères incompréhensibles. La force régionale de Yandex signifie que de nombreux résultats reviennent en russe, donc cela importe davantage ici que sur un scraping Google.
Mes sélecteurs ne retournent rien. Qu'est-ce qui a changé ?
Presque certainement le balisage de Yandex. Les noms de classes comme organic__url-text et organic__content-wrapper peuvent changer lorsque Yandex redéploie son interface, 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.
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.
