1、A股大盘数据采集
1.1 A股大盘数据采集准备
1.1.1 配置ID生成器bean
A股大盘数据采集入库时,主键ID保证唯一,所以在stock_job工程配置ID生成器:
@Configuration
public class CommonConfig {/*** 配置基于雪花算法生成全局唯一id* 参与元算的参数: 时间戳 + 机房id + 机器id + 序列号* 保证id唯一* @return*/@Beanpublic IdWorker idWorker(){//指定当前为1号机房的2号机器生成return new IdWorker(2L,1L);}
}
1.1.2 股票常量数据配置
1) 配置股票地址参数
在stock_job工程下,定义股票相关配置文件application-stock.yml,该文件与stock_backend下的配置一致,然后我们把大盘、板块、股票相关的通用参数配置进来:
# 配置股票相关的参数
stock:inner: # 国内大盘ID- sh000001 # 上证ID- sz399001 # 深证IDouter: # 外盘ID- int_dji # 道琼斯- int_nasdaq # 纳斯达克- int_hangseng # 恒生- int_nikkei # 日经指数- b_TWSE # 台湾加权- b_FSSTI # 新加坡marketUrl: http://hq.sinajs.cn/list=blockUrl: http://vip.stock.finance.sina.com.cn/q/view/newSinaHy.php
2)股票常量数据封装
在stock_common工程继续完善StockInfoConfig类:
package com.itheima.stock.pojo.domain;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;
/*** @author by itheima* @Date 2021/12/30* @Description*/
@ConfigurationProperties(prefix = "stock")
@Data
public class StockInfoConfig {//a股大盘ID集合private List<String> inner;//外盘ID集合private List<String> outer;//大盘参数获取urlprivate String marketUrl;//板块参数获取urlprivate String blockUrl;
}
2) 在公共配置类上开启配置
@EnableConfigurationProperties(StockInfoConfig.class)//开启常用参数配置bean
@Configuration
public class CommonConfig {//......
}
1.1.3 A股大盘响应数据说明
var hq_str_sh000001="上证指数,3358.9338,3361.5177,3398.6161,3417.0085,3358.9338,0,0,381243178,510307202948,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2022-06-30,15:30:39,00,";
参数说明:
0:指数名称
1:开盘点
2:前收盘点
3:当前点
4:最高点
5:最低点
8:成交量
9:成交金额
30:当前日期
31:当前时间
1.2 java正则回顾
上一小结我们发现,采集的大盘数据是标准的Js格式数据(非json),需要我们自行解析处理,显然在批量解析数据时,我们可借助java的正则实现,所以接下来我们回顾下前面讲的关于正则的一些知识点。
重点应用:
- 正则表达式理解;
- 捕获组理解;
- 核心类:Pattern、Matcher;
参考:day05\资料\基础知识点预习\Java正则表达式.mhtml
@Testpublic void testRep2(){// 按指定模式在字符串查找String line = "This order was placed for QT3000! OK?";String pattern = "(\\D*)(\\d+)(.*)";// 创建 Pattern 对象Pattern r = Pattern.compile(pattern);// 现在创建 matcher 对象Matcher m = r.matcher(line);if (m.find( )) {System.out.println("Found value: " + m.group(0) );System.out.println("Found value: " + m.group(1) );System.out.println("Found value: " + m.group(2) );System.out.println("Found value: " + m.group(3) );} else {System.out.println("NO MATCH");}}
1.3 A股大盘数据采集实现
1.3.1 定义A股大盘数据采集服务
在stock_job工程下定义服务接口:
/*** @author by itheima* @Description 定义采集股票数据的定时任务的服务接口*/
public interface StockTimerTaskService {/*** 获取国内大盘的实时数据信息*/void getInnerMarketInfo();
}
定义服务接口实现:
@Service("stockTimerTaskService")
@Slf4j
public class StockTimerTaskServiceImpl implements StockTimerTaskService {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate StockInfoConfig stockInfoConfig;@Autowiredprivate IdWorker idWorker;@Overridepublic void getInnerMarketInfo() {//1.定义采集的url接口String url=stockInfoConfig.getMarketUrl() + String.join(",",stockInfoConfig.getInner());//2.调用restTemplate采集数据//2.1 组装请求头HttpHeaders headers = new HttpHeaders();//必须填写,否则数据采集不到headers.add("Referer","https://finance.sina.com.cn/stock/");headers.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");//2.2 组装请求对象HttpEntity<Object> entity = new HttpEntity<>(headers);//2.3 resetTemplate发起请求String resString = restTemplate.postForObject(url, entity, String.class);//log.info("当前采集的数据:{}",resString);//3.数据解析(重要)
// var hq_str_sh000001="上证指数,3267.8103,3283.4261,3236.6951,3290.2561,3236.4791,0,0,402626660,398081845473,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2022-04-07,15:01:09,00,";
// var hq_str_sz399001="深证成指,12101.371,12172.911,11972.023,12205.097,11971.334,0.000,0.000,47857870369,524892592190.995,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,2022-04-07,15:00:03,00";String reg="var hq_str_(.+)=\"(.+)\";";//编译表达式,获取编译对象Pattern pattern = Pattern.compile(reg);//匹配字符串Matcher matcher = pattern.matcher(resString);ArrayList<StockMarketIndexInfo> list = new ArrayList<>();//判断是否有匹配的数值while (matcher.find()){//获取大盘的codeString marketCode = matcher.group(1);//获取其它信息,字符串以逗号间隔String otherInfo=matcher.group(2);//以逗号切割字符串,形成数组String[] splitArr = otherInfo.split(",");//大盘名称String marketName=splitArr[0];//获取当前大盘的开盘点数BigDecimal openPoint=new BigDecimal(splitArr[1]);//前收盘点BigDecimal preClosePoint=new BigDecimal(splitArr[2]);//获取大盘的当前点数BigDecimal curPoint=new BigDecimal(splitArr[3]);//获取大盘最高点BigDecimal maxPoint=new BigDecimal(splitArr[4]);//获取大盘的最低点BigDecimal minPoint=new BigDecimal(splitArr[5]);//获取成交量Long tradeAmt=Long.valueOf(splitArr[8]);//获取成交金额BigDecimal tradeVol=new BigDecimal(splitArr[9]);//时间Date curTime = DateTimeUtil.getDateTimeWithoutSecond(splitArr[30] + " " + splitArr[31]).toDate();//组装entity对象StockMarketIndexInfo info = StockMarketIndexInfo.builder().id(idWorker.nextId()).marketCode(marketCode).marketName(marketName).curPoint(curPoint).openPoint(openPoint).preClosePoint(preClosePoint).maxPoint(maxPoint).minPoint(minPoint).tradeVolume(tradeVol).tradeAmount(tradeAmt).curTime(curTime).build();//收集封装的对象,方便批量插入list.add(info);}log.info("采集的当前大盘数据:{}",list);//批量插入if (CollectionUtils.isEmpty(list)) {return;}//TODO 后续完成批量插入功能}
}
1.3.2 A股大盘数据采集测试
package com.itheima.stock;import com.itheima.stock.job.service.StockTimerService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;/*** @author by itheima* @Date 2022/1/1* @Description*/
@SpringBootTest
public class TestStockTimerService {@Autowiredprivate StockTimerTaskService stockTimerService;/*** 获取大盘数据*/@Testpublic void test01(){stockTimerService.getInnerMarketInfo();}
}
效果:
1.4 A股大盘批量保存
1.4.1 定义mapper接口方法
在StockMarketIndexInfoMapper接口添加方法:
/*** 批量插入股票大盘数据* @param infos*/int insertBatch(List<StockMarketIndexInfo> infos);
1.4.2 绑定xml
在StockMarketIndexInfoMapper.xml添加SQL:
<insert id="insertBatch">insert into stock_market_index_info( id,mark_Id,cur_time,mark_name,cur_point,current_price,updown_rate,trade_account,trade_volume)values<foreach collection="list" item="smi" separator=",">(#{smi.id,jdbcType=BIGINT},#{smi.markId,jdbcType=CHAR},#{smi.curTime,jdbcType=TIMESTAMP},#{smi.markName,jdbcType=VARCHAR},#{smi.curPoint,jdbcType=DECIMAL},#{smi.currentPrice,jdbcType=DECIMAL},#{smi.updownRate,jdbcType=DECIMAL},#{smi.tradeAccount,jdbcType=BIGINT},#{smi.tradeVolume,jdbcType=BIGINT})</foreach></insert>
1.4.3 国内大盘数据批量插入实现
注入mapper,然后批量插入:
@Autowiredprivate StockMarketIndexInfoMapper stockMarketIndexInfoMapper; /*** 获取国内大盘数据*/@Overridepublic void getInnerMarketInfo() {//....省略N行....//批量插入int count = this.stockMarketIndexInfoMapper.insertBatch(infos);log.info("批量插入了:{}条数据",count);}