教程

从 AkShare 迁移到 ashareapi:接口对照与改写

AkShare 强在覆盖广,我们强在不用自己维护。如果你已经在用 AkShare、又被"上游改版→接口报错"折腾过,迁移主要是三处改动:代码格式、调用方式、字段名。下面给对照表与可运行示例,也写清哪些迁移不过来。

先想清楚:为什么从 AkShare 迁出来

AkShare 是 MIT 开源的免费 Python 库,数据面比我们宽得多(几乎什么都抓)。迁移动机通常不是"数据更多",而是这三个:

  • 不想维护:AkShare 抓的是公开网页,上游改版 → 接口失效,得升级版本或改代码自己修
  • 要稳定与缓存:我们的每个端点有多源备份(某个源出问题自动换)+ 缓存 + 健康巡检
  • 要给 AI 用 / 非 Python 环境:我们用 HTTP + MCP,任意语言都能调,不用装 1,300+ 依赖

如果你预算为零、已在用 Python、且玩的是研究探索(不是生产跑任务),AkShare 是很好的选择——这页是给"想少维护一点"的人看的,不是要说服所有人。两者也可以同时用。

第一步:把代码格式从纯数字改成带前缀

这是迁移里最容易踩的坑。AkShare 的 `symbol` 是纯 6 位数字(`"600667"`);我们的是前缀式(`sh600667`)。所有端点都吃这个格式。

Python
# AkShare                              # ashareapi
# "600667"   (沪 A)      →   sh600667
# "000001"   (深 A)      →   sz000001
# "830799"   (北交所)    →   bj830799
# "00700"    (港股)      →   hk00700
# "AAPL"     (美股)      →   usAAPL

# 按代码首位判断市场(A 股规则)——够用但不完备,北交所/新老代码需按实际核对
def to_code(symbol: str) -> str:
    """把 AkShare 的纯数字代码转成 ashareapi 前缀式代码"""
    if not symbol.isdigit():
        return "us" + symbol.upper()          # 非数字 → 美股
    if symbol.startswith(("60", "68")):       # 沪市主板 / 科创板
        return "sh" + symbol
    if symbol.startswith(("00", "30")):        # 深市主板 / 创业板
        return "sz" + symbol
    if symbol.startswith(("83", "87", "43")):  # 北交所
        return "bj" + symbol
    return "sh" + symbol                        # 兜底(务必按实际核对)
  • 最稳的做法:先用 `/v1/search?q=证券名称或代码` 拿到代码,它返回的就是正确的前缀式(自动消歧)
  • 前缀式同时消掉了"同一个 000001 是平安银行还是上证指数"这类歧义

第二步:换调用方式(函数 → HTTP 请求)

AkShare 是 `import akshare as ak` 后调函数、拿 DataFrame;我们是发一个 GET 请求、拿统一的 JSON 信封。两端都不复杂,但形态不同。

Python(可直接运行,K线部分无需 Key)
# ── 改写前(AkShare)─────────────────────────
# import akshare as ak
# df = ak.stock_zh_a_hist(symbol="600667", period="daily",
#                         start_date="20260101", end_date="20260925",
#                         adjust="")
# print(df[["日期", "收盘", "成交量"]])

# ── 改写后(ashareapi)──────────────────────
import requests

BASE = "https://api.ashareapi.com/v1"
H = {}          # 免费端点无需 Key;付费端点加 {"Authorization": "Bearer ct-你的Key"}

def get(path, **params):
    r = requests.get(f"{BASE}/{path}", params=params, headers=H, timeout=30)
    if r.status_code == 429:                  # 超频:见第五节
        raise RuntimeError("rate limited")
    r.raise_for_status()
    body = r.json()
    if not body.get("ok"):
        raise RuntimeError(f"upstream failed (not counted): {body}")
    return body["data"]

# 历史 K 线(免费)——等价 stock_zh_a_hist(无区间参数,取最近 N 根,回来自己按日期过滤)
bars = get("kline", code="sh600667", period="day", count=30)
for r in bars:
    print(r["date"], r["last"], r["volume"])   # 原「收盘」→ last

