news 2026/6/10 12:46:12

Java量化系列(三十一) 别再手动整理板块数据了!Java 批量爬取某券商板块列表,3 种分类自动入库

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java量化系列(三十一) 别再手动整理板块数据了!Java 批量爬取某券商板块列表,3 种分类自动入库

请大家关注一下地球号,这个可以比较快的接收到最新的文章: Java量化系列(三十一) 别再手动整理板块数据了!Java 批量爬取某券商板块列表,3 种分类自动入库

你是否在做量化系统开发时,遇到过这些痛点?🤔 手动整理板块数据耗时耗力,容易遗漏最新板块;板块分类混乱(行业、概念、地域傻傻分不清),导致数据管理杂乱;手动更新板块信息不及时,影响策略回测准确性。

今天这篇系列第三十一篇,就彻底解决这些问题 —— 从板块,概念,地区 基础认知,到数据库设计,再到东方财富板块列表批量爬取实战(分页 + 接口解析 + 自动入库),全程聚焦技术实现,帮你搭建高效的板块数据自动化管理模块。所有内容均为技术学习用途,不涉及任何投资建议,可放心复用。

一、先搞懂:3 种核心板块分类(对应技术枚举设计)

在量化系统中,板块本质是 “时序数据的分类标签”,不同分类对应不同的分析维度。结合代码中的BKType枚举,核心分为 3 类,覆盖绝大多数分析场景:

分类类型枚举值(code)核心含义典型示例
行业板块1(BK)按行业属性划分,反映某一行业的整体趋势新能源、半导体、生物医药
概念板块2(GN)按特定概念 / 主题划分,反映市场热点方向人工智能、光伏、数字经济
地域板块3(DY)按地域属性划分,反映区域经济相关趋势长三角、粤港澳、京津冀

💡 技术设计亮点:通过BKType枚举统一管理分类,后续新增分类(如 “主题板块”)只需扩展枚举,无需修改核心业务逻辑,符合 “开闭原则”。

二、数据存储设计:板块信息表(stock_bk)结构解析

板块数据需要持久化存储,方便后续查询、筛选和关联分析。下面拆解stock_bk表的设计思路,适配 3 种分类的存储需求:

2.1 表结构核心字段说明

CREATE TABLE `stock_bk` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', `code` varchar(10) DEFAULT NULL COMMENT '版块编码(唯一标识)', `name` varchar(30) DEFAULT NULL COMMENT '版块名称', `type` int DEFAULT '1' COMMENT '类型 1=板块 2=概念 3=地域(关联BKType枚举)', `hot_num` int DEFAULT '0' COMMENT '热度(用于排序展示)', `create_date` datetime DEFAULT NULL COMMENT '创建时间', `ths_code` varchar(10) DEFAULT NULL COMMENT '同花顺版块Code(多源数据兼容)', `ths_name` varchar(30) DEFAULT NULL COMMENT '同花顺版块Name(多源数据兼容)', -- 其他扩展字段(五行、成绩标记等,用于个性化分析) PRIMARY KEY (`id`), KEY `idx_stock_bk_1` (`code`) -- 编码索引,提升查询效率 ) ENGINE=InnoDB COMMENT='股票版块信息表';

2.2 设计思路拆解

  1. 多源兼容:预留ths_codeths_name字段,支持东方财富、同花顺等多平台板块数据接入,避免单一数据源依赖;
  2. 分类明确type字段直接关联BKType枚举,确保分类统一,后续查询 “某类板块” 时直接通过type过滤,高效便捷;
  3. 可扩展性hot_num(热度)、five_xing(五行)等字段为扩展字段,可根据业务需求灵活使用(如按热度排序展示热门板块);
  4. 实体映射:对应StockBkDo实体类,通过 MyBatis-Plus 实现 ORM 映射,无需手动编写 SQL,提升开发效率。

三、重点实战:东方财富板块列表批量爬取(全程代码解析)

这是本文核心内容 —— 通过东方财富公开接口,实现板块列表的批量爬取,支持分页获取,自动解析数据并适配后续入库逻辑。

实体类: StockBkDo 和 BKInfo 一致

