chore: sync project files
This commit is contained in:
316
TEST_FILES_README.md
Executable file
316
TEST_FILES_README.md
Executable file
@@ -0,0 +1,316 @@
|
||||
# 🧪 Fichiers de test - Guide d'utilisation
|
||||
|
||||
Ce dossier contient des fichiers JSON de test pour valider les sélecteurs et le fonctionnement des stores sans faire de requêtes réelles.
|
||||
|
||||
## 📁 Fichiers disponibles
|
||||
|
||||
```
|
||||
├── test_amazon.json Configuration de test pour Amazon
|
||||
├── test_cdiscount.json Configuration de test pour Cdiscount
|
||||
└── test_selectors.py Script de validation des sélecteurs
|
||||
```
|
||||
|
||||
## 🎯 Objectif
|
||||
|
||||
Ces fichiers permettent de :
|
||||
1. **Tester la détection d'URL** : Vérifier que les stores sont correctement détectés
|
||||
2. **Valider l'extraction de référence** : ASIN pour Amazon, SKU pour Cdiscount
|
||||
3. **Documenter les sélecteurs** : Avoir une référence claire des sélecteurs utilisés
|
||||
4. **Faciliter le debug** : Identifier rapidement les sélecteurs qui ne fonctionnent plus
|
||||
|
||||
## 📋 Structure d'un fichier de test JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"test_config": {
|
||||
"store": "amazon", // ID du store
|
||||
"url": "https://...", // URL d'exemple
|
||||
"description": "Description du test"
|
||||
},
|
||||
"selectors": {
|
||||
"title": { // Champ à extraire
|
||||
"type": "css", // Type: css ou regex
|
||||
"selector": "#productTitle", // Sélecteur CSS
|
||||
"expected": "Valeur attendue" // Valeur exemple
|
||||
},
|
||||
"price": {
|
||||
"type": "css",
|
||||
"selector": "span[itemprop='price']",
|
||||
"attribute": "content", // Attribut HTML (optionnel)
|
||||
"expected": "299.99"
|
||||
}
|
||||
},
|
||||
"test_data": {
|
||||
"valid_urls": [ // URLs valides pour test
|
||||
"https://www.amazon.fr/dp/B08N5WRWNW",
|
||||
"https://www.amazon.fr/product/dp/B08N5WRWNW/ref=xyz"
|
||||
],
|
||||
"expected_canonical": "...", // URL canonique attendue
|
||||
"expected_asin": "B08N5WRWNW" // Référence attendue
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 Utilisation
|
||||
|
||||
### 1. Tester les sélecteurs avec le script Python
|
||||
|
||||
```bash
|
||||
# Activer l'environnement
|
||||
source venv/bin/activate
|
||||
|
||||
# Tester Amazon
|
||||
python test_selectors.py test_amazon.json
|
||||
|
||||
# Tester Cdiscount
|
||||
python test_selectors.py test_cdiscount.json
|
||||
```
|
||||
|
||||
### 2. Tester avec une vraie page
|
||||
|
||||
```bash
|
||||
# Étape 1: Récupérer une vraie page HTML
|
||||
pricewatch fetch "https://www.amazon.fr/dp/B08N5WRWNW" --http
|
||||
|
||||
# La page sera sauvegardée dans scraped/ si save_html: true
|
||||
# Ensuite parser avec le store approprié
|
||||
|
||||
# Étape 2: Parser le HTML récupéré
|
||||
pricewatch parse amazon --in scraped/amazon_B08N5WRWNW.html
|
||||
```
|
||||
|
||||
### 3. Tester le pipeline complet
|
||||
|
||||
Éditer `scrap_url.yaml` avec l'URL du fichier de test :
|
||||
|
||||
```yaml
|
||||
urls:
|
||||
- "https://www.amazon.fr/dp/B08N5WRWNW"
|
||||
|
||||
options:
|
||||
use_playwright: true
|
||||
save_html: true
|
||||
save_screenshot: true
|
||||
```
|
||||
|
||||
Puis lancer :
|
||||
|
||||
```bash
|
||||
pricewatch run --yaml scrap_url.yaml --debug
|
||||
```
|
||||
|
||||
## 📊 Résultats des tests
|
||||
|
||||
### ✅ Tests Amazon
|
||||
|
||||
```
|
||||
📍 Test URL: https://www.amazon.fr/dp/B08N5WRWNW
|
||||
✓ Store détecté: amazon
|
||||
✓ URL canonique: https://www.amazon.fr/dp/B08N5WRWNW
|
||||
✓ Référence: B08N5WRWNW
|
||||
```
|
||||
|
||||
**Sélecteurs testés** :
|
||||
- `#productTitle` → Titre du produit
|
||||
- `span.a-price-whole` → Prix
|
||||
- `span.a-price-symbol` → Devise
|
||||
- `#availability span` → Stock
|
||||
- `#landingImage` → Image principale
|
||||
- `#wayfinding-breadcrumbs_feature_div` → Catégorie
|
||||
|
||||
### ✅ Tests Cdiscount
|
||||
|
||||
```
|
||||
📍 Test URL: https://www.cdiscount.com/.../f-1070123-exemple.html
|
||||
✓ Store détecté: cdiscount
|
||||
✓ URL canonique: https://www.cdiscount.com/.../f-1070123-exemple.html
|
||||
✓ Référence: 1070123-exemple
|
||||
```
|
||||
|
||||
**Sélecteurs testés** :
|
||||
- `h1[itemprop='name']` → Titre
|
||||
- `span[itemprop='price']` → Prix (attribut content)
|
||||
- `meta[itemprop='priceCurrency']` → Devise (attribut content)
|
||||
- `link[itemprop='availability']` → Stock (attribut href)
|
||||
- `img[itemprop='image']` → Images
|
||||
- `.breadcrumb` → Catégorie
|
||||
|
||||
## 🔧 Maintenance des sélecteurs
|
||||
|
||||
Les sites e-commerce changent fréquemment leurs sélecteurs. Voici comment mettre à jour :
|
||||
|
||||
### 1. Identifier un sélecteur cassé
|
||||
|
||||
Si le parsing échoue :
|
||||
```bash
|
||||
pricewatch run --debug
|
||||
# Regarde les logs pour voir quel champ est manquant
|
||||
```
|
||||
|
||||
### 2. Trouver le nouveau sélecteur
|
||||
|
||||
```bash
|
||||
# Récupérer la page HTML
|
||||
pricewatch fetch "URL" --http
|
||||
|
||||
# Ouvrir scraped/page.html dans un navigateur
|
||||
# Inspecter l'élément (F12 → Inspecter)
|
||||
# Copier le nouveau sélecteur CSS
|
||||
```
|
||||
|
||||
### 3. Mettre à jour les fichiers
|
||||
|
||||
**Dans `test_amazon.json` ou `test_cdiscount.json`** :
|
||||
```json
|
||||
{
|
||||
"selectors": {
|
||||
"title": {
|
||||
"selector": "#nouveauSelecteur" // ← Nouveau sélecteur
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Dans `pricewatch/app/stores/amazon/selectors.yml`** :
|
||||
```yaml
|
||||
title:
|
||||
- "#nouveauSelecteur" # Nouveau (prioritaire)
|
||||
- "#productTitle" # Ancien (fallback)
|
||||
```
|
||||
|
||||
### 4. Re-tester
|
||||
|
||||
```bash
|
||||
python test_selectors.py test_amazon.json
|
||||
# Vérifier que la détection fonctionne toujours
|
||||
```
|
||||
|
||||
## 💡 Bonnes pratiques
|
||||
|
||||
### Sélecteurs robustes
|
||||
|
||||
✅ **Préférer** :
|
||||
- Sélecteurs avec `id` : `#productTitle`
|
||||
- Attributs schema.org : `[itemprop='name']`
|
||||
- Classes stables : `.product-title`
|
||||
|
||||
❌ **Éviter** :
|
||||
- Classes génériques : `.row`, `.col-md-6`
|
||||
- Noms de classes avec hash : `.css-1a2b3c4`
|
||||
- Sélecteurs trop spécifiques : `div > div > div > span`
|
||||
|
||||
### Fallbacks multiples
|
||||
|
||||
Toujours prévoir plusieurs sélecteurs dans le YAML :
|
||||
|
||||
```yaml
|
||||
title:
|
||||
- "#productTitle" # Sélecteur principal
|
||||
- ".product-title" # Fallback 1
|
||||
- "h1.product-name" # Fallback 2
|
||||
```
|
||||
|
||||
Le parser essaiera chaque sélecteur dans l'ordre jusqu'à trouver un match.
|
||||
|
||||
### Extraction d'attributs
|
||||
|
||||
Pour extraire un attribut HTML (ex: `src`, `href`, `content`) :
|
||||
|
||||
```json
|
||||
{
|
||||
"images": {
|
||||
"type": "css",
|
||||
"selector": "img#landingImage",
|
||||
"attribute": "src" // ← Important pour les attributs
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📝 Ajouter un nouveau store
|
||||
|
||||
Pour ajouter un nouveau store (ex: Fnac) :
|
||||
|
||||
### 1. Créer le fichier de test JSON
|
||||
|
||||
```bash
|
||||
cp test_amazon.json test_fnac.json
|
||||
# Éditer test_fnac.json avec les infos Fnac
|
||||
```
|
||||
|
||||
### 2. Créer le store Python
|
||||
|
||||
```python
|
||||
# pricewatch/app/stores/fnac/store.py
|
||||
from pricewatch.app.stores.base import BaseStore
|
||||
|
||||
class FnacStore(BaseStore):
|
||||
def match(self, url: str) -> float:
|
||||
return 0.9 if "fnac.com" in url.lower() else 0.0
|
||||
|
||||
# ... implémenter les autres méthodes
|
||||
```
|
||||
|
||||
### 3. Créer le fichier de sélecteurs
|
||||
|
||||
```yaml
|
||||
# pricewatch/app/stores/fnac/selectors.yml
|
||||
title:
|
||||
- ".product-title"
|
||||
price:
|
||||
- ".price-amount"
|
||||
# ... etc
|
||||
```
|
||||
|
||||
### 4. Tester
|
||||
|
||||
```bash
|
||||
python test_selectors.py test_fnac.json
|
||||
```
|
||||
|
||||
## 🐛 Debug
|
||||
|
||||
### Problème : Store non détecté
|
||||
|
||||
```bash
|
||||
# Vérifier le score de match
|
||||
python test_selectors.py test_amazon.json
|
||||
|
||||
# Si score = 0, vérifier la méthode match() du store
|
||||
```
|
||||
|
||||
### Problème : Sélecteur ne trouve rien
|
||||
|
||||
```bash
|
||||
# 1. Sauvegarder le HTML
|
||||
pricewatch fetch "URL" --http
|
||||
|
||||
# 2. Inspecter le HTML
|
||||
cat scraped/page.html | grep -i "productTitle"
|
||||
|
||||
# 3. Tester avec BeautifulSoup
|
||||
python -c "
|
||||
from bs4 import BeautifulSoup
|
||||
html = open('scraped/page.html').read()
|
||||
soup = BeautifulSoup(html, 'lxml')
|
||||
print(soup.select('#productTitle'))
|
||||
"
|
||||
```
|
||||
|
||||
### Problème : Parsing incomplet
|
||||
|
||||
Les logs indiquent quel champ manque :
|
||||
```
|
||||
debug.errors: ["Titre non trouvé", "Prix non trouvé"]
|
||||
```
|
||||
|
||||
Ajuster les sélecteurs en conséquence.
|
||||
|
||||
## 📚 Ressources
|
||||
|
||||
- **Documentation sélecteurs CSS** : https://developer.mozilla.org/fr/docs/Web/CSS/CSS_Selectors
|
||||
- **BeautifulSoup** : https://www.crummy.com/software/BeautifulSoup/bs4/doc/
|
||||
- **Schema.org** : https://schema.org/Product (pour Cdiscount et sites avec métadonnées)
|
||||
|
||||
---
|
||||
|
||||
**Note** : Ces fichiers de test sont essentiels pour maintenir la robustesse du scraping. Mettez-les à jour dès qu'un sélecteur cesse de fonctionner.
|
||||
Reference in New Issue
Block a user