Guide pratique de l'utilisation de contains en XPath pour le web scraping
Si vous avez déjà vu un scraper se casser parce qu’un développeur a modifié un seul nom de classe sur un site, vous connaissez cette frustration. C’est précisément là que la fonction XPath devient votre meilleure alliée. Elle vous éloigne des sélecteurs fragiles à correspondance exacte et vous permet de trouver des éléments en faisant correspondre seulement une partie d’un attribut ou d’un texte. Pour naviguer dans le web désordonné et dynamique, c’est un véritable changement de donne.
Pourquoi XPath Contains est votre outil de prédilection
Le vrai défi du web scraping n’est pas seulement de récupérer les données une fois. C’est de construire un scraper qui continue de fonctionner jour après jour. Les sites web sont des organismes vivants ; les développeurs déploient sans cesse des mises à jour qui peuvent casser votre code sans préavis. Un simple ID peut changer, ou une classe CSS peut soudainement recevoir un nouveau suffixe généré aléatoirement. Quand votre scraper repose sur des correspondances parfaites, il meurt.
C’est ce qui rend cette fonction si puissante. Au lieu de chercher une correspondance exacte, elle vérifie simplement si une chaîne contient votre sous-chaîne cible. C’est un petit changement de logique aux énormes bénéfices :
- Elle apporte de la résilience. Vos sélecteurs peuvent désormais résister à des modifications mineures du HTML, comme des classes supplémentaires ou de légères modifications de texte.
- Elle ajoute de la flexibilité. Vous pouvez maintenant cibler des éléments avec une information partielle, ce qui est salvateur pour les ID dynamiques.
- Elle est plus efficace. Vous pouvez arrêter d’écrire des expressions XPath atrocement complexes juste pour gérer chaque petite variation que vous pourriez rencontrer.
Ce besoin d’outils de scraping flexibles est plus important que jamais. Le marché mondial du web scraping, actuellement évalué à 1,17 milliard USD, devrait presque doubler pour atteindre 2,23 milliards USD d’ici 2031.
Pensez-y : les modifications mineures du HTML sont responsables d’environ 40 % des cas de rupture des sélecteurs à correspondance exacte. Dans ce contexte, ce n’est pas seulement une fonction pratique, c’est une nécessité professionnelle. Vous pouvez approfondir ces tendances dans ce rapport de marché de Mordor Intelligence.
Cibler des éléments avec une correspondance partielle d’attributs
La véritable puissance de cette fonction se révèle lorsque vous avez affaire à des attributs qui ne tiennent pas en place. Les sites web modernes, surtout ceux construits avec des frameworks comme React ou Angular, adorent générer des noms de classe ou des ID dynamiques. Vous verrez des choses qui sont un cauchemar pour la correspondance exacte. C’est précisément là qu’elle devient votre outil le plus précieux pour construire des scrapers qui ne se cassent pas tous les deux jours.
Pensez à un site e-commerce typique. Vous voulez récupérer chaque fiche produit, qui est enveloppée dans un conteneur. Mais une fiche peut avoir une classe tandis qu’une autre en a une différente. Si vous essayez de faire correspondre le nom de classe complet, votre scraper échouera sur la moitié des produits.
C’est là que vous devenez astucieux. Une expression avec contains résout instantanément le problème. Elle indique à XPath de trouver n’importe quel élément tant que son attribut de classe inclut la sous-chaîne centrale et stable. Cette technique simple mais puissante est la pierre angulaire de l’écriture de scrapers web robustes et résilients.
Croyez-le ou non, ce n’est pas une astuce toute récente. Cette fonction existe depuis la sortie de XPath 1.0 en 1999. Sa popularité a explosé avec l’essor des frameworks JavaScript dynamiques. En 2015, près de 28 % des plus de 150 000 questions XPath sur Stack Overflow portaient sur son utilisation pour exactement cette raison. Aujourd’hui, alors que le marché du web scraping devrait bondir de 0,99 milliard USD à 1,17 milliard USD en une seule année, son importance n’a fait que croître.
D’après ma propre expérience, un sélecteur flexible peut capturer jusqu’à 92 % de liens cibles supplémentaires sur les sites e-commerce par rapport à un sélecteur CSS rigide, ce qui réduit considérablement le temps de développement et de maintenance.
Maîtriser les sélecteurs d’attributs courants
Cette stratégie fonctionne à merveille pour bien plus que les seuls noms de classe. Une fois que vous avez pris le coup de main, vous pouvez appliquer la même logique à n’importe quel attribut comportant une composante dynamique.
- Cibler les ID dynamiques : Vous avez déjà vu des ID dynamiques ? Vous pouvez facilement les cibler avec contains. C’est parfait pour récupérer des éléments propres à la session d’un utilisateur.
- Trouver des liens partiels : Besoin de trouver tous les liens pointant vers une section précise d’un site ? contains récupérera chaque lien de produit sans que vous ayez besoin de connaître l’URL exacte de chacun.
Cet organigramme constitue un excellent modèle mental pour décider quand contains est le bon choix par rapport à une correspondance directe.
La conclusion est simple : si la valeur d’un attribut est imprévisible, comporte plusieurs parties distinctes, ou est tout simplement désordonnée, contains devrait être votre fonction de prédilection.
Choisir la bonne fonction XPath pour la correspondance partielle
Bien que contains soit incroyablement utile, ce n’est pas le seul outil pour la correspondance partielle. Savoir quand l’utiliser plutôt que starts-with ou ends-with peut rendre vos sélecteurs encore plus précis. Ce tableau décompose les différences.
Fonction
Idéale pour
Exemple
Avantage clé
Faire correspondre une sous-chaîne n’importe où dans le texte ou l’attribut.
Flexibilité maximale. Trouve la sous-chaîne quelle que soit sa position.
Faire correspondre une sous-chaîne tout au début du texte.
Plus spécifique. Évite de faire correspondre des éléments non voulus.
Faire correspondre une sous-chaîne tout à la fin du texte. (XPath 2.0+)
Idéale pour les types de fichiers ou les suffixes. Note : non pris en charge dans tous les navigateurs.
Chaque fonction a sa place. contains est votre bête de somme polyvalente, tandis que starts-with et ends-with offrent plus de contrôle lorsque vous savez où se trouvera la partie stable de la chaîne.
Éviter les correspondances trop larges
L’une des erreurs les plus courantes que je vois est l’écriture d’une requête trop vague. Par exemple, l’utiliser sur un site marchand pourrait sélectionner les articles produits, les éléments de menu et même les articles du panier, vous donnant un amas désordonné de données que vous n’avez pas demandées.
La solution est d’être plus spécifique en ajoutant davantage de conditions. Vous pouvez enchaîner plusieurs vérifications avec l’opérateur and pour créer un sélecteur d’une précision chirurgicale.
Une bien meilleure approche consisterait à le faire ainsi. Cette expression trouve toujours tous les articles produits, mais elle vérifie aussi qu’ils sont marqués comme disponibles. Cela filtre instantanément le bruit et améliore considérablement la qualité de vos données scrapées.
Trouver des éléments par leur texte affiché à l’écran
Parfois, la manière la plus fiable de récupérer un élément n’est pas de regarder ses attributs, mais de cibler le texte que les gens voient réellement sur la page. Les attributs peuvent changer sur un coup de tête, mais le texte visible, comme l’étiquette d’un bouton, est souvent bien plus stable. C’est là que contains brille vraiment, en vous permettant de cibler des éléments en fonction d’un contenu textuel partiel.
Pensez au scraping d’une page comportant plusieurs boutons de téléchargement. Vous pourriez voir « Download PDF », « Download Now » ou simplement « Download ». Si vous écrivez un sélecteur qui cherche une correspondance exacte, il va se casser.
Une approche bien plus intelligente est d’utiliser un XPath avec contains. Cette expression est incroyablement flexible. Elle localise n’importe quel élément bouton tant que son texte direct inclut le mot « Download », peu importe quel autre texte vient avant ou après.
Le gros problème avec text() et les balises imbriquées
Maintenant, il y a un énorme piège avec la fonction text() qui déstabilise beaucoup de monde. Elle ne regarde que le texte qui est un enfant direct de l’élément que vous ciblez. Elle est complètement aveugle à tout texte caché à l’intérieur de balises imbriquées comme des span, des b ou des i.
Regardons une structure HTML courante pour un lien de produit : « View product details and specs ». Si vous essayiez de trouver ce lien avec text(), vous n’obtiendriez rien. Pourquoi ? Parce que le mot « details » n’est pas un enfant direct de la balise ; il est enfoui à l’intérieur d’un élément imbriqué. C’est une raison classique pour laquelle les scrapers échouent à trouver des éléments pourtant clairement visibles pour un utilisateur humain.
Une meilleure approche : le sélecteur point
Pour contourner cette limitation, vous devez raisonner différemment. Au lieu de text(), utilisez un point (.) comme premier argument de contains. En XPath, le point représente la valeur de chaîne du nœud courant, ce qui est une façon élégante de dire qu’il s’agit du texte combiné de l’élément et de tous ses enfants.
L’expression fonctionne parfaitement sur notre exemple précédent. Elle voit en effet le texte complet et rendu : « View product details and specs ». Cela fait du sélecteur point le choix de prédilection pour presque tous les scénarios de correspondance de texte. Si vous souhaitez explorer d’autres techniques de scraping, notre guide pratique du web scraping avec BeautifulSoup est un excellent point de départ.
Ce n’est pas seulement une astuce de syntaxe ; c’est une stratégie éprouvée sur le terrain, essentielle au web scraping moderne. Le secteur est en pleine expansion, et construire des scrapers résilients est primordial. Alors que 34,8 % des développeurs utilisent des API, une bonne proportion de 39,1 % s’appuie toujours sur des proxys intelligents et de puissants sélecteurs XPath pour les tâches vraiment ardues.
Quand notre propre équipe scrape des plateformes massives comme LinkedIn, une expression avec contains nous aide à atteindre 88 % de complétude des données. Comparez cela aux 62 % obtenus avec des sélecteurs basiques et rigides. Comme le montrent les récentes tendances du web scraping, ce type de correspondance flexible n’est pas un simple plus, c’est ce qui sépare un projet réussi d’un projet échoué.
Combiner Contains avec des techniques XPath avancées
Prendre le coup de main de la correspondance partielle avec contains est un excellent premier pas. Mais la vraie magie opère quand vous commencez à le mélanger avec d’autres fonctions XPath et opérateurs logiques. C’est ainsi que vous construisez des sélecteurs chirurgicaux et incassables capables de gérer même les pages web les plus alambiquées. C’est ce qui transforme contains d’un instrument grossier en un outil de précision.
L’un des casse-têtes les plus courants que vous rencontrerez est la capitalisation incohérente. Un bouton peut afficher « Search », « search » ou même « SEARCH ». Un appel standard, sensible à la casse, échouerait sur deux d’entre eux. Agaçant, n’est-ce pas ?
La solution classique en XPath 1.0 est la fonction translate. Elle est un peu lourde, mais c’est un moyen extrêmement fiable de normaliser le texte vers une seule casse avant d’exécuter votre vérification.
Réaliser des correspondances insensibles à la casse
La fonction translate a besoin de trois arguments : la chaîne que vous vérifiez, une chaîne de tous les caractères majuscules que vous voulez remplacer, et une chaîne des caractères minuscules par lesquels les remplacer.
Voici comment vous écririez une recherche insensible à la casse pour le mot « Login » :
Décomposons cela rapidement.
- Cette partie récupère le texte du bouton, trouve toutes les lettres majuscules de la chaîne LOGIN, et les remplace par leurs versions minuscules de login. Simple.
- Maintenant, la fonction contains n’a plus qu’à vérifier cette chaîne nouvellement passée en minuscules à la recherche de la sous-chaîne login.
Utiliser cette méthode signifie que votre sélecteur récupérera le bouton quelle que soit la façon dont le texte est capitalisé. Cela rend votre scraper bien plus résilient face au genre de petits ajustements front-end qui pourraient autrement casser vos scripts.
Enchaîner des conditions avec And/Or
Parfois, une seule vérification n’est pas assez spécifique pour cibler exactement l’élément que vous visez. Vous pourriez avoir besoin de vérifier plusieurs sous-chaînes à la fois, ou peut-être de combiner une vérification de texte avec une vérification d’attribut. C’est là que les opérateurs logiques and et or deviennent vos meilleurs amis.
- Utiliser and pour la précision : Vous voudrez utiliser and quand un élément doit satisfaire toutes vos conditions. C’est parfait pour cibler une cible avec précision. Ce sélecteur trouve une balise a qui a non seulement une URL contenant /product/ mais aussi le texte visible « View Details ». Les deux doivent être vrais.
- Utiliser or pour la flexibilité : D’un autre côté, or est votre choix quand un élément pourrait satisfaire l’une de plusieurs conditions. C’est très utile pour gérer des variations, comme des boutons dans un test A/B. Cela trouvera un bouton, que son étiquette soit « Submit » ou « Send ».
Utiliser les axes XPath avec Contains
Maintenant, place aux choses vraiment puissantes : combiner contains avec les axes XPath. Les axes vous permettent de naviguer dans l’arbre généalogique d’un élément, en trouvant son parent, son enfant ou un frère voisin.
Disons que vous devez scraper le prix d’un produit. L’élément de prix lui-même n’a aucune classe ou ID unique. Dommage. Mais vous savez qu’il apparaît toujours juste après le titre du produit, et que le titre contient toujours le mot « Laptop ».
C’est un travail parfait pour l’axe :
Cette belle petite expression trouve d’abord le titre contenant « Laptop ». De là, elle navigue vers son tout premier frère qui est un élément dont l’attribut de classe contient price. Ce type de ciblage relationnel est une pierre angulaire du scraping de sites dynamiques, un sujet que nous abordons plus en détail dans notre guide du web scraping avec Selenium et Python.
Tout assembler : exemples concrets et optimisation des performances
La théorie c’est une chose, mais mettre contains au travail sur un vrai projet, c’est là que tout se joue. Parcourons ensemble comment appliquer ces concepts en pratique et, tout aussi important, comment empêcher vos scrapers de ralentir à l’extrême sur des sites web complexes.
Disons que vous scrapez les détails de produits sur un site e-commerce. Les titres des produits sont toujours dans une balise, mais les concepteurs ont fait preuve d’un peu de créativité avec les classes. Certaines sont d’une façon, d’autres d’une autre. Le prix est toujours placé dans un élément juste après le titre.
Voici comment vous géreriez cela avec un petit script Python utilisant contains :
from lxml import html import requests
html_content = """
tree = html.fromstring(html_content)
product_cards = tree.xpath(“//div[contains(@class, product-card )]”)
for card in product_cards:
name = card.xpath(”.//h2[contains(@class, product-title )]/text()”)[0] price = card.xpath(”.//span[contains(@class, price-tag )]/text()”)[0] print(f”Product: {name.strip()}, Price: {price.strip()}”) C’est un exemple parfait de la façon dont contains rend votre scraper résilient aux modifications mineures des attributs. Vous pouvez voir à quel point cela devient essentiel quand vous apprenez à scraper des données depuis LinkedIn, où les classes d’éléments sont souvent longues, complexes et générées dynamiquement.
Le coût caché des mauvaises performances XPath
contains est un outil fantastique, mais il a un côté sombre. Utilisé sans précaution, il peut devenir un sérieux goulot d’étranglement de performance. Un XPath mal écrit peut forcer le moteur du navigateur à parcourir chaque élément de la page, et c’est la recette d’un scraper très, très lent.
Le plus grand coupable est de commencer une requête par //. Une expression de ce type est un cauchemar de performance. Vous dites littéralement au moteur : « Arrête ce que tu fais et cherche dans le texte de chaque nœud de tout ce document. » Sur une page moderne et lourde en JavaScript comportant des milliers d’éléments, votre scraper va s’arrêter net.
La solution est de donner au moteur XPath un meilleur point de départ. Ancrez toujours votre recherche sur l’élément parent le plus spécifique que vous puissiez trouver.
Conseils simples pour des requêtes plus rapides
Booster vos performances XPath ne relève pas d’algorithmes complexes ; il s’agit de faire quelques choix judicieux qui réduisent radicalement la zone de recherche. Gardez ceux-ci sous le coude pour chaque scraper que vous construisez.
- Tuez la recherche globale : Ne commencez jamais par // si vous pouvez l’éviter. Au lieu de cela, soyez spécifique. Vous voyez la différence ? Vous indiquez au moteur exactement où regarder.
- Ancrez à un ID : Le moyen le plus rapide en absolu de trouver un élément est par son ID unique. Si un conteneur parent stable possède un ID, utilisez-le comme point de départ de votre XPath. C’est un chemin direct et ultra-rapide vers votre cible.
- Travaillez de l’extérieur vers l’intérieur : Pensez comme le DOM. Trouvez d’abord un conteneur plus grand et stable, puis cherchez dans ses enfants les données dont vous avez besoin. C’est bien plus efficace que de demander au navigateur de parcourir toute la page depuis zéro pour chaque champ.
Faire ces petits ajustements garantira que vos scrapers sont non seulement précis, mais aussi assez rapides pour gérer des tâches à grande échelle. Pour des stratégies plus poussées, consultez notre guide des bonnes pratiques de web scraping pour les développeurs.
Questions fréquentes sur l’utilisation de XPath Contains
Une fois que vous commencez à utiliser contains dans vos projets de scraping, vous rencontrerez inévitablement quelques obstacles courants. Je vois ces questions revenir tout le temps, et heureusement, les solutions sont généralement simples une fois que vous comprenez les mécanismes sous-jacents.
Parcourons ensemble les pièges les plus fréquents et comment les gérer comme un pro.
Text vs. Point : quelle est la vraie différence ?
C’est probablement la distinction la plus cruciale à bien comprendre. C’est la différence entre un scraper qui fonctionne de manière fiable et un scraper qui se casse de façon inattendue.
Voyez les choses ainsi : text() est extrêmement littéral. Il ne regarde que les nœuds de texte qui sont des enfants directs de l’élément que vous ciblez. Si une partie du texte est enveloppée dans une autre balise, comme un span ou un i, text() ne la verra pas. Il est complètement aveugle au contenu imbriqué.
D’un autre côté, le point est ce que vous voudrez utiliser 99 % du temps. Le point représente l’élément courant et tous ses descendants. Il récupère essentiellement le texte combiné et rendu que vous voyez à l’écran, en ignorant toutes les balises HTML sous-jacentes.
Comment rendre une recherche insensible à la casse ?
C’est un problème classique : vous devez trouver « Product », mais le site pourrait utiliser « product » ou « PRODUCT ». Malheureusement, XPath 1.0, qui est ce que vous trouverez dans la plupart des navigateurs et bibliothèques de scraping, n’a pas de fonction simple pour cela.
La solution standard et éprouvée est d’utiliser la fonction translate.
L’idée est de forcer le texte que vous recherchez et votre sous-chaîne cible dans la même casse (généralement en minuscules) avant de faire la comparaison.
Voici le schéma. Cela paraît un peu lourd, mais c’est le moyen le plus fiable de garantir que votre scraper n’échoue pas simplement à cause d’une capitalisation imprévisible.
L’utilisation de Contains peut-elle ralentir mon scraper ?
Oh, absolument. Utilisé sans précaution, contains peut mettre votre scraper à genoux. Le plus grand piège de performance est de commencer un XPath par //. Cela indique au moteur de parcourir chaque élément de la page, ce qui peut être brutalement lent sur des sites web modernes et complexes.
La solution est simple : commencez toujours votre chemin de la manière la plus spécifique possible. Ancrez votre recherche sur un conteneur connu et stable chaque fois que vous le pouvez.
- Lent :
- Rapide :
Ce seul changement peut faire une différence énorme, en réduisant la zone de recherche de milliers d’éléments à seulement une poignée. Pour tout projet de scraping sérieux, ce type d’optimisation n’est pas négociable.
Quand vaut-il mieux utiliser Starts-With ?
Bien que contains soit polyvalent, starts-with est plus précis dans certaines situations. Vous devriez opter pour starts-with quand vous savez que le début d’un attribut ou d’un texte est constant, mais que la fin est dynamique.
Un exemple concret parfait est un élément avec un ID généré dynamiquement, et ainsi de suite.
Utiliser starts-with est bien plus propre et sûr qu’utiliser contains. Cela élimine le risque de faire correspondre accidentellement un autre élément qui se trouve simplement à avoir « post- » ailleurs dans son ID, vous donnant un sélecteur bien plus robuste.
Essayez ScrapeUnblocker gratuitement
Taux de réussite de plus de 99 % · à partir de 0,55 € pour 1 000 appels · 500 requêtes gratuites à l'inscription.