PriceWatch 🛒
Application Python de suivi de prix e-commerce (Amazon, Cdiscount, extensible).
Description
PriceWatch est une application CLI permettant de scraper et suivre les prix de produits sur différents sites e-commerce. L'application gère automatiquement la détection du site, la récupération des données (HTTP + fallback Playwright), et produit un historique exploitable.
Fonctionnalités
- ✅ Scraping automatique avec détection du site marchand
- ✅ Récupération multi-méthode (HTTP prioritaire, Playwright en fallback)
- ✅ Support Amazon et Cdiscount (architecture extensible)
- ✅ Extraction complète des données produit (prix, titre, images, specs, stock)
- ✅ Pipeline YAML → JSON reproductible
- ✅ Logging détaillé et mode debug
- ✅ Tests pytest avec fixtures HTML
Prérequis
- Python 3.12+
- pip
Installation
# Cloner le dépôt
git clone <repository-url>
cd scrap
# Installer les dépendances
pip install -e .
# Installer les navigateurs Playwright
playwright install
Structure du projet
pricewatch/
├── app/
│ ├── core/ # Modèles et utilitaires centraux
│ │ ├── schema.py # ProductSnapshot (modèle Pydantic)
│ │ ├── registry.py # Détection automatique des stores
│ │ ├── io.py # Lecture YAML / Écriture JSON
│ │ └── logging.py # Configuration logging
│ ├── scraping/ # Méthodes de récupération
│ │ ├── http_fetch.py # Récupération HTTP
│ │ └── pw_fetch.py # Récupération Playwright
│ ├── stores/ # Parsers par site marchand
│ │ ├── base.py # Classe abstraite BaseStore
│ │ ├── amazon/
│ │ │ ├── store.py
│ │ │ ├── selectors.yml
│ │ │ └── fixtures/
│ │ └── cdiscount/
│ │ ├── store.py
│ │ ├── selectors.yml
│ │ └── fixtures/
│ ├── db/ # Persistence SQLAlchemy (Phase 2)
│ │ ├── models.py
│ │ ├── connection.py
│ │ └── migrations/
│ ├── tasks/ # Jobs RQ (Phase 3)
│ │ ├── scrape.py
│ │ └── scheduler.py
│ └── cli/
│ └── main.py # CLI Typer
├── tests/ # Tests pytest
├── scraped/ # Fichiers de debug (HTML, screenshots)
├── scrap_url.yaml # Configuration des URLs à scraper
└── scraped_store.json # Résultat du scraping
Usage CLI
Pipeline complet
# Scraper toutes les URLs définies dans scrap_url.yaml
pricewatch run --yaml scrap_url.yaml --out scraped_store.json
# Avec debug
pricewatch run --yaml scrap_url.yaml --out scraped_store.json --debug
# Avec persistence DB
pricewatch run --yaml scrap_url.yaml --out scraped_store.json --save-db
Commandes utilitaires
# Détecter le store depuis une URL
pricewatch detect https://www.amazon.fr/dp/B08N5WRWNW
# Récupérer une page (HTTP)
pricewatch fetch https://www.amazon.fr/dp/B08N5WRWNW --http
# Récupérer une page (Playwright)
pricewatch fetch https://www.amazon.fr/dp/B08N5WRWNW --playwright
# Parser un fichier HTML avec un store spécifique
pricewatch parse amazon --in scraped/page.html
# Vérifier l'installation
pricewatch doctor
Commandes base de donnees
# Initialiser les tables
pricewatch init-db
# Generer une migration
pricewatch migrate "Initial schema"
# Appliquer les migrations
pricewatch upgrade
# Revenir en arriere
pricewatch downgrade -1
Commandes worker
# Lancer un worker RQ
pricewatch worker
# Enqueue un job immediat
pricewatch enqueue "https://example.com/product"
# Planifier un job recurrent
pricewatch schedule "https://example.com/product" --interval 24
Base de donnees (Phase 2)
# Lancer PostgreSQL + Redis en local
docker-compose up -d
# Exemple de configuration
cp .env.example .env
Guide de migration JSON -> DB: MIGRATION_GUIDE.md
API REST (Phase 3)
L'API est protegee par un token simple.
export PW_API_TOKEN=change_me
docker compose up -d api
Exemples:
curl -H "Authorization: Bearer $PW_API_TOKEN" http://localhost:8001/products
curl http://localhost:8001/health
Filtres (exemples rapides):
curl -H "Authorization: Bearer $PW_API_TOKEN" \\
"http://localhost:8001/products?price_min=100&stock_status=in_stock"
curl -H "Authorization: Bearer $PW_API_TOKEN" \\
"http://localhost:8001/products/1/prices?fetch_status=success&fetched_after=2026-01-14T00:00:00"
curl -H "Authorization: Bearer $PW_API_TOKEN" \\
"http://localhost:8001/logs?fetch_status=failed&fetched_before=2026-01-15T00:00:00"
Exports (CSV/JSON):
curl -H "Authorization: Bearer $PW_API_TOKEN" \\
"http://localhost:8001/products/export?format=csv"
curl -H "Authorization: Bearer $PW_API_TOKEN" \\
"http://localhost:8001/logs/export?format=json"
CRUD (examples rapides):
curl -H "Authorization: Bearer $PW_API_TOKEN" -X POST http://localhost:8001/products \\
-H "Content-Type: application/json" \\
-d '{"source":"amazon","reference":"REF1","url":"https://example.com"}'
Webhooks (exemples rapides):
curl -H "Authorization: Bearer $PW_API_TOKEN" -X POST http://localhost:8001/webhooks \\
-H "Content-Type: application/json" \\
-d '{"event":"price_changed","url":"https://example.com/webhook","enabled":true}'
curl -H "Authorization: Bearer $PW_API_TOKEN" -X POST http://localhost:8001/webhooks/1/test
Web UI (Phase 4)
Interface Vue 3 dense avec themes Gruvbox/Monokai, header fixe, sidebar filtres, et split compare.
docker compose up -d frontend
# Acces: http://localhost:3000
Configuration (scrap_url.yaml)
urls:
- "https://www.amazon.fr/dp/B08N5WRWNW"
- "https://www.cdiscount.com/informatique/clavier-souris-webcam/example/f-1070123-example.html"
options:
use_playwright: true # Utiliser Playwright en fallback
headful: false # Mode headless (true = voir le navigateur)
save_html: true # Sauvegarder HTML pour debug
save_screenshot: true # Sauvegarder screenshot pour debug
timeout_ms: 60000 # Timeout par page (ms)
Format de sortie (ProductSnapshot)
Chaque produit scraped est représenté par un objet ProductSnapshot contenant :
Métadonnées
source: Site d'origine (amazon, cdiscount, unknown)url: URL canonique du produitfetched_at: Date/heure de récupération (ISO 8601)
Données produit
title: Nom du produitprice: Prix (float ou null)currency: Devise (EUR, USD, etc.)shipping_cost: Frais de port (float ou null)stock_status: Statut stock (in_stock, out_of_stock, unknown)reference: Référence produit (ASIN pour Amazon, SKU pour autres)images: Liste des URLs d'imagescategory: Catégorie du produitspecs: Caractéristiques techniques (dict clé/valeur)
Debug
debug.method: Méthode utilisée (http, playwright)debug.errors: Liste des erreurs rencontréesdebug.notes: Notes techniquesdebug.status: Statut de récupération (success, partial, failed)
Tests
# Lancer tous les tests
pytest
# Tests avec couverture
pytest --cov=pricewatch
# Tests d'un store spécifique
pytest tests/stores/amazon/
pytest tests/stores/cdiscount/
# Mode verbose
pytest -v
Architecture des stores
Chaque store implémente la classe abstraite BaseStore avec :
match(url) -> float: Score de correspondance (0.0 à 1.0)canonicalize(url) -> str: Normalisation de l'URLextract_reference(url) -> str: Extraction référence produitfetch(url, method, options) -> str: Récupération HTMLparse(html, url) -> ProductSnapshot: Parsing vers modèle canonique
Les sélecteurs (XPath/CSS) sont externalisés dans selectors.yml pour faciliter la maintenance.
Ajouter un nouveau store
- Créer
pricewatch/app/stores/nouveaustore/ - Créer
store.pyavec une classe héritant deBaseStore - Créer
selectors.ymlavec les sélecteurs XPath/CSS - Ajouter des fixtures HTML dans
fixtures/ - Enregistrer le store dans le
Registry - Écrire les tests dans
tests/stores/nouveaustore/
Gestion des erreurs
L'application est conçue pour être robuste face aux anti-bots :
- 403 Forbidden : Fallback automatique vers Playwright
- Captcha détecté : Logged dans
debug.errors, statutfailed - Timeout : Configurable, logged
- Parsing échoué : ProductSnapshot partiel avec
debug.status=partial
Aucune erreur ne doit crasher silencieusement : toutes sont loggées et tracées dans le ProductSnapshot.
Roadmap
Phase 1 : CLI (actuelle)
- ✅ Pipeline YAML → JSON
- ✅ Support Amazon + Cdiscount
- ✅ Scraping HTTP + Playwright
- ✅ Tests pytest
Phase 2 : Persistence
- Base de données PostgreSQL
- Migrations Alembic
- Historique des prix
Phase 3 : Automation
- Worker (Redis + RQ/Celery)
- Planification quotidienne
- Gestion de la queue
Phase 4 : Web UI
- Interface web responsive
- Dark theme (Gruvbox)
- Graphiques historique prix
- Gestion des alertes
Phase 5 : Alertes
- Notifications baisse de prix
- Notifications retour en stock
- Webhooks/email
Développement
Règles
- Python 3.12 obligatoire
- Commentaires et discussions en français
- Toute décision technique doit être justifiée (1-3 phrases)
- Pas d'optimisation prématurée
- Logging systématique (méthode, durée, erreurs)
- Tests obligatoires pour chaque store
Documentation
README.md: Ce fichierTODO.md: Liste des tâches prioriséesCHANGELOG.md: Journal des modificationsCLAUDE.md: Guide pour Claude Code
License
À définir
Auteur
À définir