Compare commits

...

57 Commits

Author SHA1 Message Date
Congkiet4695
f87df03715 fix bug 2024-12-11 00:01:57 +07:00
vpckiet
fc59d1f47c Merge branch 'bug/update_symbol' into 'develop'
fix bug chart day

See merge request india/india_market_java!54
2024-12-10 14:57:04 +00:00
vpckiet
6fdc13a72d fix bug chart day 2024-12-10 21:56:23 +07:00
vpckiet
6b5623dc33 Merge branch 'bug/update_symbol' into 'develop'
fix bug get chart

See merge request india/india_market_java!53
2024-12-10 13:15:40 +00:00
vpckiet
4a22fc0a95 fix bug get chart 2024-12-10 20:14:42 +07:00
vpckiet
563dae1c45 Merge branch 'feature/update_bseindia_detail' into 'develop'
update chart

See merge request india/india_market_java!52
2024-12-10 12:55:38 +00:00
vpckiet
fa02ebf03b update chart 2024-12-10 19:54:45 +07:00
vpckiet
0f5f25f744 Merge branch 'feature/update_bseindia_detail' into 'develop'
update get detail from bseindia

See merge request india/india_market_java!51
2024-12-10 09:38:33 +00:00
vpckiet
615aae7e1d update get detail from bseindia 2024-12-10 16:37:54 +07:00
vu-tran
c89345329d uncomment scheduler 2024-11-12 11:13:22 +07:00
vpckiet
f18521d190 Merge branch 'bug/nse_type' into 'develop'
fix bug

See merge request india/india_market_java!50
2024-10-28 10:40:50 +00:00
vpckiet
e84c212bf0 fix bug 2024-10-28 17:40:04 +07:00
vogiahuy2058
1ff1797b0b done new logic to add moneystock 2024-10-24 14:10:42 +07:00
vogiahuy2058
89c0fe0321 change cron 2024-10-23 16:39:41 +07:00
vogiahuy2058
b6052a46ff done save exchange type and save money stock 2024-10-23 16:35:59 +07:00
vpckiet
d40c30bcb5 Merge branch 'bug/crawl_news' into 'develop'
update crawl

See merge request india/india_market_java!48
2024-10-21 09:19:14 +00:00
vpckiet
5b16f1f2c9 update crawl 2024-10-21 16:14:22 +07:00
vpckiet
b8d4e0d3f2 Merge branch 'bug/update_kline_format' into 'develop'
update

See merge request india/india_market_java!46
2024-10-10 03:50:50 +00:00
vpckiet
c19277e390 update 2024-10-10 10:50:01 +07:00
vpckiet
514875878f Merge branch 'bug/update_kline_format' into 'develop'
fix bug kline

See merge request india/india_market_java!45
2024-10-10 01:47:17 +00:00
vpckiet
4257541342 fix bug kline 2024-10-09 17:18:26 +07:00
quangnguyen202
441adac15a Merge branch 'feature/optional-stock' into 'develop'
Add api for optional stock

See merge request india/india_market_java!44
2024-10-01 07:07:59 +00:00
quangnguyen202
ba29ab98c7 Add api for optional stock 2024-10-01 14:06:24 +07:00
Gavin g
94ec73874b Merge branch 'feature/kline-alternate-source' into 'develop'
Add alternate source

See merge request india/india_market_java!43
2024-09-26 09:57:06 +00:00
quangnguyen202
549345719a Add alternate source 2024-09-26 16:51:41 +07:00
gavin
3870400411 修改切换备用数据源的判断条件 2024-09-19 15:59:12 +08:00
Gavin g
94d2936ffb Merge branch 'feature/stock-kline-nseindia' into 'develop'
Add alternal source

See merge request india/india_market_java!42
2024-09-19 07:37:45 +00:00
quangnguyen202
59e4aa9e1a Add alternal source 2024-09-19 14:33:22 +07:00
gavin
bae645e3c6 修复官方查询时名称写死的问题 2024-09-12 14:15:31 +08:00
gavin
94d9aea2c8 指定股票更换详情测试代码 2024-09-10 13:11:01 +08:00
gavin
5ae9762d45 指定股票更换详情测试代码 2024-09-09 14:59:38 +08:00
quangnguyen202
ece52491dd Merge branch 'refactor/optimization' into 'develop'
Optimize

See merge request india/india_market_java!38
2024-09-09 06:54:16 +00:00
quangnguyen202
6235d41711 Optimize 2024-09-06 11:17:41 +07:00
vpckiet
c865eccaf4 Merge branch 'refactor/optimization' into 'develop'
Optimize code

See merge request india/india_market_java!37
2024-09-06 01:53:33 +00:00
quangnguyen202
136020a497 Update 2024-09-05 16:30:46 +07:00
quangnguyen202
d7da59aca1 Optimize code 2024-09-05 15:59:13 +07:00
gavin
8427bed427 指定股票更换详情测试代码 2024-09-04 12:52:17 +08:00
gavin
269f02b79d 指定股票更换详情测试代码 2024-09-04 11:56:04 +08:00
gavin
7cc456bcd8 同步手动更新代码 2024-09-02 15:32:50 +08:00
vpckiet
be05d403af Merge branch 'bug/craw_img_news' into 'develop'
update crawl img news

See merge request india/india_market_java!33
2024-09-02 06:47:52 +00:00
Congkiet4695
4a29bf6659 update crawl img news 2024-09-02 13:46:22 +07:00
gavin
5b2eb8519a 大盘缓存数据改为6秒 2024-07-26 15:04:56 +08:00
gavin
2e4449bd64 大盘数据更换moneycontrol 数据源 2024-07-26 14:53:50 +08:00
Thanh Nguyen
b321fd9d4e Update automatic-deployment link 2024-07-23 09:39:48 +07:00
gavin
2f9e54bf4f 更改数据库连接
更新新闻时间格式为24小时制
2024-07-12 15:33:25 +08:00
3bb354bbc6 Merge remote-tracking branch 'origin/develop' into develop 2024-07-08 12:38:26 +08:00
a403cba964 fix: 时间字段错乱 2024-07-08 12:38:13 +08:00
Achilles
99bde81670 Merge remote-tracking branch 'origin/develop' into develop 2024-06-28 17:00:04 +08:00
Achilles
bae941828e 代码优化和优化 2024-06-28 16:59:58 +08:00
gs
2f86571578 价格问题处理 2024-06-25 18:00:21 +08:00
gs
d491bef735 新闻时间处理 2024-06-25 17:45:15 +08:00
gs
74c64eb7d4 Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	src/main/java/cn/stock/market/web/StockApiController.java
2024-06-20 16:55:50 +08:00
gs
f50b6b5519 新闻时间处理 2024-06-20 16:54:56 +08:00
2446d89b30 fix: 时间字段错乱 2024-06-20 16:33:38 +08:00
gs
33a68eb7e8 新闻处理 2024-06-20 14:50:15 +08:00
gs
7b0a08150d Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	src/main/java/cn/stock/market/domain/basic/service/StockService.java
2024-06-20 14:47:53 +08:00
gs
146e9d9bc0 新闻处理 2024-06-20 14:47:04 +08:00
23 changed files with 1386 additions and 202 deletions

