MaxSainz2000's picture
Update app.py
6297b89 verified
from fastapi import FastAPI
from playwright.async_api import async_playwright
# Note: We removed 'playwright-stealth' because mobile emulation handles the user-agent naturally
import urllib.parse
import asyncio
app = FastAPI()
@app.get("/")
def home():
return {"status": "Mobile Worker is Running"}
@app.get("/search")
async def search_aliexpress(query: str):
encoded_query = urllib.parse.quote(query)
# 1. Use the Mobile URL (m.aliexpress.com)
url = f"https://www.aliexpress.com/wholesale?SearchText={encoded_query}"
results = []
error_snapshot = ""
async with async_playwright() as p:
# 2. Use a Preset Device Profile (Google Pixel 7)
pixel_7 = p.devices['Pixel 7']
browser = await p.chromium.launch(headless=True, args=[
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-blink-features=AutomationControlled'
])
# 3. Create context with the Device Profile (Sets User-Agent, Screen Size, Touch, etc.)
context = await browser.new_context(
**pixel_7,
locale='en-US',
timezone_id='America/New_York'
)
page = await context.new_page()
try:
await page.goto(url, timeout=60000)
# Wait for items (Mobile layout is different, but links still contain /item/)
try:
await page.wait_for_selector('a[href*="/item/"]', timeout=15000)
except:
error_snapshot = await page.title()
# If we see a captcha title, we throw an error
if "captcha" in error_snapshot.lower() or "security" in error_snapshot.lower():
raise Exception(f"Blocked by Security. Title: {error_snapshot}")
raise Exception(f"Products not found. Title: {error_snapshot}")
# Extract Data (Logic adapted for Mobile/Responsive Layout)
products = await page.eval_on_selector_all('a[href*="/item/"]', """
links => {
return links.slice(0, 10).map(link => {
// Find the container card
let card = link.closest('div[class*="search-item"]') || link.parentElement.parentElement;
// Default values
let title = "No Title";
let price = "0.00";
let img = "";
if (card) {
// Try to find image
const imgEl = card.querySelector('img');
if (imgEl) img = imgEl.src;
// Try to find text
const text = card.innerText;
const lines = text.split('\\n');
if (lines.length > 0) title = lines[0];
// Regex for price
const priceMatch = text.match(/[\\$€£]\\s?(\\d+(\\.\\d+)?)/);
if (priceMatch) price = priceMatch[0];
}
return {
title: title,
price: price,
image: img,
link: link.href
};
});
}
""")
# Simple Deduplication
seen = set()
for item in products:
if item['link'] and item['link'] not in seen:
results.append(item)
seen.add(item['link'])
except Exception as e:
return {"error": str(e), "debug_title": error_snapshot}
finally:
await browser.close()
return {"results": results}