akshare实战:一键获取所有A股基础信息并落库
2026/9/9 15:26:56 网站建设 项目流程

简介:这份压缩包为A股投资者与分析人员提供了一份沪深两市三千余只股票基础信息的数据库及配套代码,涵盖股票代码、名称、所属市场、财务指标、市值、市盈率、市净率、流通股本、分红记录等核心字段,便于开展批量筛选与统计分析。资源共48个文件、5.2MB,以XML数据文件、C#源码、DLL库、配置文件及工程说明文档为主,可借助源码快速解析和扩展数据字段,适合有Python或C#基础、希望本地化处理股票数据的初级到中级学习者。已有1712人学习下载。通过解析其中数据与脚本,可快速搭建本地A股信息查询库,理解交易所基础数据结构;也能将数据导出为DataFrame,结合Pandas进行清洗、可视化与简单选股分析,为投资研究提供数据支撑。需要留意,基础信息反映的是历史静态指标,实际决策还需结合政策、行业趋势及风险控制。

1. 项目背景与整体思路拆解

刚拿到“获取所有A股股票基础信息.rar”这个东西的时候,我第一反应是:这大概率不是一份简单的下载好的数据表,而是把“怎么拿数据”这套流程连同结果一起打包了。在很多量化社群、数据交流群里,经常有人花大把时间在数据源上纠结——用哪个库、要不要token、字段全不全、更新频率够不够。其实这类需求特别典型:你要的不只是某一只股票的K线,而是全市场5000多只股票的代码、名称、行业、市值、市盈率这批“户口本”一样的基础信息。有了这个底子,后面的行情抓取、因子计算、策略回测才有依附。

我拿到这个项目后,先做的事情是拆解需求:要覆盖全部A股(沪深主板、创业板、科创板、北交所都算上),字段要包含代码、简称、上市日期、所处行业、总股本、流通股本、总市值、流通市值、市盈率、市净率这些核心项;输出形态要方便后续程序读取,无论是写进SQLite还是转成CSV都能直接复用。如果你自己也收藏过类似的压缩包,会发现里面通常就是一个Python脚本加一个数据文件(或者一份说明文档)。但问题在于,不同时间下载的包,脚本依赖的接口版本很可能已经变了,直接跑会报错。所以我这篇博文打算把这一套从头到尾讲透,你能照着抄,也能理解里面每一步在干什么。

这套方案选型时我走过一些弯路,最后定下来的是:用akshare作为主数据源,辅以pandas做清洗,落地到SQLite数据库,同时导出CSV备份。选akshare而不是别的库,原因后面我会细讲,但简单说三点:免费、无需注册token、覆盖面广。对于抱着“我就想拿一份干净的全量列表”这个目标的人来说,没有比它更顺手的了。适合来看这篇内容的人,我猜大概是这几类:刚开始接触量化但被数据预处理劝退的新手;已经在用量化框架但觉得自带的股票池更新太慢、想自己维护一份底层数据的;以及做财务分析、行业研究时需要按行业或板块批量筛选个股的朋友。无论你属于哪一类,这篇文章都能帮你把“获取全市场基础信息”这条路趟平。

2. 数据源选型对比与关键字段解析

2.1 为什么开源库首选akshare

市面上的免费A股数据接口我基本都试过一遍,各自脾气摸得比较清楚。tushare是老牌选手,但Pro版的多个核心接口有积分门槛,新注册用户拿不到完整的stock_basic数据,积分攒起来很磨人;baostock数据稳定但是字段相对偏K线,基础信息类的覆盖不够全;efinanceadata这些后来者也都在进步,但文档完善度和社区活跃度参差不齐。综合下来,akshare的“零门槛”属性是最适合新手和需要快速拿结果的场景的。

这里有个选择逻辑可以分享:选数据源不是看谁功能最多,而是看你在“获取基础信息”这一步上愿意投入多少摩擦成本。如果你愿意注册、攒积分、申请权限,那tushare的质量确实不错;但如果你今天拿到这个项目,希望一个小时内就把全市场股票清单握在手里,那akshare就是最优解。而且akshare的数据源是公开财经网站,接口挂了通常过几个小时就会修,社区反馈也及时,长期维护成本其实比很多人想象中低。

