Fix: Deep fix for Action.com availability false positives. Advanced title normalization and clarified unavailability detection logic. Optimized ActionParser.

This commit is contained in:
Michael committed 2026-01-13 13:56:12 +01:00
1 parent 8329eb28a3
commit 4a686e1b86
3 files changed
+74 -36

No files matched your search

+32 -23
View File
@@ -1,9 +1,11 @@
from bs4 import BeautifulSoup
from app.services.parsers.base_parser import BaseParser, ProductResult
import logging
import re
logger = logging.getLogger(__name__)
class ActionParser(BaseParser):
def __init__(self):
super().__init__("action.com", "https://www.action.com")
@@ -11,55 +13,62 @@ class ActionParser(BaseParser):
def parse_search_results(self, html: str, query: str, search_url: str) -> list[ProductResult]:
soup = BeautifulSoup(html, "html.parser")
results = []
# Action products
# Config: a.group[href^='/fr-fr/p/']
links = soup.select("a[href^='/fr-fr/p/']")
seen_urls = set()
for link in links:
try:
href = link.get('href')
href = link.get("href")
if not href or href in seen_urls:
continue
seen_urls.add(href)
url = self.make_absolute_url(href)
# Action usually has the card content inside the link
title = None
title_el = link.select_one("[class*='title'], h3, h4")
if title_el:
title = title_el.get_text(strip=True)
else:
title = link.get_text(strip=True)
# Fallback to specific spans or remove price info from text
# Often Action cards have a .title span
title = link.get_text(" ", strip=True)
# Remove price-like patterns from title if we had to get whole link text
title = re.sub(r"\d+,\d+\s*€.*$", "", title)
title = re.sub(r"\d+\s*€.*$", "", title)
if not title:
continue
img_url = self.extract_image_url(link)
price = None
price_el = link.select_one("[class*='price']")
if price_el:
price = self.parse_price_text(price_el.get_text())
results.append(ProductResult(
title=title,
url=url,
source="Action",
price=price,
currency="EUR",
in_stock=True,
image_url=img_url,
snippet=f"Product from Action"
))
results.append(
ProductResult(
title=title,
url=url,
source="Action",
price=price,
currency="EUR",
in_stock=True,
image_url=img_url,
snippet=f"Product from Action",
)
)
except Exception as e:
logger.error(f"Error parsing Action product: {e}")
continue
logger.info(f"ActionParser found {len(results)} results")
return results
+30 -1
View File
@@ -54,10 +54,17 @@ def _normalize_title(title: str) -> str:
title = re.sub(r"([a-zA-Z])(\d)", r"\1 \2", title)
title = re.sub(r"(\d)([a-zA-Z])", r"\1 \2", title)
# Remove extra spaces and punctuation that might differ between sites
# Remove non-word characters (punctuation) early to simplify regex
title = re.sub(r"[^\w\s]", " ", title)
title = " ".join(title.split())
# Remove technical metadata at the end (Action specific noise)
# Match various patterns like "0 09 pce 342" or "100 pièces" etc.
title = re.sub(r"\s+\d+\s+\d+\s+pce.*$", "", title)
title = re.sub(r"\s+\d+\s+pièces.*$", "", title)
title = re.sub(r"\s+\d+\s+€.*$", "", title)
title = re.sub(r"\s+\d+\s+\d+\s+€.*$", "", title)
return title.strip()
@@ -363,6 +370,28 @@ async def process_item_check(item_id: int):
f"Stored: '{item_data['name']}', Page title: '{page_title}'"
)
# For Action.com, if we haven't confirmed unavailability above,
# don't mark as unavailable yet, just mark as potential replacement error
# unless the title is almost completely different
if is_action:
# Check if at least some significant words match
norm_stored = _normalize_title(item_data["name"])
norm_page = _normalize_title(page_title)
stored_words = set(norm_stored.split())
page_words = set(norm_page.split())
intersection = stored_words & page_words
if len(intersection) >= 2 or (len(stored_words) <= 3 and len(intersection) >= 1):
logger.warning(
f"Borderline title match for Action.com item {item_id}. Keeping as available but marking error."
)
await loop.run_in_executor(
None,
_update_db_error,
item_id,
f"Titre différent mais produit probablement correct : {page_title}",
)
return
await loop.run_in_executor(
None,
_update_db_product_unavailable,
+12 -12
View File
@@ -1,21 +1,21 @@
# Nettoyage et Commit du Projet
# Deep Debugging Action.com Availability
## Contexte
## Context
Après avoir corrigé les problèmes de disponibilité d'Action.com et Amazon, il est nécessaire de nettoyer le répertoire racine des scripts de diagnostic et fichiers temporaires avant de committer les changements.
Some products on Action.com are still marked as unavailable even after the first round of fixes.
## Focus Actuel
## Current Focus
Identification et suppression des fichiers inutiles, suivi du commit et push.
Identifying why specific Action.com products fail the availability check.
## Master Plan
- [ ] Identifier les fichiers non essentiels à l'application
- [ ] Supprimer les fichiers de diagnostic et scripts temporaires
- [ ] Vérifier que l'application fonctionne toujours (build/syntaxe)
- [ ] Committer les changements vers le dépôt Git
- [ ] Pusher les changements
- [ ] List currently unavailable Action.com items from the database (if possible) or logs
- [ ] Reproduce the check for a specific problematic item
- [ ] Analyze the HTML and Title for these items
- [ ] Refine the matching logic or the unavailability detection
- [ ] Verify fix with multiple Action.com items
## Log de Progression
## Progress Log
- [ ] Planification du nettoyage commencée.
- [/] Task started.