【java爬虫】基于springboot+jdbcTemplate+sqlite+OkHttp获取个股的详细数据

注:本文所用技术栈为:springboot+jdbcTemplate+sqlite+OkHttp

前面的文章我们获取过沪深300指数的成分股所属行业以及权重数据,本文我们来获取个股的详细数据。

我们的数据源是某狐财经,接口的详细信息在下面的文章中,本文就不再赘述了

用爬虫分析沪深300指数超长走势-CSDN博客

下面是一组url和返回值的示例

https://q.stock.sohu.com/hisHq?code=cn_000001&start=20190101&end=20190102&stat=1&order=D&period=d&callback=historySearchHandler&rt=jsonp
historySearchHandler([{"status":0,"hq":[["2019-01-02","9.39","9.19","-0.19","-2.03%","9.16","9.42","539386","49869.51","0.31%"]],"code":"cn_000001","stat":["累计:","2019-01-02至2019-01-02","-0.19","-2.03%",9.16,9.42,539386,49869.51,"0.31%"]}])

我们需要关心的是"hq"中的值,"hq"中的值是一个列表,列表中还有很多列表,每个列表代码一组数据,至于数据的具体含义,可以登陆搜狐财经网站上去看看。

宁德时代(300750) - 历史行情 - 股票行情中心 - 搜狐证券 (sohu.com)

这边我就随便截取一端数据

数据的从左到右分别代表日期,开盘价,收盘价,涨跌额,涨跌幅,最低,最高,成交量,成交金额和换手率,最后的盘后量是没有的。

