Files
EMWebApi/docs/blueprint.md
T
toor 11ddbd3c49 实现全部 CHOICE 财务接口, 补充测试/文档/部署配置
- 新增 9 个抓取模块: 三大报表/盈利能力/资本结构/营运能力/成长能力/杜邦/分红
- api.py 新增 10 个 /fin/* 接口并统一无数据返回
- 新增 _emchoice.py 共享请求辅助 (emws 跳转取 URL / datacenter 报表拉取)
- 新增冒烟测试 tests/test_interfaces.py (24 用例)
- 新增接口文档 api_manual.md 与施工蓝图 blueprint.md
- 新增 Dockerfile / docker-compose.yml / deploy.sh 部署配置
2026-08-15 09:19:11 +08:00

122 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# EMWeb API 项目施工蓝图
> 记录项目目标、架构、接口清单、实施进度与施工规范,避免"做到一半忘记当初的规划"。
---
## 1. 项目简介
**目标**:以东方财富 CHOICE 数据接口为基础,封装一套稳定、可复用的财务数据抓取服务,对外以 FastAPI 提供 HTTP 接口。
**核心诉求**:
- 不需要登录 / cookie,直接调公开接口即可拿到数据
- 每个数据模块独立成文件,可脚本直接调用,也可通过 API 暴露
- 数据以 pandas DataFrame 为内部统一载体,出 HTTP 时转 JSON-safe 结构
**技术栈**:Python >= 3.11 · FastAPI + Uvicorn · requests · pandas · uv 管理依赖
---
## 2. 架构总览
```
EMWebApi/
├── api.py # FastAPI 入口, 聚合各 utils 模块对外暴露 HTTP 接口
├── utils/
│ ├── fin_summary.py # 财务摘要(报告期) —— 最底层, 含共享常量/SSL修复
│ ├── _emchoice.py # 内部共享请求辅助 (emws 跳转取 URL / datacenter 报表拉取)
│ ├── fin_quarterly.py # 财务摘要(单季度)
│ ├── fin_main_business.py # 主营构成(按产品/地区)
│ ├── fin_balance.py # 资产负债表
│ ├── fin_income.py # 利润表
│ ├── fin_cashflow.py # 现金流量表
│ ├── fin_profitability.py # 盈利能力与收益质量
│ ├── fin_capital_structure.py # 资本结构与偿债能力
│ ├── fin_operate.py # 营运能力
│ ├── fin_growth.py # 成长能力
│ ├── fin_dupont.py # 杜邦分析
│ └── fin_dividend.py # 分红明细 + 分红统计
├── tests/
│ └── test_interfaces.py # 冒烟测试 (连真实接口)
└── docs/
├── api_docs.md # 从 Reqable 抓包沉淀的原始接口记录
├── api_manual.md # 对外 HTTP 接口使用文档
└── blueprint.md # 本文件: 施工蓝图
```
**依赖方向**:
- `fin_quarterly.py` / `fin_main_business.py` 复用 `fin_summary.py` 里的 `HEADERS` / `TIMEOUT` / `BASE_URL`(顺带触发其模块级的 SSL 自动修复)
- 其余 9 个新模块复用 `_emchoice.py` 的 `get_data_url` / `fetch_report`(同样会触发 SSL 修复)
---
## 3. 数据源接口清单(源自 docs/api_docs.md)
| # | 接口 | 报表名/路径 | 实现状态 |
|---|------|-------------|----------|
| 1 | 财务摘要(单季度) | `RPT_HSF9_FIN_SUMMARYQUARTERNEW` | ✅ 已实现 |
| 2 | 主营构成(产品/地区) | `ZYGC_AFLZS` → `RPT_HSF9_FN_MAINOPBUSINESS` | ✅ 已实现 |
| 3 | 资产负债表 | `CWSJ_ZCFZB` → `RPT_CUSTOM_HSF9_FINA_GBALANCE` | ✅ 已实现 |
| 4 | 利润表 | `CWSJ_LRB` → `RPT_CUSTOM_HSF9_FINA_GINCOMESYN` | ✅ 已实现 |
| 5 | 现金流量表 | `CWSJ_XJLLB` → `RPT_CUSTOM_HSF9_FINA_GCASHFLOW` | ✅ 已实现 |
| 6 | 盈利能力与收益质量 | `CWFX_YLNLYSYZL` → `RPT_HSF9_FINA_PROFITEARNING` | ✅ 已实现 |
| 7 | 资本结构与偿债能力 | `CWFX_ZBJGYCZNL` → `RPT_HSF9_FINA_CAPPAYAB` | ✅ 已实现 |
| 8 | 营运能力 | `RPT_HSF9_FINA_OPERATEABILITY` | ✅ 已实现 |
| 9 | 成长能力 | `CWFX_CZNL` → `RPT_HSF9_FINA_GROWTH` | ✅ 已实现 |
| 10 | 杜邦分析 | `RPT_HSF9_FINA_DUPONT` | ✅ 已实现 |
| 11 | 分红明细 + 分红统计 | `RPT_HSF9_ASSIGNPLAN_DETAIL` / `_STATICS` | ✅ 已实现 |
**文档外补充**:财务摘要(报告期) 用 `RPT_CUSTOM_ORGF9_FIN_SUMMARY`,需 ORG_CODE(不在 api_docs.md 里)。
---
## 4. 实施进度
### ✅ 已完成(11 类接口全部落地)
| 功能 | 核心文件 | HTTP 接口 |
|------|----------|-----------|
| 财务摘要(报告期) | `utils/fin_summary.py` | `GET /fin/summary` |
| 财务摘要(单季度) | `utils/fin_quarterly.py` | `GET /fin/quarterly-summary` |
| 主营构成(产品/地区) | `utils/fin_main_business.py` | `GET /fin/main-business` |
| 资产负债表 | `utils/fin_balance.py` | `GET /fin/balance` |
| 利润表 | `utils/fin_income.py` | `GET /fin/income` |
| 现金流量表 | `utils/fin_cashflow.py` | `GET /fin/cashflow` |
| 盈利能力与收益质量 | `utils/fin_profitability.py` | `GET /fin/profitability` |
| 资本结构与偿债能力 | `utils/fin_capital_structure.py` | `GET /fin/capital-structure` |
| 营运能力 | `utils/fin_operate.py` | `GET /fin/operate-ability` |
| 成长能力 | `utils/fin_growth.py` | `GET /fin/growth` |
| 杜邦分析 | `utils/fin_dupont.py` | `GET /fin/dupont` |
| 分红明细 + 统计 | `utils/fin_dividend.py` | `GET /fin/dividend-detail` / `dividend-statics` |
| 测试 | `tests/test_interfaces.py` | `uv run pytest tests/ -q` (24 用例) |
### 🧹 待清理
- `fin_summary.py` 里的 `_debug_report`(向 `127.0.0.1:7777/event` 发 POST)是调试残留,可移除
- `_auto_fix_ssl` 里残留 Windows 路径(`%USERPROFILE%\...`),运行环境是 macOS,可精简
---
## 5. 施工规范(新模块必须遵守)
1. **文件命名**:`utils/fin_<主题>.py`,一个主题一个文件,内部函数私有化(`_` 开头);仅内部共享的请求辅助放 `utils/_emchoice.py`
2. **结构**:`_build_*(参数构造)` → `_fetch_one(单只拉取)` → `get_<主题>(批量主入口)`
3. **共享**:`from utils.fin_summary import HEADERS, TIMEOUT`,不重复定义;不同 base_url 的接口在本文件内定义新常量;emws 跳转接口用 `_emchoice.get_data_url`,datacenter 报表用 `_emchoice.fetch_report`
4. **数据流**:内部统一 `pandas.DataFrame`,每行冗余 `SECUCODE` 列便于多股票合并
5. **校验**:`payload.get("success")` 失败抛 `RuntimeError`;空数据返回空 DataFrame 而非报错
6. **接口暴露**:api.py 中新增 `GET /fin/<主题>`,参数用 FastAPI `Query`,返回 `{success, count, columns, data, errors}` 风格,NaN/NaT/inf 转 None(复用 `_df_to_json_payload`),无数据统一走 `_empty_response`
7. **礼貌抓取**:批量循环中加随机延时(参考 `SLEEP_RANGE`)
8. **注释语言**:中文,解释"为什么"(如接口编码映射差异)
9. **测试**:新模块在 `tests/test_interfaces.py` 注册冒烟用例(连真实接口取 1 年数据,断言非空 + 关键列)
---
## 6. 常用命令
```bash
uv sync # 创建环境并安装依赖
uv run python api.py # 启动服务 (默认端口 8765)
uv run pytest tests/ -q # 跑冒烟测试 (连真实接口)
uv run python -c "..." # 直接跑脚本
```