chore: sync project files
This commit is contained in:
+115
@@ -0,0 +1,115 @@
|
||||
# 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!
|
||||
Reference in New Issue
Block a user