← 返回博客列表

【零依赖量化数据实战 #20】行业板块分类全景:2 个 URL 把行业与概念一次拉齐

2026年08月27日 09:38 · 智兔数服 · 零依赖量化数据实战

摘要:【零依赖量化数据实战 #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_keyname/title 等不同字段名下都能取到值)、_to_float3.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 下的自验结果,不编造任何真实行情/分类数值

五、坑与注意事项

  1. 这是"分类清单",不是行情/hibk/zjhhy/hibk/gnbk 返回的是行业/概念的分类维度,不含涨跌、成交额。要做"板块涨跌扫描",需要把这个分类接到个股实时行情(#01 /hs/real/ssjy)或指数行情(#19 /hz/real/ssjy)上自行聚合。
  2. 字段名以实际返回为准:文档给的是分类语义,具体字段名(是 name 还是 hyname/bkname)以你换真实 token 后的返回为准;本文用 _hit_key 做了多候选键容错,真跑时无需改代码。
  3. 返回形态可能是 list 也可能是 dict:部分接口会把数组包在 data 字段里,_coerce_list 已处理,遍历前不用自己判断。
  4. token 是查询参数:这两个接口没有路径参数,鉴权走 ?token=,别把 token 拼进路径。
  5. 不要自创接口:本文两个端点全部来自官方文档,未做任何路径拼接或猜测;想扩展板块维度前,先回文档核对。

六、小结与下篇预告

至此,#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 自验,未含任何真实数据;文中合成数据仅为逻辑自验用途,不构成投资建议,亦不承诺收益。

想亲自试一下?免费获取证书