@Data@EqualsAndHashCode(callSuper=false)@TableName("stock_bk")publicclassStockBkDoimplementsSerializable{privatestaticfinallongserialVersionUID=1L;/** * id */@TableId(value="id",type=IdType.AUTO)privateIntegerid;/** * 板块编码 */@TableField("code")privateStringcode;/** * 板块名称 */@TableField("name")privateStringname;/** * 类型 1是板块 2是 概念 3是地域 */@TableField("type")privateIntegertype;/** * 板块顺序 */@TableField("hot_num")privateStringhotNum;/** * 板块五行 */@TableField("five_xing")privateStringfiveXing;/** * 五行原因 */@TableField("five_reason")privateStringfiveReason;/** * 成绩标记 */@TableField("score_type")privateIntegerscoreType;/** * 成绩标记原因 */@TableField("score_message")privateStringscoreMessage;@TableField("create_date")privateDatecreateDate;@TableField("ths_code")privateStringthsCode;@TableField("ths_name")privateStringthsName;@TableField(exist=false)privateStringwebUrl;}

3.1 先分析:爬取接口核心信息

目标接口:

https://push2.eastmoney.com/api/qt/clist/get?cb=jinhaiyuejiang&pn=1&pz=50&po=1&np=1&fields=f12,f13,f14,f62&fid=f62&fs=m:90+t:2&ut=b2884a393a59ad64002292a3e90d46a5&_=

提取关键词:

`https://push2.eastmoney.com/api/qt/clist/get?cb={0}&pn={1}&pz=50&po=1&np=1&fields=f12,f13,f14,f62&fid=f62&fs=m:90+t:2&ut=b2884a393a59ad64002292a3e90d46a5&_=`
接口参数说明(关键!)
  • cb:回调函数名(用于 JSONP 跨域,代码中通过CB_BK常量定义);
  • pn:页码(分页核心参数,从 1 开始递增);
  • pz:每页条数(固定 50 条,接口限制);
  • fields:需要返回的字段(f12=板块编码f14=板块名称,对应后续解析字段);
  • fs:筛选条件(m:90+t:2表示查询行业板块列表,若查询概念 / 地域需调整该参数)。

3.2 核心代码:分页爬取实现

