From 66d9046de2c3fa3f48bf443d06bb6c44127ccaab Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 29 Nov 2025 23:56:39 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20Normalize=20alternative=20French=20price?= =?UTF-8?q?=20format=20(digits=E2=82=ACcents=20without=20separator)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem:** L'Incroyable product showing "3€99" was detected as 399.00 EUR instead of 3.99 EUR. URL: https://www.lincroyable.fr/p95361-porte-magique-lutin/ **Root Cause:** Previous normalization only handled "3,99 €" (with comma separator). Some French sites use alternative format: "3€99" (euro symbol as separator). Existing regex: ```python re.sub(r'(\d+),(\d{2})\s*€', r'\1.\2 €', content) # Only matches "3,99 €" ``` Missed format: ``` "3€99" → No match → AI sees "399" → Returns 399.00 ``` **Solution: Add Pattern for Euro-as-Separator Format** 1. **Text Normalization** (browserless_service.py:408-411) ```python # NEW Pattern 1: digits€XX → digits.XX € content = re.sub(r'(\d+)€(\d{2})\b', r'\1.\2 €', content) # "3€99" → "3.99 €" # "19€50" → "19.50 €" # Pattern 2: digits,XX € → digits.XX € (existing) content = re.sub(r'(\d+),(\d{2})\s*€', r'\1.\2 €', content) # "3,99 €" → "3.99 €" ``` 2. **Extracted Price Normalization** (browserless_service.py:438-441) - Same patterns applied to directly extracted prices - Ensures consistency regardless of extraction method **Regex Details:** - `(\d+)€(\d{2})\b` matches: * `\d+` = one or more digits (euros) * `€` = euro symbol as separator * `(\d{2})` = exactly 2 digits (cents) * `\b` = word boundary (prevents matching "10€999") - Replacement: `\1.\2 €` = "digits.cents €" **Supported Formats After Fix:** ``` "3,99 €" → "3.99 €" ✓ (existing) "3€99" → "3.99 €" ✓ (NEW) "19,50 €" → "19.50 €" ✓ (existing) "19€50" → "19.50 €" ✓ (NEW) "1 234,56" → "1234.56" ✓ (existing) ``` **Flow:** ``` Page text: "Porte Magique 3€99" ↓ Normalization: "Porte Magique 3.99 €" ↓ Extracted: "3€99" → Normalized: "3.99 €" ↓ Sent to AI: "PRIX DÉTECTÉ: 3.99 €\n\nPorte Magique 3.99 €" ↓ AI sees: "3.99" (NOT "399") ↓ Returns: 3.99 ✓ ``` **Expected Results:** - Before: "3€99" → AI returns 399.00 ❌ - After: "3€99" → Normalized to "3.99 €" → AI returns 3.99 ✅ Fixes L'Incroyable and any other sites using euro-as-separator format. Complements existing comma-separator normalization. --- app/services/browserless_service.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/services/browserless_service.py b/app/services/browserless_service.py index 8e7b4c7..b1082ed 100644 --- a/app/services/browserless_service.py +++ b/app/services/browserless_service.py @@ -403,9 +403,11 @@ class BrowserlessService: content = await page.inner_text('body') logger.info(f"Extracted {len(content)} chars of visible text from page") - # Normalize French prices to English format for AI (3,99 € → 3.99 €) + # Normalize French prices to English format for AI import re - # Replace comma with dot in price patterns: digits,XX € → digits.XX € + # Pattern 1: digits€XX → digits.XX € (e.g., "3€99" → "3.99 €") + content = re.sub(r'(\d+)€(\d{2})\b', r'\1.\2 €', content) + # Pattern 2: digits,XX € → digits.XX € (e.g., "3,99 €" → "3.99 €") content = re.sub(r'(\d+),(\d{2})\s*€', r'\1.\2 €', content) # Remove spaces in thousands: 1 234.56 → 1234.56 content = re.sub(r'(\d+)\s(\d{3})', r'\1\2', content) @@ -432,11 +434,12 @@ class BrowserlessService: # Prepend extracted price to content if found if extracted_price: - # Convert French format to English for AI (3,99 → 3.99) + # Convert French format to English for AI import re normalized_price = extracted_price - # Replace comma with dot for decimal separator (French to English) - # Pattern: digits, comma, 2 digits → digits, dot, 2 digits + # Pattern 1: digits€digits → digits.digits € (e.g., "3€99" → "3.99 €") + normalized_price = re.sub(r'(\d+)€(\d{2})', r'\1.\2 €', normalized_price) + # Pattern 2: digits,digits → digits.digits (e.g., "3,99" → "3.99") normalized_price = re.sub(r'(\d+),(\d{2})', r'\1.\2', normalized_price) # Remove spaces in thousands separators if any (1 234,56 → 1234.56) normalized_price = normalized_price.replace(' ', '')