上一篇违规了这次删掉重新发。做量化的都懂龙虎榜是主力资金的“风向标”。第51篇我们搞定了全市场股票数据解决了“无标的”的痛点但想要真正抓住强势标的、跟上主力节奏光有全市场标的还不够——龙虎榜记录了每日最活跃股票的买卖营业部、资金净额、上榜原因是判断主力持仓、预判股价走势的核心数据也是量化策略从“普适”到“精准”的关键一步。很多量化新手卡在龙虎榜这一关要么找不到稳定的数据源要么爬取的数据残缺缺营业部信息、缺买卖净额要么不会解析接口、不会落地数据库最后只能手动查看龙虎榜无法嵌入自动化策略错失主力异动信号。今天第52篇#金亥跃江 直接给粉丝们上硬菜完整拆解龙虎榜数据爬取全流程从数据库设计、实体类定义到接口调用、数据解析、批量存储再到实战联动所有代码、配置均为实战可运行版本适配前51篇的量化框架零门槛落地彻底打通“全市场数据龙虎榜主力数据”的闭环注全文无敏感词、无违禁内容基于Java主流量化框架开发适配某券商龙虎榜最新接口给定URL直接复用兼容MySQL、MyBatis-Plus建议 评论 收藏转发避免后续找不到一、先搞懂龙虎榜数据对量化策略的核心价值在拆解代码前先跟大家说清楚为什么量化策略必须接入龙虎榜数据核心价值有4点尤其适合短线、波段策略新手必看1. 捕捉主力异动避免被第二天低开龙虎榜会详细记录“买入/卖出前五营业部”通过营业部类型游资营业部、机构营业部、买卖净额能快速判断主力是“真拉升”还是“假出货”避免被诱多套牢提升策略的容错率。2. 筛选强势标的减少股票范围能上龙虎榜的股票本身就是当日市场最活跃的标的结合全市场数据筛选如第51篇的资金净流入、异动信号能快速锁定“全市场优质主力加持”的强势标的大幅提升策略的命中率。3. 落地自动化策略解放双手和双脚手动查看龙虎榜效率极低且无法实时联动策略通过代码爬取、自动存储、实时解析能将龙虎榜数据嵌入自动化策略实现“主力异动→自动筛选→信号提醒”的全流程自动化不用再熬夜盯盘。关键提醒本篇给定的代码已做好反爬优化、异常兜底、批量存储直接复制到项目中注入依赖、配置URL即可实现“每日自动爬取当日龙虎榜数据”无需手动操作真正适配实战场景。4. 统计各个营业部对于第二天股票的处理情况有些营业部对于第二天的股票直接下杀 有些营业部对于第二天的股票直接一字板有些营业部对于第二天的股票 高开后下杀 有些营业部对于第二天的股票下杀后拉升。 可以对这样的营业部进行统计如果你拥有这些票那么明天就可以对趋势有一个大概的计划避免手忙脚乱出现问题。二、基础准备数据库设计实体类龙虎榜数据落地核心想要实现龙虎榜数据的爬取、解析、存储首先要做好“数据载体”——数据库表设计和实体类定义给定的表结构和实体类已适配所有爬取、解析逻辑无需修改直接复用即可。1. 数据库表设计stock_lhb_history龙虎榜历史表作用存储龙虎榜核心数据股票信息、上榜原因、营业部信息、买卖数据等支持按股票编码、日期快速查询适配量化策略的多条件筛选表结构已做好索引优化避免大数据量查询卡顿。CREATE TABLE stock_lhb_history ( id int NOT NULL AUTO_INCREMENT COMMENT 主键, code varchar(6) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 股票编码, name varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 股票名称, reason varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 上榜原因, lhb_explain varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 解读, curr_date timestamp NULL DEFAULT NULL COMMENT 当前日期, type tinyint DEFAULT NULL COMMENT 类型 1为买入 2为卖出, dept_code varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 营业部编码, dept_name varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 营业部名称, sort_num int DEFAULT NULL COMMENT 对应的排序编号, buy_money decimal(18,4) DEFAULT NULL COMMENT 买入金额, buy_percent decimal(18,4) DEFAULT NULL COMMENT 买入占成交比例, sell_money decimal(18,4) DEFAULT NULL COMMENT 卖出金额, sell_percent decimal(18,4) DEFAULT NULL COMMENT 卖出占成交比例, sub_money decimal(18,4) DEFAULT NULL COMMENT 净额, PRIMARY KEY (id) USING BTREE, KEY idx_stock_lhb_history_1 (code,curr_date) USING BTREE, -- 按股票编码日期索引查询更快 KEY idx_stock_lhb_history_2 (dept_code) USING BTREE -- 按营业部编码索引便于分析营业部动向 ) ENGINEInnoDB AUTO_INCREMENT564234 DEFAULT CHARSETutf8mb3 ROW_FORMATDYNAMIC COMMENT股票龙虎榜历史;✅ 关键说明① 字段设计覆盖“股票信息上榜信息营业部信息买卖数据”无冗余字段适配所有爬取的龙虎榜数据② 索引优化新增两个核心索引解决“按股票查龙虎榜”“按营业部查动向”的查询卡顿问题适配大数据量存储③ 数据类型金额字段用decimal(18,4)避免小数精度丢失量化策略计算核心细节日期用timestamp统一时间格式。2. 核心实体类StockLhbHistoryDo数据封装载体作用封装龙虎榜所有数据与数据库表stock_lhb_history一一映射是爬取、解析、存储全流程的数据载体给定代码已做好注解配置直接复制使用无需修改。Data EqualsAndHashCode(callSuper false) TableName(stock_lhb_history) // 与数据库表名映射 Schema(description StockLhbHistoryDo对象龙虎榜数据实体) public class StockLhbHistoryDo implements Serializable { private static final long serialVersionUID 1L; Schema(description 主键) TableId(value id, type IdType.AUTO) // 自增主键 private Integer id; Schema(description 当前日期) TableField(curr_date) // 与数据库字段映射 private Date currDate; Schema(description 股票编码) TableField(code) private String code; Schema(description 股票名称) TableField(name) private String name; Schema(description 上榜原因) TableField(reason) private String reason; Schema(description 解读) TableField(lhb_explain) private String lhbExplain; Schema(description 类型 1为买入 2为卖出) TableField(type) private Integer type; Schema(description 营业部编码) TableField(dept_code) private String deptCode; Schema(description 营业部名称) TableField(dept_name) private String deptName; Schema(description 对应的排序编号) TableField(sort_num) private Integer sortNum; Schema(description 买入金额) TableField(buy_money) private BigDecimal buyMoney; Schema(description 买入占成交比例) TableField(buy_percent) private BigDecimal buyPercent; Schema(description 卖出金额) TableField(sell_money) private BigDecimal sellMoney; Schema(description 卖出占成交比例) TableField(sell_percent) private BigDecimal sellPercent; Schema(description 净额) TableField(sub_money) private BigDecimal subMoney; }✅ 关键说明实体类字段与数据库表字段完全对应通过TableName、TableField注解实现映射无需手动编写SQL语句适配MyBatis-Plus框架直接用于数据存储、查询。三、核心拆解龙虎榜数据爬取全流程6个核心方法2个接口这是本篇的核心也是大家最关心的部分——给定的6个核心Java方法爬取入口分页爬取总页数获取解析明细查询明细解析搭配2个某券商龙虎榜接口涵盖“爬取→解析→明细补充→存储”全流程每一行代码都拆解清楚新手也能看懂、会用。先明确核心逻辑先获取龙虎榜总页数→分页爬取龙虎榜列表股票信息、上榜原因→根据股票编码日期爬取对应股票的买卖明细营业部、买卖金额→解析所有数据→批量存储到数据库形成完整闭环。先看2个核心接口某券商龙虎榜直接复用爬取龙虎榜数据的核心的是某券商的两个接口已在配置文件中定义好直接复制到application.yml中无需修改接口地址适配最新接口格式避免反爬。# 龙虎榜相关接口配置直接复制到配置文件 extend: # 1. 龙虎榜列表接口获取上榜股票列表、总页数 lhb: https://datacenter-web.eastmoney.com/api/data/v1/get?callback{0}sortColumnsSECURITY_CODE,\ TRADE_DATEsortTypes1,-1pageSize50pageNumber{1}reportNameRPT_DAILYBILLBOARD_DETAILSNEWcolumnsSECURITY_CODE,\ SECUCODE,SECURITY_NAME_ABBR,TRADE_DATE,EXPLAIN,CLOSE_PRICE,CHANGE_RATE,BILLBOARD_NET_AMT,BILLBOARD_BUY_AMT,\ BILLBOARD_SELL_AMT,BILLBOARD_DEAL_AMT,ACCUM_AMOUNT,DEAL_NET_RATIO,DEAL_AMOUNT_RATIO,\ TURNOVERRATE,FREE_MARKET_CAP,EXPLANATION,D1_CLOSE_ADJCHRATE,D2_CLOSE_ADJCHRATE,\ D5_CLOSE_ADJCHRATE,D10_CLOSE_ADJCHRATE,SECURITY_TYPE_CODEsourceWEB\ clientWEBfilter(TRADE_DATE{2})(TRADE_DATE{3}) # 2. 龙虎榜明细接口获取单个股票的买卖营业部、金额等明细 lhbDetail: https://datacenter-web.eastmoney.com/api/data/v1/get?callback{0}columnsALL\ filter(TRADE_DATE{1})(SECURITY_CODE{2})pageNumber{3}\ pageSize50sortTypes-1sortColumns{4}reportName{5}sourceWEBclientWEB_{6}✅ 接口说明① lhb接口用于获取龙虎榜列表分页参数{0}回调标识、{1}页码、{2}结束日期、{3}开始日期每页返回50条上榜股票② lhbDetail接口用于获取单个股票的龙虎榜明细参数包含日期、股票编码、买卖类型买入/卖出返回该股票当日买入/卖出前五营业部数据。查询总数据:https://datacenter-web.eastmoney.com/api/data/v1/get?callbackyueshushusortColumnsNET_BUY_AMTsortTypes-1pageSize5pageNumber1reportNameRPT_ORGANIZATION_TRADE_DETAILSNEWcolumnsALLsourceWEBclientWEBfilter(TRADE_DATE%3E%3D%272026-03-13%27)https://datacenter-web.eastmoney.com/api/data/v1/get?callbackyueshushucolumnsALLfilter(TRADE_DATE%272026-03-13%27)(SECURITY_CODE%27000533%27)pageNumber1pageSize50sortTypes-1sortColumnsBUYreportNameRPT_BILLBOARD_DAILYDETAILSBUYsourceWEBclientWEB_17008124325491. 核心入口asyncLhbByDate当日龙虎榜数据爬取存储作用对外提供的核心入口传入日期字符串如“2026-03-13”即可自动爬取该日期的龙虎榜数据并批量存储到数据库适配定时任务后续会讲自动更新直接调用即可。/** * 异步爬取指定日期的龙虎榜数据并批量存储到数据库 * param dateStr 日期字符串格式yyyy-MM-dd如2026-03-13 */ public void asyncLhbByDate(String dateStr) { // 1. 调用方法爬取指定日期的龙虎榜数据列表明细 ListStockLhbHistoryDo lhbList extStockService.findLhbCodeByDateRange(dateStr, dateStr); // 2. 数据非空校验若有数据批量存储批次大小1000提升存储效率 if (!CollectionUtil.isEmpty(lhbList)){ stockLhbHistoryDoDomainService.saveBatch(lhbList,1000); log.info(日期{}的龙虎榜数据爬取完成共{}条已批量存储到数据库, dateStr, lhbList.size()); } else { log.info(日期{}未获取到龙虎榜数据, dateStr); } }✅ 关键拆解① 调用findLhbCodeByDateRange方法传入相同的开始/结束日期即可获取当日所有龙虎榜数据含明细② 批量存储使用saveBatch方法批次大小设为1000避免单条插入导致的效率低下适配大数据量场景③ 异步设计方法名带async可配合Spring的Async注解实现异步爬取不影响主线程执行适配自动化策略。2. 核心爬取findLhbCodeByDateRange分页爬取龙虎榜列表明细作用核心爬取方法根据日期范围分页获取龙虎榜列表再根据每只上榜股票的编码日期爬取对应的买卖明细整合所有数据后返回是龙虎榜数据爬取的核心逻辑。Override public ListStockLhbHistoryDo findLhbCodeByDateRange(String startDate, String endDate) { // 1. 获取龙虎榜总页数调用getLhbTotalPage方法 Integer lhbTotalPage getLhbTotalPage(startDate, endDate); if (lhbTotalPage 0) { log.info(日期{}~{}未查询到龙虎榜数据总页数为0, startDate, endDate); return Collections.emptyList(); } log.info(日期 {} ~ {} 能查询出 {} 页龙虎榜数据, startDate, endDate, lhbTotalPage); ListStockLhbHistoryDo totalList new ArrayList(); // 存储所有龙虎榜明细数据 // 2. 分页爬取循环遍历每一页获取上榜股票列表 for (int i 1 ;i lhbTotalPage; i) { try { // 2.1 拼接龙虎榜列表接口URL替换占位符回调标识、页码、日期 String url MessageFormat.format(extendProperties.getLhb(), CB_LHB, i, addPattern2DateStr(endDate), addPattern2DateStr(startDate)); // 2.2 发送HTTP请求复用反爬配置避免IP封禁 String content HttpUtil.sendGet(HttpClientConfig.proxyNoUseCloseableHttpClient(), url, buildDfHeaderMap()); // 2.3 处理接口返回内容去除回调前缀和后缀获取纯JSON字符串 content content.substring(CB_LHB.length() 1); content content.substring(0, content.length() - 2); // 2.4 调用解析方法将JSON解析为龙虎榜列表仅包含股票基本信息、上榜原因 ListStockLhbHistoryDo stockLhbHistoryDoList stockInfoParser.parseLhb(content); // 3. 明细补充若当前页有上榜股票爬取每只股票的买卖明细 if(CollectionUtil.isEmpty(stockLhbHistoryDoList)) { continue; // 无数据跳过当前页 } log.info(日期 {} ~ {} , 第{}页 共查询出上榜股票 {} 条, startDate, endDate, i, stockLhbHistoryDoList.size()); // 3.1 遍历每只上榜股票爬取其买卖明细 stockLhbHistoryDoList.forEach(stockLhbHistoryDo - { // 3.2 格式化日期适配明细接口的日期格式 String date DateUtil.format(stockLhbHistoryDo.getCurrDate(), Const.SIMPLE_DATE_FORMAT); // 3.3 调用方法获取该股票当日的买卖明细买入卖出 ListStockLhbHistoryDo detailDoList findLhbDetailByCodeAndDateRange(stockLhbHistoryDo.getCode(), date); // 3.4 补充明细数据将股票名称、上榜原因、日期等信息填充到明细中 if (!CollectionUtil.isEmpty(detailDoList)) { detailDoList.forEach(detailDo - { detailDo.setName(stockLhbHistoryDo.getName()); // 股票名称 detailDo.setReason(stockLhbHistoryDo.getReason()); // 上榜原因 detailDo.setCurrDate(stockLhbHistoryDo.getCurrDate()); // 日期 detailDo.setLhbExplain(stockLhbHistoryDo.getLhbExplain()); // 解读 }); // 3.5 将明细数据添加到总列表 totalList.addAll(detailDoList); } }); } catch (Exception e) { // 异常兜底打印日志记录异常返回null可根据需求调整为继续爬取 log.error({} findLhbCodeByDateRange 获取龙虎榜列表出错, ThreadLocalUtils.getIp(), e); try { globalWebExceptionHandlerAspect.addException(); // 异常记录复用全局异常处理 } catch (Exception ex) { // 二次异常兜底避免流程崩溃 } return null; } } log.info(日期 {} ~ {} 共查询出龙虎榜明细 {} 条, startDate, endDate, totalList.size()); return totalList; // 返回所有龙虎榜明细数据 }反爬重点必看① 复用HttpClient反爬配置避免IP封禁② 接口返回内容需去除回调前缀CB_LHB和后缀否则无法解析JSON③ 循环爬取时无异常捕获避免单页爬取失败导致整个流程中断。3. 辅助方法getLhbTotalPage获取龙虎榜总页数作用获取指定日期范围内龙虎榜的总页数用于分页爬取避免无限循环核心是调用龙虎榜列表接口解析返回的总页数。/** * 获取指定日期范围内龙虎榜的总页信息 * param startDate 开始日期格式yyyyMMdd * param endDate 结束日期格式yyyyMMdd * return 龙虎榜总页数0表示无数据 */ private Integer getLhbTotalPage (String startDate, String endDate) { try { // 1. 拼接龙虎榜列表接口URL页码设为1仅获取总页数 String url MessageFormat.format(extendProperties.getLhb(), CB_LHB, 1, addPattern2DateStr(endDate), addPattern2DateStr(startDate)); // 2. 发送HTTP请求获取接口返回内容 String content HttpUtil.sendGet(HttpClientConfig.proxyNoUseCloseableHttpClient(), url); // 3. 处理接口返回内容去除回调前缀和后缀获取纯JSON字符串 content content.substring(CB_LHB.length() 1); content content.substring(0, content.length() - 2); // 4. 调用解析方法获取总页数 return stockInfoParser.parseLhbTotalPage(content); } catch (Exception e) { log.error(获取龙虎榜总页数出错日期范围{}~{}, startDate, endDate, e); return 0; // 异常时返回0表示无数据 } }4. 列表解析parseLhb龙虎榜列表JSON解析作用将龙虎榜列表接口返回的JSON字符串解析为StockLhbHistoryDo列表提取核心字段股票编码、名称、上榜原因、日期等仅包含上榜股票的基本信息不包含买卖明细。public ListStockLhbHistoryDo parseLhb(String content) { // 1. 将接口返回的纯JSON字符串转换为JSON对象 JSONObject jsonObject JSONObject.parseObject(content); // 2. 获取核心数据字段result接口返回格式固定不可修改 JSONObject data jsonObject.getJSONObject(result); if (ObjectUtils.isEmpty(data)) { return Collections.emptyList(); // 无数据返回空列表 } // 3. 获取上榜股票列表data.data字段核心列表 JSONArray jsonArray data.getJSONArray(data); if (jsonArray.size() 0) { return Collections.emptyList(); // 列表为空返回空列表 } // 4. 解析每一条上榜股票数据封装为StockLhbHistoryDo ListStockLhbHistoryDo result new ArrayList(8); jsonArray.forEach(n - { JSONObject tempObject JSONObject.parseObject(n.toString()); StockLhbHistoryDo stockLhbHistoryDo new StockLhbHistoryDo(); // 填充核心字段仅列表信息无明细 stockLhbHistoryDo.setCode(tempObject.getString(SECURITY_CODE)); // 股票编码 stockLhbHistoryDo.setName(tempObject.getString(SECURITY_NAME_ABBR)); // 股票名称 stockLhbHistoryDo.setLhbExplain(tempObject.getString(EXPLAIN)); // 解读 stockLhbHistoryDo.setReason(tempObject.getString(EXPLANATION)); // 上榜原因 // 日期格式化将接口返回的日期字符串转换为Date类型 String currDateStr tempObject.getString(TRADE_DATE); stockLhbHistoryDo.setCurrDate(DateUtil.parse(currDateStr, Const.DATE_FORMAT)); result.add(stockLhbHistoryDo); // 添加到结果列表 }); return result; // 返回解析后的上榜股票列表 }✅ 解析重点接口返回的核心字段对应关系必记SECURITY_CODE 股票编码、SECURITY_NAME_ABBR 股票名称、EXPLAIN 解读、EXPLANATION 上榜原因、TRADE_DATE 交易日期。5. 明细查询findLhbDetailByCodeAndDateRange获取股票龙虎榜明细作用根据股票编码和日期获取该股票当日的龙虎榜明细买入卖出核心是调用findLhbTypeDetail方法分别获取买入、卖出明细再整合返回。Override public ListStockLhbHistoryDo findLhbDetailByCodeAndDateRange(String code, String date) { // 1. 先获取买入明细type1 ListStockLhbHistoryDo doList findLhbTypeDetail(code, date, 1); if (CollectionUtil.isEmpty(doList)) { // 若买入明细为空直接返回卖出明细可能只有卖出 return findLhbTypeDetail(code, date, 2); } // 2. 再获取卖出明细type2并添加到买入明细列表中 ListStockLhbHistoryDo lhbTypeDetail findLhbTypeDetail(code, date, 2); Optional.ofNullable(lhbTypeDetail).map(doList::addAll); // 避免空指针 return doList; // 返回买入卖出明细 }6. 明细爬取解析findLhbTypeDetail parseLhbDetail这两个方法是明细爬取和解析的核心配合使用findLhbTypeDetail负责调用明细接口、爬取明细数据parseLhbDetail负责将JSON解析为明细对象填充营业部、买卖金额等核心字段。/** * 爬取单个股票指定日期、指定类型买入/卖出的龙虎榜明细 * param code 股票编码 * param date 日期格式yyyyMMdd * param type 类型1买入2卖出 * return 该股票的龙虎榜明细列表 */ private ListStockLhbHistoryDo findLhbTypeDetail(String code, String date, Integer type) { try { // 1. 根据类型设置明细接口的参数报表名称、排序字段 String reportName type 1 ? RPT_BILLBOARD_DAILYDETAILSBUY : RPT_BILLBOARD_DAILYDETAILSSELL; String sort type 1 ? BUY : SELL; // 2. 拼接明细接口URL替换占位符回调标识、日期、股票编码、页码等 String url MessageFormat.format(extendProperties.getLhbDetail(), CB_LHB, addPattern2DateStr(date), addPattern2Code(code), 1, sort, reportName, System.currentTimeMillis()); // 3. 发送HTTP请求获取接口返回内容 String content HttpUtil.sendGet(HttpClientConfig.proxyNoUseCloseableHttpClient(), url); // 4. 处理接口返回内容去除回调前缀和后缀获取纯JSON字符串 content content.substring(CB_LHB.length() 1); content content.substring(0, content.length() - 2); // 5. 调用解析方法将JSON解析为明细列表 ListStockLhbHistoryDo stockLhbHistoryDoList stockInfoParser.parseLhbDetail(content); // 6. 填充类型字段1买入2卖出 if(!CollectionUtil.isEmpty(stockLhbHistoryDoList)) { stockLhbHistoryDoList.forEach(stockLhbHistoryDo - stockLhbHistoryDo.setType(type)); } return stockLhbHistoryDoList; } catch (Exception e) { // 异常兜底打印日志返回空列表不影响整体流程 log.error({} findLhbTypeDetail 获取龙虎榜明细列表出错股票编码{}日期{}类型{}, ThreadLocalUtils.getIp(), code, date, type, e); try { globalWebExceptionHandlerAspect.addException(); // 异常记录 } catch (Exception ex) { } return new ArrayList(); } } public ListStockLhbHistoryDo parseLhbDetail(String content) { // 1. 将接口返回的纯JSON字符串转换为JSON对象 JSONObject jsonObject JSONObject.parseObject(content); // 2. 获取核心数据字段result接口返回格式固定不可修改 JSONObject data jsonObject.getJSONObject(result); if (ObjectUtils.isEmpty(data)) { return Collections.emptyList(); // 无数据返回空列表 } // 3. 获取明细列表data.data字段 JSONArray jsonArray data.getJSONArray(data); if (jsonArray.size() 0) { return Collections.emptyList(); // 列表为空返回空列表 } // 4. 解析每一条明细数据封装为StockLhbHistoryDo ListStockLhbHistoryDo result new ArrayList(8); AtomicInteger sortNum new AtomicInteger(0); // 排序编号自增标记营业部排名 jsonArray.forEach(n - { JSONObject tempObject JSONObject.parseObject(n.toString()); StockLhbHistoryDo stockLhbHistoryDo new StockLhbHistoryDo(); // 填充明细核心字段 stockLhbHistoryDo.setCode(tempObject.getString(SECURITY_CODE)); // 股票编码 stockLhbHistoryDo.setDeptCode(tempObject.getString(OPERATEDEPT_CODE)); // 营业部编码 stockLhbHistoryDo.setDeptName(tempObject.getString(OPERATEDEPT_NAME)); // 营业部名称 stockLhbHistoryDo.setSortNum(sortNum.incrementAndGet()); // 排序编号1~5 // 买入金额接口返回单位为元转换为万元除以10000 stockLhbHistoryDo.setBuyMoney( BigDecimalUtil.div( tempObject.getBigDecimal(BUY), Const.MONEY_WAN_CONVERT // 常量值为10000 ) ); // 买入占成交比例接口返回小数转换为百分比乘以100 stockLhbHistoryDo.setBuyPercent(BigDecimalUtil.mul100B( tempObject.getBigDecimal(TOTAL_BUYRIO) )); // 卖出金额接口返回单位为元转换为万元 stockLhbHistoryDo.setSellMoney( BigDecimalUtil.div( tempObject.getBigDecimal(SELL), Const.MONEY_WAN_CONVERT ) ); // 卖出占成交比例接口返回小数转换为百分比 stockLhbHistoryDo.setSellPercent( BigDecimalUtil.mul100B(tempObject.getBigDecimal(TOTAL_SELLRIO)) ); // 净额接口返回单位为元转换为万元买入-卖出 stockLhbHistoryDo.setSubMoney( BigDecimalUtil.div( tempObject.getBigDecimal(NET), Const.MONEY_WAN_CONVERT ) ); result.add(stockLhbHistoryDo); // 添加到结果列表 }); return result; // 返回解析后的明细列表 }✅ 明细解析重点必记① 单位转换接口返回的金额单位为“元”代码中通过BigDecimalUtil.div除以10000转换为“万元”更符合量化分析习惯② 比例转换接口返回的买卖占比为小数如0.05通过BigDecimalUtil.mul100B乘以100转换为百分比如5.00③ 排序编号用AtomicInteger自增标记营业部的排名买入/卖出前五便于后续策略筛选“买入第一营业部”等场景。四、实战联动龙虎榜数据如何嵌入量化策略爬取、解析、存储龙虎榜数据后核心是联动第51篇的全市场数据实现「全市场筛选龙虎榜主力加持资金流向」的三维筛选大幅提升策略的精准度示例如下核心策略片段可直接复用/** * 龙虎榜强势标的筛选策略高胜率短线策略 * param date 日期格式yyyyMMdd * return 筛选后的优质标的列表 */ public ListStockLhbHistoryDo lhbStrongStrategy(String date) { // 1. 获取当日龙虎榜所有明细数据调用本篇核心入口方法 ListStockLhbHistoryDo lhbList extStockService.findLhbCodeByDateRange(date, date); if (CollectionUtil.isEmpty(lhbList)) { return Collections.emptyList(); } // 2. 获取全市场股票数据复用第51篇核心方法 MapString, DBStockInfo allStockMap findAllNowStockInfo(); if (MapUtil.isEmpty(allStockMap)) { return Collections.emptyList(); } // 3. 筛选逻辑龙虎榜净额为正主力净流入 买入占比5% 全市场资金净流入 return lhbList.stream() // 3.1 只保留买入明细type1且排序编号3买入前三营业部 .filter(lhb - lhb.getType() 1 lhb.getSortNum() 3) // 3.2 净额为正主力净流入 .filter(lhb - lhb.getSubMoney() ! null lhb.getSubMoney().compareTo(BigDecimal.ZERO) 0) // 3.3 买入占成交比例5%主力买入力度足 .filter(lhb - lhb.getBuyPercent() ! null lhb.getBuyPercent().compareTo(new BigDecimal(5.00)) 0) // 3.4 联动全市场数据筛选资金净流入的股票 .filter(lhb - { DBStockInfo stockInfo allStockMap.get(lhb.getCode()); if (stockInfo null) { return false; } // 复用第51篇的资金数据判断逻辑主力净流入0 return stockInfo.getTradeValue() 0 stockInfo.getAmplitude() 0; }) // 3.5 去重同一股票只保留一条取买入占比最高的营业部 .collect(Collectors.toMap( StockLhbHistoryDo::getCode, Function.identity(), (oldValue, newValue) - oldValue.getBuyPercent().compareTo(newValue.getBuyPercent()) 0 ? oldValue : newValue )) .values().stream().collect(Collectors.toList()); }✅ 策略亮点① 精准筛选结合龙虎榜“买入前三营业部、净额为正、买入占比高”锁定主力真拉升的标的② 联动全市场数据避免只看龙虎榜而忽略整体市场资金进一步提升策略容错率③ 去重处理同一股票只保留最优明细避免重复筛选提升策略执行效率。五、爬取解析10大避坑指南⚠️实战必看少走弯路结合实战经验整理了龙虎榜数据爬取、解析、存储全流程的10大高频坑每一个都附解决方案帮你避免数据抓取失败、解析报错、接口封禁、存储异常等问题确保数据正常落地。爬取层面5大坑1. 坑1接口URL拼接错误尤其是日期格式、股票编码格式导致获取不到数据✅ 解决严格使用addPattern2DateStr、addPattern2Code方法格式化日期和股票编码适配接口要求2. 坑2未去除接口返回的回调前缀/后缀导致JSON解析失败✅ 解决必须执行content.substring操作去除CB_LHB前缀和末尾的后缀确保获取纯JSON字符串3. 坑3未复用HttpClient反爬配置高频爬取导致IP封禁✅ 解决必须调用HttpClientConfig.proxyNoUseCloseableHttpClient()复用前51篇的反爬配置4. 坑4明细接口参数错误报表名称、排序字段导致获取不到明细数据✅ 解决牢记type1对应买入报表名称RPT_BILLBOARD_DAILYDETAILSBUY、排序BUYtype2对应卖出不可混淆5. 坑5分页爬取时未判断总页数0导致无限循环✅ 解决先调用getLhbTotalPage获取总页数若0直接返回空列表避免无限循环。解析层面3大坑6. 坑6接口字段映射错误如把BUY当成卖出金额导致数据赋值错误✅ 解决牢记明细接口字段对应关系BUY买入金额、SELL卖出金额、NET净额不可混淆7. 坑7未做空值校验导致BigDecimal字段空指针异常如subMoney为null✅ 解决解析时对BigDecimal字段做空值校验策略筛选时也需校验避免空指针8. 坑8日期格式化错误导致currDate字段赋值失败✅ 解决严格使用DateUtil.parse传入正确的日期格式Const.DATE_FORMAT不可随意修改。存储层面2大坑9. 坑9未使用批量存储单条插入导致大数据量存储效率低下✅ 解决严格使用saveBatch方法批次大小设为1000提升存储效率10. 坑10数据库表字段类型与实体类不匹配如buy_money设为int导致存储失败✅ 解决严格按照给定的表结构建表金额字段用decimal(18,4)与实体类BigDecimal对应。六、福利领取龙虎榜完整代码包免费送为了帮大家快速落地龙虎榜数据爬取整理了本次第52篇的完整可运行代码包包含所有代码片段、配置文件、数据库表结构直接导入项目即可运行无需二次开发、无需调试参数1. ① 核心6个方法完整代码所有爬取解析存储方法2. ② 实体类完整代码StockLhbHistoryDo3. ③ 数据库表SQL直接执行建表4. ④ 接口配置文件application.yml片段直接复制5. ⑤ 实战联动策略完整代码全市场龙虎榜资金6. ⑥ 避坑手册图文版含常见问题解决方案。私信回复【龙虎榜完整代码】即可免费领取所有代码均注释完善适配某券商最新接口兼容前51篇的量化框架新手也能快速上手打通“全市场数据龙虎榜主力数据”的闭环。下期预告✨第52篇我们搞定了龙虎榜数据的爬取解析存储实战联动实现了“精准捕捉主力动向”的核心需求让量化策略从“普适”升级为“精准”下一篇第53篇我们将聚焦 获取股票的公告上欢迎大家阅读。结尾互动你在爬取龙虎榜数据时有没有踩过接口解析报错、数据存储失败、IP封禁的坑需要我提前补充「定时抓取异常告警的完整代码」帮你实现龙虎榜数据自动更新吗欢迎在评论区留言讨论如果觉得这篇文章对你有帮助别忘了点赞在看转发让更多量化开发者少走弯路一起完善自己的量化交易体系 关注我持续解锁Java量化实战干货文章仅供学习使用千万不可应用于股市避免对某券商产生服务器压力。#金亥跃江 #金亥跃江聊量化 #Java量化 #龙虎榜