You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
2.8 KiB
84 lines
2.8 KiB
"""东方财富 CHOICE API 公司介绍 + 所属行业抓取工具。
|
|
- 输入: 股票代码列表 (如 ['603233.SH'])
|
|
- 输出: pandas DataFrame (公司基本资料 / 所属行业)
|
|
- 不需要登录, 不需要 cookie, 无文件落盘
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import pandas as pd
|
|
|
|
from utils._emchoice import fetch_report
|
|
|
|
|
|
def _fetch_one(secucode: str, params: dict[str, str]) -> pd.DataFrame:
|
|
"""按给定参数拉一只股票的数据."""
|
|
rows = fetch_report(params)
|
|
df = pd.DataFrame(rows)
|
|
if not df.empty:
|
|
df["SECUCODE"] = secucode
|
|
return df
|
|
|
|
|
|
def _concat(frames: list[pd.DataFrame]) -> pd.DataFrame:
|
|
if not frames:
|
|
return pd.DataFrame()
|
|
return pd.concat(frames, ignore_index=True)
|
|
|
|
|
|
# ---------------------------------------------------------------- 公司介绍
|
|
|
|
def _build_company_params(secucode: str) -> dict[str, str]:
|
|
"""构造 RPT_HSF9_BASIC_ORGINFO 查询参数 (公司基本资料)."""
|
|
return {
|
|
"source": "CHOICE",
|
|
"reportName": "RPT_HSF9_BASIC_ORGINFO",
|
|
"columns": "HSF9_ORGINFO",
|
|
"quoteColumns": "",
|
|
"filter": f'(SECUCODE="{secucode}")',
|
|
"pageNumber": "1",
|
|
"pageSize": "200",
|
|
"client": "SW",
|
|
}
|
|
|
|
|
|
def get_company_info(secucodes: list[str]) -> pd.DataFrame:
|
|
"""抓取指定股票的公司介绍 (基本资料, 每只 1 行)."""
|
|
codes = [code.strip() for code in secucodes if code.strip()]
|
|
if not codes:
|
|
return pd.DataFrame()
|
|
|
|
frames = [_fetch_one(code, _build_company_params(code)) for code in codes]
|
|
return _concat([df for df in frames if not df.empty])
|
|
|
|
|
|
# ---------------------------------------------------------------- 所属行业
|
|
|
|
def _build_industry_params(secucode: str) -> dict[str, str]:
|
|
"""构造 RPT_STOCKF9_INDUSTRY 查询参数 (当前生效的行业分类)."""
|
|
return {
|
|
"reportName": "RPT_STOCKF9_INDUSTRY",
|
|
"columns": (
|
|
"SECUCODE,SECURITY_CODE,SECURITY_NAME_ABBR,INDUSTRY_TYPE_CODE,"
|
|
"INDUSTRY_TYPE,INDUSTRY_NAME,INDUSTRY_CODE,SECURITY_INNER_CODE,"
|
|
"INDUSTRY_NAME_MIN,INDUSTRY_CODE_MIN,ENTRY_DATE,OUT_DATE,"
|
|
"SECURITY_TYPE_CODE,STATE,STATE_CODE,RN"
|
|
),
|
|
"quoteColumns": "",
|
|
"filter": f'(SECUCODE="{secucode}")(STATE_CODE="1")',
|
|
"pageNumber": "",
|
|
"pageSize": "",
|
|
"sortTypes": "1",
|
|
"sortColumns": "RN",
|
|
"source": "CHOICE",
|
|
"client": "SW",
|
|
}
|
|
|
|
|
|
def get_industry(secucodes: list[str]) -> pd.DataFrame:
|
|
"""抓取指定股票的所属行业 (当前生效分类)."""
|
|
codes = [code.strip() for code in secucodes if code.strip()]
|
|
if not codes:
|
|
return pd.DataFrame()
|
|
|
|
frames = [_fetch_one(code, _build_industry_params(code)) for code in codes]
|
|
return _concat([df for df in frames if not df.empty])
|
|
|