知行札记
AKShare 实现与跨语言接入调查

AKShare 实现与维护机制

分析函数组织、导出、解析、JS 资产、错误及维护责任。

调查基线为原材料记载的 2026-10-04、AKShare v1.19.1、浅克隆短提交号 fac1e50。本轮读取了归档报告;未取得原运行环境或重跑接口、全库计数及 npm 检索。下文统计和“实测”均属于原调查记录,不能自动代表当前版本或服务可用性。短提交链接本轮未成功取得,数字保留为历史证据并披露复算边界。

一、项目概览与实现原理

结论先行:akshare 主要实现为一个"对东方财富、新浪财经、金十、巨潮资讯、同花顺、各交易所官网等数十家金融网站的公开(含逆向出的私有)HTTP 接口做同步抓取与聚合"的 Python 爬虫集合。

单个接口的实现范式

每个接口函数是一个自包含单元,典型五段式:

  1. URL(含 token)硬编码在函数体内;
  2. 按需伪造浏览器请求头;
  3. requests 同步请求;
  4. 手工解析(JSON / jsonp 剥壳 / read_html / read_excel / JS 解密);
  5. 中文列名重命名 + to_datetime/to_numeric 类型收敛,返回 pandas.DataFrame。

以 A 股日线 stock_zh_a_hist 为例:URL https://push2his.eastmoney.com/api/qt/stock/kline/get 与 ut token 均硬编码(akshare/stock_feature/stock_hist_em.py:981-991),r.json() 后将 klines 每行按逗号 split 建 DataFrame(:993-996),再逐列清洗(:998-1039)。新浪期货日线则需手工剥 jsonp 壳:r.text.split("=(")[1].split(");")[0](akshare/futures/futures_zh_sina.py:651-688)。

包结构与接口导出

  • 打包:setup.py 是 6 行空壳,真正配置在 pyproject.toml——setuptools>=61 后端(pyproject.toml:1-3)、动态版本取 akshare._version.__version__(:97-98)、requires-python >=3.11(:10)、随包分发 *.json/*.js/*.pk/*.zip 数据文件(:100-104,即逆向用的 ths.js/cninfo.js 等)。
  • 组织维度:数据品类子包(stock、stock_feature、stock_fundamental、futures、option、fund、bond、index、economic、fx、crypto、news 等,实测 36 个代码子包)× 每个数据源一个文件,如 stock_feature/stock_hist_em.py="东方财富历史行情"、stock_lhb_sina.py="新浪龙虎榜"。
  • 导出:__init__.py 共 7103 行,自 :3311 起 344 条 from akshare.子包.模块 import 函数,纯 import 聚合、无工厂无懒加载;__all__ 实有 1102 项 = 1096 个接口函数 + 6 个异常类(akshare/exceptions.py:6-40)。
  • 接口注册表:构建期 scripts/build_registry.py 解析 docs 与 __init__.py 生成 akshare/data/interfaces.json(实测 1090 条),运行时支撑 ak.search() / interface_info() / list_categories() 检索(akshare/registry.py:31-41)。

逆向是确凿的核心手段

  • py_mini_racer(V8 JS 引擎)在 40 个源文件中使用,执行从网站前端抠出的 JS:
    • 同花顺:读取打包的 akshare/data/ths.js(含 v_cookie 函数,ths.js:2)→ js_code.call('v') 生成 v_code → 以 Cookie: v={v_code} 与 hexin-v 头请求(akshare/stock_feature/stock_board_industry_ths.py:43-52, :237);
    • 巨潮资讯:akshare/data/cninfo.js(CryptoJS 实现)→ call('getResCode1') 生成 mcode → 塞进 Accept-Enckey 请求头 POST webapi.cninfo.com.cn(akshare/stock/stock_new_cninfo.py:38-45;债券侧 akshare/bond/bond_issue_cninfo.py:44-47);
    • 新浪:内嵌 hk_js_decode JS 常量(akshare/stock/cons.py:239)解密加密 K 线文本(akshare/stock/stock_zh_a_sina.py:183-187)。
  • TLS 指纹伪装:curl_cffi impersonate="chrome" 模拟 Chrome JA3 指纹(akshare/economic/macro_china_nbs.py:63)。
  • 东财 push2 接口的 ut token 直接硬编码(stock_hist_em.py:28, :985)。
  • 唯一 token 制例外 pro_api:对接奇货可查 api.qhkch.com 的鉴权 API(tushare 风格),token 持久化到用户目录(akshare/pro/data_pro.py、akshare/utils/token_process.py)。

架构现状与维护机制

  • 无统一抽象层/基类/持久化缓存/全局限速:406 个源文件中 314 个直接调用 requests.get/post("直接"=文件内出现 requests.get/post 字面调用、不经 request_with_retry/make_request_with_retry_* 等共享封装。注意这是文件级口径,与 请求头口径 的"849 处调用点不带 headers"是调用点级口径,两个维度正交——直接调用可以带伪装头,封装调用也可能不带);带指数退避+随机抖动的 request_with_retry 仅 6 个文件使用(定义于 akshare/utils/request.py:15-64);限速仅局部——翻页间 time.sleep(random.uniform(0.5,1.5))(akshare/utils/func.py:49)。复核纠正:并非"完全没有缓存"——functools.lru_cache 在约 30 个文件 50+ 处做局部记忆化(多为品种映射表),但确无统一/持久化缓存层。
  • 异常体系定义了 6 个异常类,但接口层很少抛出(全库仅 13 个文件 30 处 raise)。失败时调用者实际拿到什么:绝大多数直调请求未设超时(全库仅 85 处出现 timeout=,对应 1291 个调用点,原调研修订 grep 复核),失败时 requests 原生异常(ConnectionError/Timeout/JSONDecodeError 等)原样向上冒泡、不会转译为自定义异常——经 AKTools 透传给 TS 端的就是 HTTP 错误码 + 异常文本,无结构化错误契约。
  • 接口增删维护:__init__.py:9-3310 是手写逐版本更新记录 docstring(约 3300 行);docs/changelog.md 有接口更名一览表;发布前 scripts/check_release.py 校验 git tag / _version.py / docstring / changelog 四处一致。
  • tests/ 仅 8 个文件且全部测工具(registry/构建/发布脚本/乐咕 csrf,monkeypatch 不联网),无任何数据接口回归测试(因依赖外网无法稳定 CI)。
  • 本仓库为 depth=1 浅克隆,无法做 git 历史维度的接口增删频率分析(改以版本记录为证据)。

最后更新于

本页目录