chore: sync project files
This commit is contained in:
163
pricewatch/app/stores/aliexpress/fixtures/README.md
Executable file
163
pricewatch/app/stores/aliexpress/fixtures/README.md
Executable file
@@ -0,0 +1,163 @@
|
||||
# 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:
|
||||
|
||||
```javascript
|
||||
window._d_c_.DCData = {
|
||||
"imagePathList": ["https://ae01.alicdn.com/kf/..."],
|
||||
"summImagePathList": ["https://ae01.alicdn.com/kf/..."],
|
||||
"i18nMap": {...},
|
||||
"extParams": {...}
|
||||
}
|
||||
```
|
||||
|
||||
### Sélecteurs identifiés
|
||||
|
||||
#### Titre
|
||||
```css
|
||||
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:
|
||||
```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:
|
||||
```regex
|
||||
/item/(\d+)\.html
|
||||
```
|
||||
Exemple: `/item/1005007187023722.html` → SKU = "1005007187023722"
|
||||
|
||||
#### Stock
|
||||
Chercher bouton "Add to cart" / "Ajouter au panier"
|
||||
```css
|
||||
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
|
||||
|
||||
```python
|
||||
@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
|
||||
|
||||
```python
|
||||
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
|
||||
863
pricewatch/app/stores/aliexpress/fixtures/aliexpress_1005007187023722.html
Executable file
863
pricewatch/app/stores/aliexpress/fixtures/aliexpress_1005007187023722.html
Executable file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user