那么我们就可以根据上述信息建立数据表和实体类

    @Overridepublic void createTbaleIfNotExist() {Integer count = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name = ?", Integer.class, TABLE_NAME);if (count == 0) {String sql = "CREATE TABLE " + TABLE_NAME + "(" +"id VARCHAR(50) PRIMARY KEY," +"code VARCHAR(20)," +           // 股票代码"record_date VARCHAR(20)," +    // 记录的时间"open_price float," +           // 开盘价"close_price float," +           // 收盘价"change_ament float," +          // 涨跌额"change_range float," +          // 涨跌幅"max_price float," +             // 最高价格"min_price float," +             // 最低价格"volume float," +                // 成交量(手)"turnover float," +              // 成交额(万)"turnover_rate float)";               // 换手率jdbcTemplate.execute(sql);log.info(TABLE_NAME + "建表成功");} else {log.info("建表失败,表格已存在");}}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class StockEntity {private String id;private String code;private String record_date;private Double open_price;private Double close_price;private Double change_amend;private Double change_range;private Double max_price;private Double min_price;private Double volume;private Double turnover;private Double turnover_rate;// 将数据转换为Object数组public Object[] changeToArray() {Object[] arr = new Object[]{id,code,record_date,open_price.toString(),close_price.toString(),change_amend.toString(),change_range.toString(),max_price.toString(),min_price.toString(),volume.toString(),turnover.toString(),turnover_rate.toString()};return arr;}}

其中id字段是用来放置重复插入的,他的值是code+日期,这样就能保证某一只股票当日的数据是唯一的。

下面是最重要的获取数据和插入数据的方法。

我们采用批量插入的方法,传入一个列表,一次性将列表中所有的值都插入数据库

    @Overridepublic void insertItems(List<StockEntity> entityList) {String sql = "INSERT OR IGNORE INTO " + TABLE_NAME + " (id, code, record_date," +"open_price, close_price, change_ament," +"change_range, max_price, min_price," +"volume, turnover, turnover_rate) values (?,?,?,?,?,?,?,?,?,?,?,?)";// 将列表转为Object数组List<Object[]> arr = new ArrayList<>();for(int i=0; i<entityList.size(); i++) {arr.add(entityList.get(i).changeToArray());}jdbcTemplate.batchUpdate(sql, arr);}

下面就是获取数据的代码

    // 获取数据并且存入数据库// 三个参数分别是:股票代码,开始时间和结束时间// 开始时间和结束时间都填年份,代码中会自动补全具体时间public int getDataByYear(String code, String start, String end) {String url = "https://q.stock.sohu.com/hisHq?";Request request = null;Response response = null;int num = 0;try {for (int i = Integer.parseInt(start); i <= Integer.parseInt(end); i++) {for (int j = 1; j <= 12; j++) {HttpUrl.Builder httpBuiler = HttpUrl.parse(url).newBuilder();String starttime = null;String endtime = null;if (j != 12) {StringBuilder sb = new StringBuilder();sb.append(i);if (j < 10) {sb.append("0");}sb.append(j);sb.append("01");starttime = sb.toString();sb = new StringBuilder();sb.append(i);if (j + 1 < 10) {sb.append("0");}int tmp = j + 1;sb.append(tmp);sb.append("01");endtime = sb.toString();} else {starttime = i + "1201";endtime = i + "1231";}log.info("开始计算时间段[" + starttime + "," + endtime + "]内数据");httpBuiler.addQueryParameter("code", "cn_" + code);httpBuiler.addQueryParameter("start", starttime);httpBuiler.addQueryParameter("end", endtime);httpBuiler.addQueryParameter("stat", "1");httpBuiler.addQueryParameter("order", "D");httpBuiler.addQueryParameter("period", "d");httpBuiler.addQueryParameter("callback", "history");httpBuiler.addQueryParameter("rt", "jsonp");request = new Request.Builder().url(httpBuiler.build()).get()   //默认就是GET请求,可以不写.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36").build();response = client.newCall(request).execute();String res = response.body().string();log.info("请求得到的数据:" + res);// 将数据解析成List列表if (!res.equals(NO_DATA_RESPONSE1) && !res.equals(NO_DATA_RESPONSE2)) {List<StockEntity> entities = parseStrToArr(res, code);sqLiteStockDao.insertItems(entities);log.info("时间段[" + starttime + "," + endtime + "]内有" + entities.size() + "条数据");num += entities.size();} else {log.info("时间段[" + starttime + "," + endtime + "]没有数据");}}}} catch (IOException e) {e.printStackTrace();}return num;}// 将string数据解析成List列表private List<StockEntity> parseStrToArr(String res, String code) {List<StockEntity> entities = new ArrayList<>();res = res.split("\\(\\[")[1].split("]\\)")[0];JSONObject jsonObject = JSON.parseObject(res);// 获取 hq 字段的值Object hq = jsonObject.get("hq");// 判断 hq 的值是否为数组if (hq instanceof JSONArray) {// 遍历数组for (Object arr : (JSONArray) hq) {JSONArray jsonArray = (JSONArray) arr;StockEntity entity = new StockEntity();entity.setRecord_date((String) jsonArray.get(0));Double open_price = Double.parseDouble((String) jsonArray.get(1));Double close_price = Double.parseDouble((String) jsonArray.get(2));Double change_amend = Double.parseDouble((String) jsonArray.get(3));Double change_range = Double.parseDouble(((String) jsonArray.get(4)).split("%")[0]);Double max_price = Double.parseDouble((String) jsonArray.get(5));Double min_price = Double.parseDouble((String) jsonArray.get(6));Double volume = Double.parseDouble((String) jsonArray.get(7));Double turnover = Double.parseDouble((String) jsonArray.get(8));Double turnover_rate = Double.parseDouble(((String) jsonArray.get(9)).split("%")[0]);entity.setOpen_price(open_price);entity.setClose_price(close_price);entity.setChange_amend(change_amend);entity.setChange_range(change_range);entity.setMax_price(max_price);entity.setMin_price(min_price);entity.setVolume(volume);entity.setTurnover(turnover);entity.setTurnover_rate(turnover_rate);entity.setCode(code);entity.setId(entity.getCode() + "_" + (String) jsonArray.get(0));entities.add(entity);}}return entities;}

主要就是获取了数据然后进行解析,每一次解析都是从当前月份的1日到第二个月的1日,如果是12月的话是从12月1日到12月31日。

最后提供一个get接口进行方法的调用

    @RequestMapping("/getDataByYear/{code}/{start}/{end}")@ResponseBodypublic String getDataByYear(@PathVariable("code") String code,@PathVariable("start") String start,@PathVariable("end") String end) {Integer num = stockService.getDataByYear(code, start, end);return num.toString();}

最后获取到的数据是这样的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/297304.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python小细节之代码极致简化到一行(2)(技法慎用)

一行代码合并字典&#xff08;新字典&#xff09; 引言开整一行代码合并字典普通方法举例 简化高级方法举例 总结&#xff1a;结尾 引言 上次的极简化&#xff0c;看起来大家反应还不错 所以继续肝&#xff0c;但是我觉得这种讲细一点会比较好 所以&#xff0c;每次就KO一个…

Point-BERT:一种基于Transformer架构的点云深度网络

目录 1. 前言 2. Point Tokenization 3. Transformer Backbone 4. Masked Point Modeling 5. Experiments Reference 1. 前言 从PointNet [1] 开始&#xff0c;点云深度网络逐渐成为解决点云特征提取与语义分析的主要研究方向。尤其在OpenAI的GPT模型获得了突破性成果后&#…

CleanMyMac X 4.14.6最新版本使用实用技巧

我们称赞 Mac 的设计、简单性和安全性&#xff0c;却常常忽视了它们的功能。有如此之多的功能、快捷方式和技巧&#xff0c;一旦理解&#xff0c;就可以简化您的生活&#xff0c;让使用 Mac 变得更加有趣。你对学习这些感到兴奋吗&#xff1f;以下是 5 个简单的Mac实用技巧分享…

CDA数据分析师备考必看,L1L2通用

CDA数据分析师L1,L2均可 可安排当月月底的线上考试 线上考的为双机位监考&#xff0c;但是不用担心 安全无隐患&#xff0c;需要联系 当月拿证

如何使用固定二级子域名公网访问多个本地Windows Web网站

文章目录 1. 下载windows版Nginx2. 配置Nginx3. 测试局域网访问4. cpolar内网穿透5. 测试公网访问6. 配置固定二级子域名7. 测试访问公网固定二级子域名 1. 下载windows版Nginx 进入官方网站(http://nginx.org/en/download.html)下载windows版的nginx 下载好后解压进入nginx目…

【美团大数据面试】Java面试题附答案

目录 1.多线程代码示例 2.单例代码示例 3.LinkedBlockingQueue原理解析 4.模板设计模式讲解 5.生产者-消费者队列设计方法 6.堆内存和栈内存的区别 7.ThreadLocal底层机制 8.synchronized原理&#xff0c;存在的问题&#xff0c;解决方案 9.volatile使用场景和原理&am…

IDEA中使用数据库可视化操作工具

文章目录 1.入门介绍2. 没有数据库驱动3. 准备&测试连接3.1测试报错 4.连接5.编写SQL语句 1.入门介绍 在IDEA的专业版的右侧工具栏应该会有DataBase按钮如果没有的同学可以这样操作(必须是IDEA专业版) 新建数据库 2. 没有数据库驱动 如果提示: missing driver files ,…

小狐狸ChatGPT付费创作系统 安装或者升级后出现404错误无法登陆或一直提示解决办法

近几天很多会员安装或者升级小狐狸ChatGPT付费创作系统至2.1.8版本&#xff0c;不管打开超管后台或者站点管理后台都出现404的错误提示&#xff0c;或者新安装登陆超管后台还是提示未登陆状态。近几天将系统安装至多台服务器多个站点测试均出现以下提示&#xff0c;重启了服务器…

C# float/double 减 float/double 等 (X.xxxxxxxxxxxxxE-07)(黑盒测试)

问题 因为没有深究原理&#xff0c;所有只进行了“黑盒测试” 黑盒测试结论&#xff1a; 问题操作结论float/double运算进过一系列的运算后大概率 &#xff01; 0.0 &#xff0c; 而是等于0.00000000000xxxx等于X.xxxxxxxx一串数字的时候不影响下一步继续使用当需要显示fl…

Django之按钮(actions)

开篇就是道歉&#xff0c;哈哈哈哈&#xff0c;托更了好久好久&#xff0c;最近太忙了没啥时间更新&#xff0c;各位看官有催更的阔以给我私信哇&#xff0c;希望各位看官给个三连&#xff01;&#xff01;&#xff01;&#x1f60d;&#x1f60d;&#x1f60d;&#x1f60d; …

SLAM算法与工程实践——SLAM基本库的安装与使用(6):g2o优化库(2)g2o编程框架

SLAM算法与工程实践系列文章 下面是SLAM算法与工程实践系列文章的总链接&#xff0c;本人发表这个系列的文章链接均收录于此 SLAM算法与工程实践系列文章链接 下面是专栏地址&#xff1a; SLAM算法与工程实践系列专栏 文章目录 SLAM算法与工程实践系列文章SLAM算法与工程实践…

嵌入式 开发——DMA内存到外设

学习目标 加强理解DMA数据传输过程加强掌握DMA的初始化流程掌握DMA数据表查询理解源和目标的配置理解数据传输特点能够动态配置源数据学习内容 需求 串口发送数据 uint8_t data = 0x01; 串口发送(data); 实现串口的发送数据, 要求采用dma的方式 数据交互流程 CPU配置好DM…