Aller au contenu
Retour au blog

Aide-mémoire sur les sélecteurs CSS pour le web scraping : syntaxe et code

Ștefan RăcilăDernière mise à jour le 7 min read
Aide-mémoire sur les sélecteurs CSS pour le web scraping : syntaxe et code

Les sélecteurs CSS sont des modèles permettant d’identifier des éléments dans un document HTML ; les robots d’extraction s’en servent pour cibler précisément le texte ou l’attribut qu’ils souhaitent extraire. Cinq sélecteurs assurent l’essentiel du travail : .class, [attribute], les combinateurs de descendants et d’enfants (un espace et >), :nth-child(), et :has(). Cette fiche de référence sur les sélecteurs CSS les couvre tous ainsi que le reste de la syntaxe standard, chacun étant accompagné d’un exemple de scraping. Vous y trouverez également un tableau récapitulatif indiquant quels sélecteurs fonctionnent dans les navigateurs, BeautifulSoup, Scrapy, Cheerio, Playwright et selectolax, la même extraction écrite dans quatre environnements différents, des recettes pour les modèles de pages courants, ainsi qu’un tableau de solutions pour les sélecteurs qui renvoient un résultat vide.

Points clés à retenir

  • La plupart des opérations de scraping ne nécessitent que des classes, des attributs, l’espace et les > les combinateurs, :nth-child(), ainsi que :has().
  • :has() les sélecteurs de parents. Les navigateurs modernes et les principaux analyseurs de scraping prennent cela en charge.
  • Le CSS standard ne permet pas de sélectionner du texte ou des valeurs d’attributs. ::text, ::attr(), et :-soup-contains() sont des extensions de bibliothèques, et non du CSS.
  • Ancrage sur data-* des attributs et des classes sémantiques, et non sur des classes générées par hachage ou de longues chaînes copiées.
  • Si un sélecteur fonctionne dans DevTools mais pas dans votre outil de scraping, le contenu est probablement rendu par JavaScript.

Que sont les sélecteurs CSS dans le web scraping ?

Les sélecteurs CSS identifient des éléments par balise, classe, ID, attribut, position ou relation avec d’autres éléments. Les navigateurs les utilisent pour appliquer des styles. Les scrapers utilisent la même syntaxe pour trouver les éléments contenant des données, puis extraient le texte ou les attributs de chaque élément dans des champs tels que le nom, le prix et l’URL.

Une page HTML est analysée sous forme d’arborescence : chaque balise est un nœud ayant un parent, des frères et des enfants. Un sélecteur décrit un chemin ou une condition dans cette arborescence, et l’analyseur renvoie tous les nœuds qui correspondent.

Presque tous les scrapers suivent les quatre étapes suivantes :

  1. Récupérer la page à l’aide d’un client HTTP ou d’un navigateur.
  2. Analyser le code HTML pour le transformer en arborescence.
  3. Sélectionner les nœuds qui vous intéressent à l’aide de sélecteurs CSS.
  4. Extraire le texte ou les valeurs d’attributs et les enregistrer sous forme d’enregistrements.

La première étape est cruciale. Un client HTTP tel que requests, le fetchou le téléchargeur de Scrapy, reçoit le code HTML brut envoyé par le serveur, sur lequel travaillent ensuite des analyseurs syntaxiques tels que BeautifulSoup, Parsel et Cheerio. Un navigateur exécute d’abord le JavaScript de la page ; les sélecteurs voient donc le DOM rendu, qui peut inclure du contenu n’apparaissant jamais dans la réponse brute. C’est ce qui se produit lorsqu’une page est rendue dans un navigateur sans interface graphique tel que Playwright ou par une API de rendu. La syntaxe de votre sélecteur reste la même des deux côtés de la bifurcation. L’arborescence sur laquelle il s’applique peut toutefois être très différente, et cet écart est à l’origine de la plupart des bugs du type « mon sélecteur ne renvoie rien ».

Chaque exemple de cette page s’applique à une petite fiche produit, ce qui vous permet de comparer les codes ligne par ligne :

<main id="catalog">
  <div class="product card" data-sku="A1" data-testid="product">
    <h2 class="title">Blue Mug</h2>
    <span class="price">$12.00</span>
    <span class="badge sale">Sale</span>
    <a class="link" href="/p/blue-mug">View</a>
    <img src="/img/a1.jpg" alt="Blue Mug">
  </div>
  <div class="product card" data-sku="b2" data-testid="product">
    <h2 class="title">Red Mug</h2>
    <span class="price">$14.00</span>
    <a class="link" href="/p/red-mug">View</a>
    <a class="spec" href="/files/red-mug.pdf">Spec sheet</a>
    <img src="/img/blank.gif" data-src="/img/b2.jpg" alt="Red Mug">
  </div>
  <div class="product card out-of-stock" data-sku="C3" data-testid="product">
    <h2 class="title">Green Mug</h2>
    <span class="price">$9.00</span>
    <p class="note">Out of stock</p>
    <a class="link" href="/p/green-mug">View</a>
  </div>
  <table class="specs">
    <tr><th>Name</th><th>Value</th></tr>
    <tr><td>Weight</td><td>300 g</td></tr>
    <tr><td>Color</td><td>Blue</td></tr>
  </table>
  <dl class="details">
    <dt>Material</dt><dd>Stoneware</dd>
    <dt>Capacity</dt><dd>350 ml</dd>
  </dl>
  <ul class="pager">
    <li><a href="?page=1">1</a></li>
    <li class="active"><a href="?page=2">2</a></li>
    <li><a href="?page=3">3</a></li>
  </ul>
  <a rel="next" href="?page=3">Next</a>
</main>

Aide-mémoire des sélecteurs CSS

Les tableaux ci-dessous répertorient tous les sélecteurs standard pertinents pour le scraping, regroupés par type, avec ce que chacun correspond et un exemple basé sur la liste de produits ci-dessus. Les extensions propres à certaines bibliothèques, telles que ::text disposent de leur propre tableau, car elles cessent de fonctionner dès que vous changez de bibliothèque. Pour consulter la norme complète, reportez-vous à la référence sur les sélecteurs CSS de MDN.

Sélecteurs de base

Sélecteur

Cible

Exemple de scraping

*

Chaque élément

.product > * répertorie tous les enfants directs d'une carte lorsque vous cartographiez une mise en page inconnue

tag

Éléments portant ce nom de balise

h2 renvoie les trois titres de produits

.class

Éléments portant cette classe

.price renvoie les trois prix

.a.b

Éléments portant ces deux classes

.product.card renvoie les trois fiches produits

#id

L'élément ayant cet identifiant