View File

@@ -2,7 +2,7 @@ stages:
# 构建 # 构建
- build - build
- dockerize - dockerize
- webhook - deploy
build: build:
image: maven:3.6.3-openjdk-8 image: maven:3.6.3-openjdk-8
@@ -60,16 +60,20 @@ dockerize:
- docker push juyoutech/india_stock_market:latest - docker push juyoutech/india_stock_market:latest
- docker push juyoutech/india_stock_market:$CI_PIPELINE_ID - docker push juyoutech/india_stock_market:$CI_PIPELINE_ID
- docker push juyoutech/india_stock_market:$CI_COMMIT_BRANCH - docker push juyoutech/india_stock_market:$CI_COMMIT_BRANCH
webhook: deploy-dev:
stage: webhook stage: deploy
only: only:
- develop - develop
script: script:
- echo ">>>>>>Start Deploy<<<<<<" - echo "Deploying application..."
- ls - ls
- apt-get update - apt-get update
- apt-get install -y curl - apt-get install -y curl
- curl --max-time 30 http://149.88.86.7:11113/api/webhook/justpull?project=india_market_java\&setenv_file=alpha.sh\&publish_env=alpha\&shell=deploy-test.sh - |
- echo ">>>>>>Start Deploy Finish<<<<<<" curl -X POST \
-H "Content-Type: application/json" \
-d '{"namespace":"yddev", "deployment_name":"india-stock-market"}' \
https://updater-yddev.moneytj.com/restart-deployment
- echo "Application successfully deployed."

View File

@@ -185,6 +185,12 @@
<version>30.1-jre</version> <version>30.1-jre</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@@ -0,0 +1,41 @@
package cn.stock.market.infrastructure.db.po;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.Generated;
import com.querydsl.core.types.Path;
/**
* QOptionalStockPO is a Querydsl query type for OptionalStockPO
*/
@Generated("com.querydsl.codegen.EntitySerializer")
public class QOptionalStockPO extends EntityPathBase<OptionalStockPO> {
private static final long serialVersionUID = 1161631810L;
public static final QOptionalStockPO optionalStockPO = new QOptionalStockPO("optionalStockPO");
public final StringPath company = createString("company");
public final NumberPath<Integer> id = createNumber("id", Integer.class);
public final StringPath symbol = createString("symbol");
public QOptionalStockPO(String variable) {
super(OptionalStockPO.class, forVariable(variable));
}
public QOptionalStockPO(Path<? extends OptionalStockPO> path) {
super(path.getType(), path.getMetadata());
}
public QOptionalStockPO(PathMetadata metadata) {
super(OptionalStockPO.class, metadata);
}
}

View File

