Retour au blog
Cas d'utilisation
Mihai MaximLast updated on May 1, 202616 min read

Sélecteurs XPath et CSS : Choisir le bon

Sélecteurs XPath et CSS : Choisir le bon
En bref : les sélecteurs XPath et CSS permettent tous deux de localiser des éléments du DOM, mais ils répondent à des besoins différents. Les sélecteurs CSS sont plus rapides et plus lisibles pour les sélections simples. XPath s'impose lorsqu'il faut parcourir le DOM dans n'importe quelle direction, faire correspondre du contenu textuel ou gérer une logique conditionnelle complexe. La plupart des projets en production tirent profit d'une utilisation stratégique des deux.

Chaque script de web scraping, chaque workflow d'automatisation de navigateur et chaque test de bout en bout partage une exigence fondamentale : trouver des éléments dans le DOM. La question du choix entre les sélecteurs XPath et CSS se pose très tôt dans chaque projet, et choisir la mauvaise approche peut entraîner un ralentissement de l'exécution, des localisateurs fragiles et une maintenance fastidieuse.

XPath (XML Path Language) est un langage de requête conçu pour naviguer et sélectionner des nœuds dans des documents XML et HTML. Les sélecteurs CSS sont des chaînes de caractères de type modèle initialement conçues pour styliser le HTML, mais largement adoptées pour la sélection d'éléments dans les frameworks de test et de scraping. Les deux vous permettent d'accéder aux mêmes éléments, mais le chemin qu'ils empruntent (et les compromis en cours de route) diffèrent considérablement.

Ce guide détaille la syntaxe, les caractéristiques de performance, la prise en charge par les frameworks et le comportement dans les cas limites de chaque approche afin que vous puissiez faire un choix éclairé et en toute confiance pour votre projet.

XPath vs sélecteurs CSS en bref

Les sélecteurs XPath et CSS identifient tous deux des éléments au sein d'un document HTML ou XML, mais ils proviennent de mondes différents. XPath a été conçu pour la navigation dans les documents XML et prend en charge la traversée bidirectionnelle, ce qui signifie que vous pouvez passer d'un enfant à un parent aussi facilement que d'un parent à un enfant. Les sélecteurs CSS trouvent leur origine dans les feuilles de style et ne se déplacent que dans un seul sens : du parent vers l'enfant (ou le frère).

Voici le verdict en bref : si vos besoins en matière de sélection sont simples (ID, classes, attributs, combinateurs), les sélecteurs CSS constituent le choix le plus rapide et le plus lisible. Lorsque vous devez remonter la hiérarchie, faire correspondre du contenu textuel ou appliquer des filtres conditionnels complexes, XPath est la seule option qui vous permettra d'y parvenir.

Dimension

Sélecteurs CSS

XPath

Direction

De parent à enfant uniquement

