Files
EMWebApi/docs/blueprint.md
T
toor 2ce68b7b5d 新增公司资料/指数/重大事项等 13 个接口, 文档全面对齐
- 新增 fin_mda/fin_equity/fin_company/fin_belong_index/fin_major_events 5 个模块
- 覆盖: 管理层讨论、股本结构、公司介绍、所属行业、指数分类/统计/成分、并购/股权激励/诉讼/关联交易/违规/担保
- _emchoice.fetch_report 支持"数据为空"按空结果处理
- api.py 增加 _simple_endpoint 统一生成纯 stocks 参数接口, 路由达 29 个 /fin 端点
- 冒烟测试扩展至 56 用例, 全部通过
- api_manual/blueprint/SKILLS/待优化 文档与代码路径 100% 对齐
2026-08-15 11:34:11 +08:00

162 lines
9.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 # 分红明细 + 分红统计
│ ├── fin_free_holders.py # 十大流通股东
│ ├── fin_holders.py # 十大股东明细
│ ├── fin_holder_num.py # 股东户数
│ ├── fin_mda.py # 管理层讨论与分析(MD&A)
│ ├── fin_equity.py # 股本结构
│ ├── fin_company.py # 公司介绍 + 所属行业
│ ├── fin_belong_index.py # 所属指数分类/统计/成分权重
│ └── fin_major_events.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 自动修复)
- 其余新模块复用 `_emchoice.py` 的 `get_data_url` / `fetch_report`(同样会触发 SSL 修复)
- `fin_major_events.py` / `fin_company.py` / `fin_belong_index.py` 内部有 `_run` / `_fetch_one` 复用,避免六接口重复样板
---
## 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` | ✅ 已实现 |
| 12 | 十大流通股东 | `RPT_F10_EH_FREEHOLDERS` | ✅ 已实现 |
| 13 | 十大股东明细 | `RPT_DMSK_HOLDERS` | ✅ 已实现 |
| 14 | 股东户数 | `RPT_F10_EH_HOLDERNUM` | ✅ 已实现 |
| 15 | 管理层讨论与分析 | `RPT_BUSINESSANALYSIS` | ✅ 已实现 |
| 16 | 股本结构 | `RPT_F10_EH_EQUITY` | ✅ 已实现 |
| 17 | 公司介绍 | `RPT_HSF9_BASIC_ORGINFO` | ✅ 已实现 |
| 18 | 所属行业 | `RPT_STOCKF9_INDUSTRY` | ✅ 已实现 |
| 19 | 指数分类 | `RPT_HSF9_BELONGINDEX_CLASSIF` | ✅ 已实现 |
| 20 | 纳入指数统计 | `RPT_CUSTOM_HSF9_BELONG_INDEX` | ✅ 已实现 |
| 21 | 指数成分权重 | `RPT_HSF9_BELONG_INDEX` | ✅ 已实现 |
| 22 | 并购事件 | `RPT_HS_ACQUISITIONS_EVENT` | ✅ 已实现 |
| 23 | 股权激励 | `RPT_DMSK_SH_EQUITYINCENTIVE` | ✅ 已实现 |
| 24 | 诉讼仲裁 | `RPT_LITIGATION_ARBITRATION_BSINFO` | ✅ 已实现 |
| 25 | 关联交易 | `RPT_RELATED_TRANSACTION` | ✅ 已实现 |
| 26 | 违规处罚 | `RPT_HSF9_OP_VIOLATION` | ✅ 已实现 |
| 27 | 对外担保 | `RPT_F9_GUARANTEE` | ✅ 已实现 |
**文档外补充**:财务摘要(报告期) 用 `RPT_CUSTOM_ORGF9_FIN_SUMMARY`,需 ORG_CODE(不在 api_docs.md 里)。
---
## 4. 实施进度
### ✅ 已完成(api_docs.md 全部 27 项落地)
| 功能 | 核心文件 | HTTP 接口 |
|------|----------|-----------|
| 健康检查 | `api.py` | `GET /health` |
| 财务摘要(报告期) | `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` / `GET /fin/dividend-statics` |
| 十大流通股东 | `utils/fin_free_holders.py` | `GET /fin/free-holders` |
| 十大股东明细 | `utils/fin_holders.py` | `GET /fin/holders` |
| 股东户数 | `utils/fin_holder_num.py` | `GET /fin/holder-num` |
| 管理层讨论与分析 | `utils/fin_mda.py` | `GET /fin/mda` |
| 股本结构 | `utils/fin_equity.py` | `GET /fin/equity` |
| 公司介绍 | `utils/fin_company.py` | `GET /fin/company-info` |
| 所属行业 | `utils/fin_company.py` | `GET /fin/industry` |
| 指数分类/统计/成分 | `utils/fin_belong_index.py` | `GET /fin/index-classif` / `GET /fin/belong-index` / `GET /fin/index-membership` |
| 并购事件 | `utils/fin_major_events.py` | `GET /fin/acquisitions` |
| 股权激励 | `utils/fin_major_events.py` | `GET /fin/equity-incentive` |
| 诉讼仲裁 | `utils/fin_major_events.py` | `GET /fin/litigation` |
| 关联交易 | `utils/fin_major_events.py` | `GET /fin/related-transaction` |
| 违规处罚 | `utils/fin_major_events.py` | `GET /fin/violation` |
| 对外担保 | `utils/fin_major_events.py` | `GET /fin/guarantee` |
| 测试 | `tests/test_interfaces.py` | `uv run pytest tests/ -q` (56 用例) |
### 🧹 待清理
- `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. **校验**:`fetch_report` 中 `success=False` 且 message 为"返回数据为空/暂无数据/无数据"时按空结果处理(返回空列表),其余失败抛 `RuntimeError`;空数据返回空 DataFrame 而非报错
6. **接口暴露**:api.py 中新增 `GET /fin/<主题>`,参数用 FastAPI `Query`,返回 `{success, count, columns, data, errors}` 风格,NaN/NaT/inf 转 None(复用 `_df_to_json_payload`),无数据统一走 `_empty_response`;仅 `stocks`(+`years`) 参数的接口可用 `_simple_endpoint` 统一生成
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 "..." # 直接跑脚本
```