Spaces:
Running
Running
| import httpx | |
| import asyncio | |
| import pandas as pd | |
| import io | |
| from fastapi import FastAPI, Query | |
| from bs4 import BeautifulSoup | |
| from datetime import datetime | |
| app = FastAPI(title="AgriFusion AI Agri-Price API") | |
| HEADERS = { | |
| "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" | |
| } | |
| # --- DATA SOURCES --- | |
| LCFE_URL = "https://lcfe.ng/market-data.php" | |
| WFP_CSV_URL = "https://data.humdata.org/dataset/42db041f-7aaf-4ab4-961f-2a12096861e7/resource/12b51155-0cd3-4806-9924-61ede4077591/download/wfp_food_prices_nga.csv" | |
| async def fetch_lcfe(): | |
| """Scrapes LCFE Exchange Prices""" | |
| try: | |
| async with httpx.AsyncClient(headers=HEADERS, timeout=15.0, verify=False) as client: | |
| resp = await client.get(LCFE_URL) | |
| soup = BeautifulSoup(resp.text, 'html.parser') | |
| table = soup.find('table') | |
| if not table: return [] | |
| rows = table.find_all('tr')[1:] | |
| return [{ | |
| "date": r.find_all('td')[0].text.strip(), | |
| "crop": r.find_all('td')[1].text.strip(), | |
| "location": r.find_all('td')[2].text.strip(), | |
| "price": r.find_all('td')[4].text.strip(), | |
| "type": "Wholesale (Exchange)" | |
| } for r in rows if len(r.find_all('td')) >= 5] | |
| except: return [] | |
| async def fetch_retail_wfp(): | |
| """Fetches Retail Market Prices from WFP""" | |
| try: | |
| async with httpx.AsyncClient(timeout=20.0) as client: | |
| resp = await client.get(WFP_CSV_URL) | |
| df = pd.read_csv(io.StringIO(resp.text)).iloc[1:] | |
| # Get latest month only | |
| latest_date = df['date'].max() | |
| df_latest = df[df['date'] == latest_date] | |
| return [{ | |
| "date": row['date'], | |
| "crop": row['commodity'], | |
| "market": row['market'], | |
| "price": f"₦{row['price']}", | |
| "unit": row['unit'], | |
| "type": "Retail (Market)" | |
| } for _, row in df_latest.iterrows()] | |
| except: return [] | |
| # --- ENDPOINTS --- | |
| def home(): | |
| return { | |
| "message": "Welcome to the Open Nigeria Agri-Price API", | |
| "endpoints": ["/all-prices", "/search?crop=Rice"] | |
| } | |
| async def get_all_prices(): | |
| lcfe_data, wfp_data = await asyncio.gather(fetch_lcfe(), fetch_retail_wfp()) | |
| return { | |
| "timestamp": datetime.now().isoformat(), | |
| "sources": ["LCFE", "WFP-HDX"], | |
| "results": lcfe_data + wfp_data | |
| } | |
| async def search_prices(crop: str = Query(..., description="Crop name to search for")): | |
| data = await get_all_prices() | |
| results = [item for item in data['results'] if crop.lower() in item['crop'].lower()] | |
| return { | |
| "search_term": crop, | |
| "count": len(results), | |
| "results": results | |
| } |