Bidirectionnel (n'importe quel axe)

Vitesse

Généralement plus rapide (moteur natif)

Plus lent dans les navigateurs

Correspondance de texte

Non pris en charge

text(), contains()

Lisibilité

Concis, familier

Détaillé, courbe plus raide

Types de documents

HTML uniquement

HTML et XML

Fonctionnement de XPath

XPath, abréviation de XML Path Language, est un langage d'expression permettant de parcourir et d'interroger des documents XML, y compris HTML. Il traite le document comme une arborescence de nœuds et vous permet d'écrire des expressions de chemin qui sélectionnent un ou plusieurs de ces nœuds.

Chemins absolus vs chemins relatifs. Un chemin XPath absolu part de la racine du document et détaille chaque étape : /html/body/div[1]/ul/li[3]. Il est fragile car toute modification structurelle le rend invalide. Un chemin XPath relatif commence par // et correspond aux nœuds quelle que soit leur position dans l'arborescence : //li[@class='active']. Dans la pratique, les chemins relatifs sont presque toujours ce que vous recherchez.

C'est avec les méthodes d'axes que le XPath montre toute sa puissance. Des méthodes telles que parent::, ancestor::, following-sibling::et preceding-sibling:: vous permettent de vous déplacer dans n'importe quelle direction à partir d'un nœud de contexte. Par exemple, //span[@id='price']/parent::div sélectionne le parent div d'un élément spécifique span, ce que les sélecteurs CSS ne peuvent tout simplement pas faire.

Des fonctions clés telles que contains(), starts-with()et text() ajoutent un filtrage conditionnel. Vous pouvez localiser un élément dont le texte visible contient une sous-chaîne (//a[contains(text(), 'Next Page')]) sans s'appuyer du tout sur les attributs.

Une mise en garde importante : la plupart des environnements de navigateur ne prennent encore en charge que XPath 1.0, publié en 1999 par le W3C. XPath 2.0 et 3.0 ont introduit des fonctionnalités puissantes telles que les expressions régulières et des systèmes de types plus riches, mais vous les rencontrerez rarement dans l'automatisation basée sur les navigateurs. Des bibliothèques comme lxml (Python) offrent une prise en charge de XPath 2.0, donc la version dont vous disposez dépend de votre chaîne d'outils.

Fonctionnement des sélecteurs CSS

Un sélecteur CSS est une chaîne de caractères qui cible des éléments HTML en fonction de leur nom de balise, de leur ID, de leur classe, de leurs attributs, de leur position ou de leur état. Conçus à l'origine pour appliquer des styles dans des feuilles de style, les sélecteurs CSS sont devenus la méthode de sélection d'éléments par défaut dans la plupart des frameworks modernes d'automatisation et de scraping.

Les bases sont familières à tout développeur front-end. #main cible un élément par son ID. .card correspond aux éléments ayant une classe spécifique. div > p sélectionne les p d'un div. Les sélecteurs d'attributs tels que input[type="email"] et les pseudo-classes de position telles que :nth-child(2) vous permettent d'affiner davantage votre sélection.

Les pseudo-classes modernes comblent le fossé avec XPath. Le :has() , désormais largement pris en charge, vous permet de sélectionner un parent en fonction de ses enfants : div:has(> img.hero) sélectionne tout div qui contient directement un img avec la classe hero. Le :is() et :where() simplifient le regroupement, et :not() permet de gérer les exclusions. Ces ajouts signifient que les sélecteurs CSS peuvent désormais gérer certains cas de figure qui nécessitaient auparavant l'utilisation d'XPath.

Cela dit, les sélecteurs CSS ne peuvent pas sélectionner directement des nœuds de texte et restent limités à la traversée vers l'avant (de parent à enfant). Ils ne fonctionnent également qu'avec des documents HTML ; si vous devez interroger du XML brut ou des flux non HTML, XPath est votre seule option.

Comparaison syntaxique côte à côte

Comparer côte à côte les sélecteurs XPath et CSS est le moyen le plus rapide d’intérioriser leurs différences. Le tableau ci-dessous met en correspondance des objectifs de sélection courants avec les deux syntaxes, en ciblant les mêmes éléments de page hypothétiques.

Objectif de sélection

Sélecteur CSS

XPath

Par ID

#username

//*[@id='username']

Par classe

.card

//*[contains(@class,'card')]

Par attribut

a[href^="https"]

//a[starts-with(@href,'https')]

Enfant direct

ul > li

//ul/li

N-ième enfant

li:nth-child(3)

//li[3]

Par contenu textuel

Impossible

//a[text()='Login']

Parent de l'élément

div:has(> span.icon) (CSS4)

//span[@class='icon']/parent::div

Frère suivant

h2 ~ p

//h2/following-sibling::p

Ancêtre

Impossible

//span/ancestor::form

Quelques points ressortent. Pour les sélections d'ID, de classe et d'attribut, le CSS est nettement plus court et plus facile à lire. Mais dès que vous avez besoin d'une correspondance de texte ou d'une traversée d'ancêtres, XPath est la seule solution disponible. La pseudo-classe CSS :has() réduit cet écart pour la sélection des parents, mais il ne peut pas remplacer le système d'axes complet d'XPath.

Du point de vue de la lisibilité, les sélecteurs CSS semblent naturels à quiconque a déjà écrit une feuille de style. La syntaxe basée sur les chemins d'XPath est plus verbeuse, mais cette verbosité vous apporte de la précision pour les requêtes complexes. Si votre équipe comprend des développeurs front-end à l'aise avec le CSS, ils maîtriseront les sélecteurs CSS beaucoup plus rapidement que les expressions XPath.

Performances et vitesse

L'idée reçue est que les sélecteurs CSS sont plus rapides que XPath dans les environnements de navigateur, et dans la pratique, cela s'avère généralement vrai. Les navigateurs intègrent des moteurs de sélecteurs CSS natifs hautement optimisés, car la correspondance CSS est un élément central du pipeline de rendu. L'évaluation XPath, en revanche, se situe en dehors de ce chemin rapide et entraîne généralement plus de surcharge.

Cela dit, il n'existe pas de benchmarks publics standardisés et largement cités qui quantifient la différence exacte de performances entre XPath et les sélecteurs CSS. L'écart est réel mais souvent négligeable, à moins que vous n'exécutiez des dizaines de milliers d'évaluations de sélecteurs par page. Pour la plupart des workflows de scraping et de test, la vitesse des sélecteurs est rarement le goulot d'étranglement ; la latence réseau et le rendu des pages dominent le temps d'exécution.

En dehors du navigateur, la situation change. Des bibliothèques telles que lxml compilent les expressions XPath en code C optimisé, rendant l'évaluation XPath extrêmement rapide pour le scraping côté serveur en Python. Les utilisateurs de Scrapy, par exemple, ne constateront pratiquement aucune différence de vitesse entre les sélecteurs XPath et CSS, car les deux sont évalués via lxml en arrière-plan.

Filtrage avancé, parcours et lisibilité

La traversée bidirectionnelle de XPath est son principal avantage technique. L'utilisation d'axes tels que parent::, ancestor::, following-sibling::et preceding-sibling::, vous pouvez parcourir l'arborescence DOM dans n'importe quelle direction à partir de n'importe quel nœud de départ. Cela est indispensable lorsque l'élément que vous devez sélectionner ne possède pas d'attribut unique, mais entretient une relation prévisible avec un frère ou un ancêtre qui en possède un.

Les sélecteurs CSS ne fonctionnent que dans un sens. Vous pouvez passer d’un parent à un enfant (>) ou d'un frère précédent à un frère suivant (~, +), mais vous ne pouvez pas remonter. La :has() pseudo-classe comble partiellement cette lacune : elle vous permet de sélectionner conditionnellement un parent en fonction de ses descendants. Cependant, :has() ne vous offre pas un parcours complet des ancêtres, et sa prise en charge par les navigateurs, bien qu'en progression, n'est pas encore universelle dans les environnements plus anciens.

La sélection des nœuds de texte est un autre avantage évident de l'XPath. Des expressions telles que //td[contains(text(), 'Total')] vous permettent de localiser des éléments en fonction de leur contenu visible, ce qui est inestimable pour l'extraction de données sur des pages où les éléments ne portent aucune classe ou aucun identifiant significatif. Le CSS n'a pas d'équivalent.

La courbe d'apprentissage mérite d'être mentionnée lorsque vous évaluez les sélecteurs XPath par rapport aux sélecteurs CSS pour votre équipe. Les sélecteurs CSS bénéficient d'une grande familiarité ; la plupart des développeurs les ont utilisés dans des feuilles de style bien avant de s'intéresser à l'automatisation. Les expressions XPath, en particulier celles utilisant plusieurs axes ou des prédicats imbriqués, impliquent une charge cognitive plus importante. Cette complexité en vaut la peine lorsque vous en avez besoin, mais pour des sélections plus simples, elle constitue une charge inutile.

Compatibilité avec les frameworks et les bibliothèques

Tous les frameworks ne traitent pas les sélecteurs XPath et CSS de la même manière. Avant de vous engager dans une stratégie de sélecteurs, vérifiez ce que votre chaîne d'outils prend réellement en charge.

Framework / Bibliothèque

Sélecteurs CSS

XPath

Selenium (tous les langages)

Oui

Oui

Playwright

Oui

Oui

Marionnettiste

Oui

Oui (via $x())

Scrapy (Python)

Oui (via parsel)

Oui (via parsel/lxml)

lxml (Python)

Oui (via cssselect)

Oui (natif)

BeautifulSoup (Python)

Oui

Non (utiliser le backend lxml)

Cheerio (Node.js)

Oui

Non

Quelques nuances à noter. Puppeteer expose XPath via une méthode distincte $x() plutôt que via l'API de sélecteur principale $() API de sélection, ce qui rend l'intégration légèrement moins fluide. BeautifulSoup ne dispose pas d'un moteur XPath intégré ; si vous avez besoin d'utiliser XPath avec BeautifulSoup, vous devrez l'associer à un backend de parseur lxml. Cheerio est conçu pour fonctionner uniquement avec le CSS.

Pour les utilisateurs de Selenium qui comparent les sélecteurs XPath et CSS, les deux types sont des éléments de premier plan via By.CSS_SELECTOR et By.XPATH. De même, Playwright prend en charge les deux, ce qui en fait un bon choix si vous souhaitez bénéficier de la flexibilité nécessaire pour combiner différentes stratégies de sélection au sein d’une même suite de tests ou d’un pipeline d’analyse de données.

Cas particuliers : Shadow DOM, iframes et contenu dynamique

Les pages réelles sont rarement aussi épurées que les exemples des tutoriels, et le choix entre les sélecteurs XPath et CSS devient plus nuancé lorsque le Shadow DOM, les iframes et le contenu injecté dynamiquement entrent en jeu.

Shadow DOM. Par défaut, les sélecteurs CSS ne peuvent pas traverser une racine Shadow fermée. Playwright propose le préfixe css=pierce/ préfixe comme solution de contournement, mais les moteurs CSS standard des navigateurs s'arrêtent à la limite du Shadow DOM. XPath n'est d'aucune aide ici non plus ; il n'a absolument aucun concept natif de Shadow DOM. Dans les deux cas, vous avez généralement besoin d'API spécifiques au framework (comme locator() avec la fonction « piercing ») pour atteindre les éléments shadow.

Iframes. Ni XPath ni les sélecteurs CSS ne franchissent les limites des iframes par eux-mêmes. Vous devez d'abord basculer le pilote ou le contexte vers le document de l'iframe (driver.switchTo().frame() dans Selenium, frame.contentFrame() dans Playwright), puis exécuter votre sélecteur dans cette portée.

Contenu dynamique. Les applications monopages qui réécrivent le DOM lors de la navigation posent un défi différent. Les sélecteurs CSS ciblant des attributs stables comme data-testid ou aria-label ont tendance à être plus fiables ici que les sélecteurs basés sur les classes, qui peuvent changer d'une version à l'autre. Les expressions XPath liées au contenu textuel peuvent également être fiables, à condition que le texte visible reste cohérent.

Écrire des sélecteurs résilients

Quelle que soit votre position sur le débat XPath vs sélecteurs CSS, l'écriture de sélecteurs qui résistent aux modifications du DOM importe plus que le langage que vous choisissez. Les localisateurs fragiles sont la principale cause de tests instables et de scrapers défaillants.

Bonnes pratiques pour les deux types :

  • Privilégiez les attributs stables. Utilisez data-testid, aria-labelou d'autres attributs sémantiques plutôt que des noms de classe générés automatiquement ou des index de position.
  • Restez concis dans vos sélecteurs. Un sélecteur CSS tel que [data-testid="submit-btn"] est plus résilient que div.form-wrapper > div:nth-child(3) > button.btn-primary. Il en va de même pour XPath : //button[@data-testid='submit-btn'] est préférable à un chemin absolu à cinq niveaux.
  • Évitez les XPath absolus. Les sélecteurs commençant par /html/body/... ne fonctionnent plus dès qu'un élément parent change. Utilisez toujours des XPath relatifs commençant par //.

Anti-modèles courants à éviter :

  • Enchaîner plus de trois niveaux de combinateurs de descendants en CSS
  • Utilisation de la sélection XPath position() ou la sélection basée sur l'index (div[4]) alors qu'un attribut sémantique existe
  • S'appuyer sur des noms de classes générés dynamiquement (courant dans les frameworks CSS-in-JS) pour l'un ou l'autre type de sélecteur

Investir dès le départ dans une stratégie de sélection, choisir des ancrages stables et documenter vos conventions permet de gagner un temps considérable en débogage à mesure que votre projet évolue.

Quand utiliser XPath, les sélecteurs CSS ou les deux

Il n'y a pas de gagnant universel dans le débat XPath contre sélecteurs CSS. Le bon choix dépend de ce que vous développez.

Privilégiez les sélecteurs CSS lorsque vos sélections impliquent des ID, des classes, des attributs ou des pseudo-classes de position. Ils sont plus rapides dans les navigateurs, plus faciles à lire et pris en charge partout. Pour les tâches simples de web scraping et la plupart des automatisations de tests front-end, les sélecteurs CSS couvrent 80 % ou plus de vos besoins de localisation avec moins de code.

Optez pour XPath lorsque vous devez remonter la hiérarchie (sélection de parents ou d'ancêtres), faire correspondre du contenu textuel ou appliquer des filtres conditionnels complexes enchaînant plusieurs prédicats. XPath est également le meilleur choix lorsque vous travaillez avec des documents XML non HTML ou lorsque les éléments cibles ne possèdent aucun attribut utile.

Utilisez les deux lorsque votre projet le justifie. Dans Selenium ou Playwright, il n'y a aucun coût à mélanger By.CSS_SELECTOR et By.XPATH dans le même fichier de test. Une approche hybride vous permet d'utiliser CSS pour les sélections simples et rapides et XPath pour les quelques cas particuliers qui le nécessitent.

Liste de contrôle de référence rapide

Utilisez cette liste de contrôle pour faire correspondre les contraintes de votre projet au type de sélecteur approprié :

  • La vitesse est la priorité absolue et vous exécutez le test dans un navigateur : utilisez les sélecteurs CSS.
  • Vous avez besoin d'un parcours des parents ou des ancêtres : utilisez XPath.
  • Vous devez effectuer une correspondance en fonction du contenu textuel visible : utilisez XPath.
  • Votre framework ne prend en charge qu'un seul type (par exemple, Cheerio ne prend en charge que le CSS) : utilisez ce qui est disponible.
  • Vous effectuez du scraping sur des flux XML ou des données non HTML : utilisez XPath.
  • Votre équipe est principalement composée de développeurs front-end : privilégiez les sélecteurs CSS pour une prise en main plus rapide.
  • Le DOM change fréquemment et vous souhaitez des localisateurs résilients : utilisez le type qui cible data-testid ou aria-label (les deux gèrent bien cela).

Points clés

  • Les sélecteurs CSS sont généralement plus rapides dans les environnements de navigateur et plus lisibles pour les sélections standard (ID, classe, attribut, positionnel).
  • XPath est la seule option lorsque vous avez besoin d'un parcours bidirectionnel du DOM, d'une correspondance de contenu textuel ou d'une sélection d'ancêtres.
  • Les pseudo-classes CSS modernes telles que :has() réduisent l'écart de fonctionnalités, mais elles ne remplacent pas entièrement le système d'axes de XPath.
  • La prise en charge des frameworks varie : Cheerio et BeautifulSoup (sans lxml) sont exclusivement CSS, tandis que Selenium et Playwright prennent en charge les deux types de sélecteurs de manière égale.
  • Lorsqu'on compare les sélecteurs XPath et CSS, la décision la plus importante consiste à écrire des sélecteurs résilients qui ciblent des attributs stables plutôt que des localisateurs positionnels ou de classe générée, plus fragiles.

FAQ

Puis-je utiliser à la fois des sélecteurs XPath et CSS dans le même test Selenium ?

Oui. Selenium prend en charge les deux types de sélecteurs via By.CSS_SELECTOR et By.XPATH, et vous pouvez les combiner librement au sein d'un même fichier de test, voire d'une même méthode de test. Le passage de l'un à l'autre n'entraîne aucune perte de performance ; utilisez donc le type qui convient le mieux à la recherche de chaque élément.

Les sélecteurs CSS modernes tels que :has() remplacent-ils XPath pour la sélection des éléments parents ?

En partie. La :has() pseudo-classe vous permet de sélectionner un élément parent en fonction de ses enfants, ce qui couvre le scénario de sélection de parent le plus courant. Cependant, elle ne prend pas en charge la traversée complète des ancêtres sur plusieurs niveaux, la logique des frères et sœurs précédents, ni les chaînes conditionnelles que permettent les axes XPath. Considérez :has() couvre environ 60 % des cas qui nécessitaient auparavant l'utilisation de XPath pour la navigation ascendante.

Quel type de sélecteur est le plus fiable pour les applications dynamiques à page unique ?

Aucun des deux n'est intrinsèquement plus fiable. La fiabilité dépend de ce à quoi vous ancrez votre sélecteur, et non du langage de sélection lui-même. Les sélecteurs ciblant data-testid ou aria-label restent stables lors des réaffichages du framework, qu'ils soient écrits en CSS ou en XPath. Évitez les sélecteurs qui s'appuient sur des noms de classe générés automatiquement ou des indices de position profonds.

XPath est-il pris en charge dans Puppeteer et Playwright ?

Oui, les deux prennent en charge XPath. Puppeteer l'expose via la $x() méthode (ou page.evaluate avec document.evaluate). Playwright prend en charge XPath en natif dans son locator() et $() API. Dans les deux outils, les sélecteurs CSS sont la valeur par défaut et les plus couramment utilisés, mais XPath est disponible lorsque vous avez besoin de ses capacités de parcours.

Conclusion

La question « XPath ou sélecteurs CSS ? » n'a pas de réponse unique, car il s'agit d'outils complémentaires qui résolvent des problèmes qui se recoupent mais qui sont distincts. Les sélecteurs CSS devraient être votre choix par défaut pour leur rapidité, leur lisibilité et leur simplicité. XPath devrait être votre solution de prédilection lorsque vous vous heurtez à un mur avec la traversée unidirectionnelle, que vous avez besoin d'une correspondance textuelle ou que vous travaillez avec des formats de documents non HTML.

Le langage de sélection importe moins que la qualité de la sélection. Ancrez vos localisateurs à des attributs sémantiques stables. Veillez à ce qu'ils restent courts. Documentez vos conventions afin que le prochain développeur (ou vous-même à l'avenir) n'ait pas à faire de l'ingénierie inverse pour comprendre pourquoi une expression XPath spécifique existe.

À propos de l'auteur
Mihai Maxim, Développeur Full Stack @ WebScrapingAPI
Mihai MaximDéveloppeur Full Stack

Mihai Maxim est développeur Full Stack chez WebScrapingAPI ; il participe à l'ensemble du produit et contribue à la création d'outils et de fonctionnalités fiables pour la plateforme.

Commencez à créer

Prêt à faire évoluer votre système de collecte de données ?

Rejoignez plus de 2 000 entreprises qui utilisent WebScrapingAPI pour extraire des données Web à l'échelle de l'entreprise, sans aucun coût d'infrastructure.