stockIpo代码提交

This commit is contained in:
Achilles
2023-12-28 21:23:38 +08:00
parent 29b31f1f2c
commit 4ac7f49927
15 changed files with 628 additions and 1 deletions

19
pom.xml
View File

@@ -216,6 +216,25 @@
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>src/main/generated</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
<plugin> <plugin>
<groupId>com.mysema.maven</groupId> <groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId> <artifactId>apt-maven-plugin</artifactId>

View File

@@ -0,0 +1,63 @@
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;
/**
* QStockIpoPO is a Querydsl query type for StockIpoPO
*/
@Generated("com.querydsl.codegen.EntitySerializer")
public class QStockIpoPO extends EntityPathBase<StockIpoPO> {
private static final long serialVersionUID = 1023664740L;
public static final QStockIpoPO stockIpoPO = new QStockIpoPO("stockIpoPO");
public final StringPath apply = createString("apply");
public final DateTimePath<java.util.Date> createDate = createDateTime("createDate", java.util.Date.class);
public final NumberPath<Integer> id = createNumber("id", Integer.class);
public final NumberPath<Integer> isList = createNumber("isList", Integer.class);
public final NumberPath<Integer> isShow = createNumber("isShow", Integer.class);
public final DateTimePath<java.util.Date> listingDate = createDateTime("listingDate", java.util.Date.class);
public final NumberPath<java.math.BigDecimal> peRatio = createNumber("peRatio", java.math.BigDecimal.class);
public final StringPath sourceType = createString("sourceType");
public final StringPath stockCode = createString("stockCode");
public final StringPath stockName = createString("stockName");
public final NumberPath<java.math.BigDecimal> stockPrice = createNumber("stockPrice", java.math.BigDecimal.class);
public final DateTimePath<java.util.Date> subscriptionDate = createDateTime("subscriptionDate", java.util.Date.class);
public final NumberPath<Integer> totalNumber = createNumber("totalNumber", Integer.class);
public final DateTimePath<java.util.Date> updateDate = createDateTime("updateDate", java.util.Date.class);
public QStockIpoPO(String variable) {
super(StockIpoPO.class, forVariable(variable));
}
public QStockIpoPO(Path<? extends StockIpoPO> path) {
super(path.getType(), path.getMetadata());
}
public QStockIpoPO(PathMetadata metadata) {
super(StockIpoPO.class, metadata);
}
}

View File

@@ -0,0 +1,35 @@
package cn.stock.market.application.assembler;
import cn.qutaojing.common.utils.Beans;
import cn.qutaojing.common.utils.SpringUtils;
import cn.stock.market.domain.basic.entity.StockIpo;
import cn.stock.market.dto.StockIpoDTO;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
/**
* StockIpoAssembler
*
* @author rplees
* @email rplees.i.ly@gmail.com
* @created 2023/12/28
*/
@Component
@Lazy
public class StockIpoAssembler {
public StockIpoDTO toDTO(StockIpo e) {
StockIpoDTO dto = Beans.mapper(e, StockIpoDTO.class);
if(dto == null) return dto;
fill(e, dto);
return dto;
}
protected void fill(StockIpo e, StockIpoDTO dto) {
if(dto == null) return;
return;
}
public static StockIpoAssembler of() {
return SpringUtils.getBean(StockIpoAssembler.class);
}
}

View File

@@ -0,0 +1,23 @@
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.StockIpo;
import cn.stock.market.infrastructure.db.po.StockIpoPO;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
/**
* StockIpoConvert
*
* @author rplees
* @email rplees.i.ly@gmail.com
* @created 2023/12/28
*/
@Component
@Lazy
public class StockIpoConvert extends SimpleEntityPOConvert<StockIpo, StockIpoPO> {
public static StockIpoConvert of() {
return SpringUtils.getBean(StockIpoConvert.class);
}
}

View File

@@ -0,0 +1,28 @@
package cn.stock.market.domain.basic.entity;
import cn.qutaojing.common.utils.Beans;
import cn.stock.market.dto.command.StockIpoCreateCommand;
import cn.stock.market.infrastructure.db.po.StockIpoPO;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* StockIpo
*
* @author rplees
* @email rplees.i.ly@gmail.com
* @created 2023/12/28
*/
@Data
@NoArgsConstructor
@SuperBuilder
@EqualsAndHashCode(
callSuper = false
)
public class StockIpo extends StockIpoPO {
public void update(StockIpoCreateCommand cmd) {
Beans.copyProperties(cmd, this);
}
}

