Files
ljwx-stock/backend/FULL_DATA_FETCH_GUIDE.md
T
brunoandClaude Sonnet 4.5 c553009853 feat: 添加全量A股数据抓取系统 v2.1.0
新增功能:
- 5个专业数据抓取器(公司信息、板块、财务、资金流、龙虎榜)
- 一键执行脚本 run_all_fetchers.sh(完整/测试/自定义三种模式)
- 扩展数据库Schema(11张新表)
- 数据源迁移至免费API(东方财富、新浪、腾讯)

数据能力:
- 公司基础信息:5,295只A股
- 板块数据:~400个板块 + 20万成分股关系
- 财务报表:利润表+资产负债表(最近4季)
- 资金流:主力资金、大单、中单、小单(700天)
- 龙虎榜:上榜记录+营业部明细(2年)
- 总数据量:~395万条记录,3-5GB存储

技术亮点:
- 断点续传支持
- UPSERT策略避免重复
- API限流控制
- 实时进度显示
- 错误容错机制
- 完整日志记录

文档更新:
- README添加"全量数据抓取"章节
- 60+页技术方案文档
- 完整的使用指南和维护文档

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 08:35:43 +08:00

18 KiB
Raw Blame History

A股全量历史数据抓取指南

📖 概述

本系统提供全自动、可断点续传、支持增量更新的A股历史数据抓取功能,可抓取所有A股股票过去10年的完整历史数据。

核心特性

  • ✅ 全量抓取: 支持抓取全部5000+只A股股票
  • ✅ 断点续传: 中途失败可以继续,不会重复抓取
  • ✅ 增量更新: 自动检测缺失数据,只抓取新增部分
  • ✅ 进度跟踪: 实时显示抓取进度,支持查看统计信息
  • ✅ 容错机制: 自动重试失败的股票
  • ✅ 速率限制: 避免请求过快被封禁
  • ✅ 数据完整性: 自动去重,确保数据质量

🚀 快速开始

1. 首次运行(抓取所有股票)

cd backend
source .venv/bin/activate

# 抓取所有A股股票过去10年数据
python fetch_full_historical_data.py

预期结果:

  • 自动从新浪财经获取5000+只A股股票列表
  • 开始批量抓取每只股票的历史数据
  • 实时显示进度和统计信息
  • 数据自动存储到PostgreSQL数据库

预计时间:

  • 5000只股票 × 0.5秒/只 ≈ 42分钟(实际时间取决于网络速度)

2. 增量更新(只抓取新数据)

当您已经抓取过一次数据,现在想更新到最新数据时:

python fetch_full_historical_data.py --mode incremental

工作原理:

  • 自动检查数据库中每只股票的最后交易日期
  • 只抓取该日期之后的新数据
  • 大幅减少抓取时间(通常只需几分钟)

推荐: 设置定时任务每天运行增量更新

# 添加到 crontab (每天收盘后18:00更新)
0 18 * * * cd /path/to/backend && source .venv/bin/activate && python fetch_full_historical_data.py --mode incremental

3. 重试失败的股票

如果某些股票抓取失败(网络问题、数据源问题等),可以单独重试:

python fetch_full_historical_data.py --mode retry

4. 指定股票列表

只抓取特定股票:

# 抓取贵州茅台、平安银行、浦发银行
python fetch_full_historical_data.py --symbols 600519,000001,600000

5. 自定义日期范围

# 只抓取最近5年数据
python fetch_full_historical_data.py --start-date 2020-01-01 --end-date 2025-12-31

# 抓取过去20年数据
python fetch_full_historical_data.py --start-date 2005-01-01

📊 进度管理

查看整体进度

python manage_fetch_progress.py --action status

输出示例:

================================================================================
  📊 抓取进度统计
================================================================================
  总股票数: 5,234
  ✅ 已完成: 4,890 (93.4%)
  ⏳ 待处理: 200
  ❌ 失败: 144
  🔄 进行中: 0
  📈 总数据量: 12,456,789 条
  📊 平均数据/股: 2,546 条
