# python-aqi-project **Repository Path**: fushenxiang/python-aqi-project ## Basic Information - **Project Name**: python-aqi-project - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-10 - **Last Updated**: 2026-06-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 多城市 AQI 等级预测 — Python 后端 基于 FastAPI 的 REST 后端,对接《前端接口需求文档》中的 9 个业务 API,并扩展自动数据同步与城市目录能力。 **前端同学请同时阅读**:[前端对接补充说明_自动同步与扩展接口.md](./前端对接补充说明_自动同步与扩展接口.md) ## 环境要求 - Python 3.10+ - 依赖见 `requirements.txt` ```bash pip install -r requirements.txt ``` ## 启动即用(推荐) **无需手动跑采集脚本。** 启动 API 后会自动: 1. **首次启动**(无 `data/processed/clean_air_quality.csv`):API **立即**对外服务,后台提交全量同步 Job(约数分钟,需联网);业务接口在数据就绪前返回 `4004`,前端轮询 `/health` 即可 2. **已有数据**:同样立即服务,后台提交增量同步任务 3. **定时任务**:每 30 分钟提交一次增量同步(仅更新已有完整历史的城市 + 每轮补全 2 个新城市) ```bash uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 ``` > **重要**:修改代码后须重启 uvicorn(或使用 `--reload`),否则仍是旧进程,新接口或字段会缺失。 ### 自测 服务启动后执行: ```bash python scripts/test_api.py # 期望 Passed 12/12 python scripts/check_requirements.py # 文件、脚本、API 全覆盖检查 ``` ## 数据与城市 | 项目 | 说明 | |------|------| | 城市目录 | `data/cities_cn.json`(约 88 城,含搜索/拼音/省份/tier) | | 热门城市 | `tier === 1`(一线),参与定时增量与历史补全队列 | | 增量同步范围 | 清洗库中**已有完整历史**的城市(`needs_backfill === false`) | | 历史补全 | 每轮增量最多拉 2 个「热门或已订阅且历史不足」城市的 2024 年起全量 | | 单城补全 | `POST /api/v1/meta/cities/{id}/sync?full=true`(城市选择器「补全历史」) | | 模型训练 | **与同步解耦**;默认不在同步后自动训练,需 `POST /api/v1/meta/train` 或离线脚本 | 配置项见 `app/core/config.py`:`CITY_BACKFILL_MIN_DAYS`、`BACKFILL_CITIES_PER_SYNC`、`RETRAIN_MODEL_ON_SYNC` 等。 ## 同步与前端按钮(职责分离) | 用户操作 | 前端 | 后端 | |----------|------|------| | **刷新图表** | 顶栏按钮,仅 `GET meta/cities` + 重拉图表 API | 不触发采集 | | **同步数据** | 设置页「增量/全量同步」 | `POST /meta/sync` → 立即返回 `job_id`,后台执行 | | **补全历史** | 城市选择器 | `POST /meta/cities/{id}/sync?full=true` | | **训练模型** | 设置页 | `POST /meta/train`(阻塞至训练完成) | 同步任务为**后台 Job**:HTTP 立即返回,前端轮询 `GET /api/v1/meta/sync-status` 直至 `job_status` 非 `queued`/`running`。 ### 元数据与同步相关接口 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/health` | 探活 + `data.data.ready` / `minutes_since_update` | | GET | `/api/v1/meta/sync-status` | 同步状态、`job_id`、`incremental_cities`、`backfill_pending` | | GET | `/api/v1/meta/cities` | 城市目录(搜索/分页/热门/订阅)+ `catalog_size` + `data_freshness` | | GET | `/api/v1/meta/cities/nearby` | 按经纬度找最近城市 | | POST | `/api/v1/meta/cities/{id}/sync` | 单城市同步(`full=true` 补 2024 年起历史) | | POST | `/api/v1/meta/sync` | 提交后台同步(`full=true` 全量) | | POST | `/api/v1/meta/train` | 手动训练模型 | ### 在线文档 - Swagger:http://127.0.0.1:8000/docs - 健康检查:http://127.0.0.1:8000/health ## 离线脚本(可选) 仅用于课程报告出图或强制全量重建,日常开发**不必执行**: ```bash python scripts/run_all.py # 全量同步 + 分析 + 出图 python scripts/bootstrap.py # 同上(不含可视化前的分步说明) python scripts/analyze.py # Q1-Q5 统计分析 python scripts/visualize.py # 生成 6 张中文图表 python scripts/check_requirements.py # 对照需求文档自检 python scripts/generate_cities_cn.py # 重新生成 cities_cn.json ``` 采集 / 清洗 / 训练逻辑已统一到 `app/pipeline/`,脚本为薄封装。 ## API 列表 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/health` | 探活 + 数据新鲜度 | | GET | `/api/v1/meta/cities` | 城市目录(`keyword`/`province`/`tier`/分页) | | GET | `/api/v1/meta/cities/nearby` | 附近城市 | | POST | `/api/v1/meta/cities/{id}/sync` | 单城市同步 | | POST | `/api/v1/meta/sync` | 提交后台同步任务 | | POST | `/api/v1/meta/train` | 手动训练模型 | | GET | `/api/v1/meta/sync-status` | 数据同步状态 | | GET | `/api/v1/dashboard/today` | 今日 AQI 卡片 | | GET | `/api/v1/dashboard/overview` | 首页概览 | | GET | `/api/v1/charts/calendar-heatmap` | 年度 AQI 日历热力图 | | GET | `/api/v1/charts/map-snapshot` | 地图散点快照 | | GET | `/api/v1/charts/aqi-trend` | AQI 趋势 | | GET | `/api/v1/charts/monthly-compare` | 月均对比 | | GET | `/api/v1/charts/pollutant-distribution` | 污染物分布 | | GET | `/api/v1/charts/correlation-heatmap` | 相关性热力图 | | GET | `/api/v1/charts/aqi-level-ratio` | 等级占比 | | GET | `/api/v1/model/evaluation` | 模型评价(指标在 `data.metrics` 内) | | POST | `/api/v1/predict/aqi-level` | AQI 等级预测 | ## 项目结构 ``` app/ api/v1/ # HTTP 端点(业务 + 元数据/同步扩展) pipeline/ # 采集、清洗、训练、同步编排(核心数据链路) services/ # 数据缓存、城市目录、分析、预测、定时调度 core/ # 配置、统一响应、异常 scripts/ # 离线脚本、自测、需求检查 data/ cities_cn.json # 全国城市目录(搜索/同步范围) raw/ # raw_hourly.csv、fetch_meta.json processed/ # clean_air_quality.csv、preprocess_report.json models/ # 三个 .joblib、metrics.json、training_report.json output/ # analysis_report.json、charts/*.png sync_state.json # 最近一次同步状态(自动生成) data_dictionary.json vite-project/ # Vue 3 前端(代理 /api → 8000) ``` ## 需求覆盖说明 | 需求模块 | 实现位置 | |----------|----------| | 数据获取 | `app/pipeline/fetch.py`(自动同步 + `scripts/fetch_data.py`) | | 数据预处理 | `app/pipeline/preprocess.py`(自动同步 + `scripts/preprocess.py`) | | 统计分析 (Q1-Q5) | `scripts/analyze.py` → `data/output/analysis_report.json` | | 可视化 (≥6 张图) | `scripts/visualize.py` → `data/output/charts/` | | 建模预测 | `app/pipeline/train.py` + `POST /api/v1/predict/aqi-level` | | 前端接口 (9 个业务 API) | `app/api/v1/*` | | 自动同步(扩展) | `app/pipeline/sync.py`、`app/services/scheduler.py` | | 城市目录(扩展) | `app/services/city_catalog.py`、`data/cities_cn.json` | | 数据字典 | `data/data_dictionary.json` | 课程报告、答辩 PPT、压缩包由小组另行撰写,不在本仓库代码范围内。 ## 常见问题 **Q:`test_api.py` 只有 9/12 通过?** A:8000 端口上是旧进程。停掉后重新 `uvicorn app.main:app --reload ...`,再跑测试。 **Q:首次打开页面报 `dataset not ready`?** A:全量同步进行中,轮询 `/health` 直到 `data.data.ready === true`。 **Q:为什么只有部分城市有 2024 年起的长历史?** A:新加入目录的城市先经「补全队列」逐轮拉全量;也可在城市选择器点「补全历史」或 `POST .../sync?full=true`。 **Q:顶栏「刷新图表」很慢?** A:刷新图表**不应**调用 `POST /meta/sync`,只重拉已有数据的图表接口;同步请用设置页。 **Q:数据能更新到哪一天?** A:自动同步至**当天**(`latest_data_date`),数据源为 Open-Meteo 小时级 API。