View File

@@ -0,0 +1,28 @@
package cn.stock.market.domain.basic.factory;
import cn.qutaojing.common.utils.SpringUtils;
import cn.stock.market.domain.basic.entity.StockIpo;
import cn.stock.market.dto.command.StockIpoCreateCommand;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
/**
* StockIpoFactory
*
* @author rplees
* @email rplees.i.ly@gmail.com
* @created 2023/12/28
*/
@Component
@Lazy
public class StockIpoFactory {
public static StockIpoFactory of() {
return SpringUtils.getBean(StockIpoFactory.class);
}
public StockIpo from(StockIpoCreateCommand cmd) {
StockIpo e = StockIpo.builder().build();
e.update(cmd);
return e;
}
}

View File

@@ -0,0 +1,46 @@
package cn.stock.market.domain.basic.repository;
import cn.qutaojing.common.domain.convert.IEntityPOConvert;
import cn.qutaojing.common.domain.respostory.SimplePoConvertEntityRepository;
import cn.qutaojing.common.utils.SpringUtils;
import cn.stock.market.domain.basic.convert.StockIpoConvert;
import cn.stock.market.domain.basic.entity.StockIpo;
import cn.stock.market.infrastructure.db.po.StockIpoPO;
import cn.stock.market.infrastructure.db.repo.StockIpoRepo;
import com.rp.spring.jpa.GenericJpaRepository;
import java.lang.Integer;
import java.lang.Override;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
/**
* StockIpoRepository
*
* @author rplees
* @email rplees.i.ly@gmail.com
* @created 2023/12/28
*/
@Repository
@RequiredArgsConstructor(
onConstructor = @__(@Autowired)
)
public class StockIpoRepository extends SimplePoConvertEntityRepository<StockIpo, StockIpoPO, Integer> {
final StockIpoRepo repo;
final StockIpoConvert convert;
@Override
public GenericJpaRepository<StockIpoPO, Integer> repo() {
return repo;
}
@Override
public IEntityPOConvert<StockIpo, StockIpoPO> convert() {
return convert;
}
public static StockIpoRepository of() {
return SpringUtils.getBean(StockIpoRepository.class);
}
}

View File

@@ -0,0 +1,33 @@
package cn.stock.market.domain.basic.service;
import cn.qutaojing.common.utils.SpringUtils;
import cn.stock.market.domain.basic.factory.StockIpoFactory;
import cn.stock.market.domain.basic.repository.StockIpoRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* StockIpoService
*
* @author rplees
* @email rplees.i.ly@gmail.com
* @created 2023/12/28
*/
@Service
@RequiredArgsConstructor(
onConstructor = @__(@Autowired)
)
public class StockIpoService {
final StockIpoRepository repository;
final StockIpoFactory factory;
public StockIpoRepository repository() {
return repository;
}
public static StockIpoService of() {
return SpringUtils.getBean(StockIpoService.class);
}
}

View File

@@ -0,0 +1,23 @@
package cn.stock.market.dto;
import cn.stock.market.infrastructure.db.po.StockIpoPO;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* StockIpoDTO
*
* @author rplees
* @email rplees.i.ly@gmail.com
* @created 2023/12/28
*/
@Data
@NoArgsConstructor
@SuperBuilder
@EqualsAndHashCode(
callSuper = false
)
public class StockIpoDTO extends StockIpoPO {
}

View File

