Emeritus-21's picture
Update app.py
303e7ed verified
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 ---
@app.get("/")
def home():
return {
"message": "Welcome to the Open Nigeria Agri-Price API",
"endpoints": ["/all-prices", "/search?crop=Rice"]
}
@app.get("/all-prices")
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
}
@app.get("/search")
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
}