2.2 一份完整的A股基础信息表应该包含哪些字段

基础信息不等于“越多越好”,字段选多了反而冗余,选少了后面用起来又得回头补。我实际操作下来,下面这张字段清单是性价比最高的一组,覆盖了从代码识别到基本面快照的绝大多数场景:

字段名含义用途示例
code股票代码去重、关联行情
name股票简称可视化、筛选
industry所属行业行业分组统计
list_date上市日期次新股筛选
total_share总股本(股)计算市值
float_share流通股本(股)区分流通盘大小
total_mv总市值(元)规模因子过滤
float_mv流通市值(元)流动性判断
pe市盈率(动态)估值初筛
pb市净率估值辅助
market所属板块区分沪深北

你可能注意到我没有把“52周最高/最低”或者“均价”这类行情类字段放进来。原因很简单:基础信息表追求的是低频稳定,行情数据本来就应该走日频增量更新的通道,混在一起会让整张表的更新逻辑变得混乱。这是我踩过坑之后得出的教训——一开始图省事把一堆行情字段塞进基础表,结果每天跑批时接口报错就得全表重建,得不偿失。

2.3 板块拆分与代码规律的隐性价值

A股代码本身是有规律可循的,这个规律在你清洗和验证数据时特别有用。沪市主板以600、601、603、605开头,深市主板是000、001、002(中小板并入后),创业板是300、301,科创板是688、689,北交所是8开头和4开头(例如83、87、43等)。拿到全量数据后,我会先用代码规则做一轮交叉验证,看有没有明显异常的代码混进来。

这块还有个容易忽略的点:北交所股票在很多第三方接口里默认不包含,如果你只用常规的stock_zh_a_spot_em接口,可能拿不全北交所的票。要做全市场覆盖,就得额外拉取北交所清单再合并。我后面给的完整代码里就把这一步做进去了,这样你拿到手的才是真正意义上的“所有A股”。

3. 完整实操流程与代码实现

3.1 环境准备与依赖安装

项目操作环境是Python 3.9以上(我本机用的是3.10,实测没问题)。安装依赖用pip一把梭就行,核心库就三个:

pip install akshare pandas sqlalchemy openpyxl

sqlalchemy是拿来连SQLite的,openpyxl是后面导出Excel用的(如果不需要Excel可以跳过)。akshare的依赖比较多,首次安装可能需要一两分钟,耐心等就好。

如果你之前装过akshare,建议先升级到最新版,因为这类爬虫类数据接口改动比较频繁,旧版本可能因为网页结构调整而报错:

pip install akshare --upgrade

3.2 获取全市场实时快照(含主力接口)

核心接口是stock_zh_a_spot_em(),它返回的是东方财富全A股的实时快照,包含但不限于最新价、涨跌幅、总市值、市盈率这些字段。这个接口一次调用就能拿到5000多只股票的数据,非常符合“全量获取”的需求。

直接贴我的核心代码(这是经过多次调整后的稳定版):

import akshare as ak import pandas as pd def fetch_all_a_spot(): df = ak.stock_zh_a_spot_em() # 字段裁剪:只保留基础信息相关列 keep_cols = { "代码": "code", "名称": "name", "最新价": "price", "总市值": "total_mv", "流通市值": "float_mv", "市盈率-动态": "pe", "市净率": "pb", } df = df.rename(columns=keep_cols) df = df[list(keep_cols.values())].copy() # 去除退市整理期等无用记录 df = df[~df["code"].astype(str).str.startswith("退")] return df if __name__ == "__main__": data = fetch_all_a_spot() print(data.shape) print(data.head())

这一步跑完后,你手上就已经有了全市场股票的价格和市值快照。但我必须提醒一点:这个接口拿不到“上市日期”和“所属行业”。如果你只需要市值、市盈率层面的基础信息,到这里已经够了;但如果需要更完整的“户口本”,继续往下看,我补了一个增强方案。

