# Fixtures Cdiscount Ce dossier contient des fichiers HTML réels capturés depuis Cdiscount.com pour les tests. ## ⚠️ Note importante sur Cdiscount Cdiscount utilise une **protection anti-bot forte** (Cloudflare/Baleen): - HTTP simple retourne une page de protection JavaScript (~14 KB) - **Playwright est OBLIGATOIRE** pour récupérer le vrai contenu - Temps de chargement: ~2-3 secondes ## Fichiers ### cdiscount_tuf608umrv004_pw.html - **Produit**: PC Portable Gamer ASUS TUF Gaming A16 - **SKU**: tuf608umrv004 - **URL**: https://www.cdiscount.com/informatique/ordinateurs-pc-portables/pc-portable-gamer-asus-tuf-gaming-a16-sans-windo/f-10709-tuf608umrv004.html - **Taille**: ~310 KB - **Lignes**: 399 - **Méthode**: Playwright (headless) - **Date capture**: 2026-01-13 - **Usage**: Test complet parsing produit tech ## Différences avec Amazon | Aspect | Amazon | Cdiscount | |--------|--------|-----------| | **Anti-bot** | Faible (HTTP OK) | ✗ Fort (Playwright requis) | | **Sélecteurs** | Stables (IDs) | Instables (classes générées) | | **Structure** | `#productTitle`, `.a-price` | `data-e2e="title"`, classes dynamiques | | **Prix** | 3 parties (whole+fraction+symbol) | Texte direct "1499,99 €" | | **Référence** | ASIN dans URL `/dp/{ASIN}` | SKU dans URL `/f-{cat}-{SKU}.html` | | **Catégorie** | Breadcrumb HTML | Dans l'URL path | | **Specs** | Tables HTML | Peut être dans onglets cachés | ## Sélecteurs identifiés ### Titre ```css h1[data-e2e="title"] ``` Exemple: "PC Portable Gamer ASUS TUF Gaming A16 | Sans Windows - 16" WUXGA..." ### Prix Classes CSS instables. Utiliser **regex sur le texte**: ```regex (\d+[,\.]\d+)\s*€ ``` Exemple: "1199,99 €" → 1199.99 ### Images ```css img[alt] ``` Filtrer celles dont `alt` contient le titre du produit. Format URL: `https://www.cdiscount.com/pdt2/0/0/4/{num}/700x700/{sku}/rw/...` ### SKU Extraction depuis l'URL: ```regex /f-\d+-([a-z0-9]+)\.html ``` Groupe 1 = SKU (ex: `tuf608umrv004`) ### Catégorie Extraction depuis l'URL path: ``` /informatique/ordinateurs-pc-portables/... ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ catégorie1 catégorie2 ``` ## Utilisation dans les tests ```python @pytest.fixture def cdiscount_fixture_tuf608umrv004(): fixture_path = Path(__file__).parent.parent.parent / \ "pricewatch/app/stores/cdiscount/fixtures/cdiscount_tuf608umrv004_pw.html" with open(fixture_path, "r", encoding="utf-8") as f: return f.read() def test_parse_real_fixture(store, cdiscount_fixture_tuf608umrv004): url = "https://www.cdiscount.com/informatique/.../f-10709-tuf608umrv004.html" snapshot = store.parse(cdiscount_fixture_tuf608umrv004, url) assert snapshot.title is not None assert "ASUS" in snapshot.title assert snapshot.price == 1199.99 assert snapshot.reference == "tuf608umrv004" ``` ## Points d'attention pour les tests 1. **Ne pas tester les valeurs exactes** (prix, nombre d'avis) car elles changent 2. **Tester le format** et la présence des données 3. **Prévoir des fallbacks** pour chaque champ (sélecteurs instables) 4. Les classes CSS peuvent changer à tout moment 5. Utiliser `data-e2e` attributes quand disponibles (plus stables) 6. Parser le prix par regex plutôt que par sélecteurs CSS ## Comment capturer une nouvelle fixture ```python from pricewatch.app.scraping.pw_fetch import fetch_playwright url = "https://www.cdiscount.com/..." result = fetch_playwright(url, headless=True, timeout_ms=60000) if result.success: with open("fixture.html", "w", encoding="utf-8") as f: f.write(result.html) ``` ⚠️ **N'utilisez JAMAIS** `fetch_http()` pour Cdiscount - cela ne fonctionnera pas!