mirror of
https://github.com/R0m1k3/Priceflow.git
synced 2026-10-22 06:38:12 +02:00
2 files changed
+84
-32
No files matched your search
@@ -353,14 +353,29 @@ class AmazonScraperService:
|
|||||||
logger.debug(f" ⏭️ Card {idx}: No title")
|
logger.debug(f" ⏭️ Card {idx}: No title")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# URL
|
# URL
|
||||||
link_elem = card.select_one('h2 a') or card.select_one('a.s-link-style')
|
link_elem = card.select_one('h2 a') or card.select_one('a.s-link-style')
|
||||||
if not link_elem:
|
if not link_elem:
|
||||||
logger.debug(f" ⏭️ Card {idx}: No link")
|
logger.debug(f" ⏭️ Card {idx}: No link element")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
href = link_elem.get('href', '')
|
href = link_elem.get('href', '')
|
||||||
product_url = f"{AMAZON_FR_BASE_URL}{href}" if href.startswith('/') else href
|
|
||||||
|
# CRITICAL: Validate href is not empty or just '#'
|
||||||
|
if not href or href == '#' or href.strip() == '':
|
||||||
|
logger.warning(f" ⏭️ Card {idx}: Invalid href '{href}' for {title[:30] if title else 'unknown'}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Build absolute URL
|
||||||
|
if href.startswith('/'):
|
||||||
|
product_url = f"{AMAZON_FR_BASE_URL}{href}"
|
||||||
|
elif href.startswith('http'):
|
||||||
|
product_url = href
|
||||||
|
else:
|
||||||
|
logger.warning(f" ⏭️ Card {idx}: Unexpected href format '{href[:50]}' for {title[:30] if title else 'unknown'}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
logger.debug(f" ✓ Card {idx}: URL = {product_url[:80]}...")
|
||||||
|
|
||||||
# Price
|
# Price
|
||||||
price = None
|
price = None
|
||||||
|
|||||||
@@ -326,52 +326,89 @@ class ImprovedSearchService:
|
|||||||
if not all_words_found:
|
if not all_words_found:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Extract Image URL - Multiple strategies
|
# Extract Image URL - PRIORITIZE CONFIGURED SELECTOR
|
||||||
image_url = None
|
image_url = None
|
||||||
|
|
||||||
# Strategy 1: Look for img directly in the link
|
# PRIORITY 1: Use product_image_selector if configured (site-specific)
|
||||||
img = link.find("img")
|
if "product_image_selector" in config:
|
||||||
if img:
|
# Try in link first
|
||||||
# Try multiple attributes (src, data-src, data-lazy-src, etc.)
|
img_el = link.select_one(config["product_image_selector"])
|
||||||
image_url = (
|
|
||||||
img.get("src") or
|
|
||||||
img.get("data-src") or
|
|
||||||
img.get("data-lazy-src") or
|
|
||||||
img.get("data-original") or
|
|
||||||
img.get("srcset", "").split(",")[0].split()[0] if img.get("srcset") else None
|
|
||||||
)
|
|
||||||
|
|
||||||
# Strategy 2: Look in parent container if configured
|
# If not found in link, search in parent container
|
||||||
if not image_url and "product_image_selector" in config:
|
if not img_el:
|
||||||
container = link.find_parent("article") or link.find_parent("div", class_=lambda x: x and "product" in x)
|
container = link.find_parent("article") or link.find_parent("div", class_=lambda x: x and "product" in x)
|
||||||
if container:
|
if container:
|
||||||
img_el = container.select_one(config["product_image_selector"])
|
img_el = container.select_one(config["product_image_selector"])
|
||||||
if img_el:
|
|
||||||
image_url = (
|
|
||||||
img_el.get("src") or
|
|
||||||
img_el.get("data-src") or
|
|
||||||
img_el.get("data-lazy-src")
|
|
||||||
)
|
|
||||||
|
|
||||||
# Strategy 3: Look for picture > source elements
|
if img_el:
|
||||||
|
# Try multiple attributes in order of priority
|
||||||
|
image_url= (
|
||||||
|
img_el.get("src") or
|
||||||
|
img_el.get("data-src") or
|
||||||
|
img_el.get("data-lazy-src") or
|
||||||
|
img_el.get("data-original")
|
||||||
|
)
|
||||||
|
|
||||||
|
# Handle srcset (use first URL)
|
||||||
|
if not image_url and img_el.get("srcset"):
|
||||||
|
srcset = img_el.get("srcset")
|
||||||
|
# srcset format: "url1 size1, url2 size2"
|
||||||
|
image_url = srcset.split(",")[0].split()[0]
|
||||||
|
|
||||||
|
if image_url:
|
||||||
|
logger.debug(f" 🖼️ Image found via product_image_selector: {image_url[:50]}...")
|
||||||
|
|
||||||
|
# PRIORITY 2: Fallback - Look for any img directly in the link
|
||||||
|
if not image_url:
|
||||||
|
img = link.find("img")
|
||||||
|
if img:
|
||||||
|
image_url = (
|
||||||
|
img.get("src") or
|
||||||
|
img.get("data-src") or
|
||||||
|
img.get("data-lazy-src") or
|
||||||
|
img.get("data-original")
|
||||||
|
)
|
||||||
|
|
||||||
|
# Handle srcset
|
||||||
|
if not image_url and img.get("srcset"):
|
||||||
|
srcset = img.get("srcset")
|
||||||
|
image_url = srcset.split(",")[0].split()[0]
|
||||||
|
|
||||||
|
if image_url:
|
||||||
|
logger.debug(f" 🖼️ Image found via link.find('img'): {image_url[:50]}...")
|
||||||
|
|
||||||
|
# PRIORITY 3: Look for picture > source elements
|
||||||
if not image_url:
|
if not image_url:
|
||||||
picture = link.find("picture")
|
picture = link.find("picture")
|
||||||
if picture:
|
if picture:
|
||||||
source = picture.find("source")
|
source = picture.find("source")
|
||||||
if source:
|
if source and source.get("srcset"):
|
||||||
image_url = source.get("srcset", "").split(",")[0].split()[0] if source.get("srcset") else None
|
srcset = source.get("srcset")
|
||||||
|
image_url = srcset.split(",")[0].split()[0]
|
||||||
|
|
||||||
if not image_url:
|
if not image_url:
|
||||||
img_in_picture = picture.find("img")
|
img_in_picture = picture.find("img")
|
||||||
if img_in_picture:
|
if img_in_picture:
|
||||||
image_url = img_in_picture.get("src") or img_in_picture.get("data-src")
|
image_url = img_in_picture.get("src") or img_in_picture.get("data-src")
|
||||||
|
|
||||||
# Clean up image URL
|
if image_url:
|
||||||
|
logger.debug(f" 🖼️ Image found via <picture>: {image_url[:50]}...")
|
||||||
|
|
||||||
|
# Clean up and validate image URL
|
||||||
if image_url:
|
if image_url:
|
||||||
# Remove data URIs and 1x1 pixels
|
# Remove data URIs, 1x1 pixels, placeholders
|
||||||
if image_url.startswith("data:") or "1x1" in image_url or "placeholder" in image_url.lower():
|
if (image_url.startswith("data:") or
|
||||||
|
"1x1" in image_url or
|
||||||
|
"placeholder" in image_url.lower() or
|
||||||
|
image_url.strip() == ""):
|
||||||
|
logger.debug(f" ⏭️ Skipping invalid image: {image_url[:50]}")
|
||||||
image_url = None
|
image_url = None
|
||||||
elif not image_url.startswith("http"):
|
elif not image_url.startswith("http"):
|
||||||
image_url = urljoin(base_url, image_url)
|
image_url = urljoin(base_url, image_url)
|
||||||
|
logger.debug(f" 🔗 Made image URL absolute: {image_url[:80]}...")
|
||||||
|
|
||||||
|
if not image_url:
|
||||||
|
logger.warning(f" ⚠️ No image found for: {title[:50]}")
|
||||||
|
|
||||||
# Create result
|
# Create result
|
||||||
results.append(SearchResult(
|
results.append(SearchResult(
|
||||||
|
|||||||
Reference in new issue
Block a user