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)