- 新增 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% 对齐
58 lines
1.7 KiB
Python
58 lines
1.7 KiB
Python
"""东方财富 CHOICE API 股本结构抓取工具。
|
|
- 输入: 股票代码列表 (如 ['603233.SH'])
|
|
- 输出: pandas DataFrame (按报告期末的股本结构, 全量历史)
|
|
- 不需要登录, 不需要 cookie, 无文件落盘
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import pandas as pd
|
|
|
|
from utils._emchoice import fetch_report
|
|
|
|
|
|
_REPORT_NAME = "RPT_F10_EH_EQUITY"
|
|
_COLUMNS = "CHOICE_F9_EH_EQUITY"
|
|
|
|
|
|
def _build_params(secucode: str, end_date: str) -> dict[str, str]:
|
|
"""构造 RPT_F10_EH_EQUITY 查询参数."""
|
|
return {
|
|
"source": "CHOICE",
|
|
"reportName": _REPORT_NAME,
|
|
"columns": _COLUMNS,
|
|
"quoteColumns": "",
|
|
"pageNumber": "1",
|
|
"pageSize": "",
|
|
"sortColumns": "END_DATE",
|
|
"client": "SW",
|
|
"filter": f'(SECUCODE="{secucode}")(LISTING_DATE>=\'1900-01-01\')(LISTING_DATE<=\'{end_date}\')',
|
|
"sortTypes": "-1",
|
|
}
|
|
|
|
|
|
def _fetch_one(secucode: str) -> pd.DataFrame:
|
|
"""拉一只股票的股本结构 (全量历史)."""
|
|
end_date = pd.Timestamp.today().strftime("%Y-%m-%d")
|
|
rows = fetch_report(_build_params(secucode, end_date))
|
|
df = pd.DataFrame(rows)
|
|
if not df.empty:
|
|
df["SECUCODE"] = secucode
|
|
return df
|
|
|
|
|
|
def get_equity(secucodes: list[str]) -> pd.DataFrame:
|
|
"""抓取指定股票的股本结构(全量历史)并按股票合并。"""
|
|
codes = [code.strip() for code in secucodes if code.strip()]
|
|
if not codes:
|
|
return pd.DataFrame()
|
|
|
|
frames: list[pd.DataFrame] = []
|
|
for code in codes:
|
|
df = _fetch_one(code)
|
|
if not df.empty:
|
|
frames.append(df)
|
|
|
|
if not frames:
|
|
return pd.DataFrame()
|
|
return pd.concat(frames, ignore_index=True)
|