【零依赖量化数据实战 #20】行业板块分类全景:2 个 URL 把行业与概念一次拉齐
摘要:【零依赖量化数据实战 #20】行业板块分类全景:2 个 URL 把行业与概念一次拉齐 系列:《零依赖量化数据实战》|零依赖 · 纯 GET · 不 import 任何 SDK 适用:想做板块轮动、题材筛选、行业/
系列:《零依赖量化数据实战》|零依赖 · 纯 GET · 不 import 任何 SDK
适用:想做板块轮动、题材筛选、行业/概念成分归类的开发者,不想装库或对接多个数据源
你将得到什么
- 2 个「行业板块分类」端点的路径、返回形态和语义(证监会行业分类 / 概念板块分类),照公开文档核对过的,不是猜的
- 一段
sector_overview()把两个分类一次性拉齐,整理成「证监会行业」「概念板块」两张清单 - 字段名容错写法(候选键命中
_hit_key),对字段名不敏感、对返回形态(list / dict)不敏感 - 完整可复制运行代码,把
你的智兔token换成真实智兔证书即可直接跑
一、两个端点,一张语义表
「行业板块」在智兔里拆成两条独立分类线,都走 /hibk/ 前缀,无路径参数,鉴权用 ?token=:
GET https://api.zhituapi.com/hibk/zjhhy?token=<你的智兔token> 证监会行业分类(一级行业清单)
GET https://api.zhituapi.com/hibk/gnbk?token=<你的智兔token> 概念板块分类(概念题材清单)
zjhhy= 证监会行业分类,按监管口径的一级行业(农林牧渔 / 采矿业 / 制造业 …)。gnbk= 概念板块分类,按市场题材(人工智能 / 锂电池 / 新能源车 …)。
两个都是「分类清单」型接口:返回的是分类维度本身,不是行情。拿到分类后,你可以把它接到前面 #18/#19 的个股/指数/北交所实时行情上,做「某行业下有哪些票在涨」式的板块扫描。
二、先把"拿数据"这件小事解决
和本系列前面的写法一致,只依赖 requests,不引入任何 SDK。三个小工具先备好:
import requests
BASE = "https://api.zhituapi.com"
TOKEN = "你的智兔token"
HEADERS = {"User-Agent": "Mozilla/5.0"}
def fetch(url):
"""GET 一个 JSON 端点,返回 (data, err)。"""
try:
r = requests.get(url, headers=HEADERS, timeout=10)
try:
return r.json(), None
except Exception:
return None, "JSON 解析失败, HTTP %d, body=%s" % (r.status_code, r.text[:200])
except Exception as e:
return None, "请求异常: %s" % e
def _hit_key(row, *keys):
"""在 dict 里按候选键顺序命中第一个存在且不空的值。"""
if not isinstance(row, dict):
return None
for k in keys:
if k in row and row[k] not in (None, ""):
return row[k]
return None
def _to_float(s):
"""把 '3.5%' / '1,234.56' / 'NaN' 规整成 float;无法解析返回 None。"""
if s is None:
return None
if isinstance(s, (int, float)):
return float(s)
t = str(s).replace("%", "").replace(",", "").strip()
try:
v = float(t)
return v if v == v else None # NaN -> None
except Exception:
return None
def _coerce_list(payload):
"""接口返回可能是 list,也可能是 {'data': [...]};统一成 list。"""
if isinstance(payload, list):
return payload
if isinstance(payload, dict):
for k in ("data", "list", "items", "result", "rows"):
if isinstance(payload.get(k), list):
return payload[k]
return []
要点:
fetch永远返回(data, err)二元组,调用方必须处理err,不做"假设一定成功"的写法。_hit_key是字段名容错的核心——不同接口返回的字段名可能叫name/title/hyname/bkname,用候选键顺序命中,代码不会因为字段名差异而崩。_coerce_list把"有时是 list、有时包在data里"的差异抹平,后面迭代样本时不用反复判断类型。
三、核心模板:sector_overview()
把两个分类端点拉齐,整理成「证监会行业」「概念板块」两张清单,各取前 5 个做样本:
def sector_overview(token=TOKEN):
"""拉取证监会行业分类 + 概念板块分类,整理成两类清单。"""
out = {}
for label, path in (("证监会行业", "/hibk/zjhhy"), ("概念板块", "/hibk/gnbk")):
url = "%s%s?token=%s" % (BASE, path, token)
data, err = fetch(url)
if err:
out[label] = {"err": err, "count": 0, "sample": []}
continue
rows = _coerce_list(data)
sample = []
for row in rows[:5]:
name = _hit_key(row, "name", "板块名称", "行业名称", "hyname", "bkname", "title")
code = _hit_key(row, "code", "板块代码", "hycode", "bkcode", "id")
sample.append({"code": code, "name": name})
out[label] = {"err": None, "count": len(rows), "sample": sample}
return out
if __name__ == "__main__":
import json
ov = sector_overview()
print(json.dumps(ov, ensure_ascii=False, indent=2))
跑起来后,ov["证监会行业"]["count"] 是证监会行业的总数,ov["概念板块"]["sample"] 是概念板块前 5 个样本(含 code / name)。把这套清单缓存下来,就是一张"全市场板块字典",可以喂给任何后续筛选逻辑。
四、代码自验结果
离线 selftest(合成数据,仅验证逻辑,非真实行情):
selftest PASS
自验覆盖了:候选键命中(_hit_key 在 name/title 等不同字段名下都能取到值)、_to_float 对 3.5% / 1,234.56 / NaN / None 的解析、list 与 {"data":[...]} 两种返回形态的统一、以及 sector_overview 在合成数据下的整理逻辑(证监会行业 3 条、概念板块 3 条均被正确计数与抽样)。
联网实测(占位 token,真实 HTTP 响应原样保留):
{
"证监会行业": {
"err": "JSON 解析失败, HTTP 404, body=102:Licence证书(你的智兔token)不存在\n",
"count": 0,
"sample": []
},
"概念板块": {
"err": "JSON 解析失败, HTTP 404, body=102:Licence证书(你的智兔token)不存在\n",
"count": 0,
"sample": []
}
}
两个端点都返回 404 102:Licence证书(你的智兔token)不存在 —— 这是鉴权先于路由的结果:路径本身合法,但占位 token 没有对应证书,所以被拦在鉴权层。换上你自己的真实 token,上面的脚本就能直接打印行业板块分类数据。文中所有数字均为占位 token 下的自验结果,不编造任何真实行情/分类数值。
五、坑与注意事项
- 这是"分类清单",不是行情:
/hibk/zjhhy和/hibk/gnbk返回的是行业/概念的分类维度,不含涨跌、成交额。要做"板块涨跌扫描",需要把这个分类接到个股实时行情(#01/hs/real/ssjy)或指数行情(#19/hz/real/ssjy)上自行聚合。 - 字段名以实际返回为准:文档给的是分类语义,具体字段名(是
name还是hyname/bkname)以你换真实 token 后的返回为准;本文用_hit_key做了多候选键容错,真跑时无需改代码。 - 返回形态可能是 list 也可能是 dict:部分接口会把数组包在
data字段里,_coerce_list已处理,遍历前不用自己判断。 - token 是查询参数:这两个接口没有路径参数,鉴权走
?token=,别把 token 拼进路径。 - 不要自创接口:本文两个端点全部来自官方文档,未做任何路径拼接或猜测;想扩展板块维度前,先回文档核对。
六、小结与下篇预告
至此,#09–#20 把数据面从基金链延伸到指数层、北交所、公司基本面,再到板块分类维度:基金持仓(#09) → 基金实时/清单(#10) → ETF K线均线(#11) → ETF 排名分红(#12) → ETF 盘中估值(#13) → A股异动池(#14) → 可转债(#15) → 港股通(#16) → 公司基本面(#17) → 北交所实时(#18) → 沪深指数(#19) → 行业板块分类(#20)。
下一篇(#21)讲北交所公司财务三表——用 /bj/fin/balance(资产负债表)、/bj/fin/income(利润表)、/bj/fin/cashflow(现金流量表)、/bj/fin/ratios(财务比率),把 #18 的「北交所实时行情」升级到「北交所公司财务面」,看一家北交所公司的资产、盈利与现金流质量。
免费领取证书
数据来自 智兔数服(www.zhituapi.com):零 SDK、纯 GET、免费版即可起步。
领取路径:进入 www.zhituapi.com → 点击「请求证书」→「证书获取」→「免费版」(邮箱验证 3 步即可拿到 token)。
把代码里的 你的智兔token 换成你拿到的真实 token,上面的脚本就能直接打印行业板块分类数据。
免责声明
本文仅演示公开数据接口的用法,所有代码示例均以占位 token 自验,未含任何真实数据;文中合成数据仅为逻辑自验用途,不构成投资建议,亦不承诺收益。