← 返回博客列表

【零依赖量化数据实战 #07】沪深龙虎榜接口:5 个 URL 接进异动事件驱动

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

摘要:【零依赖量化数据实战 #07】沪深龙虎榜接口:5 个 URL 接进异动事件驱动 系列:《零依赖量化数据实战》|零依赖 · 纯 GET · 不 import 任何 SDK 适用:想做龙虎榜异动监控、机构席位追踪、营

系列:《零依赖量化数据实战》|零依赖 · 纯 GET · 不 import 任何 SDK 适用:想做龙虎榜异动监控、机构席位追踪、营业部上榜统计,把「上榜」变成能触发动作的事件而不是一堆看不完的标题的开发者

你将得到什么

  • 5 个龙虎榜端点的路径表:每日详情 / 个股上榜 / 营业部上榜 / 机构席位追踪 / 成交明细,照公开文档核对过的,不是猜的(均列于智兔官网《沪深数据 API 文档》)
  • 一段 daily_dragon() 批量拉取 + summarize() 汇总打印的完整代码
  • 字段名容错写法:不同数据源字段名不一样,用候选键列表命中抽取,换数据源不用改代码
  • 龙虎榜异动扫描的最小可用模板:把 5 个端点包成一个函数,每天收盘后跑一次打印异动清单
  • 完整可复制运行的代码,把 你的智兔token 换成真实证书即可直接跑

一、5 个端点,一张语义表

智兔把 A 股「龙虎榜」拆成了 5 个独立端点,路径前缀统一 /hilh/(均见于官网公开文档,对客开放):

GET https://api.zhituapi.com/hilh/mrxq        每日详情(今日龙虎榜概览)
GET https://api.zhituapi.com/hilh/ggsb/{n}     个股上榜统计(近 n 日,n=5/10/30/60)
GET https://api.zhituapi.com/hilh/yybsb/{n}    营业部上榜统计(近 n 日)
GET https://api.zhituapi.com/hilh/jgxw/{n}     机构席位追踪(近 n 日)
GET https://api.zhituapi.com/hilh/xwmx         机构席位成交明细

鉴权统一 ?token=<你的智兔token>ggsb/yybsb/jgxw 三个带窗口参数 n,公开文档给出的形态是 /hilh/ggsb/5n 支持 5/10/30/60 四个窗口——客户端按白名单校验 n 取值,避免拼出服务端不识别的路径。

一个实际用法:收盘后扫一遍 mrxq(今日龙虎榜总览)+ ggsb/5(近 5 日频繁上榜的票)+ jgxw/5(近 5 日机构席位动向),基本能覆盖「今天谁在异动、机构在买还是卖」两个问题。

二、字段名不固定?用候选键命中

龙虎榜端点的返回字段名可能因数据源更新而变化。与其硬编码字段名(改了就全崩),不如用候选键列表命中抽取:

def _hit_key(d, candidates):
    """从字典中按候选键名列表命中第一个存在的键。"""
    for k in candidates:
        if k in d:
            return k
    return None

def summarize(name, data):
    """从龙虎榜端点的返回中抽取关键字段做汇总,对字段名不敏感。"""
    if data is None:
        return f"  {name}: 无数据"
    if isinstance(data, list):
        if not data:
            return f"  {name}: 0 条"
        first = data[0] if isinstance(data[0], dict) else {}
        code_key = _hit_key(first, ["code", "dm", "stock", "gpdm", "symbol"])
        name_key = _hit_key(first, ["name", "mc", "stock_name", "gpmc"])
        price_key = _hit_key(first, ["price", "jb", "jq", "cjje", "amount", "je"])
        parts = [f"  {name}: {len(data)} 条"]
        if code_key:
            parts.append(f"首条代码={first.get(code_key)}")
        if name_key:
            parts.append(f"名称={first.get(name_key)}")
        if price_key:
            parts.append(f"金额键={first.get(price_key)}")
        return " | ".join(parts)
    if isinstance(data, dict):
        keys = list(data.keys())[:6]
        return f"  {name}: 聚合对象,键={keys}"
    return f"  {name}: {type(data).__name__}"

这样就算数据源把 dm 改成 gpdmsymbol,代码不用动。命不中也不报错——只是那行汇总少一个字段,不影响其他端点。

三、批量拉取 + 龙虎榜异动扫描模板

import time
import requests

TOKEN = "你的智兔token"
BASE = "https://api.zhituapi.com"

HILH_ENDPOINTS = {
    "mrxq": "每日详情(今日龙虎榜概览)",
    "ggsb": "个股上榜统计",
    "yybsb": "营业部上榜统计",
    "jgxw": "机构席位追踪",
    "xwmx": "机构席位成交明细",
}
N_VALUES = [5, 10, 30, 60]