3.3 补充行业与上市日期字段的增强方案

行业和上市日期这两个字段对于做行业轮动、次新股分析的朋友来说是刚需。之前图省事想靠一个接口全搞定,后来发现最稳的做法是分步骤拼装:

def fetch_industry_and_listdate(): # 获取全部A股个股信息(逐个请求,较慢,但字段全) code_list = ak.stock_info_a_code_name() code_list.columns = ["code", "name"] # 使用股票列表去一个一个取个股基本面指标 info_list = [] for code in code_list["code"][:5]: # 先测试5个,确认没问题再全量跑 try: info = ak.stock_individual_info_em(symbol=code) info_dict = dict(zip(info["item"], info["value"])) info_list.append({ "code": code, "industry": info_dict.get("行业", ""), "list_date": str(info_dict.get("上市时间", ""))[:10], }) except Exception as e: print(f"{code} 获取失败: {e}") continue return pd.DataFrame(info_list)

这里有个不得不说的性能问题:stock_individual_info_em是一次请求一只股票,全市场5000多只要跑很久,而且很容易触发对方的风控。所以我实际使用时的策略是:这个增强脚本只在首次建库或者每月更新一次时跑,日常的日频更新只用3.2里那个快照接口。行业字段如果对实时性要求不高,完全不需要天天刷。

如果你的网络环境或者时间不允许全量逐只请求,还有一个折中办法:用ak.stock_board_industry_name_em()拿到行业列表,再用ak.stock_board_industry_cons_em(symbol=行业名)倒推出每只股票属于哪个行业。这种“以板块反查个股”的方式请求次数少很多,但是代码稍复杂一点,适合对代码结构有信心的朋友。

3.4 数据落地:SQLite存储与CSV备份

数据拿到手只是第一步,怎么存决定了你后续调用的便利性。我个人的习惯是SQLite为主、CSV为辅。SQLite的好处是查询方便,可以直接用SQL做条件过滤;CSV的好处是方便分享和备份,放进你的.rar包里也不占多大空间。

完整的存储代码如下:

from sqlalchemy import create_engine engine = create_engine("sqlite:///a_stock_basic.db") def save_to_db(df, table_name="stock_basic"): df.to_sql(table_name, engine, if_exists="replace", index=False) print(f"已写入 {table_name} 表,共 {len(df)} 条记录") # 执行 spot_df = fetch_all_a_spot() spot_df.to_csv("a_spot_snapshot.csv", index=False, encoding="utf-8-sig") save_to_db(spot_df, "stock_spot_snapshot")

关于编码这里多说一句:导出的CSV如果直接用utf-8,在Windows上用Excel打开会乱码。必须用utf-8-sig加BOM头,或者直接导出成Excel格式,才能避免“打开全是乱码”的尴尬。这是很多人第一次实操最容易踩的坑,别问我怎么知道的。

4. 常见问题与实战排坑记录

4.1 接口返回空数据或报错

akshare偶尔会因为目标网站改版导致解析失败,常见报错是KeyError或者AttributeError。遇到这种情况最直接的办法就是升级akshare到最新版,然后再重新跑。如果升级后还报错,去GitHub的Issues区看一眼,通常热点问题当天就会有解决方案。

另外一个技巧是设置重试机制。接口请求偶尔会因为网络波动返回空DataFrame,盲目重跑容易浪费时间。我习惯在调用外面套一个简单的重试逻辑:

import time def call_with_retry(func, retries=3, delay=2): for i in range(retries): try: df = func() if df is not None and not df.empty: return df except Exception as e: print(f"第{i+1}次请求失败: {e}") time.sleep(delay) raise RuntimeError("多次重试后仍失败,请检查网络或接口版本")

提示:不要用太短的delay,比如0.1秒这种,很容易触发对方网站的反爬限制。2秒起步比较稳妥。

4.2 全市场股票数量对不上

有的朋友跑完后发现股票数量只有4000多只,而不是想象中5000多只。大概率是北交所的票没算进去。stock_zh_a_spot_em()这个接口在多数时间会包含北交所,但如果版本差异或者数据源调整,可能导致北交所缺失。