# 实时行情(免费)——等价 stock_zh_a_spot_em 的单只版本
q = get("quote", code="sh600667")
print(q[0]["last"], q[0]["turnover"])          # 最新价 / 换手率
  • 没有 `adjust`(复权)参数 —— 口径固定为前复权(除权除息日不跳空);⚠️ 不要再自己复权(会二次复权);也不提供不复权 / 后复权数据
  • 没有 `start_date` / `end_date` —— 用 `count` 取最近 N 根,再本地过滤(也避免"区间内无数据"被当成接口错误)
  • 返回是 `list[dict]`(字段为字符串数字),不是 DataFrame;要 DataFrame 可以 `import pandas as pd; pd.DataFrame(bars)`

第三步:改字段名

只有几个常用字段名不同,其余同名同义。注意我们返回的数值是字符串(`"19.41"` 而非 `19.41`),比较/计算前记得转换。

日期
日期
date
我们带横线(2026-09-24)
收盘 / 最新
收盘
last
字段名不同,含义一致
今开
开盘
open
同名同义
最高 / 最低
最高 / 最低
high / low
同名同义
成交量(手)
成交量
volume
同为手
成交额(元)
成交额
amount
元
换手率(%)
换手率
turnover
2026-09-26 由 `exchange` 改名(旧名易误读为「交易所」)· 与 `snapshot` 同名同值
股票代码
代码 / symbol
code
前缀式 sh600667

接口对照表(AkShare 函数 → 我们的端点)

左列是 AkShare 官方文档里的常用函数名;右列是等价(或最接近)的端点。没有等价端点的不硬凑,见备注。

stock_zh_a_spot_em(全市场实时)
GET /v1/quote(单只)· /v1/hot(热度)
我们不做全市场快照批量导出,只有按代码取单只
stock_zh_a_hist(历史行情)
GET /v1/kline
period=day|week|month,count 取最近 N 根(无区间参数)
stock_zh_a_hist_min_em(分钟)
❌
不做分钟级数据(这是我们明确的边界)
stock_individual_info_em(个股信息)
GET /v1/profile · /v1/snapshot
profile = 上市日期/主营/行业;snapshot = 估值/市值/股本/涨停价
stock_bid_ask_em(五档盘口)
GET /v1/orderbook
买一~买五/卖一~卖五的价格与挂单量
stock_financial_abstract(财务摘要)
GET /v1/finance
三大报表多期(num 控期数),ROE/毛利率等在返回里
stock_profit_sheet_by_report_em(利润表)
GET /v1/finance
三表一次返回,不必三次调用
stock_individual_fund_flow(个股资金流)
GET /v1/fund
一个端点拿全:主力资金 + 龙虎榜 + 大宗 + 两融
stock_market_fund_flow(大盘资金流)
❌
没有全市场资金流分时;可看 /v1/changedist(市场广度,免费)
stock_lhb_detail_em(龙虎榜明细)
GET /v1/lhb
type=institution 机构 / hotmoney 游资 / activeseat 活跃席位
stock_margin_detail_sse / _szse(两融)
GET /v1/margin-trade
融资余额/买入/偿还/融券;code 支持批量
stock_dzjy_mrmx(大宗交易明细)
GET /v1/block-trade
成交价/折溢价/成交量/买卖方营业部
stock_dividend_cninfo(分红送转)
GET /v1/dividend
years 控年份(默认 3 年)
stock_gdfx_free_top_10_em(十大流通股东)
GET /v1/shareholder
十大股东 + 股东户数 + 机构持仓
stock_zh_a_gdhs(股东户数)
GET /v1/shareholder
股东户数(筹码集中度)
bond_zh_cov(可转债比价表)
GET /v1/bond
条款为主:转股价/强赎触发/双低/溢价率;不提供转债日线
fund_etf_spot_em(ETF 实时)
GET /v1/etf
行情/规模/溢折率/资金流(code 形如 sh510300)
stock_new_gh_detail_em(新股)
GET /v1/ipo
发行/申购/中签/上市日历(days 控天数)
stock_board_industry_name_em(行业板块)
GET /v1/sector · /v1/sector-valuation
板块行情榜 + 板块估值(含历史分位)
stock_board_concept_name_em(概念板块)
GET /v1/sector · /v1/industry-chain
sector 含概念板块;industry-chain 给产业链上下游与关联度
stock_zh_index_daily(指数日线)
❌
有 /v1/market-overview(大盘画像/风格轮动/估值分位),不是指数 K 线
stock_news_em / 公告 / 研报全文
❌
不做新闻与公告全文;研报只有脱水摘要(/v1/dehydrated)
股票列表 / 全市场导出
GET /v1/search(按关键词)
不提供全量列表批量导出

第四步:限流与错误处理

