chore: sync project files
This commit is contained in:
143
pricewatch/app/stores/backmarket/fixtures/README.md
Executable file
143
pricewatch/app/stores/backmarket/fixtures/README.md
Executable file
@@ -0,0 +1,143 @@
|
||||
# Fixtures Backmarket
|
||||
|
||||
Ce dossier contient des fichiers HTML réels capturés depuis Backmarket.fr pour les tests.
|
||||
|
||||
## ⚠️ Note importante sur Backmarket
|
||||
|
||||
Backmarket utilise une **protection anti-bot**:
|
||||
- HTTP simple retourne **403 Forbidden**
|
||||
- **Playwright est OBLIGATOIRE** pour récupérer le contenu
|
||||
- Temps de chargement: ~2-3 secondes
|
||||
|
||||
## Spécificité Backmarket
|
||||
|
||||
Backmarket vend des **produits reconditionnés**:
|
||||
- Prix variable selon la **condition** (Correct, Bon, Excellent, etc.)
|
||||
- Chaque produit a plusieurs offres avec des états différents
|
||||
- Le prix extrait correspond à l'offre sélectionnée par défaut
|
||||
|
||||
## Fichiers
|
||||
|
||||
### backmarket_iphone15pro.html
|
||||
- **Produit**: iPhone 15 Pro (reconditionné)
|
||||
- **SKU**: iphone-15-pro
|
||||
- **URL**: https://www.backmarket.fr/fr-fr/p/iphone-15-pro
|
||||
- **Taille**: ~1.5 MB
|
||||
- **Date capture**: 2026-01-13
|
||||
- **Prix capturé**: 571 EUR (prix de l'offre par défaut)
|
||||
- **Usage**: Test complet parsing smartphone reconditionné
|
||||
|
||||
## Structure HTML Backmarket
|
||||
|
||||
### JSON-LD Schema.org ✓
|
||||
Backmarket utilise **JSON-LD structuré** (contrairement à Cdiscount):
|
||||
```json
|
||||
{
|
||||
"@type": "Product",
|
||||
"name": "iPhone 15 Pro",
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": "571.00",
|
||||
"priceCurrency": "EUR"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Sélecteurs identifiés
|
||||
|
||||
#### Titre
|
||||
```css
|
||||
h1.heading-1
|
||||
```
|
||||
Classes stables, simple et propre.
|
||||
|
||||
#### Prix
|
||||
Priorité: **JSON-LD** (source la plus fiable)
|
||||
Fallback: `div[data-test='price']`
|
||||
|
||||
#### Images
|
||||
```css
|
||||
img[alt]
|
||||
```
|
||||
URLs CDN: `https://d2e6ccujb3mkqf.cloudfront.net/...`
|
||||
|
||||
#### SKU
|
||||
Extraction depuis l'URL:
|
||||
```regex
|
||||
/p/([a-z0-9-]+)
|
||||
```
|
||||
Exemple: `/p/iphone-15-pro` → SKU = "iphone-15-pro"
|
||||
|
||||
#### Condition (État du reconditionné)
|
||||
```css
|
||||
button[data-test='condition-button']
|
||||
div[class*='condition']
|
||||
```
|
||||
Valeurs possibles: Correct, Bon, Très bon, Excellent, Comme neuf
|
||||
|
||||
## Comparaison avec autres stores
|
||||
|
||||
| Aspect | Amazon | Cdiscount | Backmarket |
|
||||
|--------|--------|-----------|------------|
|
||||
| **Anti-bot** | Faible | Fort | Fort |
|
||||
| **Méthode** | HTTP OK | Playwright | Playwright |
|
||||
| **JSON-LD** | Partiel | ✗ Non | ✓ Oui (complet) |
|
||||
| **Sélecteurs** | Stables (IDs) | Instables | Stables (classes) |
|
||||
| **SKU format** | `/dp/{ASIN}` | `/f-{cat}-{SKU}` | `/p/{slug}` |
|
||||
| **Particularité** | - | Prix dynamiques | Reconditionné (condition) |
|
||||
|
||||
## Utilisation dans les tests
|
||||
|
||||
```python
|
||||
@pytest.fixture
|
||||
def backmarket_fixture_iphone15pro():
|
||||
fixture_path = Path(__file__).parent.parent.parent / \
|
||||
"pricewatch/app/stores/backmarket/fixtures/backmarket_iphone15pro.html"
|
||||
with open(fixture_path, "r", encoding="utf-8") as f:
|
||||
return f.read()
|
||||
|
||||
def test_parse_real_fixture(store, backmarket_fixture_iphone15pro):
|
||||
url = "https://www.backmarket.fr/fr-fr/p/iphone-15-pro"
|
||||
snapshot = store.parse(backmarket_fixture_iphone15pro, url)
|
||||
|
||||
assert snapshot.title == "iPhone 15 Pro"
|
||||
assert snapshot.price == 571.0
|
||||
assert snapshot.reference == "iphone-15-pro"
|
||||
assert snapshot.currency == "EUR"
|
||||
```
|
||||
|
||||
## Points d'attention pour les tests
|
||||
|
||||
1. **JSON-LD prioritaire** - Le prix vient du JSON-LD, pas du HTML visible
|
||||
2. **Prix variable** - Change selon la condition sélectionnée
|
||||
3. **Ne pas tester le prix exact** - Il varie avec les offres disponibles
|
||||
4. **Tester le format** et la présence des données
|
||||
5. Backmarket = **produits reconditionnés** uniquement
|
||||
|
||||
## Comment capturer une nouvelle fixture
|
||||
|
||||
```python
|
||||
from pricewatch.app.scraping.pw_fetch import fetch_playwright
|
||||
|
||||
url = "https://www.backmarket.fr/fr-fr/p/..."
|
||||
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 Backmarket - cela retournera 403!
|
||||
|
||||
## Avantages de Backmarket
|
||||
|
||||
✓ **JSON-LD structuré** → Parsing très fiable
|
||||
✓ **Classes CSS stables** → Moins de casse que Cdiscount
|
||||
✓ **URL propre** → SKU facile à extraire
|
||||
✓ **Schema.org complet** → Prix, nom, images dans JSON
|
||||
|
||||
## Inconvénients
|
||||
|
||||
✗ **Protection anti-bot** → Playwright obligatoire (lent)
|
||||
✗ **Prix multiples** → Un produit = plusieurs offres selon état
|
||||
✗ **Stock complexe** → Dépend de l'offre et de la condition
|
||||
Reference in New Issue
Block a user