#catalog limite tout à la liste

tag.class

Cette balise avec cette classe

div.product ignore tout élément non-div qui réutilise cette classe

Un espace change complètement le sens. .product.card (sans espace) signifie un élément possédant les deux classes. .product .card (avec un espace) signifie un .card quelque part à l’intérieur d’un .product, et sur cette page, cela ne correspond à rien. Ce simple espace est le premier bug le plus courant dans un nouveau scraper.

Utilisez des identifiants (ID) pour les valeurs uniques, comme un titre de page ou un conteneur. Les éléments répétés, tels que les fiches produits ou les lignes de résultats, n’ont presque jamais d’identifiant ; sélectionnez-les donc plutôt par classe ou par attribut.

Sélecteurs d'attributs

Sélecteur

Correspondances

Exemple de scraping

[attr]

L'attribut est présent

[data-sku] renvoie toutes les cartes comportant un SKU

[attr="v"]

La valeur est exactement v

[data-sku="A1"] renvoie une seule carte

[attr~="v"]

v est un mot figurant dans une liste séparée par des espaces

[class~="sale"] correspond à class="badge sale" mais pas presale

[attr|="v"]

La valeur est v ou commence par v-

[lang|="en"] correspond en et en-US

[attr^="v"]

La valeur commence par v

a[href^="/p/"] ne renvoie que des liens vers des produits

[attr$="v"]

La valeur se termine par v

a[href$=".pdf"] affiche la fiche technique

[attr*="v"]

La valeur contient v n'importe où

a[href*="mug"] renvoie tous les liens vers des mugs

[attr="v" i]

Correspondance exacte, sans tenir compte de la casse ASCII

[data-sku="a1" i] correspond data-sku="A1"

Mettez entre guillemets toute valeur contenant des espaces, des barres obliques, des points ou d’autres caractères spéciaux. a[href$=".pdf"] est sans risque, mais a[href$=.pdf] constitue une erreur de syntaxe dans la plupart des analyseurs syntaxiques.

Les sélecteurs d’attributs sont souvent les points d’ancrage les plus stables d’une page. data-* Les attributs, itemprop, aria-labelet rel existent parce que le code du site lui-même ou les outils d’accessibilité s’appuient sur eux. C’est pourquoi ils ont tendance à survivre aux refontes qui renomment les classes visuelles.

Combinateurs

Sélecteur

Correspondances

Exemple de scraping

A B

B n'importe où à l'intérieur de A

#catalog .price renvoie tous les prix de l'annonce

A > B

B qui est un enfant direct de A

.product > .title ignore les titres imbriqués plus profondément

A + B

B immédiatement après A, même parent

.title + .price renvoie le prix qui suit chaque titre

A ~ B

Tout B après A, le même parent

.title ~ a renvoie tous les liens situés après le titre dans chaque fiche

A, B

Éléments correspondant à l'un ou l'autre des sélecteurs

.title, .price renvoie les titres et les prix ensemble

Les résultats groupés sont renvoyés dans l'ordre du document, et non dans l'ordre dans lequel vous avez listé les sélecteurs. .title, .price vous donne nom, prix, nom, prix, et ainsi de suite, aussi bien dans les navigateurs que dans BeautifulSoup et Cheerio.

Le CSS ne dispose ni de combinateur « parent », ni de combinateur « frère précédent ». Vous n’avez besoin ni de l’un ni de l’autre, car :has() couvre les deux cas, comme le montre la section « Logique » ci-dessous.

Pseudo-classes de position

Sélecteur

Correspond à

Exemple de scraping

:first-child

Le premier enfant de son parent

div.product:first-child renvoie la première carte

:last-child

Le dernier enfant de son parent

.pager li:last-child a renvoie le lien vers la dernière page

:nth-child(n)

Le n-ième enfant (en comptant à partir de 1)

div.product:nth-child(2) .title renvoie « Tasse rouge »

:nth-child(odd) / (even)

Un enfant sur deux

tr:nth-child(even) pour les tableaux rayés

:nth-child(n+2)

Chaque enfant à partir du deuxième

tr:nth-child(n+2) saute une ligne d'en-tête

:nth-last-child(n)

Le n-ième enfant en comptant à partir de la fin

li:nth-last-child(1) renvoie le dernier élément de la pagination

:only-child

Un élément sans frères et sœurs

td:only-child trouve les lignes comportant une seule cellule

:first-of-type

Le premier élément frère portant cette balise

span:first-of-type renvoie le prix indiqué sur chaque fiche

:last-of-type

Le dernier élément frère portant cette balise

div.product:last-of-type renvoie la dernière carte

:nth-of-type(n)

Le n-ième élément de même niveau avec son étiquette

span:nth-of-type(2) renvoie le badge « en solde »

:only-of-type

Le seul élément de même niveau avec son étiquette

h2:only-of-type renvoie un titre par carte

La An+B formule à l’intérieur :nth-child() commence à compter à partir de 1, en n en prenant les valeurs 0, 1, 2, et ainsi de suite. n+2 correspond donc aux positions 2, 3, 4 et suivantes, ce qui permet d'ignorer la ligne d'en-tête d'un tableau. -n+3 correspond aux positions 3, 2 et 1, ce qui permet de sélectionner les trois premiers éléments. 2n est identique à even, et 2n+1 est identique à odd. Toute correspondance qui ne correspond pas au nombre réel d'enfants est ignorée.

:nth-child() et :nth-of-type() se ressemblent mais sont comptés différemment. Dans la première carte, les enfants sont h2, span.price, span.badge, a, et img. span:nth-child(2) renvoie le prix, car le prix est le deuxième enfant de la liste. span:nth-of-type(2) renvoie le badge de promotion, car le badge est le deuxième span.

Dans Scrapy et Parsel, les *-of-type pseudo-classes nécessitent un nom d’élément. div.product:nth-of-type(2) fonctionne, mais .product:nth-of-type(2) lève une ExpressionError. Les navigateurs, BeautifulSoup et Cheerio acceptent les deux formes.

Pseudo-classes logiques : :not(), :is(), :where() et :has()

Sélecteur

Correspondances

Exemple de scraping

:not(x)

Éléments qui ne correspondent pas x

div.product:not(.out-of-stock) renvoie les deux cartes en stock

:is(x, y)

Éléments correspondant à n'importe quel sélecteur de la liste

:is(h2, h3).title gère les modèles mélangeant différents niveaux d'en-têtes

:where(x, y)

Identique à :is(), avec une spécificité nulle

Interchangeable avec :is() pour le scraping

:has(x)

Les éléments contenant un élément correspondant à x

