Files
scrap/pricewatch/app/stores/aliexpress/fixtures
2026-01-13 19:49:04 +01:00
..
2026-01-13 19:49:04 +01:00

Fixtures AliExpress

Ce dossier contient des fichiers HTML réels capturés depuis AliExpress pour les tests.

⚠️ Note importante sur AliExpress

AliExpress utilise un rendu client-side (SPA React/Vue):

  • HTTP simple retourne HTML minimal (75KB sans contenu)
  • Playwright est OBLIGATOIRE avec attente (~3s)
  • Attendre le sélecteur .product-title pour obtenir les données
  • Données chargées via AJAX après le render initial

Spécificité AliExpress

AliExpress est un marketplace chinois avec des particularités:

  • Pas de JSON-LD schema.org
  • Prix: Extrait par regex (aucun sélecteur CSS stable)
  • Images: Extraites depuis window._d_c_.DCData.imagePathList (JSON embarqué)
  • Classes CSS: Générées aléatoirement (hachées) → TRÈS instables
  • SKU: ID numérique long (13 chiffres) depuis l'URL

Fichiers

aliexpress_1005007187023722.html

  • Produit: Samsung serveur DDR4 mémoire Ram ECC
  • SKU: 1005007187023722
  • URL: https://fr.aliexpress.com/item/1005007187023722.html
  • Taille: 378 KB (rendu complet)
  • Date capture: 2026-01-13
  • Méthode: Playwright avec wait_for_selector='.product-title'
  • Prix capturé: 136,69 EUR
  • Usage: Test complet parsing produit électronique

Structure HTML AliExpress

JSON-LD Schema.org ✗

AliExpress n'utilise PAS JSON-LD (contrairement à Backmarket).

Données embarquées ✓

AliExpress embarque les données dans des variables JavaScript:

window._d_c_.DCData = {
  "imagePathList": ["https://ae01.alicdn.com/kf/..."],
  "summImagePathList": ["https://ae01.alicdn.com/kf/..."],
  "i18nMap": {...},
  "extParams": {...}
}

Sélecteurs identifiés

Titre

h1                         /* Apparaît après AJAX */
meta[property="og:title"]  /* Fallback dans meta tags */

Le h1 n'existe PAS dans le HTML initial, il est ajouté dynamiquement.

Prix

⚠️ AUCUN SÉLECTEUR CSS STABLE - Utiliser regex:

([0-9]+[.,][0-9]{2})\s*€    /* Prix avant € */
€\s*([0-9]+[.,][0-9]{2})    /* € avant prix */

Images

Priorité: window.d_c.DCData.imagePathList Fallback: meta[property="og:image"]

URLs CDN: https://ae01.alicdn.com/kf/...

SKU

Extraction depuis l'URL:

/item/(\d+)\.html

Exemple: /item/1005007187023722.html → SKU = "1005007187023722"

Stock

Chercher bouton "Add to cart" / "Ajouter au panier"

button[class*='add-to-cart']

Comparaison avec autres stores

Aspect Amazon Cdiscount Backmarket AliExpress
Anti-bot Faible Fort Fort Moyen
Méthode HTTP OK Playwright Playwright Playwright
JSON-LD Partiel ✗ Non ✓ Oui ✗ Non
Sélecteurs Stables (IDs) Instables Stables Très instables
SKU format /dp/{ASIN} /f-{cat}-{SKU} /p/{slug} /item/{ID}.html
Prix extraction CSS CSS/Regex JSON-LD Regex uniquement
Rendu Server-side Server-side Server-side Client-side (SPA)
Particularité - Prix dynamiques Reconditionné SPA React/Vue

Utilisation dans les tests

@pytest.fixture
def aliexpress_fixture_samsung():
    fixture_path = Path(__file__).parent.parent.parent / \
        "pricewatch/app/stores/aliexpress/fixtures/aliexpress_1005007187023722.html"
    with open(fixture_path, "r", encoding="utf-8") as f:
        return f.read()

def test_parse_real_fixture(store, aliexpress_fixture_samsung):
    url = "https://fr.aliexpress.com/item/1005007187023722.html"
    snapshot = store.parse(aliexpress_fixture_samsung, url)

    assert snapshot.title.startswith("Samsung serveur DDR4")
    assert snapshot.price == 136.69
    assert snapshot.reference == "1005007187023722"
    assert snapshot.currency == "EUR"
    assert len(snapshot.images) >= 6

Points d'attention pour les tests

  1. HTML volumineux - 378KB pour une page (SPA chargée)
  2. Prix instable - Peut changer selon promo/devise
  3. Ne pas tester le prix exact - Tester le format et la présence
  4. Images multiples - Toujours 6+ images par produit
  5. Titre long - Souvent 100-150 caractères
  6. Stock variable - Peut changer rapidement

Comment capturer une nouvelle fixture

from pricewatch.app.scraping.pw_fetch import fetch_playwright

url = "https://fr.aliexpress.com/item/..."
result = fetch_playwright(
    url,
    headless=True,
    timeout_ms=15000,
    wait_for_selector=".product-title"  # IMPORTANT!
)

if result.success:
    with open("fixture.html", "w", encoding="utf-8") as f:
        f.write(result.html)

⚠️ N'utilisez PAS fetch_http() - il retourne un HTML minimal (75KB)! ⚠️ Utilisez TOUJOURS wait_for_selector=".product-title" avec Playwright!

Avantages de AliExpress

HTTP fonctionne → Pas d'anti-bot fort (mais HTML vide) ✓ Données embarquées → DCData JSON avec images ✓ SKU simple → ID numérique depuis URL

Inconvénients

SPA client-side → Playwright obligatoire avec wait (~3-5s) ✗ Pas de JSON-LD → Extraction moins fiable ✗ Prix par regex → Fragile, peut casser ✗ Classes CSS instables → Générées aléatoirement (hachées) ✗ Temps de chargement → 3-5s avec Playwright + wait ✗ Specs mal structurées → Souvent dans des onglets/modals