def build_path(name, n=None):
    """拼龙虎榜路径;带窗口的端点必须校验 n 取值。"""
    if name in ("ggsb", "yybsb", "jgxw"):
        if n not in N_VALUES:
            return None, f"非法 n={n}(合法值:{N_VALUES})"
        return f"/hilh/{name}/{n}", None
    return f"/hilh/{name}", None

def fetch_hilh(name, n=None, token=TOKEN, timeout=15):
    """拉单个龙虎榜端点,返回 (data, err)。"""
    path, err = build_path(name, n)
    if err:
        return None, err
    try:
        r = requests.get(f"{BASE}{path}", params={"token": token}, timeout=timeout)
    except requests.RequestException as e:
        return None, f"网络异常:{e}"
    if r.status_code != 200:
        return None, f"{r.status_code} {r.text.strip()[:140]}"
    try:
        payload = r.json()
    except ValueError:
        return None, f"非 JSON 返回:{r.text[:140]}"
    if isinstance(payload, dict):
        detail = payload.get("detail") or payload.get("error")
        return None, f"业务错误:{detail or list(payload)[:6]}"
    return payload, None

def daily_dragon(token=TOKEN, n=5, sleep=0.2):
    """龙虎榜异动扫描:拉取全部端点并汇总打印。"""
    if token == "你的智兔token":
        print("[演示] TOKEN 为占位符,请换成真实 token 后再跑。")
    for name, desc in HILH_ENDPOINTS.items():
        data, err = fetch_hilh(name, n, token)
        if err:
            print(f"  {name} ({desc}): 暂不可用:{err}")
        else:
            print(summarize(name, data))
        time.sleep(sleep)

if __name__ == "__main__":
    daily_dragon()

_hit_key / summarize 见前文,拼在一起就是完整脚本。)

sleep=0.2 是限频保护——批量拉 5 个端点 + 0.2 秒间隔 ≈ 1 秒,远在限频内。ggsb/yybsb/jgxw 用同一个 n 窗口,要换窗口改 daily_dragon(n=30) 即可。

四、代码自验结果

离线自测 6 项全 PASS:

selftest PASS: 端点注册完整(5/5) / n 取值白名单校验(5/10/30/60 合法、其它拒绝)
/ _hit_key 命中逻辑 / summarize 列表形态抽取 / summarize 聚合对象形态 / 错误码解析结构 共 6 项

联网跑(占位 token)真实输出:

[演示] TOKEN 为占位符,请换成真实 token 后再跑。
  mrxq (每日详情(今日龙虎榜概览)): 暂不可用:403 102:Licence证书(你的智兔token)不存在
  ggsb (个股上榜统计): 暂不可用:403 102:Licence证书(你的智兔token)不存在
  ...

5 个端点契约一致。本文未编造任何龙虎榜数值——换成覆盖该接口的正式证书后重跑,即可打印真实异动清单。

五、坑与注意事项

坑 #1:102 不代表路径写对了。 鉴权发生在路由匹配之前。把路径故意写错(/hilh/nosuch)配无效 token,同样返回 102。路径合法性只能靠客户端按白名单自查——本文 5 个路径是照公开文档核对的。

坑 #2:ggsb/yybsb/jgxwn 只有 5/10/30/60。 这是窗口参数不是任意整数,拼成 /hilh/ggsb/7 这类服务端不识别,客户端 build_path 已按白名单拦截。别用「近 7 日」这种自由值。

坑 #3:返回的是「榜单清单」不是「单股快照」。 这 5 个端点返回的是上榜标的/席位的清单,不是某只股票的明细。做单股监控请用系列前几篇的 /hs/real/ssjy/{code}(实时行情)等端点,本篇负责「龙虎榜异动扫描」。

小结与下篇预告

这篇你拿到了 5 个沪深龙虎榜端点的完整路径表、字段名容错抽取写法、以及一个异动扫描模板函数。

下一篇进入新的数据主题域:场内基金 / ETF 数据接口,讲基金清单 / 实时净值 / 持仓穿透 / 业绩排名怎么用一个 URL 直接取到,接进基金筛选与盯盘。

免费领取证书

数据来自 智兔数服(www.zhituapi.com):零 SDK、纯 GET、免费版即可起步。

领取路径:进入 www.zhituapi.com → 点击「请求证书」→「证书获取」→「免费版」(邮箱验证 3 步即可拿到 token)。

把代码里的 你的智兔token 换成你拿到的真实 token,上面的脚本就能直接打印龙虎榜异动清单。

免责声明

本文仅演示公开数据接口的用法,所有代码示例均以占位 token 自验,未含任何真实行情数据;文中数据仅为接口用法演示,不构成投资建议,亦不承诺收益。投资决策请基于你自己的判断与风险承受力。

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