登入失败禁止登入2
This commit is contained in:
@@ -5,9 +5,13 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
|||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface LotteryResultRepository extends JpaRepository<LotteryResult, Long> {
|
public interface LotteryResultRepository extends JpaRepository<LotteryResult, Long> {
|
||||||
// 根据时间查询(使用like匹配日期部分)
|
// 根据时间查询(使用like匹配日期部分)
|
||||||
List<LotteryResult> findByTimeContaining(String date);
|
List<LotteryResult> findByTimeContaining(String date);
|
||||||
|
|
||||||
|
// 查询最新的记录(按time降序取第一条)
|
||||||
|
Optional<LotteryResult> findTopByOrderByTimeDesc();
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
package com.tem.bocai.schedules;
|
package com.tem.bocai.schedules;
|
||||||
|
|
||||||
import com.tem.bocai.entity.LoginInfoResult;
|
import com.tem.bocai.entity.LoginInfoResult;
|
||||||
|
import com.tem.bocai.entity.LotteryResult;
|
||||||
import com.tem.bocai.repository.LoginInfoRepository;
|
import com.tem.bocai.repository.LoginInfoRepository;
|
||||||
|
import com.tem.bocai.repository.LotteryResultRepository;
|
||||||
import com.tem.bocai.util.*;
|
import com.tem.bocai.util.*;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
@@ -11,10 +13,12 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import us.codecraft.webmagic.Spider;
|
import us.codecraft.webmagic.Spider;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -24,6 +28,10 @@ public class CrawlerSchedule {
|
|||||||
private TokenCacheService tokenCacheService;
|
private TokenCacheService tokenCacheService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private LoginInfoRepository loginInfoRepository;
|
private LoginInfoRepository loginInfoRepository;
|
||||||
|
@Autowired
|
||||||
|
private LotteryResultRepository lotteryResultRepository;
|
||||||
|
|
||||||
|
|
||||||
private static final int MAX_CRA = 3;
|
private static final int MAX_CRA = 3;
|
||||||
private static final Integer ONOFF = 0;
|
private static final Integer ONOFF = 0;
|
||||||
@Value("${pypath}")
|
@Value("${pypath}")
|
||||||
@@ -31,11 +39,11 @@ public class CrawlerSchedule {
|
|||||||
// 每天凌晨2点执行爬取开奖结果
|
// 每天凌晨2点执行爬取开奖结果
|
||||||
//@Scheduled(cron = "0 0 2 * * ?")
|
//@Scheduled(cron = "0 0 2 * * ?")
|
||||||
// 每7秒执行一次爬取开奖结果
|
// 每7秒执行一次爬取开奖结果
|
||||||
//@Scheduled(cron = "*/9 * * * * ?")
|
@Scheduled(cron = "*/9 * * * * ?")
|
||||||
/*@Scheduled(cron = "0 6-59/5 7-23 * * ?")
|
/*@Scheduled(cron = "0 6-59/5 7-23 * * ?")
|
||||||
@Scheduled(cron = "0 0-55/5 0-6 * * ?")*/
|
@Scheduled(cron = "0 0-55/5 0-6 * * ?")*/
|
||||||
// 从7:00分30秒起每5分钟执行一次
|
// 从7:00分30秒起每5分钟执行一次
|
||||||
@Scheduled(cron = "30 0/5 * * * ?")
|
//@Scheduled(cron = "30 0/5 * * * ?")
|
||||||
public void executeLotteryDraw() {
|
public void executeLotteryDraw() {
|
||||||
log.info("开始爬取开奖结果");
|
log.info("开始爬取开奖结果");
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
@@ -45,10 +53,13 @@ public class CrawlerSchedule {
|
|||||||
if (firstByOrderByCreateTimeDesc == null) {
|
if (firstByOrderByCreateTimeDesc == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(firstByOrderByCreateTimeDesc.getOnOff() == ONOFF){
|
||||||
|
return;
|
||||||
|
}
|
||||||
String token = tokenCacheService.getToken();
|
String token = tokenCacheService.getToken();
|
||||||
if (token == null || token.isEmpty()) {
|
if (token == null || token.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (!success && retryCount < MAX_CRA) {
|
while (!success && retryCount < MAX_CRA) {
|
||||||
log.info("\n=== 第 " + (retryCount + 1) + " 次尝试获取开奖结果 ===");
|
log.info("\n=== 第 " + (retryCount + 1) + " 次尝试获取开奖结果 ===");
|
||||||
if (token == null || token.isEmpty()) {
|
if (token == null || token.isEmpty()) {
|
||||||
@@ -99,6 +110,31 @@ public class CrawlerSchedule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//@Scheduled(cron = "50 0/5 * * * ?")
|
||||||
|
public void executePksHistory() {
|
||||||
|
log.info("开始获取历史开奖结果");
|
||||||
|
// 获取API数据
|
||||||
|
List<Map<String, Object>> historyList = HttpClientExample.getPksHistoryList();
|
||||||
|
// 获取数据库最新时间
|
||||||
|
Optional<String> latestTimeOpt = lotteryResultRepository.findTopByOrderByTimeDesc()
|
||||||
|
.map(LotteryResult::getTime);
|
||||||
|
|
||||||
|
// 判断是否需要更新
|
||||||
|
boolean needUpdate = latestTimeOpt
|
||||||
|
.map(latestTime -> historyList.stream()
|
||||||
|
.noneMatch(item -> latestTime.equals(item.get("time"))))
|
||||||
|
.orElse(true); // 数据库为空时需要更新
|
||||||
|
|
||||||
|
if (needUpdate) {
|
||||||
|
log.info("需要更新数据,最新时间:{}",
|
||||||
|
latestTimeOpt.orElse("数据库为空"));
|
||||||
|
HttpClientExample.getPksHistory(historyList, pypath);
|
||||||
|
} else {
|
||||||
|
log.info("数据已是最新,无需更新");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*public void executeLotteryDraw() {
|
/*public void executeLotteryDraw() {
|
||||||
System.out.println("开始爬取开奖结果...");
|
System.out.println("开始爬取开奖结果...");
|
||||||
String token = tokenCacheService.getToken();
|
String token = tokenCacheService.getToken();
|
||||||
@@ -119,7 +155,7 @@ public class CrawlerSchedule {
|
|||||||
|
|
||||||
|
|
||||||
// 从7:00分30秒起每5分钟执行一次爬取今日已经结算
|
// 从7:00分30秒起每5分钟执行一次爬取今日已经结算
|
||||||
@Scheduled(cron = "35 0/5 * * * ?")
|
//@Scheduled(cron = "35 0/5 * * * ?")
|
||||||
public void executeSettlement() {
|
public void executeSettlement() {
|
||||||
log.info("开始爬取今日已经结算...");
|
log.info("开始爬取今日已经结算...");
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
@@ -128,6 +164,11 @@ public class CrawlerSchedule {
|
|||||||
if (token == null || token.isEmpty()) {
|
if (token == null || token.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
LoginInfoResult firstByOrderByCreateTimeDesc = loginInfoRepository.findFirstByOrderByCreateTimeDesc()
|
||||||
|
.orElse(null);
|
||||||
|
if(firstByOrderByCreateTimeDesc.getOnOff() == ONOFF){
|
||||||
|
return;
|
||||||
|
}
|
||||||
while (!success && retryCount < MAX_CRA) {
|
while (!success && retryCount < MAX_CRA) {
|
||||||
log.info("\n=== 第 " + (retryCount + 1) + " 次尝试获取今日注单 ===");
|
log.info("\n=== 第 " + (retryCount + 1) + " 次尝试获取今日注单 ===");
|
||||||
if (token == null || token.isEmpty()) {
|
if (token == null || token.isEmpty()) {
|
||||||
@@ -141,8 +182,7 @@ public class CrawlerSchedule {
|
|||||||
|
|
||||||
// 创建爬虫实例,传入token
|
// 创建爬虫实例,传入token
|
||||||
CompletedTodayCrawler crawler = new CompletedTodayCrawler(token);
|
CompletedTodayCrawler crawler = new CompletedTodayCrawler(token);
|
||||||
LoginInfoResult firstByOrderByCreateTimeDesc = loginInfoRepository.findFirstByOrderByCreateTimeDesc()
|
|
||||||
.orElse(null);
|
|
||||||
// 执行爬虫
|
// 执行爬虫
|
||||||
String url = firstByOrderByCreateTimeDesc.getLoginUrl()+"/member/bets?settled=true";
|
String url = firstByOrderByCreateTimeDesc.getLoginUrl()+"/member/bets?settled=true";
|
||||||
|
|
||||||
|
|||||||
232
src/main/java/com/tem/bocai/util/HttpClientExample.java
Normal file
232
src/main/java/com/tem/bocai/util/HttpClientExample.java
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
package com.tem.bocai.util;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||||
|
import org.apache.hc.client5.http.config.RequestConfig;
|
||||||
|
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||||
|
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
|
||||||
|
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||||
|
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
|
||||||
|
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
|
||||||
|
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
|
||||||
|
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
|
||||||
|
import org.apache.hc.core5.http.HttpEntity;
|
||||||
|
import org.apache.hc.core5.http.ParseException;
|
||||||
|
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
||||||
|
import org.apache.hc.core5.ssl.SSLContexts;
|
||||||
|
import org.apache.hc.core5.ssl.TrustStrategy;
|
||||||
|
import org.apache.hc.core5.util.Timeout;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class HttpClientExample {
|
||||||
|
|
||||||
|
public static String getPksHistory(List<Map<String, Object>> resultList ,String pypath) {
|
||||||
|
// 将数据写入SQLite数据库
|
||||||
|
SQLiteUtil.writeToSQLite(resultList);
|
||||||
|
// 将数据写入JSON文件(保留原有功能)
|
||||||
|
writeToJsonFile(resultList,pypath);
|
||||||
|
log.info("历史爬虫打印结果===" + resultList);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Map<String, Object>> getPksHistoryList(){
|
||||||
|
List<Map<String, Object>> resultList = new ArrayList<>();
|
||||||
|
String todayDate = DateUtils.getTodayDate();
|
||||||
|
try {
|
||||||
|
String url = "https://api.api168168.com/pks/getPksHistoryList.do?lotCode=10058&"+todayDate;
|
||||||
|
|
||||||
|
// 设置代理 127.0.0.1:7890
|
||||||
|
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890));
|
||||||
|
|
||||||
|
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(proxy);
|
||||||
|
conn.setRequestMethod("GET");
|
||||||
|
conn.setRequestProperty("Origin", "https://xy678kjw.com");
|
||||||
|
conn.setRequestProperty("Referer", "https://xy678kjw.com/");
|
||||||
|
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36");
|
||||||
|
conn.setConnectTimeout(10000);
|
||||||
|
conn.setReadTimeout(10000);
|
||||||
|
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
|
||||||
|
StringBuilder response = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
response.append(line);
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
// 使用Jackson解析JSON
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = objectMapper.readTree(response.toString());
|
||||||
|
|
||||||
|
// 检查是否成功
|
||||||
|
int errorCode = rootNode.get("errorCode").asInt();
|
||||||
|
if (errorCode == 0) {
|
||||||
|
// 获取data数组
|
||||||
|
JsonNode dataArray = rootNode
|
||||||
|
.get("result")
|
||||||
|
.get("data");
|
||||||
|
|
||||||
|
if (dataArray.isArray()) {
|
||||||
|
for (JsonNode item : dataArray) {
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
|
||||||
|
// 解析原始数据
|
||||||
|
String preDrawCode = item.get("preDrawCode").asText();
|
||||||
|
String[] codeArray = preDrawCode.split(",");
|
||||||
|
|
||||||
|
// 转换为整数数组
|
||||||
|
int[] result = new int[codeArray.length];
|
||||||
|
for (int i = 0; i < codeArray.length; i++) {
|
||||||
|
result[i] = Integer.parseInt(codeArray[i].trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算sum1和sum2
|
||||||
|
int sum1 = 0;
|
||||||
|
int sum2 = 0;
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
sum1 += result[i];
|
||||||
|
}
|
||||||
|
for (int i = 5; i < 10; i++) {
|
||||||
|
sum2 += result[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算winner(前五个号码的和)
|
||||||
|
int winner = sum1;
|
||||||
|
|
||||||
|
// 计算冠亚和(前两个号码的和)
|
||||||
|
int championSum = result[0] + result[1];
|
||||||
|
|
||||||
|
// 判断冠亚单双
|
||||||
|
String GD2 = (championSum % 2 == 0) ? "冠亚双" : "冠亚单";
|
||||||
|
|
||||||
|
// 判断冠亚大小(冠亚和11为大,11为小)
|
||||||
|
String GD1 = (championSum > 11) ? "冠亚大" : "冠亚小";
|
||||||
|
if (championSum == 11) {
|
||||||
|
GD1 = "冠亚小"; // 特殊处理:和值为11算小
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算龙虎(1-5位对比)
|
||||||
|
List<String> GLH_result = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
if (result[i] > result[9 - i]) {
|
||||||
|
GLH_result.add("龙");
|
||||||
|
} else {
|
||||||
|
GLH_result.add("虎");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建转换后的map
|
||||||
|
map.put("result", result);
|
||||||
|
map.put("sum1", sum1);
|
||||||
|
map.put("sum2", sum2);
|
||||||
|
map.put("winner", winner);
|
||||||
|
map.put("GD2", GD2);
|
||||||
|
map.put("GD1", GD1);
|
||||||
|
map.put("GLH_result", GLH_result);
|
||||||
|
map.put("id", String.valueOf(item.get("preDrawIssue").asLong()));
|
||||||
|
map.put("time", item.get("preDrawTime").asText());
|
||||||
|
|
||||||
|
resultList.add(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印转换后的结果列表
|
||||||
|
System.out.println("Total records: " + resultList.size());
|
||||||
|
|
||||||
|
// 使用ObjectMapper将结果列表转换为JSON格式输出
|
||||||
|
ObjectMapper outputMapper = new ObjectMapper();
|
||||||
|
String jsonOutput = outputMapper.writerWithDefaultPrettyPrinter().writeValueAsString(resultList);
|
||||||
|
System.out.println(jsonOutput);
|
||||||
|
|
||||||
|
// 或者以自定义格式输出(可选)
|
||||||
|
System.out.println("\n=== 转换后的数据格式 ===");
|
||||||
|
for (Map<String, Object> map : resultList) {
|
||||||
|
System.out.println("{");
|
||||||
|
System.out.println(" \"result\" : " + Arrays.toString((int[]) map.get("result")) + ",");
|
||||||
|
System.out.println(" \"sum1\" : " + map.get("sum1") + ",");
|
||||||
|
System.out.println(" \"sum2\" : " + map.get("sum2") + ",");
|
||||||
|
System.out.println(" \"winner\" : " + map.get("winner") + ",");
|
||||||
|
System.out.println(" \"GD2\" : \"" + map.get("GD2") + "\",");
|
||||||
|
System.out.println(" \"GD1\" : \"" + map.get("GD1") + "\",");
|
||||||
|
System.out.println(" \"GLH_result\" : " + map.get("GLH_result") + ",");
|
||||||
|
System.out.println(" \"id\" : \"" + map.get("id") + "\",");
|
||||||
|
System.out.println(" \"time\" : \"" + map.get("time") + "\"");
|
||||||
|
System.out.println("},");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return resultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void writeToJsonFile(List<Map<String, Object>> resultList,String pypath) {
|
||||||
|
try {
|
||||||
|
// 创建 ObjectMapper 实例
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
// 设置 JSON 格式化(可选,更易读)
|
||||||
|
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||||||
|
|
||||||
|
// 定义输出目录
|
||||||
|
String directoryPath = pypath+"/current_data"; // 项目根目录下的 output/json 文件夹
|
||||||
|
|
||||||
|
// 使用年月日作为文件名(格式:result_yyyyMMdd.json)
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
String dateStr = dateFormat.format(new Date());
|
||||||
|
String fileName = "result_" + dateStr + ".json";
|
||||||
|
String filePath = directoryPath + "/" + fileName;
|
||||||
|
|
||||||
|
// 创建目录(如果不存在)
|
||||||
|
File directory = new File(directoryPath);
|
||||||
|
if (!directory.exists()) {
|
||||||
|
directory.mkdirs(); // 创建多级目录
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建文件对象
|
||||||
|
File outputFile = new File(filePath);
|
||||||
|
|
||||||
|
// 如果文件已存在,删除旧文件(实现替换功能)
|
||||||
|
if (outputFile.exists()) {
|
||||||
|
boolean deleted = outputFile.delete();
|
||||||
|
if (!deleted) {
|
||||||
|
throw new IOException("无法删除已存在的文件: " + filePath);
|
||||||
|
}
|
||||||
|
System.out.println("已删除旧文件,准备创建新文件: " + fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将 List 写入 JSON 文件
|
||||||
|
objectMapper.writeValue(outputFile, resultList);
|
||||||
|
log.info("数据已成功写入文件: " + outputFile.getAbsolutePath());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
log.error("写入 JSON 文件失败: " + e.getMessage(), e);
|
||||||
|
throw new RuntimeException("写入 JSON 文件失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -10,4 +10,4 @@ spring.jpa.show-sql=true
|
|||||||
spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect
|
spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect
|
||||||
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
|
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
|
||||||
|
|
||||||
pypath:d:/py/PyModel
|
pypath:c:/py/PyModel
|
||||||
Reference in New Issue
Block a user