核心区分(先记住这条):"取数失败" ≠ "当前没有这类数据"。两者都有明确信号,不要混为一谈。
| 状态 | 含义 | 处理 |
|---|---|---|
| 200 | 成功(但要看 ok 字段,见下) |
读 data / structured |
| 401 | 未授权 —— 没带 Key 调了付费端点(或 Key 无效/已停用) | 拿 Key(https://ashareapi.com/pricing),或改用 5 个免费端点 |
| 403 | 禁止 —— 常见于 IP 维度限制(一个 Key 被多个 IP 共用,超出该档位允许的 IP 数) | 别把 Key 共享给多人;升级档位 |
| 404 | 路径不存在 | 核对端点名(见 endpoints.md) |
| 422 | 参数错误(缺必填 / 值非法) | 看返回里的说明;常见是缺 code |
| 429 | 超出限流(两种:每分钟次数超 · 当天条数超) | 次数超 → 降频 · 解 PoW 提额 · 升级档位;条数超 → 解 PoW 无效,次日恢复,或用 Key / 升级档位(见下) |
| 5xx | 服务端/上游异常 | 稍后重试 |
{ "ok": false, "endpoint": "block-trade", "data": [] }ok:true= 取数成功ok:false= 上游取数失败(我们已自动换源,且 不扣调用次数)→ 重试一次通常就好
ok:false 不是"你写错了" —— 是数据源那一侧的问题。所以不要因为 ok:false 就改代码逻辑。
ok:false + data: [] 或 ok:true 但列表为空 → 可能是"当前确实没有这类数据":
- 今天没有大宗交易
- 这个时间段没有解禁事件
- 该股今日不在龙虎榜
处理:换条件 / 换日期 / 稍后再试 —— 不是故障,不会计费。 不要把它当成"上游挂了"去重试到超时。
| 档位 | 额度 |
|---|---|
| 匿名(无 Key) | 5 次/分钟 · 单次最多 250 条 · 每天最多 10 万条 |
| 匿名 + PoW | 15 次/分钟(每日条数上限不变,仍 10 万条) |
| 各付费档 | 见 https://ashareapi.com/pricing(含每分钟与总量限制) |
触发时:返回 429。
# 1) 取挑战
curl "https://api.ashareapi.com/v1/challenge"
# → { "challenge": "...", "difficulty": 18, "expires_in": 600, "how_to": "..." }
# 2) 算 nonce:要求 sha256("<challenge>.<nonce>") 的十六进制前 difficulty 位为 '0'
# (普通电脑毫秒~秒级;难度由服务端定,只允许调高不允许调低)
# 3) 带上去请求
curl -H "X-PoW: <challenge>.<nonce>" \
"https://api.ashareapi.com/v1/quote?code=sh600667"要点:
- 挑战有有效期(
expires_in,通常 600 秒),过期重新取 - 挑战可以预取 + 预解算 + 延后使用(流水线化,不必每次现解)
- 付费 Key 用户不需要 PoW(额度已够)
⚠️ PoW 只提升每分钟次数,不提升每日条数 —— 匿名每天仍最多 10 万条
- 批量取数时加
time.sleep()(匿名至少 12 秒/次;PoW 后 1 秒/次) ⚠️ 匿名每天最多 10 万条 —— 批量补历史/回测请用 Key(一次 1212 条、无日上限)- 本地缓存:同一标的一天内的行情/财务不必重复取
- 需要高频就升级档位 —— 比反复解 PoW 省事
from ashareapi import (AShareAPI, AuthError, RateLimitError,
UpstreamError, EmptyResultError, APIError)
try:
df = cli.fund("sh600667")
except AuthError: # 401 / 缺 Key
...
except RateLimitError: # 429(含提额提示)
...
except UpstreamError: # ok:false —— 上游失败,已换源,不扣次数 → 重试一次
...
except EmptyResultError: # 当前无数据(如当天无大宗交易)→ 不计费,换条件
...
except APIError: # 其他(网络 / 5xx 重试耗尽)
...| SDK 异常 | 对应上面的情况 |
|---|---|
AuthError |
401 / 403(鉴权与 IP 维度) |
RateLimitError |
429 |
UpstreamError |
ok:false 且 data 非空(真失败) |
EmptyResultError |
ok:false 且 data 为空(无数据 ≠ 失败) |
APIError |
网络异常 / 5xx 重试耗尽 |
这正是 SDK 的价值:把"该重试"和"该换条件"分开,不用自己猜。
- 401 还是 429? → 缺 Key 还是超频(两者处理完全不同)
- HTTP 200 但没数据? → 看
ok与data:ok:false+空 = 无数据(换条件);ok:false+有内容 = 上游失败(重试) - 403? → 是不是把 Key 给多人用了(IP 维度)
- 422? → 看返回说明,多半少传了必填参数(如
code) - 数据看着不对? → 先查单位与日期(见
fields.md),90% 是单位/日期问题,不是接口问题