customs-data / apps /api /main_hf_simple.py
3v324v23's picture
Ultra-simple version: direct CSV loading, no database
4f1a9f4
Raw
History Blame Contribute Delete
4.53 kB
"""
Hugging Face Spaces 超简版 - 直接内联数据加载
"""
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from pathlib import Path
import pandas as pd
app = FastAPI(
title="海关数据查询系统",
description="巴西海关贸易数据查询服务",
version="1.0.0"
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
BASE_DIR = Path(__file__).resolve().parent.parent.parent
STATIC_DIR = BASE_DIR / "apps" / "api" / "static"
# 挂载静态文件
app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
@app.get("/")
async def serve_ui():
"""返回前端页面"""
return FileResponse(str(STATIC_DIR / "index.html"))
@app.get("/api/v1/health")
async def health_check():
"""健康检查"""
return {"status": "ok", "service": "Customs Data API"}
@app.post("/api/v1/trade/search")
async def search_trade_records(request: Request):
"""
查询贸易记录 - 直接从CSV读取
"""
try:
body = await request.json()
except:
body = {}
# 提取参数
source_country = body.get('source_country')
trade_direction = body.get('trade_direction')
hs_code = body.get('hs_code')
product_name = body.get('product_name')
importer_name = body.get('importer_name')
exporter_name = body.get('exporter_name')
page = int(body.get('page', 1))
limit = int(body.get('limit', 20))
# 加载CSV
csv_path = BASE_DIR / "data" / "standard_trade_records_sample.csv"
df = pd.read_csv(csv_path)
# 过滤
filtered_df = df.copy()
if source_country:
filtered_df = filtered_df[filtered_df['source_country'] == source_country]
if trade_direction:
filtered_df = filtered_df[filtered_df['trade_direction'] == trade_direction]
if hs_code:
filtered_df = filtered_df[filtered_df['hs_code'].astype(str).str.startswith(str(hs_code))]
if product_name:
filtered_df = filtered_df[filtered_df['product_name'].str.contains(product_name, na=False, case=False)]
if importer_name:
filtered_df = filtered_df[filtered_df['importer_name'].str.contains(importer_name, na=False, case=False)]
if exporter_name:
filtered_df = filtered_df[filtered_df['exporter_name'].str.contains(exporter_name, na=False, case=False)]
total = len(filtered_df)
# 分页
offset = (page - 1) * limit
page_df = filtered_df.iloc[offset:offset + limit]
# 构建响应
items = []
for _, row in page_df.iterrows():
trade_date_str = str(row['trade_date']).split()[0] if pd.notna(row['trade_date']) else '2023-01-01'
items.append({
'record_id': str(row['record_id']),
'source_record_id': str(row['source_record_id']),
'source_country': str(row['source_country']),
'trade_direction': str(row['trade_direction']),
'trade_date': trade_date_str,
'importer_name': str(row['importer_name']) if pd.notna(row['importer_name']) else "",
'exporter_name': str(row['exporter_name']) if pd.notna(row['exporter_name']) else "",
'hs_code': str(row['hs_code']) if pd.notna(row['hs_code']) else None,
'product_name': str(row['product_name']) if pd.notna(row['product_name']) else None,
'amount': float(row['amount']) if pd.notna(row['amount']) else None,
'currency': str(row['currency']) if pd.notna(row['currency']) else None,
'weight': float(row['weight']) if pd.notna(row['weight']) else None,
'weight_unit': str(row['weight_unit']) if pd.notna(row['weight_unit']) else None,
'origin_country': str(row['origin_country']) if pd.notna(row['origin_country']) else None,
'destination_country': str(row['destination_country']) if pd.notna(row['destination_country']) else None,
'departure_port': str(row['departure_port']) if pd.notna(row['departure_port']) else None,
'arrival_port': str(row['arrival_port']) if pd.notna(row['arrival_port']) else None,
'transport_mode': str(row['transport_mode']) if pd.notna(row['transport_mode']) else None
})
return {'total': total, 'items': items}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)