Skip to content

Latest commit

 

History

History
117 lines (87 loc) · 5.35 KB

errors.md

File metadata and controls

117 lines (87 loc) · 5.35 KB

错误、限流与"无数据"

核心区分(先记住这条):"取数失败" ≠ "当前没有这类数据"。两者都有明确信号,不要混为一谈。


一、HTTP 状态码

状态 含义 处理
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 字段(HTTP 200 也要看它)

{ "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 可能是其中任意一种触发;先看返回里的提示是哪种。

触发时:返回 429。

匿名提额:解一次 PoW 挑战

# 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 万条

降频建议(比死磕 429 更实际)

  • 批量取数时加 time.sleep()(匿名至少 12 秒/次;PoW 后 1 秒/次)
  • ⚠️ 匿名每天最多 10 万条 —— 批量补历史/回测请用 Key(一次 1212 条、无日上限)
  • 本地缓存:同一标的一天内的行情/财务不必重复取
  • 需要高频就升级档位 —— 比反复解 PoW 省事

五、官方 Python SDK 的 5 类异常(不用自己判状态码)

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 的价值:把"该重试"和"该换条件"分开,不用自己猜。

六、排错顺序(省时间)

  1. 401 还是 429? → 缺 Key 还是超频(两者处理完全不同)
  2. HTTP 200 但没数据? → 看 ok 与 data:ok:false+空 = 无数据(换条件);ok:false+有内容 = 上游失败(重试)
  3. 403? → 是不是把 Key 给多人用了(IP 维度)
  4. 422? → 看返回说明,多半少传了必填参数(如 code)
  5. 数据看着不对? → 先查单位与日期(见 fields.md),90% 是单位/日期问题,不是接口问题