div.product:has(.badge) renvoie la carte en promotion

:has(> x)

Éléments dont un enfant direct correspond à x

div.product:has(> .note) renvoie la carte en rupture de stock

:has(+ x)

Éléments immédiatement suivis de x

dt:has(+ dd) renvoient chaque étiquette ayant une valeur

:has() est le sélecteur de parent qui manquait au CSS depuis des années. Il permet de sélectionner un élément en fonction de ce qu’il contient ou de ce qui le suit immédiatement, ce qui couvre les deux directions dont un scraper a généralement besoin. .product:has(.badge) renvoie les cartes comportant un badge « en solde », et non les badges eux-mêmes. tr:has(td.out-of-stock) renvoie des lignes entières du tableau contenant une cellule « en rupture de stock ». dt:has(+ dd) renvoie une étiquette uniquement lorsqu'elle est suivie d'une valeur, ce qui permet d'accéder à un frère précédent. Combinez-le avec :not() pour inverser la condition : .product:not(:has(.badge)) renvoie les cartes sans badge. La spécification « Selectors Level 4 » le définit, et la page :has() sur MDN le classe comme « Baseline » (largement disponible) sur tous les navigateurs depuis décembre 2023. BeautifulSoup, Scrapy, Cheerio, Playwright et selectolax le prennent également en charge. Une seule restriction s’applique : vous ne pouvez pas imbriquer :has() à l’intérieur d’un autre :has().

:is() et :where() ne diffèrent que par leur spécificité, qui détermine quel style prévaut dans une feuille de style. La spécificité n’a aucun effet sur ce qu’un scraper sélectionne ; utilisez donc celui qui vous semble le plus lisible.

Extensions propres aux bibliothèques

Le CSS standard sélectionne des éléments, jamais leur texte ni les valeurs de leurs attributs. Chaque bibliothèque de scraping comble cette lacune à sa manière, et c’est avec les extensions ci-dessous que votre code cesse d’être portable.

Extension

Bibliothèque

Fonctionnalité

::text

Scrapy, Parsel

Sélectionne les nœuds de texte de l’élément correspondant

::attr(name)

Scrapy, Parsel

Sélectionne la valeur d’un attribut

:-soup-contains("x")

BeautifulSoup (via Soup Sieve)

Recherche les éléments dont le texte, y compris les descendants, contient x

:-soup-contains-own("x")

BeautifulSoup (via Soup Sieve)

