AKShare 实现与跨语言接入调查
AKShare 请求、代理与响应解析
按历史调用路径区分客户端、headers、代理、重试及解析机制。
调查基线为原材料记载的 2026-10-04、AKShare v1.19.1、浅克隆短提交号 fac1e50。本轮读取了归档报告;未取得原运行环境或重跑接口、全库计数及 npm 检索。下文统计和“实测”均属于原调查记录,不能自动代表当前版本或服务可用性。短提交链接本轮未成功取得,数字保留为历史证据并披露复算边界。
三、网络请求机制(HTTP 客户端、协议、请求头伪装与反爬)
直接回答:原调查记录的数据访问通道为 HTTP/HTTPS,未在所查快照找到 WebSocket 调用;原调查记录主要客户端为 Python requests,所查数据请求路径为同步调用;请求头做了大量浏览器伪装但只覆盖约 1/3 调用点,65.8% 的请求未显式传入 headers;反爬对抗不止改 header——还用 V8 引擎执行站点 JS 生成加密 cookie/请求头,用 curl_cffi 伪装 Chrome TLS 指纹。
HTTP 客户端与协议
- requests 绝对主力:323/406 个文件 import requests;括号配平解析全库共 1291 处
requests.get/post/put/head调用。 - curl_cffi 次之:5 个文件(清单见附录 A),专用于 TLS 指纹伪装。
- urllib/urllib3 仅辅助:urlencode、http.client 直连(1 处)、disable_warnings、自定义 TLS 适配器(macro_china.py、fund_amac.py)。
- 无 aiohttp、httpx、scrapy、selenium、playwright、裸 socket——全部 0 文件;全库同步阻塞式请求,无异步(用户提问中常猜的 aiohttp 在v1.19.1不存在)。
- 协议全部为 HTTP/HTTPS,无 WebSocket/FTP(websocket 仅存于
__init__.py:327/:403/:829的历史 changelog 注释,当前代码零调用)。 - 明文 http:// 大量存在:507 处 http:// vs 2626 处 https://,约占 16.2%,涉及 79 个文件。Top:data.10jqka.com.cn(51)、郑商所(41)、广期所(34)、巨潮 webapi.cninfo.com.cn(31)、大商所(25)、新浪行情(25)。典型如 A 股实时行情主接口为明文 http(
akshare/stock/cons.py:40)、郑商所明文 .xls 下载(akshare/futures/futures_to_spot.py:164-179)。
请求头伪装(全库实测历史统计)
- User-Agent:245 处 / 102 个文件显式设置。正则解析全部 291 个 UA 值 = 桌面 Chrome 287 + iPhone 2 + 旧 MSIE 2——全部是模拟浏览器的 UA;Chrome 主版本从 56 到 144 混用(
futures/cons.py:284为 Chrome/56、futures_settle.py:30为 Chrome/144、utils/cons.py:11为 Chrome/114)。两个数字口径不同、不矛盾:245 是对字典键"User-Agent"(精确大小写、单行匹配)的 grep 计数;291 是按大小写不敏感、含跨行隐式字符串拼接解析出的 UA 值个数——差值来自小写user-agent键写法与多行拼接(原调研修订复跑:大小写不敏感键计数 298 = 精确大写 245 + 小写 53,与 291 同量级,零头为个别重复键/非请求头用途)。写法以"每个函数内部字典写死"为主流;公共封装仅akshare/utils/cons.py:9-12一个 Chrome/114 常量,全库仅 26 处引用,未形成统一封装层。 - 其他请求头:Referer 135 处/74 文件(新浪
hq.sinajs.cn必须带 Referer 否则拒绝)、Host 96、Origin 66、Cookie 51;巨潮接口还原了完整 14 个浏览器头(Accept/Accept-Language/Cache-Control/X-Requested-With 等,stock_new_cninfo.py:43-58)。 - 未显式指定 headers 的请求是多数:1291 处 requests 调用中带
headers=的仅 442 处(34.2%),849 处(65.8%)完全不带 headers——发送 python-requests 默认 UA、未显式指定浏览器头。典型如东方财富 push2 系列(stock_hsgt_em.py23 处裸、stock_gdfx_em.py22 处全裸)和新浪部分接口(stock_zh_a_sina.py:62)。解读:多数数据源(尤其东财)在原调查覆盖的调用中未显式设置 UA;服务端是否校验及放行条件未穷尽验证,akshare 只在"被拦的站点"才做伪装。
反爬对抗手段(按强度排序)
- JS 引擎执行站点加密代码(核心手段):py_mini_racer 40 个文件;三条完整链路见 1.3。新浪期货另用 JS 生成
rn随机参数防缓存(futures_zh_sina.py:222-225);东财筹码分布也在本地 V8 里跑 JS 计算(stock_cyq_em.py:28-80)。 - TLS 指纹伪装:curl_cffi
impersonate="chrome"(macro_china_nbs.py:63、macro_china.py:359)与impersonate="chrome110"(news_baidu.py:32, :59, :139三处)——连 JA3 指纹一起模拟成真实 Chrome,用于百度/国家统计局/财联社等有指纹检测的站点。 - 重试:
make_request_with_retry_json最多 3 次+指数退避+429 处理(akshare/request.py:10-62);request_with_retry指数退避+随机抖动(akshare/utils/request.py:15-64);期货侧朴素重试 20 次、间隔 5 秒(akshare/futures/requests_fun.py:21-49)。 - 限速(仅局部):10 个文件使用 time.sleep;翻页随机停 0.5–1.5 秒(
utils/func.py:49、futures_hq_sina.py:298)。 - 代理(可选,且"全局"仅是配置全局、注入点不全局):
set_proxies/ProxyContext把代理存入全局单例 config(akshare/utils/context.py:1-31),但全库读取 config.proxies 的只有akshare/request.py:25, :80两处(make_request_with_retry_*系列封装内部),而使用该封装的源文件仅 3 个(qdii_jsl.py、stock_value_em.py、stock_info.py,原调研修订 grep 复核)。结论:未读取该配置的直接requests调用不会因这个配置入口自动获得代理;原材料没有逐一追踪每个调用点的实际环境代理行为——被风控时不能靠 set_proxies 全局换 IP,只能用系统级代理(如 HTTP_PROXY 环境变量,requests 默认识别)或自行改代码传 proxies。 - 降级 SSL:自定义 TLSAdapter 强制 TLSv1.2 +
DEFAULT@SECLEVEL=1兼容旧服务器(macro_china.py:28-42);11 个文件verify=False(郑商所/大商所等交易所旧站,其中 6 个同时 disable_warnings)。 - 没有的手段:验证码 OCR/打码、cookie 池轮换、IP 池、账号体系——全部 0 命中(雪球等仅提示用户自带 token,非内置账号)。
响应解析方式
.json() 891 处 + json.loads 48 处是主力;demjson(自带 250KB 实现)解析非严格 JS 对象字面量 89 处/34 文件(新浪返回 js 变量赋值文本);jsonp 手工剥壳(字符串切片 / strip jQuery 回调名);pd.read_html 156 处;BeautifulSoup+lxml 52 个文件;read_excel 35 处(交易所 .xls/xlsx 报表);PDF 只构造链接字段返回、不做内容解析;py_mini_racer 也用于执行站点 JS 还原数据(新浪 K 线解密)。
最后更新于