================================================================================

  🏆 数据量最多的10只股票:
  ----------------------------------------------------------------------------
  代码         名称              数据量      开始日期      结束日期
  ----------------------------------------------------------------------------
  600000     浦发银行          2,689条    2015-12-21    2025-12-19
  000001     平安银行          2,678条    2015-12-21    2025-12-19
  ...

查看失败的股票

python manage_fetch_progress.py --action failed

输出示例:

================================================================================
  ❌ 失败的股票列表 (共 144 只)
================================================================================

[1] 688001 (华兴源创)
    重试次数: 3
    失败时间: 2025-12-21 14:30:15
    错误信息: 无法获取K线数据

[2] 300750 (宁德时代)
    重试次数: 2
    失败时间: 2025-12-21 14:28:42
    错误信息: Connection timeout

重置失败的股票

允许重新抓取失败的股票:

python manage_fetch_progress.py --action reset-failed

然后运行:

python fetch_full_historical_data.py --mode retry

导出进度报告

python manage_fetch_progress.py --action export --output my_report.txt

生成详细的进度报告文件,包括:

  • 总体统计
  • 已完成股票列表
  • 失败股票详情
  • 数据覆盖率分析

数据质量检查

python manage_fetch_progress.py --action quality

自动检测:

  • 数据可能过时的股票(超过7天未更新)
  • 数据量异常偏低的股票
  • 数据完整性问题

🏗️ 系统架构

数据流图

┌─────────────────────────────────────────────────────────────┐
│  1. 获取股票列表                                            │
│  ┌────────────┐         ┌────────────┐                      │
│  │ 新浪财经    │ ──OR──> │ 东方财富    │                     │
│  │ 5000+股票  │         │ (备用)      │                     │
│  └──────┬─────┘         └────────────┘                      │
└─────────┼───────────────────────────────────────────────────┘
          │
          ▼
┌─────────────────────────────────────────────────────────────┐
│  2. 进度跟踪表 (fetch_progress)                             │
│  ┌──────────────────────────────────────────────┐           │
│  │ symbol │ status    │ total_records │ dates   │           │
│  ├──────────────────────────────────────────────┤           │
│  │ 600000 │ completed │ 2,689         │ 2015~25 │           │
│  │ 000001 │ pending   │ 0             │ NULL    │           │
│  │ 600519 │ failed    │ 0             │ NULL    │           │
│  └──────────────────────────────────────────────┘           │
└─────────────────────────────────────────────────────────────┘
          │
          ▼
┌─────────────────────────────────────────────────────────────┐
│  3. 批量抓取 (DataFetcherV2)                                │
│  - 每只股票: 检查进度 → 抓取数据 → 存储 → 更新进度         │
│  - 自动重试失败股票                                         │
│  - 速率限制: 0.5秒/股票                                     │
└─────────────────────────────────────────────────────────────┘
          │
          ▼
┌─────────────────────────────────────────────────────────────┐
│  4. 数据存储 (PostgreSQL)                                   │
│  ┌─────────────┐  ┌────────────────────┐                    │
│  │ stocks      │  │ daily_quotes       │                    │
│  │ (5,234)     │  │ (12,456,789)       │                    │
│  └─────────────┘  └────────────────────┘                    │
└─────────────────────────────────────────────────────────────┘

核心表结构

fetch_progress (进度跟踪表)

CREATE TABLE fetch_progress (
    symbol VARCHAR(20) PRIMARY KEY,      -- 股票代码
    name VARCHAR(100),                   -- 股票名称
    status VARCHAR(20),                  -- pending, in_progress, completed, failed
    start_date DATE,                     -- 数据开始日期
    end_date DATE,                       -- 数据结束日期
    last_fetch_date DATE,                -- 最后抓取日期
    total_records INT,                   -- 总数据量
    error_message TEXT,                  -- 错误信息
    retry_count INT,                     -- 重试次数
    created_at TIMESTAMP,                -- 创建时间
    updated_at TIMESTAMP                 -- 更新时间
);

状态说明:

  • pending: 待抓取
  • in_progress: 正在抓取
  • completed: 已完成
  • failed: 失败

💡 最佳实践

1. 首次运行策略

推荐分阶段运行,避免一次性抓取全部股票:

# 阶段1: 先抓取1000只股票测试
python fetch_full_historical_data.py --mode full

# 观察进度,如果一切正常,继续
python manage_fetch_progress.py --action status

# 阶段2: 继续抓取剩余股票
python fetch_full_historical_data.py --mode full

2. 日常维护策略

每天自动增量更新:

# 方法1: crontab定时任务
0 18 * * * cd /path/to/backend && source .venv/bin/activate && python fetch_full_historical_data.py --mode incremental >> /var/log/stock_fetch.log 2>&1

# 方法2: systemd timer
# 创建 /etc/systemd/system/stock-fetch.service 和 stock-fetch.timer

每周检查数据质量:

# 检查是否有失败的股票
python manage_fetch_progress.py --action failed

# 重试失败的股票
python fetch_full_historical_data.py --mode retry

# 查看数据质量
python manage_fetch_progress.py --action quality

3. 错误处理

常见错误及解决方法:

错误信息 原因 解决方法
Connection timeout 网络超时 重试或检查网络
无法获取K线数据 股票已退市或数据源无此股票 忽略或手动排查
Database connection failed 数据库连接失败 检查数据库服务
Rate limit exceeded 请求过快 增加sleep时间

批量重试失败股票:

# 1. 重置失败状态
python manage_fetch_progress.py --action reset-failed

# 2. 重新抓取
python fetch_full_historical_data.py --mode retry

# 3. 查看结果
python manage_fetch_progress.py --action status

4. 性能优化

调整并发数 (需修改代码):

# fetch_full_historical_data.py
# 修改 sleep 时间
await asyncio.sleep(0.5)  # 默认0.5秒,可调整为0.2~1.0秒

数据库优化:

-- 创建索引加速查询
CREATE INDEX idx_daily_quotes_symbol_date ON daily_quotes(symbol, trade_date);
CREATE INDEX idx_fetch_progress_status ON fetch_progress(status);

-- 定期VACUUM
VACUUM ANALYZE daily_quotes;
VACUUM ANALYZE fetch_progress;

📈 数据统计示例

完整抓取后的数据规模

假设抓取5000只股票,每只平均2500条数据(约10年):

总股票数: 5,000 只
总数据量: 12,500,000 条
数据库大小: 约 2-3 GB
抓取时间: 约 40-60 分钟(首次)
增量更新: 约 5-10 分钟(每天)

数据覆盖率

-- 查看各年份数据覆盖情况
SELECT
    DATE_PART('year', trade_date) as year,
    COUNT(DISTINCT symbol) as symbols,
    COUNT(*) as records
FROM daily_quotes
GROUP BY year
ORDER BY year DESC;

典型输出:

 year | symbols | records
------+---------+----------
 2025 |   5234  |  950,000
 2024 |   5180  | 1,260,000
 2023 |   5120  | 1,240,000
 2022 |   5050  | 1,220,000
 ...

🔧 故障排除

问题1: 进度表未创建

现象: relation "fetch_progress" does not exist

解决:

# 运行一次脚本会自动创建
python fetch_full_historical_data.py --symbols 600000

问题2: 大量股票失败

现象: failed 状态股票超过10%

可能原因:

  1. 网络不稳定
  2. 数据源被限流
  3. 股票已退市

解决:

# 查看失败详情
python manage_fetch_progress.py --action failed

# 重置并重试
python manage_fetch_progress.py --action reset-failed
python fetch_full_historical_data.py --mode retry

问题3: 数据重复

现象: 同一天的数据出现多次

解决: 数据库有唯一约束,自动去重

-- 手动清理重复数据(如果需要)
DELETE FROM daily_quotes a USING (
    SELECT MIN(id) as id, symbol, trade_date
    FROM daily_quotes
    GROUP BY symbol, trade_date HAVING COUNT(*) > 1
) b
WHERE a.symbol = b.symbol AND a.trade_date = b.trade_date AND a.id <> b.id;

问题4: 内存占用过高

解决:

# 分批抓取,每次限制股票数量
# 修改代码中的批量大小或手动分批执行
python fetch_full_historical_data.py --symbols $(python -c "import random; print(','.join([f'{x:06d}' for x in random.sample(range(600000, 603000), 100)]))")