@@ -0,0 +1,69 @@
package cn.stock.market.dto.command;
import java.lang.Integer;
import java.lang.String;
import java.math.BigDecimal;
import java.util.Date;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* StockIpoCreateCommand
*
* @author rplees
* @email rplees.i.ly@gmail.com
* @created 2023/12/28
*/
@Data
@SuperBuilder
@NoArgsConstructor
public class StockIpoCreateCommand {
Integer id;
/**
* 股票代码 */
String stockCode;
/**
* 股票名称 */
String stockName;
/**
* 发行价格 */
BigDecimal stockPrice;
/**
* 申购日期 */
Date subscriptionDate;
/**
* 上市日期 */
Date listingDate;
/**
* 是否显示【1 显示2 不显示】 */
Integer isShow;
/**
* 是否上市【1 未上市2 已上市】 */
Integer isList;
Date createDate;
Date updateDate;
/**
* 发行总数 */
Integer totalNumber;
/**
* 申请总额 */
String apply;
/**
* 市盈率 */
BigDecimal peRatio;
String sourceType;
}

View File

@@ -0,0 +1,24 @@
package cn.stock.market.dto.command;
import java.lang.Integer;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* StockIpoModifyCommand
*
* @author rplees
* @email rplees.i.ly@gmail.com
* @created 2023/12/28
*/
@Data
@SuperBuilder
@NoArgsConstructor
@EqualsAndHashCode(
callSuper = false
)
public class StockIpoModifyCommand extends StockIpoCreateCommand {
Integer id;
}

View File

@@ -0,0 +1,87 @@
package cn.stock.market.infrastructure.db.po;
import java.lang.Integer;
import java.lang.String;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
/**
* StockIpoPO
*
* @author rplees
* @email rplees.i.ly@gmail.com
* @created 2023/12/28
*/
@SuperBuilder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@DynamicInsert
@DynamicUpdate
@Table(
name = "stock_ipo"
)
public class StockIpoPO {
@Id
@GeneratedValue(
strategy = javax.persistence.GenerationType.IDENTITY
)
Integer id;
/**
* 股票代码 */
String stockCode;
/**
* 股票名称 */
String stockName;
/**
* 发行价格 */
BigDecimal stockPrice;
/**
* 申购日期 */
Date subscriptionDate;
/**
* 上市日期 */
Date listingDate;
/**
* 是否显示【1 显示2 不显示】 */
Integer isShow;
/**
* 是否上市【1 未上市2 已上市】 */
Integer isList;
Date createDate;
Date updateDate;
/**
* 发行总数 */
Integer totalNumber;
/**
* 申请总额 */
String apply;
/**
* 市盈率 */
BigDecimal peRatio;
String sourceType;
}

View File

@@ -0,0 +1,15 @@
package cn.stock.market.infrastructure.db.repo;
import cn.stock.market.infrastructure.db.po.StockIpoPO;
import com.rp.spring.jpa.GenericJpaRepository;
import java.lang.Integer;
/**
* StockIpoRepo
*
* @author rplees
* @email rplees.i.ly@gmail.com
* @created 2023/12/28
*/
public interface StockIpoRepo extends GenericJpaRepository<StockIpoPO, Integer> {
}

View File

