当前位置: 首页 > news >正文

别再手动抄代码了!用Python+efinance批量抓取A股全量数据(附完整脚本与MongoDB存储方案)

Python量化实战:用efinance构建A股全量数据库的工程化实践

在量化投资领域,数据是策略开发的基石。传统的手动下载和整理股票数据不仅效率低下,还容易出错。我曾见过一位量化研究员因为手动复制粘贴错了一行数据,导致回测结果完全失真——这个教训价值百万。本文将分享如何用Python的efinance库构建自动化数据管道,从零开始搭建本地A股数据库。

1. 环境准备与工具链搭建

1.1 核心工具选型

构建稳定可靠的数据采集系统需要精心挑选工具链。经过多次实践验证,我确定了以下技术组合:

  • efinance:非官方但稳定的金融数据接口,相比Tushare更轻量
  • MongoDB:文档型数据库,天然适合存储非结构化的行情数据
  • Loguru:比标准logging更友好的日志工具
  • Tqdm:进度条可视化,让长时间运行的任务不再"盲跑"

安装这些工具只需一行命令:

pip install efinance loguru tqdm pymongo

提示:建议使用Python 3.8+环境,某些库在新版本Python中可能有兼容性问题

1.2 工程化目录结构

好的项目结构能大幅降低维护成本。这是我常用的目录布局:

stock_data_pipeline/ ├── config/ # 配置文件 ├── logs/ # 日志文件 ├── src/ # 源代码 │ ├── crawler.py # 数据采集主程序 │ └── utils.py # 工具函数 └── requirements.txt # 依赖清单

2. 高效数据采集策略

2.1 股票代码批量获取

efinance的get_realtime_quotes()能获取全部活跃股票列表,但实际使用中我发现几个优化点:

import efinance as ef def fetch_stock_codes(): """获取全量股票代码并去重""" df = ef.stock.get_realtime_quotes() # 过滤掉B股和新三板 codes = df[ (df['市场类型'] == '沪深A股') & (~df['股票代码'].str.startswith('8')) ]['股票代码'].unique() return codes.tolist()

2.2 历史行情数据下载

直接循环请求容易被封IP,需要加入以下防护措施:

  • 随机延时(2-5秒)
  • 自动重试机制
  • 异常捕获与日志记录
from loguru import logger from time import sleep import random def safe_fetch_history(stock_code, retry=3): """带防护措施的历史数据下载""" for i in range(retry): try: df = ef.stock.get_quote_history(stock_code) return df except Exception as e: logger.error(f"{stock_code} 第{i+1}次失败: {str(e)}") sleep(random.uniform(2, 5)) return None

3. MongoDB存储优化方案

3.1 批量写入提升性能

逐条插入是MongoDB的性能杀手。这是我优化后的批量写入方案:

from pymongo import UpdateOne def bulk_upsert(collection, data_list): """批量更新插入操作""" operations = [ UpdateOne( {'_id': item['_id']}, {'$set': item}, upsert=True ) for item in data_list ] if operations: collection.bulk_write(operations)

3.2 数据模型设计

合理的文档结构能提升查询效率。我的设计原则是:

  1. 以股票代码作为_id主键
  2. 将K线数据按日期嵌套存储
  3. 添加元数据方便检索

示例文档结构:

{ "_id": "600519", "name": "贵州茅台", "industry": "酿酒", "daily_data": { "2023-01-04": { "open": 1800.0, "close": 1820.5, "volume": 32500 } } }

4. 实战:构建完整数据管道

4.1 主程序架构

将各个模块组合成完整工作流:

from tqdm import tqdm def run_pipeline(): codes = fetch_stock_codes() client = pymongo.MongoClient() db = client['stock_db'] with tqdm(codes) as pbar: for code in pbar: pbar.set_description(f"处理 {code}") data = safe_fetch_history(code) if data is not None: processed = process_data(code, data) bulk_upsert(db.daily, [processed]) sleep(random.uniform(1, 3))

4.2 异常处理与监控

添加以下保障措施确保长时间运行稳定:

  1. 断点续传:记录已处理的股票代码
  2. 内存监控:定期检查内存使用情况
  3. 心跳检测:每100只股票输出一次状态报告