解决办法是先单独拉北交所的列表:

def fetch_bse_list(): df = ak.stock_info_bj_name_code() df.columns = ["code", "name"] return df

然后跟主表做一次外连接合并,补齐缺失的北交所代码。合并的时候注意代码格式统一(北交所代码有6位,比如830799,不要在前面补零)。

还有一部分数量的差异来自于“停牌股”和“退市整理股”。不同接口对这类股票的处理策略不一样,有些会直接过滤掉。如果你的使用场景需要包含停牌股票(比如做全市场选股),建议把这个因素考虑进去,最好做一次与历史代码表的对比。

4.3 内存不足或程序卡死

如果你不是在服务器上跑,而是在一台只有8G内存的笔记本上运行,全量拉取时可能会卡顿。主要原因是akshare返回的DataFrame包含了大量冗余列,在全市场5000多只、几十个字段的规模下,内存占用会被放大。

优化手段有两个:一是尽早裁剪字段,只保留自己需要的列;二是用迭代式处理,不要把全量数据一次性塞进内存。还有一个小技巧:拿到DataFrame后立刻del df或者做一次垃圾回收gc.collect(),为后续操作腾出空间。

4.4 每日定时的自动化更新方案

拿到一次数据只是开始,真正有实战价值的数据源必须保持更新。我自己的方案是用系统自带的定时任务,每天收盘后跑一次快照脚本:

# update_daily.py import schedule import time def job(): df = fetch_all_a_spot() save_to_db(df, "stock_spot_snapshot") print(f"更新完成: {pd.Timestamp.now()}") schedule.every().day.at("15:30").do(job) while True: schedule.run_pending() time.sleep(60)

Windows下可以配合“任务计划程序”来实现开机启动和自动运行,Linux直接用crontab一行搞定。这样你手里那份基础信息就一直是最新状态,不需要每次手动跑脚本。

注意:定时任务首次运行前,一定要先手动跑通一次,确认环境和网络都没问题。不然定时任务报错,排查起来比手动跑一遍还费事。

5. 项目的扩展方向与进阶玩法

有了干净的全市场基础信息表,后续能做的事就多了。我挑三个自己实际做过的方向说说思路,想深入的朋友可以顺着这些脉络继续挖。

第一,技术指标叠加。把基础信息表作为主表,关联日线行情数据,可以做出“全市场低估值+高股息”的初筛策略。比如用stock_zh_a_hist接口批量拉取候选池里的历史日线,再计算均线偏离度、RSI等因子,把基础信息和行情因子组合成一个宽表,做出来的选股池在实盘模拟中表现很稳定。这个方向适合刚入门的量化爱好者。

第二,行业轮动分析。利用基础表中的行业字段,结合每日行情快照中的涨跌幅,可以统计每日每个行业的整体涨跌幅、资金流向。我最开始就是靠这个数据观察行业间的轮动节奏,后来用简单的动量因子做回测,效果中规中矩,但对理解市场结构帮助很大。如果你不想写代码,把这份数据导出Excel后用透视表也能分析。

第三,事件驱动型研究。比如统计不同上市日期区间的股票数量变化,分析注册制改革前后的扩容节奏;或者按板块拆分,对比科技类板块和其他板块的估值水平差异。这类研究不需要复杂的模型,但前提是你有一份字段丰富、覆盖完整的基础表,这篇项目正好能满足。

我个人实际操作中的感受是:数据基础打牢了,后面任何策略想法都能快速用数据去验证,而不会被“先找数据”这件事卡住。最后再分享一个小技巧:如果你打算长期维护这份基础信息表,建议每次更新时不要直接覆盖旧表,而是用if_exists="append"加上时间戳列,把历史快照也保存下来。这样以后想做“历史上某一天的股票状态还原”时,直接查库就行,不用重新去数据源拉历史数据(很多基础信息类接口根本不提供历史版本)。这个习惯帮我省了不止一次从头跑数据的功夫。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询