Skip to content
fasiondog edited this page Nov 22, 2025 · 1 revision

数据获取

**本文引用的文件** - [zh_block_em.py](file://hikyuu/fetcher/stock/zh_block_em.py) - [zh_stock_a_sina_qq.py](file://hikyuu/fetcher/stock/zh_stock_a_sina_qq.py) - [common_pytdx.py](file://hikyuu/data/common_pytdx.py) - [download_block.py](file://hikyuu/data/download_block.py) - [zhima.py](file://hikyuu/fetcher/proxy/zhima.py) - [proxy.py](file://hikyuu/fetcher/proxy/proxy.py) - [mylog.py](file://hikyuu/util/mylog.py) - [common.py](file://hikyuu/data/common.py)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件面向Hikyuu项目中的数据获取子系统,聚焦fetcher模块的架构与实现,重点说明以下内容:

  • 从东方财富、新浪、QQ财经等第三方源抓取A股市场的板块与实时行情数据
  • 通过代理服务(如zhima.py)缓解网络访问限制
  • 通达信(pytdx)协议客户端封装与K线数据获取
  • 板块信息下载工具download_block.py的工作流程
  • API调用示例与异常处理、重试机制、性能优化策略
  • 为初学者提供简单脚本示例,为高级用户提供扩展新数据源的建议

项目结构

fetcher模块位于hikyuu/fetcher,包含两类子模块:

  • stock:面向A股数据抓取,如板块与实时行情
  • proxy:代理服务封装,提供本地直连与代理请求能力
graph TB
subgraph "fetcher"
stock["stock/"]
proxy["proxy/"]
end
data["data/"]
stock --> |"板块数据<br/>实时行情"| data
proxy --> |"代理请求"| stock
data --> |"pytdx客户端封装"| data
Loading

图表来源

  • zh_block_em.py
  • zh_stock_a_sina_qq.py
  • common_pytdx.py
  • download_block.py
  • proxy.py
  • zhima.py

章节来源

  • zh_block_em.py
  • zh_stock_a_sina_qq.py
  • common_pytdx.py
  • download_block.py
  • proxy.py
  • zhima.py

核心组件

  • 板块数据抓取(东方财富):提供行业、概念、地域板块的名称与成分获取能力
  • 实时行情抓取(新浪/QQ):并发请求实时行情,解析并返回结构化数据
  • 代理服务:从代理平台获取可用代理,自动轮换与失效检测
  • pytdx客户端封装:连接通达信行情服务器,探测最优节点,批量拉取历史分时/逐笔数据
  • 板块信息下载器:统一下载并保存板块文件,带缓存与重试逻辑

章节来源

  • zh_block_em.py
  • zh_stock_a_sina_qq.py
  • proxy.py
  • zhima.py
  • common_pytdx.py
  • download_block.py

架构总览

整体数据流由“代理层”和“数据源层”组成:

  • 代理层:proxy.py封装request_with_proxy/request_with_local;zhima.py负责从代理平台获取可用代理
  • 数据源层:zh_stock_a_sina_qq.py抓取实时行情;zh_block_em.py抓取板块数据;download_block.py统一下载并落盘;common_pytdx.py封装pytdx客户端
sequenceDiagram
participant Caller as "调用方"
participant Proxy as "proxy.request_with_proxy"
participant Zhima as "zhima.get_proxy"
participant Target as "目标数据源"
participant Parser as "解析器"
Caller->>Proxy : 发起HTTP请求
Proxy->>Zhima : 申请代理(必要时)
Zhima-->>Proxy : 返回代理地址
Proxy->>Target : 带代理发起请求
Target-->>Proxy : 返回原始文本
Proxy-->>Caller : 返回原始文本
Caller->>Parser : 解析文本为结构化数据
Loading

图表来源

  • proxy.py
  • zhima.py

章节来源

  • proxy.py
  • zhima.py

详细组件分析

组件A:板块数据抓取(东方财富)

  • 功能要点
    • 行业板块名称与成分获取
    • 概念板块名称与成分获取
    • 地域板块名称与成分获取
    • 分页拉取与进度条适配
    • 缓存与延迟控制,降低风控风险
  • 关键流程
    • 通过fetch_paginated_data按页拉取,合并排序
    • 使用akshare与pandas进行字段映射与数值化
    • 提供get_all_hybk_info、get_all_gnbk_info、get_all_dybk_info等聚合接口
flowchart TD
Start(["开始"]) --> GetNames["获取板块名称列表"]
GetNames --> LoopPages{"遍历分页"}
LoopPages --> |是| FetchPage["请求一页数据"]
FetchPage --> Merge["合并到结果集"]
Merge --> Sleep["随机延迟"]
Sleep --> LoopPages
LoopPages --> |否| BuildDF["构建DataFrame并数值化字段"]
BuildDF --> Save["可选:保存为文件或返回"]
Save --> End(["结束"])
Loading

图表来源

  • zh_block_em.py

章节来源

  • zh_block_em.py

组件B:实时行情抓取(新浪/QQ)

  • 功能要点
    • 支持QQ行情源;新浪源已标记不再支持
    • 并发批处理请求,提升吞吐
    • 解析器分别处理新浪/QQ返回格式
    • 支持使用代理或本地直连
  • 关键流程
    • get_spot按最大批次拼接URL,ThreadPoolExecutor并发请求
    • request_data对每批结果调用对应解析器
    • parse_one_result_qq/parse_one_result_sina完成字段提取与类型转换
sequenceDiagram
participant Caller as "调用方"
participant Spot as "get_spot"
participant Pool as "线程池"
participant Req as "request_data"
participant Parse as "parse_one_result_*"
participant Src as "QQ/新浪源"
Caller->>Spot : 传入股票列表与source
Spot->>Spot : 拼接批次URL
Spot->>Pool : 提交批次任务
Pool->>Req : 执行请求
Req->>Src : 发起HTTP请求
Src-->>Req : 返回文本
Req->>Parse : 解析单条记录
Parse-->>Req : 返回字典
Req-->>Spot : 返回批次结果
Spot-->>Caller : 汇总结果
Loading

图表来源

  • zh_stock_a_sina_qq.py

章节来源

  • zh_stock_a_sina_qq.py

组件C:代理服务(zhima)

  • 功能要点
    • 从代理平台申请可用代理,带过期时间校验
    • 多线程安全的全局代理缓存
    • 自动重试与失败回退
  • 关键流程
    • request_proxy_from_zhima:请求代理并标准化返回
    • get_proxy:根据new参数决定是否强制刷新,结合过期时间判断
flowchart TD
A["调用 get_proxy"] --> CheckLock["加锁"]
CheckLock --> NewOrCache{"强制刷新或无缓存?"}
NewOrCache --> |是| Request["申请新代理"]
NewOrCache --> |否| Expire{"代理是否过期?"}
Expire --> |是| Request
Expire --> |否| ReturnCache["返回缓存代理"]
Request --> Validate{"成功获取?"}
Validate --> |是| Save["更新缓存"] --> ReturnCache
Validate --> |否| Retry["等待后重试"] --> Request
Loading

图表来源

  • zhima.py

章节来源

  • zhima.py

组件D:pytdx客户端封装

  • 功能要点
    • 自定义主机列表加载(支持用户自定义hosts)
    • 连通性探测与延迟测量
    • 最优节点选择:多节点并发探测,校验返回一致性
    • 历史分时/逐笔数据分段拉取
  • 关键流程
    • search_best_tdx:并发ping各节点,筛选可用节点
    • 校验阶段:对候选节点取同一标的的历史数据,统计一致结果最多的集合
    • pytdx_get_day_trans:按固定步长分页拉取逐笔数据
flowchart TD
Start(["开始"]) --> LoadHosts["加载主机列表"]
LoadHosts --> PingAll["并发ping各主机"]
PingAll --> FilterOK{"筛选可用主机"}
FilterOK --> Verify["校验一致性(取同一标的)"]
Verify --> SelectBest["选择一致性最高集合"]
SelectBest --> UseAPI["使用最佳主机进行数据拉取"]
UseAPI --> End(["结束"])
Loading

图表来源

  • common_pytdx.py

章节来源

  • common_pytdx.py

组件E:板块信息下载器

  • 功能要点
    • 下载行业、概念、地域、指数板块成分并保存为文件
    • 文件命名与路径管理,避免重复下载
    • 异常捕获与重试策略,针对常见网络错误给出提示
  • 关键流程
    • down_em_all_hybk_info/down_em_all_gnbk_info/down_em_all_dybk_info:按板块名称逐一下载
    • download_all_zsbk_info:指数成分拉取,兼容多个数据源
    • read_block_from_path:从本地目录读取已保存的板块文件
flowchart TD
Init["初始化保存目录"] --> ListBlks["列出待下载板块"]
ListBlks --> ForEach{"遍历板块"}
ForEach --> |是| CheckFile["检查文件是否可下载"]
CheckFile --> |可下载| Fetch["抓取板块成分"]
Fetch --> Clean["清洗与转换代码"]
Clean --> Save["保存为文件"]
Save --> Sleep["随机延迟"]
Sleep --> ForEach
ForEach --> |否| Next["跳过"]
Next --> ForEach
ForEach --> Done["完成"]
Loading

图表来源

  • download_block.py

章节来源

  • download_block.py

依赖关系分析

  • 模块间耦合
    • zh_stock_a_sina_qq.py依赖proxy模块进行网络请求
    • zh_block_em.py依赖requests、akshare、pandas进行数据抓取与处理
    • download_block.py依赖zh_block_em.py与common.py中的代码清洗工具
    • common_pytdx.py依赖pytdx库与用户自定义hosts
  • 外部依赖
    • requests、akshare、pandas、pytdx
    • 代理平台API(zhima)
graph LR
Proxy["proxy.py"] --> SinaQQ["zh_stock_a_sina_qq.py"]
Zhima["zhima.py"] --> Proxy
EM["zh_block_em.py"] --> DB["download_block.py"]
Common["common.py"] --> DB
Pytdx["common_pytdx.py"] --> DB
Loading

图表来源

  • proxy.py
  • zhima.py
  • zh_block_em.py
  • download_block.py
  • common.py
  • common_pytdx.py

章节来源

  • proxy.py
  • zhima.py
  • zh_block_em.py
  • download_block.py
  • common.py
  • common_pytdx.py

性能考量

  • 并发与批处理
    • 实时行情:get_spot使用ThreadPoolExecutor并发请求,减少总耗时
    • 板块下载:download_block.py对每个板块独立处理,避免阻塞
  • 延迟与节流
    • 随机延迟:zh_block_em.py与download_block.py在请求之间插入随机延迟,降低风控概率
    • 分页拉取:zh_block_em.py按页拉取并合并,避免一次性请求过多数据
  • 代理与容错
    • 代理重试:proxy.request_with_proxy最多尝试若干次,失败后抛出异常
    • zhima代理:get_proxy在过期或不可用时自动刷新
  • 客户端优化
    • pytdx:search_best_tdx先筛选可用节点再校验一致性,减少无效请求

章节来源

  • zh_stock_a_sina_qq.py
  • zh_block_em.py
  • download_block.py
  • proxy.py
  • zhima.py
  • common_pytdx.py

故障排查指南

  • 常见异常与处理
    • 网络错误:download_block.py对ConnectionError等进行捕获并提示,避免中断
    • 代理不可用:proxy.request_with_proxy在多次尝试后仍失败会抛出异常
    • 数据源限制:实时行情中新浪源已标记不再支持,建议使用QQ源
  • 日志与告警
    • 使用hku_info/hku_warn/hku_error输出运行状态与错误信息
    • mylog.py提供统一的日志接口与文件句柄管理
  • 重试与退避
    • 代理层:最多重试若干次,期间等待固定时间
    • 板块下载:对个别失败的板块进行warn并继续下一个

章节来源

  • download_block.py
  • proxy.py
  • zh_stock_a_sina_qq.py
  • mylog.py

结论

fetcher模块通过清晰的分层设计实现了对A股数据的稳定抓取:

  • 代理层保障网络访问稳定性
  • 数据源层提供多样化的数据源与解析能力
  • 工具层统一管理板块数据的下载与落盘
  • pytdx封装为历史数据获取提供了高效通道

在实际使用中,建议结合代理与随机延迟策略,合理设置并发度,并对异常进行捕获与重试,以获得更稳健的数据获取体验。

附录

API调用示例(路径指引)

  • 获取行业板块名称与成分
    • 函数入口:get_hybk_names
    • 成分获取:get_hybk_cons_code
    • 聚合接口:get_all_hybk_info
  • 获取概念板块名称与成分
    • 名称列表:stock_board_concept_name_em
    • 成分列表:stock_board_concept_cons_em
    • 聚合接口:get_all_gnbk_info
  • 获取地域板块名称与成分
    • 名称列表:get_dybk_names
    • 成分列表:get_all_dybk_info
  • 实时行情抓取(QQ)
    • 主入口:get_spot
    • QQ解析器:parse_one_result_qq
    • 新浪解析器(已不支持):parse_one_result_sina
  • 代理请求
    • 代理请求:request_with_proxy
    • 本地请求:request_with_local
    • 代理获取:get_proxy
  • pytdx客户端
    • 最佳节点选择:search_best_tdx
    • 连通性探测:ping
    • 逐笔数据拉取:pytdx_get_day_trans
  • 板块下载器
    • 下载行业板块:down_em_all_hybk_info
    • 下载概念板块:down_em_all_gnbk_info
    • 下载地域板块:down_em_all_dybk_info
    • 下载指数板块:download_all_zsbk_info
    • 读取本地板块:read_block_from_path

初学者脚本示例(路径指引)

  • 抓取行业板块名称与成分
    • 步骤:调用get_hybk_names获取名称,再调用get_hybk_cons_code获取成分
  • 抓取概念板块名称与成分
    • 步骤:调用stock_board_concept_name_em,再调用stock_board_concept_cons_em
  • 抓取实时行情(QQ)
    • 步骤:准备股票列表,调用get_spot,解析返回结果
  • 使用代理抓取
    • 步骤:调用request_with_proxy,内部会自动调用get_proxy

高级用户扩展指南

  • 新增数据源步骤
    • 在stock目录新增模块,定义数据源接口与解析器
    • 若涉及网络访问,优先复用proxy模块提供的request_with_proxy/request_with_local
    • 对于需要代理的服务,可在模块内调用get_proxy
  • 代理扩展
    • 在zhima.py中添加新的代理平台API,保持与现有接口一致
    • 更新proxy.py以支持新代理格式
  • 性能优化建议
    • 合理设置并发度与批大小,避免触发目标站点限流
    • 在请求间加入随机延迟,降低风控概率
    • 对热点数据使用缓存(如lru_cache装饰器),减少重复请求

Clone this wiki locally