feat: improve SPA scraping and increase test coverage
- Add SPA support for Playwright with wait_for_network_idle and extra_wait_ms - Add BaseStore.get_spa_config() and requires_playwright() methods - Implement AliExpress SPA config with JSON price extraction patterns - Fix Amazon price parsing to prioritize whole+fraction combination - Fix AliExpress regex patterns (remove double backslashes) - Add CLI tests: detect, doctor, fetch, parse, run commands - Add API tests: auth, logs, products, scraping_logs, webhooks Tests: 417 passed, 85% coverage Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -215,6 +215,19 @@ class AmazonStore(BaseStore):
|
||||
|
||||
def _extract_price(self, soup: BeautifulSoup, debug: DebugInfo) -> Optional[float]:
|
||||
"""Extrait le prix."""
|
||||
# Priorité 1: combiner les spans séparés a-price-whole et a-price-fraction
|
||||
# C'est le format le plus courant sur Amazon pour les prix avec centimes séparés
|
||||
whole = soup.select_one("span.a-price-whole")
|
||||
fraction = soup.select_one("span.a-price-fraction")
|
||||
if whole and fraction:
|
||||
whole_text = whole.get_text(strip=True).rstrip(",.")
|
||||
fraction_text = fraction.get_text(strip=True)
|
||||
if whole_text and fraction_text:
|
||||
price = parse_price_text(f"{whole_text}.{fraction_text}")
|
||||
if price is not None:
|
||||
return price
|
||||
|
||||
# Priorité 2: essayer les sélecteurs (incluant a-price-whole seul avec prix complet)
|
||||
selectors = self.get_selector("price", [])
|
||||
if isinstance(selectors, str):
|
||||
selectors = [selectors]
|
||||
@@ -227,16 +240,6 @@ class AmazonStore(BaseStore):
|
||||
if price is not None:
|
||||
return price
|
||||
|
||||
# Fallback: chercher les spans séparés a-price-whole et a-price-fraction
|
||||
whole = soup.select_one("span.a-price-whole")
|
||||
fraction = soup.select_one("span.a-price-fraction")
|
||||
if whole and fraction:
|
||||
whole_text = whole.get_text(strip=True)
|
||||
fraction_text = fraction.get_text(strip=True)
|
||||
price = parse_price_text(f"{whole_text}.{fraction_text}")
|
||||
if price is not None:
|
||||
return price
|
||||
|
||||
debug.errors.append("Prix non trouvé")
|
||||
return None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user