@@ -38,6 +38,7 @@ public class QStockIpoPO extends EntityPathBase<StockIpoPO> {
public final StringPath stockCode = createString("stockCode"); public final StringPath stockCode = createString("stockCode");
public final StringPath stockName = createString("stockName"); public final StringPath stockName = createString("stockName");
public final StringPath exchangeType = createString("exchangeType");
public final NumberPath<java.math.BigDecimal> stockPrice = createNumber("stockPrice", java.math.BigDecimal.class); public final NumberPath<java.math.BigDecimal> stockPrice = createNumber("stockPrice", java.math.BigDecimal.class);

View File

@@ -0,0 +1,16 @@
package cn.stock.market.domain.basic.convert;
import cn.qutaojing.common.domain.convert.SimpleEntityPOConvert;
import cn.qutaojing.common.utils.SpringUtils;
import cn.stock.market.domain.basic.entity.OptionalStock;
import cn.stock.market.infrastructure.db.po.OptionalStockPO;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
@Lazy
public class OptionalStockConvert extends SimpleEntityPOConvert<OptionalStock, OptionalStockPO> {
public static OptionalStockConvert of() {
return SpringUtils.getBean(OptionalStockConvert.class);
}
}

View File

@@ -0,0 +1,16 @@
package cn.stock.market.domain.basic.entity;
import cn.stock.market.infrastructure.db.po.OptionalStockPO;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@Data
@NoArgsConstructor
@SuperBuilder
@EqualsAndHashCode(
callSuper = false
)
public class OptionalStock extends OptionalStockPO {
}

View File

@@ -0,0 +1,32 @@
package cn.stock.market.domain.basic.repository;
import cn.qutaojing.common.domain.convert.IEntityPOConvert;
import cn.qutaojing.common.domain.respostory.SimplePoConvertEntityRepository;
import cn.stock.market.domain.basic.convert.OptionalStockConvert;
import cn.stock.market.domain.basic.entity.OptionalStock;
import cn.stock.market.infrastructure.db.po.OptionalStockPO;
import cn.stock.market.infrastructure.db.repo.OptionalStockRepo;
import com.rp.spring.jpa.GenericJpaRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
@RequiredArgsConstructor(
onConstructor = @__(@Autowired)
)
public class OptionalStockRepository extends SimplePoConvertEntityRepository<OptionalStock, OptionalStockPO, Integer> {
final OptionalStockRepo repo;
final OptionalStockConvert convert;
@Override
public GenericJpaRepository<OptionalStockPO, Integer> repo() {
return repo;
}
@Override
public IEntityPOConvert<OptionalStock, OptionalStockPO> convert() {
return convert;
}
}

View File

@@ -30,6 +30,8 @@ import org.apache.commons.lang3.StringUtils;
import cn.stock.market.infrastructure.db.po.QStockPO; import cn.stock.market.infrastructure.db.po.QStockPO;
import org.jsoup.Jsoup; import org.jsoup.Jsoup;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
@@ -247,12 +249,25 @@ public class StockService {
String result = ""; String result = "";
try { try {
// 使用Jsoup连接到网页 // 使用Jsoup连接到网页
Document doc = Jsoup.connect("https://www.business-standard.com/markets/news") // Document doc = Jsoup.connect("https://www.business-standard.com/markets/news")
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36") // .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36")
.header("Referer", "https://www.business-standard.com/") // .header("Referer", "https://www.business-standard.com/")
// .header("Accept-Language", "en-US,en;q=0.9")
// .get();
String url = "https://www.business-standard.com/markets/news";
Document doc = Jsoup.connect(url)
.referrer("https://www.business-standard.com/")
.header("Accept-Language", "en-US,en;q=0.9") .header("Accept-Language", "en-US,en;q=0.9")
.userAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1")
.timeout(5000) // timeout 5 seconds
.get(); .get();
result = doc.html().substring(doc.html().indexOf("<div class=\"shortvideoimg\" style=\"position:relative\">"),doc.html().lastIndexOf("<div class=\"shortvideoimg\" style=\"position:relative\">")+1200); // result = doc.html().substring(doc.html().indexOf("<div class=\"listingstyle_shortvideoimg__0TWuX shortvideoimg\">"),doc.html().lastIndexOf("<div class=\"listingstyle_shortvideoimg__0TWuX shortvideoimg\">")+500);
Elements divElements = doc.select("div.listingstyle_cardlistlist__dfq57");
StringBuilder sb = new StringBuilder();
for (Element divElement : divElements) {
sb.append(divElement.outerHtml()).append("\n");
}
result = sb.toString();
} catch (Exception e) { } catch (Exception e) {
return e.toString(); return e.toString();
} }
@@ -264,10 +279,16 @@ public class StockService {
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
try { try {
// 使用Jsoup连接到网页 // 使用Jsoup连接到网页
// Document doc = Jsoup.connect(url)
// .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36")
// .header("Referer", "https://www.business-standard.com/")
// .header("Accept-Language", "en-US,en;q=0.9")
// .get();
Document doc = Jsoup.connect(url) Document doc = Jsoup.connect(url)
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36") .referrer("https://www.business-standard.com/")
.header("Referer", "https://www.business-standard.com/")
.header("Accept-Language", "en-US,en;q=0.9") .header("Accept-Language", "en-US,en;q=0.9")
.userAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1")
.timeout(5000) // timeout 5 seconds
.get(); .get();
result = doc.html().substring(doc.html().indexOf("articleBody") + 14, doc.html().indexOf(",\"author\":") - 1); result = doc.html().substring(doc.html().indexOf("articleBody") + 14, doc.html().indexOf(",\"author\":") - 1);
list.add(result); list.add(result);
@@ -974,7 +995,7 @@ public class StockService {
String exchange = "bse"; String exchange = "bse";
IndiaIndexVo vo1 = new IndiaIndexVo(); IndiaIndexVo vo1 = new IndiaIndexVo();
String coCode = "20558"; String coCode = "20558";
JSONObject object = TodayApis.getStockDetail(exchange, coCode); JSONObject object = TodayApis.getStockDetail("in%3BSEN", coCode);
IndiaStockVO market = objToVo(object); IndiaStockVO market = objToVo(object);
market.setName("BSESENSEX指数"); market.setName("BSESENSEX指数");
vo1.setIndexVo(market); vo1.setIndexVo(market);
@@ -1004,7 +1025,7 @@ public class StockService {
String exchange = "nse"; String exchange = "nse";
IndiaIndexVo vo1 = new IndiaIndexVo(); IndiaIndexVo vo1 = new IndiaIndexVo();
String coCode = "20559"; String coCode = "20559";
JSONObject object = TodayApis.getStockDetail(exchange, coCode); JSONObject object = TodayApis.getStockDetail("in%3BNSX", coCode);
IndiaStockVO market = objToVo(object); IndiaStockVO market = objToVo(object);
market.setName("NIFTY50指数"); market.setName("NIFTY50指数");
vo1.setIndexVo(market); vo1.setIndexVo(market);
@@ -1034,23 +1055,23 @@ public class StockService {
} }
private IndiaStockVO objToVo(JSONObject object){ private IndiaStockVO objToVo(JSONObject object){
IndiaStockVO market = new IndiaStockVO(); IndiaStockVO market = new IndiaStockVO();
if(object.containsKey("prev_close")){ if(object.containsKey("priceprevclose")){
market.setClose(object.getString("prev_close")); market.setClose(object.getString("priceprevclose"));
} }
if(object.containsKey("price")){ if(object.containsKey("pricecurrent")){
market.setNowPrice(object.getString("price")); market.setNowPrice(object.getString("pricecurrent"));
} }
if(object.containsKey("perchg")){ if(object.containsKey("pricepercentchange")){
market.setRate(object.getString("perchg")); market.setRate(object.getString("pricepercentchange"));
} }
if(object.containsKey("high_price")){ if(object.containsKey("HIGH")){
market.setHigh(object.getString("high_price")); market.setHigh(object.getString("HIGH"));
} }
if(object.containsKey("low_price")){ if(object.containsKey("LOW")){
market.setLow(object.getString("low_price")); market.setLow(object.getString("LOW"));
} }
if(object.containsKey("open_price")){ if(object.containsKey("OPEN")){
market.setOpen(object.getString("open_price")); market.setOpen(object.getString("OPEN"));
} }
return market; return market;
// stockListVO.setName(jsonObject.getString("companyname")); // stockListVO.setName(jsonObject.getString("companyname"));

View File

@@ -0,0 +1,18 @@
package cn.stock.market.dto;
import lombok.Data;
@Data
public class OptionalStockResponse {
private String message;
private Integer code;
private DataResponse data = new DataResponse();
@Data
public static class DataResponse {
private String symbol;
private String company;
private Double pricecurrent;
private Float pricepercentchange;
}
}

View File

@@ -0,0 +1,48 @@
package cn.stock.market.dto.query;
import lombok.Data;
import java.time.LocalDate;
@Data
public class StockChartDto {
private Long timestamp;
private double open;
private double high;
private double low;
private double close;
private double volume;
public StockChartDto(Long date, double open, double high, double low, double close, double volume) {
this.timestamp = date;
this.open = open;
this.high = high;
this.low = low;
this.close = close;
this.volume = volume;
}
public double getVolume() {
return volume;
}
public Long getTimestamp() {
return timestamp;
}
public double getOpen() {
return open;
}
public double getHigh() {
return high;
}
public double getLow() {
return low;
}
public double getClose() {
return close;
}
}

View File

@@ -187,18 +187,17 @@ public class TodayApis {
//获取详情 //获取详情
public static JSONObject getStockDetail(String exchange,String coCode){ public static JSONObject getStockDetail(String exchange,String coCode){
String url = String.format("https://marketapi.intoday.in/widget/stockdetail/pullview?co_code=%s&exchange=%s",coCode,exchange); String url = String.format("https://priceapi.moneycontrol.com/pricefeed/notapplicable/inidicesindia/%s",exchange);
String str = get(url); String str = get(url);
JSONObject object = JSON.parseObject(str); JSONObject object = JSON.parseObject(str);
boolean bool = false; boolean bool = false;
if(object.containsKey("success")){ if(object.containsKey("code")){
bool = object.getBoolean("success"); bool = object.getInteger("code") == 200;
} }
if(!bool){ if(!bool){
return new JSONObject(); return new JSONObject();
} }
JSONArray jsonArray = JSON.parseArray(object.getString("data")); JSONObject entity = JSON.parseObject(object.getString("data"));
JSONObject entity = JSON.parseObject(jsonArray.get(0).toString());
return entity; return entity;
} }

View File

@@ -56,6 +56,14 @@ public class MoneyStockPO {
* 展示表示 */ * 展示表示 */
String selfDispId; String selfDispId;
/**
* NSE India的id */
String nseIndiaId;
/**
* NSE India Chart的id */
String nseIndiaChartId;
/** /**
* 自有self_url */ * 自有self_url */
String selfUrl; String selfUrl;
@@ -75,4 +83,6 @@ public class MoneyStockPO {
/** /**
* 是否展示 0是 1否 */ * 是否展示 0是 1否 */
Integer isShow; Integer isShow;
Boolean useFromBseindia = false;
} }

View File

@@ -0,0 +1,35 @@
package cn.stock.market.infrastructure.db.po;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@SuperBuilder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@DynamicInsert
@DynamicUpdate
@Table(
name = "optional_stock"
)
public class OptionalStockPO {
@Id
@GeneratedValue(
strategy = javax.persistence.GenerationType.IDENTITY
)
Integer id;
String symbol;
String company;
}

View File

@@ -79,6 +79,8 @@ public class StockIpoPO {
* 申请总额 */ * 申请总额 */
String apply; String apply;
String exchangeType;
/** /**
* 市盈率 */ * 市盈率 */
BigDecimal peRatio; BigDecimal peRatio;

View File

@@ -0,0 +1,7 @@
package cn.stock.market.infrastructure.db.repo;
import cn.stock.market.infrastructure.db.po.OptionalStockPO;
import com.rp.spring.jpa.GenericJpaRepository;
public interface OptionalStockRepo extends GenericJpaRepository<OptionalStockPO, Integer> {
}

View File

@@ -7,6 +7,7 @@ import cn.stock.market.domain.basic.repository.StockRepository;
import cn.stock.market.domain.basic.service.StockService; import cn.stock.market.domain.basic.service.StockService;
import cn.stock.market.infrastructure.api.investing.InvestingInvokerApis; import cn.stock.market.infrastructure.api.investing.InvestingInvokerApis;
import cn.stock.market.infrastructure.db.po.QSiteNewsPO; import cn.stock.market.infrastructure.db.po.QSiteNewsPO;
import cn.stock.market.utils.DateTimeUtil;
import cn.stock.market.utils.Utils; import cn.stock.market.utils.Utils;
import com.ag.utils.CollectionUtils; import com.ag.utils.CollectionUtils;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
@@ -25,6 +26,8 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Slf4j @Slf4j
@Component @Component
@@ -118,8 +121,16 @@ public class InvestingTask {
newsList.forEach( n -> { newsList.forEach( n -> {
String contentUrl = n.substring(1, n.indexOf("class=\"img-smllnews\"") - 2); String contentUrl = n.substring(1, n.indexOf("class=\"img-smllnews\"") - 2);
String id = contentUrl.substring(contentUrl.lastIndexOf("-") + 1, contentUrl.lastIndexOf("_")); String id = contentUrl.substring(contentUrl.lastIndexOf("-") + 1, contentUrl.lastIndexOf("_"));
String imgUrl = n.substring(n.indexOf("img loading=\"lazy\" src=") + 24, n.indexOf("?")); // String imgUrl = n.substring(n.indexOf("img loading=\"lazy\" src=") + 24, n.indexOf("?"));
String time = n.substring(n.indexOf("Last Updated") + 23, n.indexOf("IST") - 9); String imgUrl = extractImgSrc(n);
// String time = n.substring(n.indexOf("Last Updated") + 23, n.indexOf("IST") - 9);
// Extract the date and time using regex
Pattern pattern = Pattern.compile("Updated On :<!-- --> <!-- -->(.*?)<!-- -->");
Matcher matcher = pattern.matcher(n);
String time = "";
if (matcher.find()) {
time = DateTimeUtil.formatDateTimeFor24H(matcher.group(1).trim(),"dd MMM yyyy | hh:mm a");
}
SiteNews siteNews = new SiteNews(); SiteNews siteNews = new SiteNews();
siteNews.setAddTime(new Date()); siteNews.setAddTime(new Date());
@@ -140,4 +151,22 @@ public class InvestingTask {
} }
} }
public static String extractImgSrc(String htmlData) {
String searchString = "<noscript>";
int startPos = htmlData.indexOf(searchString);
if (startPos != -1) {
String startTag = "src=";
startPos = htmlData.indexOf(startTag, startPos) + startTag.length() + 1;
int endPos = htmlData.indexOf("?", startPos);
if (endPos != -1) {
return htmlData.substring(startPos, endPos);
}
}
return null;
}
} }

View File

@@ -1,14 +1,20 @@
package cn.stock.market.infrastructure.job; package cn.stock.market.infrastructure.job;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.stock.market.domain.basic.entity.BtodayStock; import cn.stock.market.domain.basic.entity.BtodayStock;
import cn.stock.market.domain.basic.entity.MoneyStock;
import cn.stock.market.domain.basic.entity.StockIpo; import cn.stock.market.domain.basic.entity.StockIpo;
import cn.stock.market.domain.basic.repository.BtodayStockRepository; import cn.stock.market.domain.basic.repository.BtodayStockRepository;
import cn.stock.market.domain.basic.repository.MoneyStockRepository;
import cn.stock.market.domain.basic.repository.StockIpoRepository; import cn.stock.market.domain.basic.repository.StockIpoRepository;
import cn.stock.market.dto.StockIpoDTO; import cn.stock.market.dto.StockIpoDTO;
import cn.stock.market.infrastructure.db.po.QMoneyStockPO;
import cn.stock.market.infrastructure.db.po.QStockIpoPO; import cn.stock.market.infrastructure.db.po.QStockIpoPO;
import cn.stock.market.infrastructure.db.po.StockIpoPO; import cn.stock.market.infrastructure.db.po.StockIpoPO;
import cn.stock.market.infrastructure.db.repo.BtodayStockRepo; import cn.stock.market.infrastructure.db.repo.BtodayStockRepo;
import com.alibaba.druid.sql.visitor.functions.Now;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
@@ -31,14 +37,11 @@ import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.ArrayList; import java.util.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@@ -54,6 +57,10 @@ public class Scraper {
private StockIpoRepository stockIpoRepository; private StockIpoRepository stockIpoRepository;
private final ExecutorService executorService = Executors.newFixedThreadPool(5); private final ExecutorService executorService = Executors.newFixedThreadPool(5);
@Autowired
private MoneyStockRepository moneyStockRepository;
private boolean times = false;
@Scheduled(cron = "0 0 1 */2 * ?") @Scheduled(cron = "0 0 1 */2 * ?")
@@ -104,6 +111,7 @@ public class Scraper {
@Scheduled(cron = "0 0 18 * * ?") @Scheduled(cron = "0 0 18 * * ?")
// @PostConstruct
@RequestMapping("/testScraperGetMoneyControllerNewIPO") @RequestMapping("/testScraperGetMoneyControllerNewIPO")
public void getMoneyControllerNewIPOSchedule() { public void getMoneyControllerNewIPOSchedule() {
log.info("定时任务执行获取新股ipo的方法开始执行"); log.info("定时任务执行获取新股ipo的方法开始执行");
@@ -163,7 +171,28 @@ public class Scraper {
stockIpo.setCreateDate(new Date()); stockIpo.setCreateDate(new Date());
stockIpo.setUpdateDate(new Date()); stockIpo.setUpdateDate(new Date());
stockIpo.setSourceType("3"); stockIpo.setSourceType("3");
listStockIpoList.add(stockIpo);
if (stockIpo.getStockCode() == null || stockIpo.getStockName() == null){
continue;
}
List<String> exchanges = getIpoExchange(stockIpo.getStockName(), stockIpo.getStockCode());
for (String exchange : exchanges) {
StockIpo ipo = new StockIpo();
ipo.setStockCode(stockIpo.getStockCode());
ipo.setStockName(stockIpo.getStockName());
ipo.setStockPrice(stockIpo.getStockPrice());
ipo.setSubscriptionDate(stockIpo.getSubscriptionDate());
ipo.setListingDate(stockIpo.getListingDate());
ipo.setTotalNumber(stockIpo.getTotalNumber());
ipo.setApply(stockIpo.getApply());
ipo.setCreateDate(stockIpo.getCreateDate());
ipo.setUpdateDate(stockIpo.getUpdateDate());
ipo.setExchangeType(exchange);
listStockIpoList.add(ipo);
}
} }
for (int i = 0; i < upcomingData.size(); i++) { for (int i = 0; i < upcomingData.size(); i++) {
@@ -186,11 +215,37 @@ public class Scraper {
stockIpo.setCreateDate(new Date()); stockIpo.setCreateDate(new Date());
stockIpo.setUpdateDate(new Date()); stockIpo.setUpdateDate(new Date());
stockIpo.setSourceType("3"); stockIpo.setSourceType("3");
listStockIpoList.add(stockIpo);
if (stockIpo.getStockCode() == null || stockIpo.getStockName() == null){
continue;
}
List<String> exchanges = getIpoExchange(stockIpo.getStockName(), stockIpo.getStockCode());
for (String exchange : exchanges) {
StockIpo ipo = new StockIpo();
ipo.setStockCode(stockIpo.getStockCode());
ipo.setStockName(stockIpo.getStockName());
ipo.setStockPrice(stockIpo.getStockPrice());
ipo.setSubscriptionDate(stockIpo.getSubscriptionDate());
ipo.setListingDate(stockIpo.getListingDate());
ipo.setTotalNumber(stockIpo.getTotalNumber());
ipo.setApply(stockIpo.getApply());
ipo.setCreateDate(stockIpo.getCreateDate());
ipo.setUpdateDate(stockIpo.getUpdateDate());
ipo.setExchangeType(exchange);
listStockIpoList.add(ipo);
}
} }
// stockIpoRepository.saveAll(listStockIpoList); // stockIpoRepository.saveAll(listStockIpoList);
if (!listStockIpoList.isEmpty())
{
listStockIpoList = listStockIpoList.stream().filter(a -> StringUtils.isNotBlank(a.getStockName())).collect(Collectors.toList());
}
List<String> scIdList = Lists.transform(listStockIpoList, StockIpo::getStockCode); List<String> scIdList = Lists.transform(listStockIpoList, StockIpo::getStockCode);
if(CollectionUtil.isNotEmpty(scIdList)){ if(CollectionUtil.isNotEmpty(scIdList)){
List<StockIpo> existStockIpoList = stockIpoRepository.findAll(QStockIpoPO.stockIpoPO.stockCode.in(scIdList)); List<StockIpo> existStockIpoList = stockIpoRepository.findAll(QStockIpoPO.stockIpoPO.stockCode.in(scIdList));
@@ -205,6 +260,7 @@ public class Scraper {
//保存全部的新股 //保存全部的新股
if(CollectionUtil.isNotEmpty(listStockIpoList)){ if(CollectionUtil.isNotEmpty(listStockIpoList)){
stockIpoRepository.saveAll(listStockIpoList); stockIpoRepository.saveAll(listStockIpoList);
log.info("定时任务执行获取新股ipo的方法开始结束,保存了数据:{}", JSON.toJSONString(listStockIpoList)); log.info("定时任务执行获取新股ipo的方法开始结束,保存了数据:{}", JSON.toJSONString(listStockIpoList));
}else { }else {
log.info("定时任务执行获取新股ipo的方法开始结束,没有数据"); log.info("定时任务执行获取新股ipo的方法开始结束,没有数据");
@@ -225,6 +281,36 @@ public class Scraper {
} }
@Scheduled(cron = "0 0 19 * * ?")
@PostConstruct
@RequestMapping("/addMoneyStock")
public void addMoneyStock() {
log.info("定时任务执行获取新股ipo的方法开始执行");
List<StockIpo> stockIpoList;
if(!times){
stockIpoList = stockIpoRepository.findAll(QStockIpoPO.stockIpoPO.listingDate.isNotNull()
.and(QStockIpoPO.stockIpoPO.listingDate.loe(DateTime.now()))
.and(QStockIpoPO.stockIpoPO.exchangeType.isNotNull())
.and(QStockIpoPO.stockIpoPO.exchangeType.isNotEmpty())
); // first time run
times = true;
}
else {
stockIpoList = stockIpoRepository.findAll(QStockIpoPO.stockIpoPO.listingDate.isNotNull()
.and(QStockIpoPO.stockIpoPO.listingDate.loe(DateTime.now())
.and(QStockIpoPO.stockIpoPO.listingDate.goe(DateUtil.offsetDay(DateTime.now(), -3))))
.and(QStockIpoPO.stockIpoPO.exchangeType.isNotNull())
.and(QStockIpoPO.stockIpoPO.exchangeType.isNotEmpty())
); // from second run
}
List<MoneyStock> moneyStockList = convertToMoneyStock(stockIpoList);
moneyStockRepository.saveAll(moneyStockList);
}
private static Timestamp convertStringToTimestamp(String dateString) { private static Timestamp convertStringToTimestamp(String dateString) {
// 实现将字符串转换为 Timestamp 的逻辑 // 实现将字符串转换为 Timestamp 的逻辑
@@ -236,12 +322,6 @@ public class Scraper {
} }
} }
private void processSubMap(Map<String, String> sefUrlList) { private void processSubMap(Map<String, String> sefUrlList) {
for (Map.Entry<String, String> entry : sefUrlList.entrySet()) { for (Map.Entry<String, String> entry : sefUrlList.entrySet()) {
String companyName = entry.getKey(); String companyName = entry.getKey();
@@ -378,4 +458,134 @@ public class Scraper {
log.info("Getting web detail URL: " + url + "..."); log.info("Getting web detail URL: " + url + "...");
return Jsoup.connect(url).ignoreContentType(true).execute().body(); return Jsoup.connect(url).ignoreContentType(true).execute().body();
} }
public List<String> getIpoExchange(String stockName, String stockCode) {
List<String> exchanges = new ArrayList<>();
String url = "https://www.moneycontrol.com/ipo/{stockName}-{stockCode}-ipodetail";
url = url.replace("{stockName}", stockName.toLowerCase().replace(" ", "-")).replace("{stockCode}", stockCode.toLowerCase());
org.apache.http.client.HttpClient client = HttpClients.createDefault();
HttpGet request = new HttpGet(url);
try {
org.apache.http.HttpResponse response = client.execute(request);
if (response.getStatusLine().getStatusCode() == 200) {
String responseBody = EntityUtils.toString(response.getEntity());
Document doc = Jsoup.parse(responseBody);
Element scriptTag = doc.selectFirst("script#__NEXT_DATA__");
if (scriptTag != null) {
String jsonDataStr = scriptTag.html();
com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(jsonDataStr);
log.info("获取到新股的json信息:" + jsonObject.toJSONString());
com.alibaba.fastjson.JSONObject pageProps = jsonObject.getJSONObject("props").getJSONObject("pageProps");
com.alibaba.fastjson.JSONObject overview = pageProps.getJSONObject("ipoDetails").getJSONObject("ipoDetails").getJSONObject("overview");
String exchangeStr = overview.getString("listing_on");
if (exchangeStr != null && !exchangeStr.isEmpty() && !exchangeStr.equals("null")) {
exchanges.addAll(new ArrayList<>(Arrays.asList(exchangeStr.split(","))));
}
}
}
}
catch (Exception e) {
log.info(e.getMessage());
}
if (exchanges.isEmpty()) {
exchanges.add("");
}
return exchanges;
}
public List<MoneyStock> convertToMoneyStock(List<StockIpo> stockIpoList) {
// Lấy danh sách tất cả stockCode và exchangeType từ stockIpoList
Set<String> stockCodes = stockIpoList.stream().map(StockIpo::getStockCode).collect(Collectors.toSet());
Set<String> exchangeTypes = stockIpoList.stream().map(StockIpo::getExchangeType).collect(Collectors.toSet());
// Lấy tất cả các MoneyStock tồn tại trong database với stockCode và exchangeType trong stockIpoList
List<MoneyStock> existingMoneyStocks = moneyStockRepository.findAll(
QMoneyStockPO.moneyStockPO.moneyScId.in(stockCodes)
.and(QMoneyStockPO.moneyStockPO.stockType.in(exchangeTypes))
);
// Lưu các stockCode và exchangeType đã tồn tại
Set<String> existingKeys = existingMoneyStocks.stream()
.map(ms -> ms.getMoneyScId() + ms.getStockType())
.collect(Collectors.toSet());
// Chỉ giữ những StockIpo chưa tồn tại
return stockIpoList.stream()
.filter(stockIpo -> !existingKeys.contains(stockIpo.getStockCode() + stockIpo.getExchangeType()))
.map(this::convert)
.collect(Collectors.toList());
}
// public List<MoneyStock> convertToMoneyStock(List<StockIpo> stockIpoList) {
// return stockIpoList.stream()
// .filter(stockIpo -> !moneyStockRepository.exists(
// QMoneyStockPO.moneyStockPO.stockType.eq(stockIpo.getExchangeType())
// .and(QMoneyStockPO.moneyStockPO.moneyScId.eq(stockIpo.getStockCode()))
// )) // Chỉ giữ những StockIpo chưa tồn tại
// .map(this::convert)
// .collect(Collectors.toList());
// }
private MoneyStock convert(StockIpo stockIpo) {
MoneyStock moneyStock = new MoneyStock();
moneyStock.setStockName(stockIpo.getStockName());
moneyStock.setMoneyScId(stockIpo.getStockCode());
moneyStock.setSelfDispId(stockIpo.getStockCode());
moneyStock.setStockType(stockIpo.getExchangeType());
moneyStock.setSaveTime(DateTime.now());
moneyStock.setNseIndiaId(getNSEId(stockIpo));
return moneyStock;
}
private String getNSEId(StockIpo stockIpo){
String url = "https://priceapi.moneycontrol.com/pricefeed/" + stockIpo.getExchangeType().toLowerCase() + "/equitycash/" + stockIpo.getStockCode();
// 创建 HttpClient 实例
HttpClient client = HttpClients.createDefault();
// 创建 HttpGet 请求
HttpGet request = new HttpGet(url);
try {
// 执行请求
HttpResponse response = client.execute(request);
// 检查请求是否成功
if (response.getStatusLine().getStatusCode() == 200) {
// 获取响应体
String responseBody = EntityUtils.toString(response.getEntity());
if (responseBody != null) {
// 获取 JSON 数据
// 将 JSON 字符串解析为 Java JSONObject
JSONObject jsonObject = JSONObject.parseObject(responseBody);
log.info("获取到新股的json信息:" + jsonObject.toJSONString());
JSONObject jsonData = jsonObject.getJSONObject("data");
if(stockIpo.getExchangeType().equals("NSE")){
return jsonData.getString("NSEID");
}
else if(stockIpo.getExchangeType().equals("BSE")){
return jsonData.getString("BSEID");
}
}
}
}
catch (Exception e){
log.info(e.getMessage());
}
return "";
}
} }

View File

@@ -5,6 +5,8 @@ import java.sql.Timestamp;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Calendar; import java.util.Calendar;
import java.util.Locale;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.DateTimeFormatter;
@@ -186,6 +188,25 @@ public class DateTimeUtil {
} }
public static String formatDateTimeFor24H(String inputDateTime,String inputFormatStr){
String outputDateTime = "";
// 1. 解析日期时间
SimpleDateFormat inputFormat = new SimpleDateFormat(inputFormatStr, Locale.ENGLISH);
Date date = null;
try {
date = inputFormat.parse(inputDateTime);
} catch (Exception e) {
e.printStackTrace();
}
if (date != null) {
// 2. 转换为24小时制
SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
outputDateTime = outputFormat.format(date);
}
return outputDateTime;
}
public static void main(String[] args) { public static void main(String[] args) {
parseToDateByMinute(10); parseToDateByMinute(10);
} }

View File

@@ -0,0 +1,181 @@
package cn.stock.market.utils;
import cn.stock.market.dto.StockHistoryRequest;
import cn.stock.market.dto.StockHistoryResponse;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.apache.commons.lang.StringUtils;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NseIndiaRequest {
private static final String NSE_INDIA_URL = "https://www.nseindia.com";
private static final String NSE_INDIA_CHART_URL = "https://charting.nseindia.com";
private static final OkHttpClient client;
private static final ObjectMapper objectMapper = new ObjectMapper();
static {
client = new OkHttpClient.Builder()
.cookieJar(new CookieJar() {
private final Map<String, List<Cookie>> cookieStore = new HashMap<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
cookieStore.put(url.host(), cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> cookies = cookieStore.get(url.host());
return cookies != null ? cookies : new ArrayList<Cookie>();
}
})
.build();
}
private static Request createRequest(String url) {
Request request = new Request.Builder()
.url(url)
.header("accept", "application/json, text/plain, */*")
.header("accept-language", "en-US,en;q=0.9")
.header("cache-control", "no-cache")
.header("pragma", "no-cache")
.header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36")
.build();
return request;
}
private static void initCookie(String url) {
Request request = createRequest(url);
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Failed to fetch initial cookies");
}
} catch (IOException e) {
throw new RuntimeException("Failed to initialize cookies", e);
}
}
private static Integer getCode(String symbol) {
Request request = createRequest(NSE_INDIA_CHART_URL + "//Charts/GetEQMasters").newBuilder()
.addHeader("referer", NSE_INDIA_CHART_URL)
.addHeader("origin", NSE_INDIA_CHART_URL)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Failed to get EQ code");
}
String result = response.body().string();
String regex = "(\\d+)\\|" + symbol + "\\|.*";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(result);
if (matcher.find()) {
return Integer.valueOf(matcher.group(1));
}
throw new IOException("No data found");
} catch (IOException e) {
throw new RuntimeException("Failed to get EQ code", e);
}
}
public static JSONObject stockByJYSFromHttp(String stockType, String symbol, String nseIndiaId) {
initCookie(NSE_INDIA_URL);
String url = NSE_INDIA_URL + "/api/quote-equity?symbol=" + nseIndiaId;
Request request = createRequest(url).newBuilder()
.addHeader("referer", NSE_INDIA_URL)
.addHeader("origin", NSE_INDIA_URL)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Request failed with code: " + response.code());
}
JSONObject jsonData = JSONObject.parseObject(response.body().string());
JSONObject data =jsonData.getJSONObject("priceInfo");
JSONObject json = new JSONObject();
json.put("pricepercentchange",data.getString("pChange"));
json.put("stockType",stockType);
json.put("pricechange",data.getString("change"));
json.put("pricecurrent",data.getString("lastPrice"));
json.put("priceprevclose",data.getString("previousClose"));
json.put("PREVDATE","");
json.put("VOL",jsonData.getJSONObject("preOpenMarket").getString("totalTradedVolume"));
json.put("dataSourceType","3");
json.put("symbol",symbol);
json.put("BSEID",symbol);
json.put("NSEID",symbol);
json.put("LTH",data.getString("upperCP"));
json.put("LTL",data.getString("lowerCP"));
json.put("OPN",data.getString("open"));
return json;
} catch (IOException e) {
throw new RuntimeException("Failed to fetch data", e);
}
}
public static StockHistoryResponse stockKLineFromHttp(StockHistoryRequest stockHistoryRequest, String resolution) {
initCookie(NSE_INDIA_CHART_URL);
Integer code = getCode(stockHistoryRequest.getSymbol());
int interval = 1;
if (StringUtils.equals("H", resolution)) {
resolution = "I";
interval = 60;
}
Map<String, Object> body = new HashMap<>();
body.put("chartPeriod", resolution);
body.put("chartStart", 0);
body.put("exch", "N");
body.put("fromDate", 0);
body.put("instrType", "C");
body.put("scripCode", code);
body.put("timeInterval", interval);
body.put("toDate", stockHistoryRequest.getTo() + 18000);
body.put("ulToken", code);
String payload;
try {
payload = objectMapper.writeValueAsString(body);
} catch (Exception e) {
throw new RuntimeException("Failed to serialize body", e);
}
RequestBody requestBody = RequestBody.create(
MediaType.get("application/json; charset=utf-8"),
payload
);
Request request = createRequest(NSE_INDIA_CHART_URL + "//Charts/symbolhistoricaldata/").newBuilder()
.addHeader("referer", NSE_INDIA_CHART_URL)
.addHeader("origin", NSE_INDIA_CHART_URL)
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Request failed with code: " + response.code());
}
StockHistoryResponse result = objectMapper.readValue(response.body().string(), StockHistoryResponse.class);
return result;
} catch (IOException e) {
throw new RuntimeException("Failed to fetch data", e);
}
}
}

View File

@@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -159,6 +160,19 @@ public class BTodayStockController {
String forObject = restTemplate.getForObject(apiUrl, String.class); String forObject = restTemplate.getForObject(apiUrl, String.class);
JSONObject jsonObject = JSON.parseObject(forObject); JSONObject jsonObject = JSON.parseObject(forObject);
JSONArray arryData = jsonObject.getJSONArray("data");
if (arryData != null&&arryData.size()>0) {
try {
JSONObject jsonObject1 = arryData.getJSONObject(0);
String price = jsonObject1.getString("price");
double priceValue = Double.parseDouble(price);
DecimalFormat df = new DecimalFormat("0.00");
jsonObject1.put("price", df.format(priceValue));
} catch (NumberFormatException e) {
// Handle the case where price is not a valid double
e.printStackTrace();
}
}
jsonObject.put("id",btodayStock.getId()); jsonObject.put("id",btodayStock.getId());
return jsonObject; return jsonObject;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,8 @@ package cn.stock.market.web;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@@ -12,6 +14,7 @@ import cn.qutaojing.common.jpa.ConditionBuilder;
import cn.stock.market.domain.basic.entity.SiteNews; import cn.stock.market.domain.basic.entity.SiteNews;
import cn.stock.market.domain.basic.repository.SiteNewsRepository; import cn.stock.market.domain.basic.repository.SiteNewsRepository;
import cn.stock.market.infrastructure.db.po.QSiteNewsPO; import cn.stock.market.infrastructure.db.po.QSiteNewsPO;
import cn.stock.market.infrastructure.job.InvestingTask;
import cn.stock.market.web.annotations.EncryptFilter; import cn.stock.market.web.annotations.EncryptFilter;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
@@ -169,15 +172,22 @@ public class StockApiController {
@RequestMapping({"test.do"}) @RequestMapping({"test.do"})
@ResponseBody @ResponseBody
public ServerResponse test(@RequestParam("url") String url, @RequestParam("pageNum") Integer pageNum) { public ServerResponse test(/*@RequestParam("url") String url, @RequestParam("pageNum") Integer pageNum*/) {
String news = stockService.getNews(); String news = stockService.getNews();
List<String> newsList = Arrays.asList(news.split("<a href=")); List<String> newsList = Arrays.asList(news.split("<a href="));
newsList = newsList.subList(1, newsList.size()); newsList = newsList.subList(1, newsList.size());
newsList.forEach( n -> { newsList.forEach( n -> {
String contentUrl = n.substring(1, n.indexOf("class=\"img-smllnews\"") - 2); String contentUrl = n.substring(1, n.indexOf("class=\"img-smllnews\"") - 2);
String id = contentUrl.substring(contentUrl.lastIndexOf("-") + 1, contentUrl.lastIndexOf("_")); String id = contentUrl.substring(contentUrl.lastIndexOf("-") + 1, contentUrl.lastIndexOf("_"));
String imgUrl = n.substring(n.indexOf("img loading=\"lazy\" src=") + 24, n.indexOf("?")); String imgUrl = InvestingTask.extractImgSrc(n);
String time = n.substring(n.indexOf("Last Updated") + 23, n.indexOf("IST") - 9); // String time = n.substring(n.indexOf("Last Updated") + 23, n.indexOf("IST") - 9);
// Extract the date and time using regex
Pattern pattern = Pattern.compile("Updated On :<!-- --> <!-- -->(.*?)<!-- -->");
Matcher matcher = pattern.matcher(n);
String time = "";
if (matcher.find()) {
time = matcher.group(1).trim();
}
SiteNews siteNews = new SiteNews(); SiteNews siteNews = new SiteNews();
siteNews.setAddTime(new Date()); siteNews.setAddTime(new Date());
@@ -238,7 +248,7 @@ public class StockApiController {
@ResponseBody @ResponseBody
public ServerResponse getIndiaIndexByToday() { public ServerResponse getIndiaIndexByToday() {
String INDEX_CODE = "TODAY_INDEX"; String INDEX_CODE = "TODAY_INDEX";
return RequestCacheUtils.cache("getIndiaIndexByToday.do", INDEX_CODE,60000, (string) -> { return RequestCacheUtils.cache("getIndiaIndexByToday.do", INDEX_CODE,6000, (string) -> {
return this.stockService.getIndexByBtoday(); return this.stockService.getIndexByBtoday();
}); });
} }

View File

@@ -3,9 +3,9 @@ spring:
show-sql: true show-sql: true
# Redis配置 # Redis配置
redis: redis:
host: 43.132.212.180 host: 43.156.40.39
password: ruTZ9J3gaDhknJ password: a5v8b86P4mVzFlUqJV
port: 36379 port: 30031
database: 1 database: 1
lettuce: lettuce:
pool: pool:
@@ -17,9 +17,9 @@ spring:
datasource: datasource:
stock-market: stock-market:
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://149.88.86.7:33306/india_stock?useUnicode=true&characterEncoding=utf-8 url: jdbc:mysql://43.156.40.39:30030/india_stock?useUnicode=true&characterEncoding=utf-8
username: root username: root
password: 33BsUUcnXRYgwtIND password: uNejHIFQGJOUtYTmE
maxActive: 500 maxActive: 500
testWhileIdle: true testWhileIdle: true
validationQuery: SELECT 1 validationQuery: SELECT 1