mydatascraper/competitor_compare
0
1import sys
2import asyncio
3
4# ── MUST be before anything else on Windows ──────────────────
5if sys.platform == "win32":
6 asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
7
8from fastapi import FastAPI
9from fastapi.middleware.cors import CORSMiddleware
10from app.config import settings
11from app.routers import compare
12
13
14app = FastAPI(
15 title=settings.API_TITLE,
16 version=settings.API_VERSION,
17 description="""
18## Grocery Price Comparison API — MVP
19
20**Real-time** price comparison across Pennsylvania grocery retailers.
21No database — scrapes live data from retailer websites on each request.
22
23### MVP Retailers
24| Retailer | Method | Strategy |
25|----------|--------|----------|
26| Walmart | httpx | Parse __NEXT_DATA__ JSON from HTML |
27| ALDI | Playwright | Instacart-powered, JS-rendered |
28| Target | Playwright | JS-rendered, parse HTML cards |
29| Wegmans | Playwright | Instacart-powered, JS-rendered |
30
31### Endpoints
32- `GET /api/v1/compare?product=whole milk` — Compare single product
33- `POST /api/v1/compare/batch` — Compare multiple products
34- `GET /api/v1/retailers` — List supported retailers
35 """,
36)
37
38app.add_middleware(
39 CORSMiddleware,
40 allow_origins=["*"],
41 allow_methods=["*"],
42 allow_headers=["*"],
43)
44
45app.include_router(compare.router)
46
47
48@app.get("/")
49async def root():
50 return {
51 "service": settings.API_TITLE,
52 "version": settings.API_VERSION,
53 "docs": "/docs",
54 "usage": {
55 "single_product": "GET /api/v1/compare?product=whole milk",
56 "multi_product": "POST /api/v1/compare/batch",
57 "retailers": "GET /api/v1/retailers",
58 },
59 }