
简介压缩包收录了沪深两市三千余只A股股票的基础信息涵盖股票代码、名称、所属市场与板块、行业分类、公司基本信息、核心财务数据、市值、市盈率、市净率、流通股本及分红派息等字段可作为投资者进行个股筛选、行业对比和财务健康度评估的底层数据参考。压缩包内共四十八个文件主要包含XML数据文件、C#工程源码、DLL动态库、配置文件以及可执行程序并附有说明文档与少量图片整体大小仅5.2MB便于快速下载与离线解析。目前已有1722人学习使用适合具有一定数据处理基础的分析师或量化入门者。借助包内数据可复用Python Pandas等工具完成数据清洗、统计分析与可视化进而挖掘估值与成长性指标也可作为开发股票信息查询或分析系统的数据源。需要注意的是基础信息属于静态历史数据实际投资仍需结合宏观经济、政策变化及市场情绪综合判断。1. 这份rar背后是一个被低估的数据工程问题第一次拿到《获取所有A股股票基础信息.rar》这类打包数据时我先入为主地以为解压就能直接用。结果打开一看满屏都是最新价、涨跌幅这类行情字段真正关心的行业、上市日期、流通股本全散在另外几个文件里编码还不对。做量化或财报分析的人都懂最耗精力的不是策略本身而是把全市场五千多家A股的股票代码、简称、行业、上市时间、股本结构这类基础字段一次性洗干净存下来。这份基础信息包要解决的正是这个起点问题——它不是给你选股结论而是给你一张能放心做二次加工的全市场快照。适合谁想跳过逐个查行情页面的重复劳动、需要一份本地全量清单做筛选池或入库开发的从业者。2. 数据从哪来三条路线怎么选2.1 交易所披露、数据接口与终端导出的取舍获取A股基础信息常见的做法是三条路线里选一条走。第一条路直接抓取交易所公开披露的挂牌公司名单和公司概况公告。这条路最权威但公开内容形态太散有PDF、有网页、有不同命名的附件解析成本很高更新节奏也跟不上你要做快照的时点。第二条路对接某数据服务商的批量接口。服务商把公开信息整理成结构化JSON返回一次分页请求能拿几百条记录字段从股票代码到实控人都有是实际工作中最常走的路线。免费的额度和频率做每日全量快照足够付费版本主要多出的是分钟级频率和更多衍生指标而不是基础字段本身。第三条路用行情终端手动导出。在软件里选好板块右键导出CSV或Excel体感最快但导出列数有限也没法做到定时自动拉取适合临时用一次不适合长期维护。路线权威性字段完整度自动化程度初始成本适用场景交易所公开披露最高字段分散需自行整合低需解析多种格式人力成本高做数据源交叉校验数据服务商接口较高字段宽结构化返回高脚本定时拉取注册即可用自动化构建快照行情终端导出一般受终端字段限制低手动操作需安装终端一次性临时提取这三条路线我建议按「接口为主、披露文件为辅」来搭配。主力数据源负责产出全部基础字段交易所披露文件只在怀疑某个字段对不上时用来人工核查。这样既不用把解析PDF的苦活全揽下来又能保证口径出问题时你有地方追根溯源。2.2 为什么基础信息用快照而不是数据库我一般不会为这些基础字段直接搭一套数据库。原因有三点。第一数据变更频率是公告级的一家公司改行业、改股本一年里也没几次没必要用支持毫秒写入的系统去维护一份每天变不了几十条的表。第二rar包本质是一份全量快照放网盘、放NAS、发同事都方便解压即用不依赖内网数据库连接。对于一个后续要拿去写策略或喂给建模流程的文件降低使用门槛是第一位的。第三数据库方案要求你搭建同步任务、处理主键冲突、管理连接池这些工作量对基础信息这种低频数据来说严重超配。但这不意味着永远不碰数据库。更合理的做法是采集端只产出快照文件谁要谁自己导走入库是下游使用者的行为。团队里一旦有人说要把基础信息做成接口服务直接从快照文件反向灌库就行不需要在采集端维护两份存储。这个取舍直接决定了你交付的rar包能不能成为团队内部的通用数据资产。2.3 动手前先定字段别抓到什么存什么接口返回的JSON嵌套很深同一个字段在不同接口里含义可能完全不同抓到什么存什么是标准化翻车的第一来源。动手前我先落一张字段清单表把每个字段的业务含义固定下来之后再写代码就只是按单子取数不会边写边改。字段名业务含义数据类型说明code股票代码str6位唯一主键需补齐前导零name中文简称str不含N、C等临时前缀name_en英文简称str缺失时可空industry所属行业str以数据源分类为准注明版本area注册地省份str缺失时置空list_date上市日期date统一成YYYY-MM-DDtotal_share总股本万股float关注数值单位float_share流通股本万股float不等于总股本减限售股total_mv_yi总市值亿元float收盘口径float_mv_yi流通市值亿元float收盘口径controller实际控制人str缺失率高不插补exchange所属板块str沪市主板/深市主板/科创板等这张表里真正决定基础信息可用性的其实是后三行。实际控制人字段缺失率可能超过四成早期版本里我直接删掉后来做舆情分析需要穿透股权关系时才发现缺了它很麻烦所以现在保留字段但允许空值。总市值和流通市值这类派生指标每个数据源算法都有一点差异包里只存源端原始值不做二次加工否则对账时说不清口径。3. 拉全量清单到打包rar一套可照抄的流程3.1 拉取全量证券清单把全市场股票基础清单拿到手本质是一次分页拉取。下面是这套流程里最核心的一段代码按数据服务商常见的JSON返回格式写成接口地址替换成你自己的数据源即可。import requests import pandas as pd import time def fetch_stock_list(api_url, page, page_size): # 常见的批量数据接口为POST用JSON传分页参数 payload { page: page, pageSize: page_size, querys: {market: all} } resp requests.post(api_url, jsonpayload, timeout30) # 约定code为0表示业务正常部分接口返回HTTP状态码非200 body resp.json() if body.get(code) ! 0: raise RuntimeError(f接口异常{body.get(msg)}) return body[data][list] all_rows [] for page in range(1, 50): items fetch_stock_list(https://api.example.com/market/list, page, 500) if not items: break all_rows.extend(items) time.sleep(0.2) # 每页间隔200ms避免对接口造成访问压力 df_stock pd.DataFrame(all_rows) print(f全量证券清单{len(df_stock)} 条) df_stock.to_csv(stock_list_raw.csv, indexFalse)这段代码的核心逻辑是循环取页直到接口返回空列表循环条件没有写死页数上限未来全市场上市公司数量增加时不会漏数据。time.sleep放在页面级而不是请求级200ms间隔在性能和频率限制之间取一个平衡值。pageSize取500单次响应体控制在1MB左右的常见量级timeout设30秒避免弱网环境下请求挂死。接口返回的业务码不一定叫code有些叫status或者success写代码前先用一条curl确认返回结构这是最省事的习惯。注意分批拉取后先看一眼列表里混进了什么。正常的全量接口往往不止返回A股股票还有可转债、ETF、优先股、REITs等品种这些都是后续标准化的隐患。此时先不急着过滤保留原始表过滤动作放到清洗阶段统一做。3.2 逐个补齐公司和股本资料全量清单里通常只有代码、简称、所属市场这类基础字段行业、上市日期、股本结构还要对每个代码单独调一次信息接口。这块的逻辑就是一个for循环套一个接口调用没有太多花活但有两个细节值得注意。import requests import pandas as pd import time def fetch_stock_detail(code, api_url): # 个股资料接口通常只接受单代码查询 params {code: code} resp requests.get(api_url, paramsparams, timeout10) body resp.json() if body.get(code) ! 0: return None detail body.get(data, {}).get(detail) if detail is None: return None detail[code] code return detail code_list df_stock[code].tolist() detail_rows [] for code in code_list: detail fetch_stock_detail(https://api.example.com/stock/detail, code) if detail is not None: detail_rows.append(detail) time.sleep(0.1) # 单代码接口限频更严格间隔收紧到100ms df_detail pd.DataFrame(detail_rows) df_merged df_stock.merge(df_detail, oncode, howleft, validateone_to_one) df_merged.to_csv(stock_basic_info_tmp.csv, indexFalse)merge时指定validateone_to_one是防止数据源侧返回重复行造成记录数膨胀一旦接口异常出现重复数据pandas会直接抛错而不是悄悄把行数翻倍。这个报错本身就是在提醒你先检查数据源不要带着重复数据继续做。time.sleep放在请求之后而不是之前保证即使某个请求超时抛异常循环退出后也有个缓冲间隔。接口里返回的detail常见字段包括总股本、流通股本、上市日期、注册资本不同数据源的字段命名差异很大在这里统一改好名字后续清洗阶段就不用手忙脚乱。还有一类接口会把注册资本和总股本混在一个字段里返回如果看到数值明显大于总股本了十倍以上基本就是拿注册资本当股本用的脏数据需要在合并前按业务常识预筛选。3.3 加时间戳、分离板块和文件落盘数据合并完成后下一步不是急着打包而是给数据加上生成日期标识并确定落盘目录。文件名里带日期是这份rar包能否长期使用的分水岭不带日期的快照文件三个月后再看就是一坨无法回溯的混沌状态。from datetime import datetime today datetime.now().strftime(%Y%m%d) out_path foutput/stock_basic_info_{today}.csv df_merged.to_csv(out_path, indexFalse, encodingutf-8-sig) # 按板块分组统计数量便于解压后先核对 print(df_merged.groupby(exchange).size())CSV编码统一用utf-8-sig这样Windows上Excel双击打开不会乱码Python读入时也不需要额外处理BOM。按板块分组统计数量是个很实用的小动作解压后肉眼核对第一道关卡就是看每个板块的数量是否在合理区间比如沪市主板一千八九百家、创业板一千三四百家偏差太大说明拉取过程出了问题不用等入库后才发现。打包这一步用rar命令行完成比在脚本里调用压缩库要直接得多cd output rar a stock_basic_info.rar stock_basic_info_20250115.csv习惯上我会在output目录里预留一个老快照目录保留最近三个版本的历史快照而不是用新文件覆盖旧的。这样一旦发现数据源某天返回了异常字段至少能回退到上一份可用的包。rar命令行在服务器上一般需要单独安装安装好之后把路径加进环境变量打包命令就能在任意目录执行。如果你的服务器上没有rar工具先用zip打包过渡也可以但交付给同事时Windows的rar工具链兼容性更好这也是这份数据包选择rar格式的实际原因。4. 字段口径和标准化决定这份基础信息能不能用4.1 全市场代码与板块的对应规则A股股票代码的板块归属有一套相对稳定的规则但每年都有新代码段启用只靠口诀记代码不加校验代码早晚会翻车。代码段所属板块常见特征600/601/603/605开头沪市主板存量老股为主688开头科创板2020年后集中上市000/001/002/003开头深市主板含原中小板合并标的300/301开头创业板注册制后扩容明显8开头、4开头、920开头北交所原新三板精选层平移900、200开头B股用外币交易A股包内不含清洗时不能看到6位数字就放行。B股代码虽然也是6位但它不在A股基础信息包的范围内需要显式剔除可转债代码11开头、ETF代码15开头这些非股票品种也会有行情数据同样要过滤。硬编码板块规则表也许是笨办法但在没有官方统一代码表可下载的现实条件下这张表就是最可靠的标准。遇到代码段规则之外的新代码先查上市板块名单不要一律放行也不要一律丢弃单独建一个unknown清单人工过一遍。4.2 名称、市值和上市日期的清洗名称清洗是看起来简单、实际最容易带脏数据过关的一步。新股上市首日简称前会带N上市次日至第五日会带C这些临时标记不属于公司真实简称必须去掉。全角空格和中文里的特殊空白符也是高频噪声源一个肉眼看不见的\u3000字符就能让两条本该匹配的记录对不上。# 名称清洗去全角空格、去新股标记、去尾部空格 def clean_name(raw): if not isinstance(raw, str): return s raw.replace(\u3000, ).strip() if len(s) 3 and s[0] in (N, C, U): # U为科创板上市后首次实现盈利的标识 s s[1:] return s # 上市日期统一成date类型部分接口返回带时分秒的字符串 df_final[list_date] pd.to_datetime(df_final[list_date]).dt.date # 股票代码严格取6位并补齐前导零 df_final[code] df_final[code].astype(str).str.zfill(6)代码里的zfill处理的是类似1被存成1的情况统一补成000001才能和其他数据源做关联。市值字段的清洗则要在数值和单位两个维度同时下手。有的接口返回的是字符串1.2亿有的返回的是原始元单位的浮点数混着存进同一列就是灾难。我习惯统一换算成亿元并写入列名写成total_mv_yi让下游使用者一眼看到单位不用去猜。上市日期字段还要警惕一类特殊值部分接口把尚未上市的公司上市日期返回成1970-01-01或者1900-01-01作为空值占位。遇到这种默认时间戳直接置空比保留它更安全否则按上市年份做筛选时这些幽灵纪录会混进结果。4.3 缺失值和字段基准日的分级处理全量数据不可能每个字段都完整处理缺失值之前先想清楚每个字段的缺失是系统性的还是偶发的再决定处置策略。系统性缺失是指一个区块的数据整个拿不到比如个别数据源不提供实际控制人字段那么这一列空值再多也不是清洗能解决的只能换源或置空。偶发性缺失是指个别股票记录单独缺某个值大概率是源头录入不完整按下面这张表分级处理。字段典型缺失率处理策略原因实际控制人30%以上置空不插补穿透披露口径复杂插补结果不可信上市日期低通过招股说明书披露日推算拟上市公司数据源更新时间滞后总股本极低查找披露公告核对新股上市后数据源未及时同步行业分类中等按最近一期报告分类更新行业分类每年会做再分类调整不插补实际控制人是血泪教训换来的规矩。早期版本为了追求字段完整率用公司名称相似度去推断实控人结果把两家名称相似但股权毫无关联的公司插补成同一实控人直接污染了下游的关联关系分析。从那以后凡是无法从权威源交叉验证的字段一律置空。字段基准日比缺失值更容易被忽略。接口返回的当前股本总额实质上是公司最新一期披露报告的数据遇到增发、回购、限售解禁时它的更新时点可能比本地文件生成日期早几十天。包里需要加一个data_asof_date字段标记每个观测值在源端对应的基准日期否则后面对比两个时期的快照时会发现股本数据对不上那时候再查就跟大海捞针一样。5. 避坑基础信息抓取中的高频翻车现场5.1 被封限流前两千条正常后两千条全部403现象脚本前两天跑得好好的第三天开始跑到一半接口返回403 Forbidden重试几次还是同样结果日志里能看到连续出现status code异常。原因请求频率固定且没有随机抖动代码里写死了sleep(0.2)服务商的风控系统识别出这是机器行为把该IP或账号的访问权限临时封禁。解决把固定间隔改成随机区间同时加上指数退避重试把单次请求的UA和Cookie保持一致模拟出正常浏览器的访问特征。import random import time def sleep_random(): # 随机控制在100ms到450ms之间避免固定节奏被识别 time.sleep(random.uniform(0.1, 0.45)) def request_with_retry(url, params, retries3): for attempt in range(retries): try: resp requests.get(url, paramsparams, timeout10) return resp except requests.exceptions.RequestException: if attempt retries - 1: raise # 重试等待时间按指数增长2s、4s、8s time.sleep(2 ** attempt)不要只在客户端加延时服务端的风控还有一层是按账号维度统计每日调用总量。每天拉一次全量已经足够别为了验证代码反复重跑第二次跑就把当天的配额消耗掉一半。被封后最好的处理是停掉脚本等24小时自然解封而不是换个代理继续打后者容易把账号送上黑名单。5.2 代码段判断失误包里混进去一堆非股票品种现象拉完清单一看总记录数比预期多了两千多条解压后一查发现可转债、ETF、REITs全混在里面。原因全量接口的market参数传了all服务商返回的是全证券品种清单不是A股股票清单。解决用代码段白名单过滤并确认每个代码段的板块属性符合预期。def is_a_stock(code: str) - bool: # 只保留A股股票代码段B股、可转债、基金不在包内 valid_prefix ( (600, 601, 603, 605), (688,), (000, 001, 002, 003, 300, 301), (8, 920), ) return any(code.startswith(p) for p in valid_prefix)这里用startswith匹配时注意8开头的北交所代码实际是8开头的三位段比如82、83、87、88写前缀时至少要保留两位否则会把8开头的其他品种误收进来。过滤完还有一道复核就是按第3章里按exchange分组的数量核对数量对不上就知道过滤逻辑写错了。5.3 股本数据日期错位昨天拉的记录和今天对不上现象同一家公司的总股本字段昨天快照里是5.2亿股今天快照变成5.6亿股但当天并没有除权除息或增发公告。原因数据源返回的股本取自最近一期财报或公告而不是拉取当日的最新市值口径两天的快照实际对应的是公司两个不同里程碑的数据状态。解决在字段表里单独维护股本基准日并在文件名之外再给每条记录打上update_date标记分析时优先按update_date对齐而不是按文件生成日对齐。按文件生成日对齐数据是新手最容易踩的隐性坑。你以为两份文件都是当日快照实际上其中一份的字段基准日是三个月前的财报发布日期但基础信息场景下这种滞后通常可以接受问题只在于你把它当成了当日数据用。5.4 跨平台解压乱码Windows打包Linux乱码现象rar包在Windows下解压一切正常传到Linux服务器用unar解压后CSV文件名变成乱码文件里的中文列名和简称全是乱码。原因Windows下的rar工具默认用GBK编码保存文件名而Linux默认按UTF-8解码两边编码表对不上。解决CSV内容统一用utf-8-sig编码写入打包时文件名全部使用英文不要出现最终版、股票数据这类中文文件名。文件名用英文、内容用UTF-8-SIG这两个习惯配合在一起之后跨平台问题基本消失。如果你收到的rar包已经乱码先试unar -e GBK一般能救回来但这不是长久之计规范的产出流程应该在源头就定好编码方案。5.5 退市股消失数据源悄悄把退市股剔除了现象拉取全量清单时总数看起来正常但和上个月的快照对比少了十几家公司一查都是最近进入退市整理期的股票。原因部分数据源的免费接口默认只返回已上市且在正常交易状态的股票退市整理期的股票被静默过滤。解决拉取时显式声明需要包含退市状态并给退市股单独标注delist_date字段。如果你做的是历史回测或财务风险分析退市股本身就是一类非常重要的样本把它们直接丢掉等于丢弃了A股市场最极端的一批尾部数据。拉取时多带一个参数就能解决真正要注意的是别在不知道的情况下被数据源默认行为带偏。6. 进阶用校验和增量更新把这包数据用稳拿到一份基础信息包先别急着写策略花十分钟跑一遍完整性校验能省下后面几天的对账时间。我习惯上按五个维度做检查数量核对、代码段分布、唯一性约束、空值率监控、时间戳比对。数量核对是最直观的打开文件看一眼总行数当前A股总数在五千家上下出现四千或六千都值得警惕。代码段分布就是把上节那张板块规则表跑一遍分组统计科创板数量大于沪市主板基本可以断定过滤逻辑出了问题。唯一性约束是校验股票代码有没有重复一行代码就能跑完# 唯一性校验重复代码会直接破坏下游关联 assert df[code].is_unique, 发现重复股票代码 # 空值率监控超过阈值直接预警不用等到入库后才发现 null_rate df.isnull().mean().sort_values(ascendingFalse) print(null_rate[null_rate 0.3])增量更新是这份数据包能否持续使用的关键设计。每周拉一次新快照和上一份做一次全字段diff新增记录大概率是新上市公司消失的记录大概率是退市股名称或行业变化的记录需要单独看是否正常。比对逻辑不复杂用merge就能实现重点是把diff结果输出成一份变更日志随rar包一起交付下游使用者一眼就能看出本周期内市场结构发生了什么变化。数据源的接口文档会更新代码段规则会调整每年年底行业分类还会重新洗牌单凭经验记规则总有覆盖不到的死角。我现在的习惯是每月手动抽查一次数据包随机挑十家公司去公开披露文件里人工核对两三个关键字段这是数据质量保障的最后一道防线。最后说一个让我自己印象深刻的教训。有一版数据包我只看数量没看字段口径把总股本和流通股本口径当成一回事拿去和另一套数据源对账整整折腾了两天最后发现两边算法本身就不一致并不是数据错误。从那以后我把字段口径说明文件放进包内和最新数据文件放在一起每次交付都提醒自己先讲口径再讲数据。这个习惯希望能帮到你让这份基础信息包从一开始就走在正确的路上。本文还有配套的精品资源点击获取