📝 脚本参数说明

fetch_full_historical_data.py

python fetch_full_historical_data.py [OPTIONS]

选项:
  --mode {full,incremental,retry}
      运行模式(默认: full)
      - full: 抓取所有待处理股票
      - incremental: 只抓取需要更新的股票
      - retry: 只重试失败的股票

  --symbols SYMBOLS
      指定股票代码,逗号分隔
      示例: --symbols 600000,000001,600519

  --start-date YYYY-MM-DD
      开始日期(默认: 10年前)

  --end-date YYYY-MM-DD
      结束日期(默认: 今天)

示例:
  # 抓取全部股票
  python fetch_full_historical_data.py

  # 增量更新
  python fetch_full_historical_data.py --mode incremental

  # 抓取指定股票
  python fetch_full_historical_data.py --symbols 600000,000001

  # 自定义日期范围
  python fetch_full_historical_data.py --start-date 2020-01-01

manage_fetch_progress.py

python manage_fetch_progress.py --action ACTION [OPTIONS]

操作:
  status        显示整体进度统计
  failed        显示失败的股票列表
  reset-failed  重置失败股票状态
  export        导出进度报告
  clear-all     清理所有进度数据
  quality       数据质量检查

选项:
  --output FILE
      导出报告的文件名(仅用于 export 操作)
      默认: progress_report.txt

示例:
  # 查看进度
  python manage_fetch_progress.py --action status

  # 导出报告
  python manage_fetch_progress.py --action export --output report_2025.txt

🎯 完整工作流程示例

场景1: 首次建立数据库

# Step 1: 初始化数据库(如果未初始化)
psql -h localhost -U stock_user -d stock_db -f database/schema_v2.sql

# Step 2: 开始全量抓取
python fetch_full_historical_data.py

# Step 3: 观察进度(可在另一个终端窗口)
watch -n 10 'python manage_fetch_progress.py --action status'

# Step 4: 等待完成后检查数据质量
python manage_fetch_progress.py --action quality

# Step 5: 如有失败,重试
python fetch_full_historical_data.py --mode retry

# Step 6: 导出报告
python manage_fetch_progress.py --action export --output initial_fetch_report.txt

场景2: 每日增量更新

# Step 1: 每天18:00运行增量更新
python fetch_full_historical_data.py --mode incremental

# Step 2: 查看更新情况
python manage_fetch_progress.py --action status

# Step 3: 如有失败,立即重试
python fetch_full_historical_data.py --mode retry

场景3: 部分股票数据缺失

# Step 1: 查看数据质量
python manage_fetch_progress.py --action quality

# Step 2: 针对缺失数据的股票重新抓取
python fetch_full_historical_data.py --symbols 600000,000001,600519

# Step 3: 验证数据
psql -h localhost -U stock_user -d stock_db -c "
SELECT symbol, COUNT(*), MIN(trade_date), MAX(trade_date)
FROM daily_quotes
WHERE symbol IN ('600000', '000001', '600519')
GROUP BY symbol;
"

📚 相关文档


❓ 常见问题

Q: 抓取5000只股票需要多久?

A: 约40-60分钟(取决于网络速度),每只股票约0.5秒。

Q: 如何停止正在运行的抓取?

A: 直接 Ctrl+C 终止,下次运行会自动断点续传。

Q: 抓取失败率高怎么办?

A:

  1. 检查网络连接
  2. 增加 sleep 时间(降低请求频率)
  3. 查看失败详情:python manage_fetch_progress.py --action failed

Q: 如何清空所有数据重新开始?

A:

# 清空进度表
python manage_fetch_progress.py --action clear-all

# 清空数据表(可选)
psql -h localhost -U stock_user -d stock_db -c "TRUNCATE daily_quotes, stocks CASCADE;"

# 重新抓取
python fetch_full_historical_data.py

Q: 支持港股、美股吗?

A: 当前版本仅支持A股,未来版本会扩展。


最后更新: 2025-12-21 版本: V2.0 维护者: Claude Code AI Assistant