import psutil def memory_guard(threshold=0.9): """内存保护机制""" if psutil.virtual_memory().percent > threshold: logger.warning("内存使用过高,暂停处理") sleep(60)

5. 进阶优化技巧

5.1 分布式采集方案

当需要采集全市场多年数据时,单机可能需数天时间。可以考虑:

  1. 按股票代码分段,多进程处理
  2. 使用Redis作为任务队列
  3. 云函数动态扩展采集节点
from multiprocessing import Pool def distributed_crawl(): codes = fetch_stock_codes() with Pool(processes=4) as pool: pool.map(process_stock, codes)

5.2 数据质量检查

采集完成后应进行完整性验证:

  1. 检查每只股票的数据量是否合理
  2. 验证关键字段无空值
  3. 对比最新数据与公开源是否一致
def validate_data(db): """数据质量检查""" problematic = [] for code in db.daily.distinct("_id"): count = db.daily.count_documents({"_id": code}) if count < 100: # 假设正常股票至少有100个交易日数据 problematic.append(code) return problematic

在实际项目中,这套系统帮我节省了数百小时的手工操作时间。最关键的体会是:不要追求一次性完美,先构建最小可行方案,再逐步迭代优化。比如最初可以只采集收盘价,等管道稳定后再扩展其他字段。

http://www.jsqmd.com/news/674706/

相关文章:

  • [具身智能-398]:AS5600磁编码器功能和管脚详解
  • 别再死记硬背了!用MySQL的`rand(0)`和`group by`亲手复现一次SQL报错注入
  • 2026年靠谱的层叠式过滤器/不锈钢层叠式过滤器厂家综合对比分析 - 品牌宣传支持者
  • 2026年全自动连线玻璃激光打孔设备厂商排行榜:专业公司推荐榜单 - 品牌策略师
  • 终极对比:Kitura vs Express 如何选择最适合你的Web框架?
  • 新手入门:AI超清画质增强镜像从部署到使用完整指南
  • 告别裸奔通信:手把手教你用Petalinux 2020.1为Zynq7000配置OpenAMP异构框架
  • Hive SQL进阶:用posexplode搞定‘多列同时炸裂’这个老大难问题(附完整避坑指南)
  • 如何快速上手Riak:10分钟构建你的第一个分布式应用
  • [具身智能-399]:AS5600 OUT信号以及PGO详解
  • Agent 出现幻觉怎么解决?RAG 检索准确率低怎么优化?Agent 多轮对话状态怎么管理?
  • C语言:指向数组的指针和指向数组首元素的指针
  • 程序员追不上机器人干脆开电瓶车跟;小米徐洁云辟谣“雷军被人堵在车里维权”;DeepSeek被曝融资20亿 | 极客头条
  • geogram实战案例:基于几何算法的10个工业应用场景解析
  • 兔抗53BP1抗体亲和纯化,高效富集目标蛋白,低丰度样品稳定输出
  • 终极指南:OCI内容描述符如何保障容器镜像的安全寻址与验证
  • 【万字文档+PPT+源码】基于springboot+vue的学生操行评分系统-计算机专业项目设计分享
  • 如何利用Nuclide键盘宏提升开发效率:完整指南与API解析
  • 如何从零部署Colanode:开源协作平台的完整生产环境搭建指南
  • 终极指南:如何用stacktrace.js构建企业级前端错误监控系统
  • Gemma-3多模态模型应用场景:博物馆文物图片智能导览系统构建
  • Space Cloud架构深度解析:GraphQL API与数据库查询优化终极指南
  • 终极指南:如何使用Eloquent-Sluggable在Laravel中快速创建SEO友好的URL
  • AutoRaise未来展望:macOS窗口管理工具的发展趋势与社区贡献指南
  • ytfzf高级技巧:10个提升终端视频体验的实用方法
  • **发散创新:基于角色权限模型的代码保护机制设计与实现**在现代软件开发中,**模型保护**已成为系统安全的
  • 深圳同袍存储解说DDR内存及SSD价格现状
  • 剪映专业版教程:制作动感照片效果
  • 终极LeetCode2测试驱动开发指南:5个步骤编写可靠算法测试用例
  • Linux挂载硬盘