File size: 4,675 Bytes
f18cadc 5c5951f f18cadc e2f64a7 f18cadc 5c5951f f18cadc e2f64a7 f18cadc 5c5951f f18cadc e2f64a7 f18cadc e2f64a7 f18cadc 5c5951f f18cadc 5c5951f e2f64a7 ec84066 e2f64a7 f18cadc 5c5951f e2f64a7 5c5951f e2f64a7 f18cadc e2f64a7 5c5951f e2f64a7 5c5951f e2f64a7 f18cadc 5c5951f e2f64a7 5c5951f f18cadc 5c5951f f18cadc e2f64a7 f18cadc e2f64a7 f18cadc e2f64a7 e5c6585 e2f64a7 e5c6585 e2f64a7 e5c6585 e2f64a7 f18cadc 5c5951f f18cadc e2f64a7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | from fastapi import FastAPI
from pydantic import BaseModel
from playwright.sync_api import sync_playwright
import random
import time
import re
app = FastAPI()
MIN_DELAY = 2
MAX_DELAY = 9 # Reduced from 9 for better user experience
def human_delay():
"""Add a random delay to mimic human behavior"""
time.sleep(random.uniform(MIN_DELAY, MAX_DELAY))
def clean_amazon_image(url):
"""Remove Amazon image size parameters to get higher quality image"""
if url:
# Remove the ._AC_.*?. pattern for cleaner URLs
return re.sub(r'\._AC_[^.]*\.', '.', url)
return url
class SearchInput(BaseModel):
upc: str
@app.get("/")
def home():
"""Health check endpoint"""
return {"status": "Amazon scraper API running", "version": "1.0"}
@app.post("/search")
def search_product(data: SearchInput):
"""
Search for a product on Amazon by UPC
Returns product details including ASIN, title, image, and URL
"""
upc = data.upc.strip()
if not upc:
return {"error": "UPC cannot be empty", "SKU": upc}
browser = None
try:
with sync_playwright() as p:
# Launch browser with additional options for better stability
browser = p.chromium.launch(
headless=True,
args=['--disable-blink-features=AutomationControlled']
)
# Set user agent to avoid detection
context = browser.new_context(
locale="en-US",
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
)
page = context.new_page()
# Navigate to Amazon search
print(f"Searching for UPC: {upc}")
page.goto(
f"https://www.amazon.com/s?k={upc}",
wait_until="domcontentloaded",
timeout=60000
)
# Wait for search results to load
try:
page.wait_for_selector(
"div[data-component-type='s-search-result']",
timeout=10000
)
except Exception as wait_error:
print(f"Wait error: {wait_error}")
# Take a screenshot for debugging
page.screenshot(path="/home/claude/debug_screenshot.png")
browser.close()
return {
"error": "No search results found or page took too long to load",
"SKU": upc
}
human_delay()
# Get the first search result
item = page.query_selector(
"div[data-component-type='s-search-result']"
)
if not item:
browser.close()
return {"error": "Product not found", "SKU": upc}
# Extract ASIN
asin = item.get_attribute("data-asin")
if not asin:
asin = ""
# Extract title
title_el = item.query_selector("h2 span")
title = title_el.inner_text().strip() if title_el else ""
# Extract image
img_el = item.query_selector("img.s-image")
image = ""
if img_el:
# Try src first, then data-image-latency-src
image = img_el.get_attribute("src")
if not image or "data:image" in image:
image = img_el.get_attribute("data-image-latency-src") or ""
image = clean_amazon_image(image)
# Extract product link
link_el = item.query_selector("h2 a")
link = ""
if link_el:
href = link_el.get_attribute("href")
if href:
# Handle both relative and absolute URLs
if href.startswith("http"):
link = href
else:
link = "https://www.amazon.com" + href
browser.close()
return {
"SKU": upc,
"ASIN": asin,
"Title": title,
"Image": image,
"AmazonURL": link
}
except Exception as e:
if browser:
try:
browser.close()
except:
pass
print(f"Error occurred: {str(e)}")
return {
"error": f"An error occurred: {str(e)}",
"SKU": upc
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000) |