Recherche les éléments dont le texte (à l'exclusion de celui des éléments descendants) contient x

:contains("x")

Cheerio, Parsel (via cssselect)

Recherche les éléments dont le texte contient x

:has-text("x")

Localisateurs Playwright uniquement

Recherche les éléments contenant x n'importe où à l'intérieur, sans distinction de casse

:text("x")

Locateurs Playwright uniquement

Correspond à l'élément le plus petit contenant x

:visible

Localisateurs Playwright uniquement

Recherche uniquement les éléments visibles sur la page

Aucune de ces règles n'est du CSS standard. Le document.querySelectorAll() lance une SyntaxError sur :contains(), et BeautifulSoup génère une erreur si vous lui transmettez ::text. Dans BeautifulSoup, :contains() continue de fonctionner comme un alias, mais il est déprécié au profit de :-soup-contains(). Soup Sieve, le moteur de sélection de BeautifulSoup, documente l’ensemble complet de ses extensions.

Ce que les sélecteurs CSS ne peuvent pas faire

Le CSS est un langage de correspondance ; certaines tâches échappent donc à son champ d’application :

  • Sélectionner un nœud de texte ou la valeur d’un attribut isolément. Vous sélectionnez l’élément, puis vous lisez son texte ou son attribut dans le code.
  • Effectuer une correspondance en fonction du contenu textuel dans le CSS standard. Seules les extensions de bibliothèque mentionnées ci-dessus permettent cela.
  • Remonter un nombre fixe d’ancêtres, par exemple « l’ancêtre de ce span ». :has() La sélection s'effectue par inclusion, et non par distance.
  • Comparer des valeurs ou effectuer des calculs, par exemple « un prix supérieur à 10 ».
  • Accéder à une iframe, qui est un document distinct.

Lorsque vous atteignez l’une de ces limites, consultez l’aide-mémoire XPath pour le web scraping, ou effectuez l’opération en code après la sélection.

Quels sélecteurs CSS fonctionnent avec quelle bibliothèque de scraping ?

Les sélecteurs standard, y compris les opérateurs d’attribut, :nth-child(), :not(), :is(), et :has(), se comportent de la même manière dans les navigateurs modernes, BeautifulSoup, Scrapy, Cheerio, Playwright et selectolax. Les différences concernent les extensions et les cas particuliers : Scrapy et Parsel ont besoin d’un nom de balise pour *-of-type, BeautifulSoup rejette ::text, et chaque bibliothèque effectue la correspondance de texte à sa manière.

Fonctionnalité

Navigateur (querySelectorAll)

BeautifulSoup

Scrapy / Parsel

Cheerio

Playwright

selectolax

Les opérateurs d'attribut et le i indicateur

Oui

Oui

Oui

Oui

Oui

Oui

Combinateurs (espace, >, +, ~, ,)

Oui

Oui

Oui

Oui

Oui

Oui

An+B (:nth-child(n+2))

Oui

Oui

Oui

Oui

Oui

Oui

*-of-type sans balise (.product:nth-of-type(2))

Oui

Oui

Erreur

Oui

Oui

Oui

*-of-type avec une balise (div.product:nth-of-type(2))

Oui

Oui

Oui

Oui

Oui

Oui

:not()

Oui

Oui

Oui

Oui

Oui

Oui

:is() et :where()

Oui

Oui

Oui

Oui

Oui

Oui

:has() et :has(> x)

Oui

Oui

Oui

Oui

Oui

Oui

:scope

Oui

Oui

Oui

Oui

Oui

Erreur

::text et ::attr()

Erreur

Erreur

Extension

Erreur

Erreur

Erreur

Correspondance de texte

Non (:contains() lance)

Extension (:-soup-contains())

Extension (:contains())

Extension (:contains())

Extension (:has-text(), :text())

Extension (:lexbor-contains())

DOM d'ombre ouvert

Non

Non

Non

Non

Oui (le CSS traverse les racines Shadow ouvertes)

Non

Situation en novembre 2026.

La présence de deux lignes est à l'origine de la plupart des bugs de migration. Lorsque vous transférez un sélecteur depuis la console du navigateur vers Scrapy et qu'il contient .something:nth-of-type(), ajoutez le nom de la balise. Lorsque vous transférez un sélecteur Scrapy dans BeautifulSoup, supprimez ::text et ::attr() et lisez plutôt le texte ou l’attribut en Python.

La ligne concernant le shadow DOM nécessite une précision. Les analyseurs HTML bruts ne détectent jamais les racines shadow ajoutées par JavaScript, car celles-ci n’existent pas dans la réponse du serveur. Seul un navigateur peut y accéder, et seul le moteur CSS de Playwright perce les racines shadow par défaut.

Les scrapers PHP suivent les mêmes règles via le composant CssSelector de Symfony. Celui-ci convertit les sélecteurs CSS en XPath avant de les exécuter ; les limites de cette conversion s’appliquent donc également.

Comment trouver et tester un sélecteur CSS ?

Inspectez l’élément, notez sa balise, ses classes et ses attributs de données, trouvez un conteneur stable situé un ou deux niveaux plus haut, puis écrivez un sélecteur court qui soit unique au sein de ce conteneur. Testez-le ensuite à l’aide de Ctrl+F dans le panneau Éléments ou document.querySelectorAll() dans la console, puis vérifiez que le nombre de correspondances correspond à vos attentes.

  1. Inspecter. Cliquez avec le bouton droit sur la valeur souhaitée et choisissez « Inspecter ». Le panneau Éléments met en surbrillance son nœud.
  2. Lisez les ancres. Recherchez les data-* attributs, id, des noms de classes sémantiques tels que price ou title, itemprop, et les aria-* . Ce sont les éléments les moins susceptibles de changer.
  3. Identifiez le conteneur récurrent. Pour les listes, remontez jusqu’à l’élément qui se répète une fois par élément, comme div.product.
  4. Écrivez le sélecteur le plus court qui soit unique à l’intérieur du conteneur. div.product .price C'est mieux que de parcourir chaque conteneur.
  5. Testez-le. Appuyez sur Ctrl+F (Cmd+F sous macOS) dans le panneau Éléments et collez le sélecteur. DevTools affiche le nombre de correspondances. Vous pouvez également l’exécuter dans la console :

``js $$("div.product .price").length // 3 ``

  1. Comparez avec « Afficher la source ». Ouvrez « Afficher la source » (Ctrl+U) et recherchez la valeur. Si elle n'y figure pas, le contenu est généré par JavaScript, et un client HTTP ne le verra pas.

Tous les principaux navigateurs permettent de copier un sélecteur généré à partir du panneau Éléments. Cliquez avec le bouton droit sur le nœud et ouvrez le sous-menu « Copier » :

Navigateur

Élément de menu

Chrome et Edge

Copier > Copier le sélecteur

Firefox

Copier > Sélecteur CSS

Safari

Copier > Chemin du sélecteur

Le guide DOM de Chrome DevTools traite plus en détail du panneau Éléments.

Comment simplifier un sélecteur copié

Un sélecteur copié décrit cette page précise et rien d’autre. Une copie type pour le prix de la deuxième carte se présente comme suit :

/* Copied from DevTools */
#catalog > div:nth-child(2) > span

/* Rewrite 1: one card, by a stable attribute */
[data-sku="b2"] .price

/* Rewrite 2: every card */
div.product .price

La version copiée dépend de la position de la carte et du fait que le prix soit le seul span dans cette carte. Ajoutez une carte sponsorisée en haut de la page et le prix affiché correspondra au mauvais produit. Ajoutez un badge « en promotion » sur cette carte et deux valeurs seront renvoyées au lieu d’une seule. La réécriture 1 remplace la position par la référence (SKU) propre au produit et remplace le simple span par sa classe sémantique. La réécriture 2 supprime entièrement la condition « une seule carte », car un scraper cherche généralement tous les prix, et non pas uniquement le deuxième. Chaque couche que vous supprimez est un élément de moins qui doit rester identique.

Sélecteurs robustes vs fragiles

Fragiles

Robustes

Pourquoi

.css-1x9k2ab

[data-testid="product"]

Les outils de build régénèrent les noms de classes hachés à chaque déploiement, tandis que les identifiants de test restent inchangés car les tests propres au site en dépendent

main > div:nth-child(3) > div:nth-child(2) > span

.product .price

Un chemin de position complet cesse de fonctionner dès qu’un wrapper est ajouté ou supprimé

.text-red.font-bold

.price

Les classes de présentation changent lors d’une refonte, tandis que les classes sémantiques décrivent le contenu

div.product:nth-child(2)

[data-sku="b2"]

Les positions changent lorsque des éléments sont triés ou insérés, contrairement à l’identifiant d’un élément

div > div > span

.price

Les chaînes de balises génériques correspondent à trop de cas et dépendent d’un imbrication exacte

Les sélecteurs robustes s’appuient sur des éléments dont dépendent les développeurs du site : identifiants de test, attributs de données, classes sémantiques et balisage de données structurées comme itemprop.

Comment extraire des données à l’aide de sélecteurs CSS en Python et JavaScript

Toutes les bibliothèques acceptent la même chaîne de sélection, mais chacune renvoie des résultats différents : select() et select_one() dans BeautifulSoup, response.css() avec ::text et ::attr() dans Scrapy, $() dans Cheerio, et page.locator() dans Playwright. Le principe reste le même partout : sélectionnez d'abord chaque élément répété, puis lisez les champs qu'il contient.

Chaque exemple ci-dessous extrait le nom, le prix et l'URL absolue des trois fiches de l'annonce.

BeautifulSoup

from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup

URL = "https://shop.example.com/mugs?page=2"
soup = BeautifulSoup(requests.get(URL, timeout=10).text, "lxml")

for card in soup.select("div.product"):
    title = card.select_one(".title")
    price = card.select_one(".price")
    link = card.select_one("a.link")
    print({
        "name": title.get_text(strip=True) if title else None,
        "price": price.get_text(strip=True) if price else None,
        "url": urljoin(URL, link.get("href")) if link else None,
    })
# {'name': 'Blue Mug', 'price': '$12.00', 'url': 'https://shop.example.com/p/blue-mug'}
# {'name': 'Red Mug', 'price': '$14.00', 'url': 'https://shop.example.com/p/red-mug'}
# {'name': 'Green Mug', 'price': '$9.00', 'url': 'https://shop.example.com/p/green-mug'}
  • select() renvoie une liste, et select_one() renvoie la première occurrence ou None. Protégez chaque select_one() avant d’appeler une méthode sur celle-ci.
  • tag["href"] lance une exception KeyError lorsque l'attribut est manquant, tandis que tag.get("href") renvoie None.
  • ::text lance une erreur. Utilisez get_text(strip=True) à la place, et :-soup-contains("Out of stock") lorsque vous avez besoin d’effectuer une correspondance par texte.
  • L'analyseur est important en cas de code HTML incorrect. lxml et html.parser peuvent générer des arborescences différentes à partir d’un même balisage mal formé ; choisissez-en donc un et conservez-le.

Pour aller plus loin, créez un scraper BeautifulSoup à partir de zéro, ou consultez la documentation de BeautifulSoup pour découvrir l'intégralité de l' select() API.

Scrapy et Parsel

import scrapy

class MugSpider(scrapy.Spider):
    name = "mugs"
    start_urls = ["https://shop.example.com/mugs?page=2"]

    def parse(self, response):
        for card in response.css("div.product"):
            yield {
                "name": card.css(".title::text").get(default="").strip(),
                "price": card.css(".price::text").get(default="").strip(),
                "url": response.urljoin(card.css("a.link::attr(href)").get()),
            }
        # {'name': 'Blue Mug', 'price': '$12.00', 'url': 'https://shop.example.com/p/blue-mug'}
        # {'name': 'Red Mug', 'price': '$14.00', 'url': 'https://shop.example.com/p/red-mug'}
        # {'name': 'Green Mug', 'price': '$9.00', 'url': 'https://shop.example.com/p/green-mug'}
        next_page = response.css('a[rel="next"]::attr(href)').get()
        if next_page:
            yield response.follow(next_page, callback=self.parse)

Cette fiche de référence sur les sélecteurs CSS de Scrapy couvre les appels que vous utiliserez le plus souvent :

Syntaxe

Résultats

Exemple dans la liste

::text

Les nœuds de texte propres à l'élément

.title::text renvoie « Blue Mug »

::text (espace initial)

Les nœuds de texte de l'élément et de tous ses descendants

.product ::text renvoie tous les nœuds de texte de la carte

::attr(name)

La valeur d’un attribut

a.link::attr(href) renvoie « /p/blue-mug »

.get()

Le premier résultat, ou None

card.css(".price::text").get()

.getall()

Tous les résultats sous forme de liste

response.css(".title::text").getall()

.get(default="")

Le premier résultat, ou votre valeur par défaut

Évite les None les vérifications avant .strip()

.attrib["href"]

Un attribut du premier élément correspondant

card.css("a.link").attrib["href"]

  • *-of-type nécessite un nom de balise. Écrivez div.product:nth-of-type(2), et non .product:nth-of-type(2).
  • a::text et a ::text sont différents. Le premier ne renvoie que les nœuds de texte propres au lien. Le second renvoie également le texte situé à l'intérieur de balises imbriquées, comme <a><span>View</span></a>.
  • Le texte est renvoyé tel quel, y compris les sauts de ligne et les indentations ; il faut donc les supprimer.

Les sélecteurs de Scrapy proviennent de Parsel ; les mêmes .css() appels fonctionnent parsel.Selector(text=html) en dehors d’un spider. Consultez la documentation de Scrapy sur les sélecteurs pour connaître les règles d’extension, ou suivez le guide complet de scraping de Scrapy pour l’exploration, les pipelines et les paramètres.

Cheerio

import * as cheerio from "cheerio";

const URL = "https://shop.example.com/mugs?page=2";
const $ = cheerio.load(await (await fetch(URL)).text());

const products = $("div.product").map((i, el) => {
  const card = $(el);
  return {
    name: card.find(".title").text().trim(),
    price: card.find(".price").text().trim(),
    url: new URL(card.find("a.link").attr("href"), URL).href,
  };
}).get();
console.log(products);
// [ { name: 'Blue Mug', price: '$12.00', url: 'https://shop.example.com/p/blue-mug' },
//   { name: 'Red Mug', price: '$14.00', url: 'https://shop.example.com/p/red-mug' },
//   { name: 'Green Mug', price: '$9.00', url: 'https://shop.example.com/p/green-mug' } ]
  • Cheerio analyse uniquement le code HTML brut. Il n’exécute pas de JavaScript ; par conséquent, tout élément ajouté par un script après le chargement de la page sera ignoré.
  • .text() Sur une sélection comportant plusieurs éléments, le texte de tous ces éléments est concaténé ; limitez donc la sélection à une seule carte avant .find() avant la lecture.
  • .attr("href") renvoie undefined lorsque l'attribut est manquant.
  • :contains() fonctionne dans Cheerio mais génère une exception dans les navigateurs ; par conséquent, un sélecteur que vous prototypez ici ne pourra peut-être pas être recollé dans la console.

Pour un projet complet, consultez la section « Web scraping avec Cheerio sous Node.js ».

Playwright

import { chromium } from "playwright";

const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto("https://shop.example.com/mugs?page=2");
await page.locator("div.product").first().waitFor();

const names = await page.locator("div.product .title").allInnerTexts();
// [ 'Blue Mug', 'Red Mug', 'Green Mug' ]
const products = await page.$$eval("div.product", cards =>
  cards.map(card => ({
    name: card.querySelector(".title")?.innerText.trim() ?? null,
    price: card.querySelector(".price")?.innerText.trim() ?? null,
    url: card.querySelector("a.link")?.href ?? null,
  }))
);
// [ { name: 'Blue Mug', price: '$12.00', url: 'https://shop.example.com/p/blue-mug' }, ... ]
await browser.close();
  • Les méthodes de localisation telles que allInnerTexts() et count() n’attendent pas que les éléments apparaissent, et $$eval() s'exécutent une seule fois sur le DOM actuel. Attendez d'abord que le conteneur s'affiche, comme ci-dessus.
  • À l’intérieur de $$eval(), la href propriété renvoie une URL absolue, tandis que getAttribute("href") renvoie la valeur brute.
  • Playwright ajoute ses propres pseudo-classes CSS : div.product:has-text("Out of stock"), :text(), et :visible. Son CSS perce également les racines d’ombre ouvertes. Rien de tout cela ne fonctionne en dehors de Playwright.

La documentation de Playwright recommande d’utiliser des localisateurs visibles par l’utilisateur, tels que getByRole() et getByTestId() plutôt que le CSS pour les clics et les saisies dans les formulaires, car le CSS lie un test à la mise en œuvre de la page. Pour lire des conteneurs de données répétitifs, le CSS reste le choix le plus pratique, car une grille de produits ne dispose d’aucun rôle accessible permettant de distinguer le prix du titre. La documentation de Playwright sur les localisateurs CSS répertorie toutes les extensions, et le guide de scraping web de Playwright aborde la navigation, l’attente et la mise à l’échelle.

Selenium

Selenium utilise le CSS standard via By.CSS_SELECTOR et l’exécute dans un navigateur réel ; il voit ainsi le DOM rendu et suit la colonne « navigateur » de la matrice. find_elements() renvoie une liste, qui est vide lorsqu’aucune correspondance n’est trouvée, tandis que find_element() lève une exception NoSuchElementException. get_attribute("href") renvoie l’URL absolue résolue.

from selenium.webdriver.common.by import By

titles = driver.find_elements(By.CSS_SELECTOR, "div.product .title")
links = driver.find_elements(By.CSS_SELECTOR, "div.product a.link")
print([t.text for t in titles])                     # ['Blue Mug', 'Red Mug', 'Green Mug']
print([a.get_attribute("href") for a in links])     # ['https://shop.example.com/p/blue-mug', ...]

Recettes de sélecteurs CSS pour les tâches courantes de scraping

La plupart des tâches de scraping reprennent quelques schémas récurrents : fiches produits, liens et pagination, images, tableaux et paires étiquette-valeur. Chaque recette ci-dessous propose un sélecteur et une ou deux lignes de code d’extraction, en utilisant d’abord du CSS standard afin que le sélecteur fonctionne dans n’importe quelle bibliothèque.

Fiches produits et listes de produits

Ciblez d’abord la fiche, puis lisez les champs qu’elle contient. Ainsi, un prix manquant dans une fiche ne risque pas de faire basculer tous les prix suivants dans un enregistrement erroné. Filtrez au niveau du sélecteur lorsque c’est possible : div.product:not(.out-of-stock) ne renvoie que les articles en stock, et div.product:has(.badge) signale les articles en promotion sans nécessiter de deuxième passage.

in_stock = [c.select_one(".title").get_text(strip=True)
            for c in soup.select("div.product:not(.out-of-stock)")]
# ['Blue Mug', 'Red Mug']
on_sale = [t.get_text(strip=True) for t in soup.select("div.product:has(.badge) .title")]
# ['Blue Mug']

Ce modèle « carte puis champ » est au cœur du suivi des prix des concurrents à grande échelle, où une seule page de liste se transforme en dizaines de lignes bien structurées.

Liens et pagination

Recherchez a[rel="next"] en premier. rel="next" est un type de lien HTML standard utilisé par de nombreux sites, et c’est généralement le point d’ancrage de pagination le plus stable sur la page. Lorsqu’un site ne le marque pas, passez de la page active à la suivante à l’aide du combinateur « next-sibling » : .pager li.active + li a. Les liens « href » sont généralement relatifs ; il faut donc les résoudre par rapport à l’URL de la page avant de les interroger.

next_href = response.css('a[rel="next"]::attr(href)').get()
# '?page=3'
next_url = response.urljoin(response.css(".pager li.active + li a::attr(href)").get())
# 'https://shop.example.com/mugs?page=3'

Images et sources à chargement différé

Les pages utilisant le chargement différé placent souvent un espace réservé à la place src et l’image réelle dans data-src, que le script remplace lors du défilement. Un analyseur HTML brut ne voit que l'élément de remplacement ; lisez donc data-src d'abord et de se rabattre sur src. Les images adaptatives peuvent également répertorier plusieurs tailles dans srcset, ou les encapsuler dans des picture source éléments ; vérifiez donc les deux lorsque vous avez besoin du fichier le plus volumineux.

const images = $("div.product img").map((i, el) => $(el).attr("data-src") ?? $(el).attr("src")).get();
// [ '/img/a1.jpg', '/img/b2.jpg' ]

Utilisez img[data-src] pour ne trouver que les images différées, et img:not([data-src]) pour le reste.

Les tableaux HTML

:nth-child() gère la plupart des opérations sur les tableaux. tr:nth-child(n+2) ignore la ligne d'en-tête, et td:nth-child(2) sélectionne la deuxième colonne. Les positions des colonnes changent toutefois plus souvent que les libellés d’en-tête. Pour toute tâche un peu plus complexe qu’une simple opération rapide, lisez la ligne d’en-tête une fois et associez chaque cellule à son nom d’en-tête.

values = [td.get_text(strip=True)
          for td in soup.select("table.specs tr:nth-child(n+2) td:nth-child(2)")]
# ['300 g', 'Blue']
headers = [th.get_text(strip=True) for th in soup.select("table.specs tr:first-child th")]
rows = [dict(zip(headers, [td.get_text(strip=True) for td in tr.select("td")]))
        for tr in soup.select("table.specs tr:has(td)")]
# [{'Name': 'Weight', 'Value': '300 g'}, {'Name': 'Color', 'Value': 'Blue'}]

Paires étiquette-valeur

Les listes de définitions et les blocs de spécifications associent une étiquette à la valeur qui la suit. dt + dd renvoie chaque valeur, et dt:has(+ dd) renvoie chaque libellé associé à une valeur. Lisez-les en parallèle et regroupez-les dans un dictionnaire. Les tableaux comportant un th étiquette et un élément de même niveau td fonctionnent de la même manière avec th + td.

labels = response.css("dl.details dt:has(+ dd)::text").getall()   # ['Material', 'Capacity']
values = response.css("dl.details dt + dd::text").getall()        # ['Stoneware', '350 ml']
specs = dict(zip(labels, values))

Lorsque vous avez besoin de « la valeur dont l’étiquette indique Capacity », il s’agit d’une correspondance de texte. Le CSS standard ne permet pas de le faire ; utilisez donc dt:-soup-contains("Capacity") + dd dans BeautifulSoup, ou une expression XPath qui fonctionne partout.

Pourquoi mon sélecteur CSS ne renvoie-t-il rien ?

Généralement parce que le code HTML reçu par votre scraper n’est pas la page que vous avez inspectée. DevTools affiche le DOM après l’exécution de JavaScript, tandis qu’un client HTTP récupère la réponse brute du serveur. D’autres causes courantes sont les iframes, le shadow DOM, les noms de classes avec hachage de compilation, les caractères spéciaux non échappés et un espace entre deux classes qui devraient être jointes.

Symptôme

Cause probable

Solution

Fonctionne dans DevTools, mais vide dans le scraper

Le contenu est rendu par JavaScript

Vérifiez le code source. Repérez la requête JSON ou XHR appelée par la page, ou affichez la page dans un navigateur.

Contenu vide sur certaines pages ou dans certains pays uniquement

Une variante différente de la page, une page de consentement ou une page de vérification

Enregistrez le code d'état et sauvegardez le corps de la réponse pour voir ce que vous avez réellement obtenu

.product .card ne renvoie rien

Un espace a transformé « les deux classes » en « descendant »

Fusionnez les classes : .product.card

Un identifiant comportant deux-points ou un chiffre en début échoue

Caractères spéciaux non échappés

Échappez-les (#a\:b) ou utilisez un sélecteur d'attribut ([id="123"])

L'élément se trouve à l'intérieur d'un iframe

L'iframe est un document distinct

Demandez directement l' src directement, ou utilisez la fonction de Playwright frameLocator()

L'élément se trouve à l'intérieur d'un composant web

Il se trouve dans une racine fantôme

Le CSS de Playwright traverse les « shadow roots ». Les analyseurs HTML bruts ne peuvent pas y accéder.

Texte provenant de ::before ou ::after est manquant

Le contenu du pseudo-élément n'est pas présent dans le DOM

Recherchez la valeur dans un attribut ou dans la feuille de style, ou ignorez-la

Les valeurs contiennent des espaces superflus ou sont fractionnées

Les nœuds de texte brut contiennent des indentations et des sauts de ligne

Nettoyez le texte, ou utilisez get_text(strip=True)

Une valeur correspond dans un cas mais pas dans un autre

La correspondance des attributs est sensible à la casse

Ajoutez l'indicateur i indicateur : [data-sku="a1" i]

Scrapy lève une ExpressionError sur *-of-type

Parsel a besoin d'un nom d'élément

Ajoutez la balise : div.product:nth-of-type(2)

Lorsque la correction est en cours de rendu, vous n’avez pas besoin de lancer vous-même une flotte de navigateurs. L’API du navigateur peut afficher la page et attendre votre sélecteur avec wait_for_css, puis renvoie le code HTML ou les champs extraits. Cela fonctionne comme une requête-réponse : vous envoyez l’URL et les instructions, et vous recevez le résultat en retour. Il ne s’agit pas d’une session de navigateur en direct que vous pilotez étape par étape.

Sélecteurs CSS vs XPath : quand faut-il changer ?

Utilisez les sélecteurs CSS par défaut. Ils sont plus courts, plus faciles à lire et pris en charge par toutes les bibliothèques de scraping et tous les navigateurs. Passez à XPath lorsque vous avez besoin d’une correspondance de texte portable, d’un ancêtre spécifique, d’une logique de position sur l’ensemble du document ou de documents XML. La plupart des scrapers en production combinent les deux.

  • Correspondance de texte : XPath contains(text(), "Capacity") fonctionne dans tous les moteurs XPath. La correspondance de texte CSS dépend de la bibliothèque.
  • Ancêtres : XPath peut remonter un nombre exact de niveaux grâce à .. ou l’ ancestor:: axe. :has() sélectionne par inclusion, et non par distance.
  • Position au niveau du document : (//div[@class="product"])[2] compte sur l'ensemble de la page, et non parmi les éléments frères.
  • XML : les flux et les plans de site avec des espaces de noms sont plus faciles à gérer en XPath.

Tâche

CSS

XPath

Titre de la deuxième carte

div.product:nth-child(2) .title

(//div[contains(@class, "product")])[2]//h2

Valeur après l'étiquette « Capacité »

dt:-soup-contains("Capacity") + dd (BeautifulSoup uniquement)

//dt[text()="Capacity"]/following-sibling::dd[1]

Pour en savoir plus sur les avantages et les inconvénients, consultez la comparaison complète des sélecteurs XPath et CSS.

Comment utiliser des sélecteurs CSS via une API ?

Envoyez vos sélecteurs avec la requête et obtenez des champs JSON en retour au lieu de code HTML brut. L'API Scraper de WebScrapingAPI accepte un extract_rules objet qui associe les noms de champs à des sélecteurs CSS ou XPath. Elle les exécute sur la page récupérée, avec un rendu JavaScript lorsque vous le demandez, et renvoie du texte, du code HTML, des valeurs d’attributs ou des données de tableau.

Cela s’avère utile lorsque la difficulté réside dans la récupération des données, et non dans la sélection. Si un site bloque vos requêtes, affiche son contenu via JavaScript ou présente des résultats différents selon les pays, vous pouvez conserver les sélecteurs que vous avez déjà écrits et confier la récupération des données aux règles d’extraction de l’API Scraper.

Chaque règle associe une clé de sortie à une chaîne de sélection, ou à un objet de règle comportant les clés suivantes :

  • selector: un sélecteur CSS ou une expression XPath.
  • selector_type: css ou xpath. Si vous ne le précisez pas, un sélecteur commençant par / est interprété comme du XPath, et tout le reste comme du CSS.
  • output: text par défaut, ou html, @attr (comme @href), table_json, table_array, ou un objet de règle imbriqué.
  • all: 1 renvoie toutes les correspondances, tandis que 0 ne renvoie que la première.
  • clean: 1 supprime les espaces et les sauts de ligne en début et en fin de texte.

extract_rules est envoyé sous forme d’objet JSON converti en chaîne de caractères ; il faut donc l’encoder en URL :

curl --get "https://api.webscrapingapi.com/v2" \
  --data-urlencode "api_key=$WSA_API_KEY" \
  --data-urlencode "url=https://shop.example.com/mugs?page=2" \
  --data-urlencode 'extract_rules={"titles":{"selector":"div.product .title","output":"text","all":1}}'

Une règle imbriquée sélectionne chaque carte, puis les champs qu’elle contient, selon le même schéma que le code à quatre piles ci-dessus :

import json, os, requests

rules = {
    "products": {
        "selector": "div.product",
        "all": 1,
        "output": {
            "name": {"selector": ".title", "output": "text", "clean": 1},
            "price": {"selector": ".price", "output": "text", "clean": 1},
            "url": {"selector": "a.link", "output": "@href"},
        },
    }
}
response = requests.get("https://api.webscrapingapi.com/v2", params={
    "api_key": os.environ["WSA_API_KEY"],
    "url": "https://shop.example.com/mugs?page=2",
    "render_js": 1,
    "extract_rules": json.dumps(rules),
}, timeout=60)
print(response.json()["products"])

Utilisez du CSS standard dans vos règles et laissez output gérer le texte et les attributs. Des extensions de bibliothèque telles que ::text ou :-soup-contains() appartiennent à leurs propres bibliothèques. L’API exécute les règles que vous envoyez. Vous restez responsable des sélecteurs, du schéma de sortie et de la validation qui vérifie que chaque champ est correct, et vous mettez à jour les règles lorsque le balisage du site change.

FAQ

Quels sont les sélecteurs CSS les plus utiles pour le web scraping ?

Les sélecteurs de classe, les sélecteurs d’attributs tels que [data-id] et a[href^="/product"], les combinateurs de descendants et d’enfants, :nth-child() pour les tableaux et les listes, ainsi que :has() pour sélectionner des conteneurs en fonction de leur contenu. Ensemble, ils couvrent la plupart des tâches d’extraction. Les extensions de bibliothèques gèrent les valeurs de texte et d’attributs.

Comment récupérer du texte ou un attribut à l'aide d'un sélecteur CSS ?

Le CSS standard sélectionne des éléments, et non leur texte ou leurs attributs ; chaque bibliothèque ajoute donc une étape supplémentaire. Dans Scrapy, utilisez ::text ou ::attr(href). Dans BeautifulSoup, appelez get_text() ou consultez tag["href"]. Dans Cheerio, utilisez .text() et .attr(). Dans Playwright, utilisez innerText() ou getAttribute().

Les sélecteurs CSS peuvent-ils sélectionner un élément parent ?

Oui. La :has() pseudo-classe sélectionne un élément en fonction de son contenu ; ainsi, .card:has(.sale) renvoie les cartes comportant un badge « soldé », et :has(> .sale) limite cette sélection aux enfants directs. Les navigateurs modernes, BeautifulSoup, Scrapy et Cheerio prennent cette fonctionnalité en charge. Utilisez XPath pour remonter d'un nombre précis de niveaux.

Les sélecteurs CSS peuvent-ils sélectionner des éléments en fonction de leur texte ?

Pas dans le CSS standard. Les bibliothèques ajoutent leurs propres extensions : :-soup-contains() dans BeautifulSoup, :contains() dans Cheerio et Parsel de Scrapy, et :has-text() dans Playwright. Elles ne sont pas portables et les navigateurs les rejettent. Pour une correspondance de texte fonctionnant avec tous les outils, utilisez XPath avec contains(text(), "…").

Quelle est la différence entre `nth-child` et `nth-of-type` ?

:nth-child(2) correspond à un élément qui est le deuxième enfant de son parent, quelle que soit sa balise. :nth-of-type(2) correspond au deuxième élément frère portant la même balise à l’intérieur de ce parent. Dans Scrapy et Parsel, les *-of-type pseudo-classes nécessitent un nom de balise ; écrivez donc div.item:nth-of-type(2), et non .item:nth-of-type(2).

Pourquoi mon sélecteur CSS fonctionne-t-il dans DevTools mais pas dans mon scraper ?

DevTools affiche la page après l'exécution de JavaScript, tandis qu'un client HTTP reçoit le code HTML brut envoyé par le serveur. Si la vue « Afficher la source » ne contient pas le texte recherché, cela signifie que le contenu est rendu côté client. Recherchez la requête JSON sous-jacente, affichez la page dans un navigateur sans interface graphique ou utilisez une API qui effectue le rendu avant l'extraction.

Dois-je utiliser des sélecteurs CSS ou XPath pour le web scraping ?

Commencez par les sélecteurs CSS. Ils sont plus courts, plus faciles à lire et pris en charge partout. Passez à XPath lorsque vous avez besoin d’une correspondance de texte portable, d’un ancêtre spécifique ou de XML. De nombreux scrapers combinent les deux, et Scrapy ainsi que Parsel vous permettent d’utiliser l’un ou l’autre sur la même réponse.

Quels sélecteurs CSS faut-il apprendre en premier ?

Commencez par les classes et les attributs pour trouver des éléments, puis l’espace et les > les combinateurs pour restreindre la sélection à un conteneur. Ajoutez :nth-child() pour les tableaux et les listes, ainsi que :has() pour sélectionner des conteneurs en fonction de leur contenu. Apprenez ensuite comment votre bibliothèque lit le texte et les attributs, qu’il s’agisse de ::text, get_text(), ou .text(). Une fois ces cinq éléments maîtrisés, vous pourrez écrire et corriger presque tous les sélecteurs dont un scraper a besoin.

Testez vos sélecteurs sans lancer le scraper

Envoyez une URL et vos sélecteurs CSS à l’API Scraper et obtenez en retour des champs JSON propres, avec un rendu JavaScript si nécessaire. Commencez avec 5 000 requêtes gratuites. Aucun crédit supplémentaire n’est facturé pour le rendu JavaScript ou le ciblage géographique, et les requêtes ayant échoué ne sont pas facturées.

Consultez les tarifs de l’API Scraper

À propos de l'auteur

Ștefan Răcilă, Développeur Full Stack @ WebScrapingAPI

Ștefan Răcilă

Développeur Full Stack

Stefan Racila est ingénieur DevOps et Full Stack chez WebScrapingAPI ; il développe des fonctionnalités pour les produits et assure la maintenance de l'infrastructure qui garantit la fiabilité de la plateforme.

Web scraping avec AWS Lambda : guide pour Python et Java 2026
Guides

Web scraping avec AWS Lambda : guide pour Python et Java 2026

TL;DR: En bref : le web scraping avec AWS Lambda fonctionne mieux lorsque chaque invocation est courte, bien délimitée et peut faire l'objet d'une nouvelle tentative de manière indépendante. Commencez par utiliser les requêtes HTTP directes, AWS SAM et S3, puis ajoutez SQS, des conteneurs, le rendu dans un navigateur, des proxys ou une couche de récupération gérée uniquement lorsque la charge de travail démontre qu'elle en a besoin.

Suciu Dan33 min read
Lire l'article
Comment utiliser GoSpider : exploration, nettoyage des URL et extraction de données
Guides

Comment utiliser GoSpider : exploration, nettoyage des URL et extraction de données

TL;DR: En bref : GoSpider est un robot d'exploration en ligne de commande destiné à découvrir des URL, et non un outil complet de collecte de données structurées. Ce guide d'utilisation de GoSpider présente comment effectuer une exploration limitée, gérer correctement les résultats, transférer les données de Colly vers un fichier CSV, ainsi qu'une procédure de diagnostic pour les réponses 403 ou les pages nécessitant un rendu JavaScript.

Suciu Dan24 min read
Lire l'article
Comment récupérer les données de Redfin : Guide Python des données immobilières
Guides

Comment récupérer les données de Redfin : Guide Python des données immobilières

TL;DR: Redfin expose des points d'extrémité d'API cachés qui renvoient du JSON structuré pour les listes de propriétés, ce qui permet d'ignorer complètement l'analyse HTML fragile. Ce guide vous accompagne dans la construction d'un scraper Python qui extrait les données de location et de vente, effectue des recherches par emplacement, surveille les nouvelles inscriptions via des sitemaps XML et exporte des résultats propres au format CSV ou JSON.

Suciu Dan15 min read
Lire l'article

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.