/** * 批量获取全量板块列表(分页爬取东方财富接口) * @return 全量板块信息列表 */@OverridepublicList<BKInfo>findAllBkList(){try{booleanstopSearch=false;// 终止爬取标记intpage=1;// 起始页码List<BKInfo>allResultList=newArrayList<>();// 分页循环爬取:直到获取不到数据为止do{// 1. 拼接完整URL(替换回调函数名和页码)Stringurl=MessageFormat.format("https://push2.eastmoney.com/api/qt/clist/get?cb={0}&pn={1}&pz=50&po=1&np=1&fields=f12,f13,f14,f62&fid=f62&fs=m:90+t:2&ut=b2884a393a59ad64002292a3e90d46a5&_={2}",CB_BK,page,MyDateUtil.getTimezone()// 时间戳参数防缓存);try{// 2. 调用接口并解析数据List<BKInfo>currentPageList=parseBKInfoList(url,BKType.BK);// 3. 处理当前页数据if(!CollUtil.isEmpty(currentPageList)){allResultList.addAll(currentPageList);page++;// 页码递增,继续爬取下一页}else{stopSearch=true;// 无数据,终止爬取}// 4. 延迟1秒:避免高频请求被限制IP(反爬关键)ThreadUtil.safeSleep(1000);}catch(Exceptione){log.error("第{}页板块数据爬取出错",page,e);throwe;// 可根据需求调整:是否终止整体爬取}}while(!stopSearch);log.info("板块列表爬取完成,共获取{}条数据",allResultList.size());returnallResultList;}catch(Exceptione){log.error("全量板块列表爬取异常",e);returnCollections.emptyList();}}

3.3 关键步骤:数据解析实现

爬取接口返回的是 JSONP 格式数据,需要先处理格式,再解析核心字段(板块编码、名称):

/** * 解析板块列表数据(JSONP格式转JSON,提取核心字段) * @param url 爬取接口URL * @param bkType 板块类型(对应BKType枚举) * @return 解析后的板块信息列表 */privateList<BKInfo>parseBKInfoList(Stringurl,BKTypebkType){try{// 1. 发送GET请求获取数据(携带请求头,模拟浏览器请求)Stringcontent=HttpUtil.sendGet(HttpClientConfig.proxyNoUseCloseableHttpClient(),url,buildDfHeaderMap()// 构建请求头(含Cookie,提升爬取稳定性));// 2. 处理JSONP格式:去掉回调函数包裹(如 cbName(...) → ... )Stringcb=getCb(bkType);content=content.substring(cb.length()+1);// 去掉"cbName("content=content.substring(0,content.length()-2);// 去掉");"// 3. JSON解析:提取data.diff中的板块列表JSONObjectjsonObject=JSONObject.parseObject(content);JSONObjectdata=jsonObject.getJSONObject("data");if(ObjectUtils.isEmpty(data)){returnCollections.emptyList();}JSONArrayjsonArray=data.getJSONArray("diff");if(jsonArray.size()<=0){returnCollections.emptyList();}// 4. 映射为BKInfo对象(后续可直接转StockBkDo入库)List<BKInfo>result=newArrayList<>(jsonArray.size());jsonArray.forEach(n->{JSONObjecttempObject=JSONObject.parseObject(n.toString());BKInfobkInfo=newBKInfo();bkInfo.setCode(tempObject.getString("f12"));// 板块编码bkInfo.setName(tempObject.getString("f14"));// 板块名称bkInfo.setType(bkType.getCode());// 板块类型编码result.add(bkInfo);});returnresult;}catch(Exceptione){log.error("板块数据解析异常",e);globalWebExceptionHandlerAspect.addException();returnCollections.emptyList();}}/** * 构建请求头(关键:模拟浏览器,提升爬取成功率) */private@NotNullMap<String,String>buildDfHeaderMap(){Map<String,String>headerMap=newHashMap<>();headerMap.put("Host","20.push2.eastmoney.com");headerMap.put("Cookie","东方财富的Cookie");returnheaderMap;}

3.4 最后一步:数据入库(衔接 StockBkDo)

将解析后的BKInfo列表转换为StockBkDo,批量插入数据库:

/** * 板块数据批量入库 * @param bkInfoList 解析后的板块信息列表 * @return 入库成功数量 */publicintbatchInsertBkData(List<BKInfo>bkInfoList){if(CollUtil.isEmpty(bkInfoList)){return0;}// 转换为StockBkDo对象List<StockBkDo>bkDoList=bkInfoList.stream().map(bkInfo->{StockBkDobkDo=newStockBkDo();bkDo.setCode(bkInfo.getCode());bkDo.setName(bkInfo.getName());bkDo.setType(bkInfo.getType());bkDo.setCreateDate(newDate());// 创建时间// 其他扩展字段可根据需求补充returnbkDo;}).collect(Collectors.toList());// 批量插入(MyBatis-Plus方法)returnstockBkMapper.insertBatch(bkDoList);}

四、技术要点:爬取稳定性与扩展性优化

4.1 稳定性优化(反爬 + 容错)

  1. 请求延迟:爬取每页后延迟 1 秒(ThreadUtil.safeSleep(1000)),避免高频请求被封 IP;
  2. 请求头伪装:携带HostCookie等请求头,模拟浏览器行为,提升爬取成功率;
  3. 异常容错:单页爬取失败时抛出异常(可根据需求调整为 “跳过当前页”),避免影响整体爬取;
  4. 时间戳防缓存:URL 拼接时间戳参数(MyDateUtil.getTimezone()),避免获取缓存的旧数据。

4.2 扩展性优化(支持多类型板块爬取)

当前代码爬取的是 “行业板块”(fs=m:90+t:2),若要爬取 “概念板块”“地域板块”,只需调整fs参数:

// 爬取概念板块:fs参数改为 m:90+t:3StringgnUrl=MessageFormat.format("https://push2.eastmoney.com/api/qt/clist/get?cb={0}&pn={1}&pz=50&po=1&np=1&fields=f12,f13,f14,f62&fid=f62&fs=m:90+t:3&ut=b2884a393a59ad64002292a3e90d46a5&_={2}",CB_GN,page,MyDateUtil.getTimezone());// 爬取地域板块:fs参数改为 m:90+t:1StringdyUrl=MessageFormat.format("https://push2.eastmoney.com/api/qt/clist/get?cb={0}&pn=1&pz=50&po=1&np=1&fields=f12,f14&fid=f62&fs=m:90+t:1&ut=b2884a393a59ad64002292a3e90d46a5&_={2}",CB_DY,page,MyDateUtil.getTimezone());

五. 避坑指南: 板块爬取的 5 个典型问题 ⚠️

  1. JSONP 格式处理错误:忘记去掉回调函数包裹(如cbName(...)),导致 JSON 解析失败 → 严格按substring方法处理格式;
  2. 高频请求被封 IP:未加延迟或请求头伪装 → 必须添加 1-2 秒延迟,携带真实 Cookie 和 Host;
  3. 分页终止条件错误:页码递增无限制 → 只有当 “当前页无数据” 时才终止爬取;
  4. 字段映射错误:把f13当成板块编码(实际f12是编码) → 先通过浏览器调试接口,确认字段含义;
  5. 数据库插入重复:未做去重处理 → 入库前先查询数据库,存在则更新,不存在则插入。

六、下期预告

下期主要讲解一下 板块,概念,地区 这些的区别,用于读者更好的理解。

私信回复: “板块获取” 获取到目前最新的 板块数据,直接导入到数据库中即可使用。

最后留个小问题:你在做量化系统时,还需要爬取哪些类型的分类数据?是否需要支持 “板块 - 数据” 关联关系的自动维护?欢迎在评论区留言讨论,后续将持续优化完善~



请大家关注一下地球号,这个可以比较快的接收到最新的文章: Java量化系列(三十一) 别再手动整理板块数据了!Java 批量爬取某券商板块列表,3 种分类自动入库

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/1 13:05:52

效率提升30%+?解读AGV调度“大脑”从分散到集中

在繁忙的现代化工厂或物流仓库里&#xff0c;AGV&#xff08;自动导引运输车&#xff09;如同不知疲倦的“搬运工”&#xff0c;穿梭于货架与产线之间&#xff0c;构成了智能物流的动脉。然而&#xff0c;你是否想过&#xff0c;这些AGV是如何被指挥和调度的&#xff1f;过去&a…

作者头像 李华
网站建设 2026/6/10 11:55:24

工厂制造运营的演进:从经验驱动到数据中枢

在传统制造车间里&#xff0c;工厂的运转常常离不开老师傅的直觉、纸质单据的来回传递&#xff0c;和此起彼伏的电话催料声。计划排产凭经验、质量追溯靠翻本、库存多少几乎靠猜——这一套在老日子里或许还转得动&#xff0c;但在如今小批量、多品类、快交付的市场压力下&#…

作者头像 李华
网站建设 2026/6/6 17:04:35

ISP算法调优

ISP 算法调优是嵌入式视觉系统图像质量调优的核心环节—— 本质是通过调整 ISP 内部算法的参数组合&#xff0c;让摄像头在不同场景下输出色彩准确、细节清晰、动态范围合理的图像。调优不是单一参数的调整&#xff0c;而是 「前端校正、中端优化、后端输出」全链路参数的协同匹…

作者头像 李华
网站建设 2026/6/10 11:21:16

前方高能!郑州要从「铁网中心」变「算网中心」?

这两天&#xff0c;郑州那边频频传出算力产业大动作征兆。据说不少专家院士已经带队前往&#xff0c;目的隐约指向前两年开建的国家超算互联网节点。这就让人想入非非了。要说郑州&#xff0c;外界最大印象就是中原重镇&#xff0c;而且正好位于全国铁路网的「十字中心」。现在…

作者头像 李华
网站建设 2026/6/10 11:19:44

赶deadline必备!AI论文网站 千笔ai写作 VS 文途AI,专科生专属神器!

随着人工智能技术的迅猛迭代与普及&#xff0c;AI辅助写作工具已逐步渗透到高校学术写作场景中&#xff0c;成为专科生、本科生、研究生完成毕业论文不可或缺的辅助手段。越来越多面临毕业论文压力的学生&#xff0c;开始依赖各类AI工具简化写作流程、提升创作效率。但与此同时…

作者头像 李华
网站建设 2026/6/10 9:05:16

AI做复盘,比我更会甩锅(给数据)

你有没有遇到过这样的销售复盘会&#xff1a;销售一句“客户根本没说清需求”就把败单责任推得一干二净&#xff0c;经理凭经验拍板却拿不出实锤证据&#xff1f;如今大模型AI销售机器人的出现&#xff0c;让“甩锅给数据”成了正经事——不是推诿责任&#xff0c;而是用NLP技术…

作者头像 李华