""" API Router pour la recherche Amazon France Utilise Server-Sent Events (SSE) pour le streaming des résultats Uses Browserless service for reliable scraping """ import json import logging from typing import AsyncGenerator from fastapi import APIRouter, Query from fastapi.responses import StreamingResponse from pydantic import BaseModel from app.services.amazon_scraper_service import amazon_scraper_service, AmazonProduct logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/amazon", tags=["amazon"]) class AmazonSearchProgress(BaseModel): """Progress model for SSE streaming""" status: str # 'searching', 'completed', 'error' total: int completed: int message: str results: list[dict] @router.get("/search") async def search_amazon( q: str = Query(..., min_length=1, description="Terme de recherche"), max_results: int = Query(50, ge=1, le=100, description="Nombre max de résultats"), ): """ Recherche de produits sur Amazon France. Retourne un flux SSE avec les résultats. Format des événements SSE: - event: progress - data: {"status": "...", "total": 1, "completed": 0/1, "results": [...]} """ async def generate() -> AsyncGenerator[str, None]: try: # Initial progress progress = AmazonSearchProgress( status="searching", total=1, completed=0, message=f"Recherche sur Amazon France: '{q}'...", results=[] ) yield f"event: progress\ndata: {progress.model_dump_json()}\n\n" # Execute search with persistent browser service logger.info(f"Starting Amazon search for: {q}") products = await amazon_scraper_service.scrape_search(q, max_results=max_results) # Convert to dict results = [p.model_dump() for p in products] # Final progress if results: progress = AmazonSearchProgress( status="completed", total=1, completed=1, message=f"✅ {len(results)} produits trouvés", results=results ) else: progress = AmazonSearchProgress( status="completed", total=1, completed=1, message="Aucun produit trouvé", results=[] ) yield f"event: progress\ndata: {progress.model_dump_json()}\n\n" except Exception as e: logger.error(f"Error during Amazon search: {e}", exc_info=True) error_progress = AmazonSearchProgress( status="error", total=1, completed=1, message=f"Erreur: {str(e)}", results=[] ) yield f"event: progress\ndata: {error_progress.model_dump_json()}\n\n" return StreamingResponse( generate(), media_type="text/event-stream", headers={ "Cache-Control": "no-cache", "Connection": "keep-alive", "X-Accel-Buffering": "no", }, ) @router.get("/health") async def amazon_health(): """Vérifie que le service Amazon est opérationnel""" return { "status": "ok", "service": "Amazon France Scraper", "anti_detection": "enabled", "features": [ "User-Agent rotation", "Proxy rotation (10 proxies)", "Random delays", "Realistic headers", "Crawl4AI anti-detection" ] }