AkShare 没有限流(本地调用);换成 HTTP API 后要处理 429 与上游失败。这也正是"稳定性"的代价与收益所在。

Python
import time, requests

BASE = "https://api.ashareapi.com/v1"
H = {}

def get_with_retry(path, tries=3, **params):
    for i in range(tries):
        r = requests.get(f"{BASE}/{path}", params=params, headers=H, timeout=30)
        if r.status_code == 429:              # 超频
            time.sleep(2 ** i)                # 退避重试(别死循环打)
            continue
        r.raise_for_status()
        body = r.json()
        if not body.get("ok"):                # 上游失败 → 不扣次数,可重试
            time.sleep(1)
            continue
        return body["data"]
    raise RuntimeError(f"{path}: failed after {tries} tries")
  • 免费端点:匿名正常配额 5 次/分,解一次 PoW 挑战(`GET /v1/challenge`)可到 60 次/分
  • 注意:短时间内连续请求会被临时收紧(实测连续 6 次后提示"匿名限流 2 次/分")——退避即可恢复,不是封禁
  • 付费 Key 按档位限流(体验 30 · 标准 120 · 专业 300 · 不限量 600 次/分)
  • 上游取数失败不会扣次数(`ok:false`),可以安全重试;429 才需要退避

能迁 / 不能迁(写在前面,免得白迁)

  • 能迁:实时行情 · 日/周/月 K 线 · 三大报表 · 资金流 · 龙虎榜 · 融资融券 · 大宗 · 分红 · 股东 · 可转债条款 · ETF · 新股 · 板块 · 产业链
  • 不能迁:分钟级行情 · 新闻/公告/研报全文 · 指数日线 · 全市场列表批量导出 · 不复权 / 后复权序列(我们的 K 线口径固定为前复权)
  • 态度:这几项请继续用 AkShare —— 它在这几块比我们强,两边同时用是最务实的组合

常见错误

  • 代码写成 `"600667"` → 400/空结果;必须 `sh600667`(或用 `/v1/search` 确认)
  • 拿字符串当数字算 → `"19.41" * 2` 不是 38.82;先 `float(...)` 再算
  • 找不到 `adjust` / `start_date` / `end_date` → 复权口径固定为前复权(无参数可调)、不做区间查询;用 `count` + 本地过滤
  • 换手率找不到 → 字段叫 `turnover`(`quote` / `kline` / `snapshot` 同名同值;2026-09-26 之前叫 `exchange`)
  • 说"数据错了"其实是上游未披露 → 财务/股东/两融按披露节奏更新,未到披露日就是没有(不是接口故障)

常见问题

AkShare 免费,为什么要迁到你们?

不是数据更多(AkShare 覆盖比我们宽),而是"少维护":AkShare 抓公开网页,上游改版时要自己修;我们做多源备份、缓存与巡检。如果预算为零、能接受维护,AkShare 是很好的选择——不必为了迁移而迁移。

能两个一起用吗?

能,而且常见。典型组合:冷门/极广的数据(新闻、公告、分钟、指数)用 AkShare 抓,核心数据(实时行情、资金、龙虎榜、板块估值)走我们,稳定性与维护成本由我们承担。

代码格式能不能不转,直接喂纯数字?

不行。所有端点都要求前缀式(`sh600667`)。最省事的转换方式是先用 `/v1/search?q=平安银行`,它返回的 code 就是正确格式,还顺带解决了"同名/同号"的消歧。

你们返回 DataFrame 吗?

HTTP 端点返回的是 `list[dict]`(字段值多为字符串)。一行就能转:`import pandas as pd; df = pd.DataFrame(bars)`。官方 Python SDK(`pip install ashareapi`)装 `[pandas]` 后可直接返回 DataFrame。

我要的接口这页没有,怎么办?

先看端点清单(32 个端点按分类),或用 `/v1/search` 搜关键词。确实没有的(分钟、新闻公告全文、指数日线、不复权 / 后复权序列、全量列表)请继续用 AkShare——这是我们的边界,写在这里免得你白迁移。

最后更新: 2026-09-25

AkShare 侧函数名取自其官方文档(akshare.akfamily.xyz);我们侧端点数与分层取自官方端点清单 endpoints.json(32 个 = 7 免费 + 25 付费,2026-09-24 生成),字段与返回结构取自线上真实返回(quote / kline 于 2026-09-25 实测)。两侧接口与字段都可能变更,以各自官方页面为准。