@@ -1,11 +1,24 @@
package cn.stock.market.infrastructure.job; package cn.stock.market.infrastructure.job;
import cn.stock.market.domain.basic.entity.BtodayStock; import cn.stock.market.domain.basic.entity.BtodayStock;
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.StockIpoRepository;
import cn.stock.market.dto.StockIpoDTO;
import cn.stock.market.infrastructure.db.po.QStockIpoPO;
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.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
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.nodes.Element;
@@ -17,6 +30,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.io.IOException; import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
@@ -33,6 +47,8 @@ public class Scraper {
@Autowired @Autowired
private BtodayStockRepository btodayStockRepo; private BtodayStockRepository btodayStockRepo;
@Autowired
private StockIpoRepository stockIpoRepository;
private final ExecutorService executorService = Executors.newFixedThreadPool(5); private final ExecutorService executorService = Executors.newFixedThreadPool(5);
@@ -80,6 +96,124 @@ public class Scraper {
} }
} }
@Scheduled(cron = "0 0 5 * * ?")
@RequestMapping("/testScraperGetMoneyControllerNewIPO")
public void schedule2() {
// 目标 URL
String url = "https://www.moneycontrol.com/ipo/open-upcoming-ipos";
// 创建 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());
// 使用 Jsoup 解析 HTML
Document doc = Jsoup.parse(responseBody);
// 找到包含 JSON 数据的 <script> 标签
Element scriptTag = doc.selectFirst("script#__NEXT_DATA__");
if (scriptTag != null) {
// 获取 JSON 数据
String jsonDataStr = scriptTag.html();
// 将 JSON 字符串解析为 Java JSONObject
JSONObject jsonObject = JSONObject.parseObject(jsonDataStr);
log.info(jsonObject.toJSONString());
JSONObject pageProps = jsonObject.getJSONObject("props").getJSONObject("pageProps");
JSONObject ipoTableData = pageProps.getJSONObject("ipoTableData");
// 解析 openData 和 upcomingData
JSONArray openData = ipoTableData.getJSONArray("openData");
JSONArray upcomingData = ipoTableData.getJSONArray("upcomingData");
List<StockIpo> listStockIpoList = new ArrayList<>();
for (int i = 0; i < openData.size(); i++) {
JSONObject entry = openData.getJSONObject(i);
StockIpo stockIpo = new StockIpo();
stockIpo.setStockCode(entry.getString("sc_id"));
stockIpo.setStockName(entry.getString("company_name"));
stockIpo.setStockPrice(entry.getBigDecimal("issue_price"));
stockIpo.setSubscriptionDate(convertStringToTimestamp(entry.getString("open_date")));
stockIpo.setListingDate(convertStringToTimestamp(entry.getString("listing_date")));
stockIpo.setTotalNumber(entry.getInteger("lot_size"));
stockIpo.setApply(entry.getString("total_subs"));
stockIpo.setCreateDate(new Date());
stockIpo.setUpdateDate(new Date());
stockIpo.setSourceType("3");
listStockIpoList.add(stockIpo);
}
for (int i = 0; i < upcomingData.size(); i++) {
JSONObject entry = upcomingData.getJSONObject(i);
StockIpo stockIpo = new StockIpo();
stockIpo.setStockCode(entry.getString("sc_id"));
stockIpo.setStockName(entry.getString("company_name"));
stockIpo.setStockPrice(entry.getBigDecimal("issue_price"));
stockIpo.setSubscriptionDate(convertStringToTimestamp(entry.getString("open_date")));
stockIpo.setListingDate(convertStringToTimestamp(entry.getString("listing_date")));
stockIpo.setTotalNumber(entry.getInteger("lot_size"));
stockIpo.setApply(entry.getString("total_subs"));
stockIpo.setCreateDate(new Date());
stockIpo.setUpdateDate(new Date());
stockIpo.setSourceType("3");
listStockIpoList.add(stockIpo);
}
// stockIpoRepository.saveAll(listStockIpoList);
List<String> nameList = Lists.transform(listStockIpoList, StockIpo::getStockName);
List<StockIpo> existStockIpoList = stockIpoRepository.findAll(QStockIpoPO.stockIpoPO.stockName.in(nameList));
List<String> existingStockNames = existStockIpoList.stream()
.map(StockIpo::getStockName)
.collect(Collectors.toList());
listStockIpoList = listStockIpoList.stream()
.filter(stockIpos -> !existingStockNames.contains(stockIpos.getStockName()))
.collect(Collectors.toList());
//保存全部的新股
stockIpoRepository.saveAll(listStockIpoList);
// 输出整个 JSON 数据
} else {
log.info("未找到包含 JSON 数据的 <script> 标签");
}
} else {
log.info("HTTP请求失败状态码" + response.getStatusLine().getStatusCode());
}
} catch (IOException e) {
log.error("获取新股接口发生异常",e);
}
}
private static Timestamp convertStringToTimestamp(String dateString) {
// 实现将字符串转换为 Timestamp 的逻辑
// 这里假设 dateString 是合法的日期时间字符串
if(StringUtils.isNotBlank(dateString)){
return Timestamp.valueOf(dateString + " 00:00:00");
}else {
return null;
}
}
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();

View File

@@ -50,7 +50,7 @@ public class JpaDDDGen {
/** /**
* cs_statistic - 要生成的数据库表 * cs_statistic - 要生成的数据库表
*/ */
Cons.tableNameToEntiyMapping.put("btoday_stock", null); Cons.tableNameToEntiyMapping.put("stock_ipo", null);
ToolDDD.g(getMySQLDataSource().getConnection()); ToolDDD.g(getMySQLDataSource().getConnection());
} }