From 6f1c990d51c8ec8d11e60b142478b56064712bf5 Mon Sep 17 00:00:00 2001
From: xuelijun <977662702@qq.com>
Date: Wed, 21 Jan 2026 16:28:53 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BB=8A=E6=97=A5=E5=B7=B2=E7=BB=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 12 +
.../com/tem/bocai/config/CacheConfig.java | 42 ++
.../tem/bocai/controller/LoginCrawler.java | 6 +
.../com/tem/bocai/service/LoginService.java | 4 +
.../bocai/service/impl/LoginServiceImpl.java | 20 +
.../tem/bocai/util/CompletedTodayCrawler.java | 396 ++++++++++++++++++
.../bocai/util/LotteryWebMagicCrawler.java | 1 +
7 files changed, 481 insertions(+)
create mode 100644 src/main/java/com/tem/bocai/config/CacheConfig.java
create mode 100644 src/main/java/com/tem/bocai/util/CompletedTodayCrawler.java
diff --git a/pom.xml b/pom.xml
index 44d7c7c..9b6e291 100644
--- a/pom.xml
+++ b/pom.xml
@@ -78,6 +78,18 @@
tess4j
5.8.0
-->
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+
+
+ com.github.ben-manes.caffeine
+ caffeine
+ 3.1.8
+
diff --git a/src/main/java/com/tem/bocai/config/CacheConfig.java b/src/main/java/com/tem/bocai/config/CacheConfig.java
new file mode 100644
index 0000000..0187c97
--- /dev/null
+++ b/src/main/java/com/tem/bocai/config/CacheConfig.java
@@ -0,0 +1,42 @@
+package com.tem.bocai.config;
+
+
+import com.github.benmanes.caffeine.cache.Caffeine;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.caffeine.CaffeineCacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+import java.util.concurrent.TimeUnit;
+
+@Configuration
+@EnableCaching // 启用缓存支持
+public class CacheConfig {
+
+ /**
+ * 主缓存管理器 - 用于token缓存(19分钟过期)
+ */
+ @Bean
+ @Primary // 标记为主缓存管理器
+ public CacheManager cacheManager() {
+ CaffeineCacheManager cacheManager = new CaffeineCacheManager();
+ cacheManager.setCaffeine(Caffeine.newBuilder()
+ .expireAfterWrite(19, TimeUnit.MINUTES) // 19分钟过期
+ .maximumSize(100) // 最大缓存数量
+ .recordStats() // 记录统计信息
+ );
+ return cacheManager;
+ }
+
+ /**
+ * 备用缓存管理器 - 如果没有配置Caffeine,使用ConcurrentMap
+ */
+ @Bean
+ @ConditionalOnMissingBean(CacheManager.class)
+ public CacheManager fallbackCacheManager() {
+ return new org.springframework.cache.concurrent.ConcurrentMapCacheManager();
+ }
+}
diff --git a/src/main/java/com/tem/bocai/controller/LoginCrawler.java b/src/main/java/com/tem/bocai/controller/LoginCrawler.java
index 3e19e89..2455772 100644
--- a/src/main/java/com/tem/bocai/controller/LoginCrawler.java
+++ b/src/main/java/com/tem/bocai/controller/LoginCrawler.java
@@ -24,6 +24,12 @@ public class LoginCrawler {
return ResponseEntity.ok(result);
}
+ @GetMapping("/ocr/completedToday")
+ public ResponseEntity completedToday() throws IOException, TesseractException {
+ String result = loginService.completedToday();
+ return ResponseEntity.ok(result);
+ }
+
}
diff --git a/src/main/java/com/tem/bocai/service/LoginService.java b/src/main/java/com/tem/bocai/service/LoginService.java
index 496828d..50758d3 100644
--- a/src/main/java/com/tem/bocai/service/LoginService.java
+++ b/src/main/java/com/tem/bocai/service/LoginService.java
@@ -7,4 +7,8 @@ public interface LoginService {
//获取token
String getToken(String username, String password, String loginUrl);
+
+ //获取token
+ String completedToday();
+
}
diff --git a/src/main/java/com/tem/bocai/service/impl/LoginServiceImpl.java b/src/main/java/com/tem/bocai/service/impl/LoginServiceImpl.java
index 6a5bde7..016b7de 100644
--- a/src/main/java/com/tem/bocai/service/impl/LoginServiceImpl.java
+++ b/src/main/java/com/tem/bocai/service/impl/LoginServiceImpl.java
@@ -1,6 +1,7 @@
package com.tem.bocai.service.impl;
import com.tem.bocai.service.LoginService;
+import com.tem.bocai.util.CompletedTodayCrawler;
import com.tem.bocai.util.LotteryDataPipeline;
import com.tem.bocai.util.LotteryWebMagicCrawler;
import com.tem.bocai.util.TokenCacheService;
@@ -107,6 +108,25 @@ public class LoginServiceImpl implements LoginService {
return "";
}
+ @Override
+ public String completedToday() {
+ String token = tokenCacheService.getToken();
+ System.out.println("得到token = " + token);
+ if (token != null && !token.isEmpty()) {
+ // 2. 创建爬虫实例,传入token
+ CompletedTodayCrawler crawler = new CompletedTodayCrawler(token);
+
+ // 4. 执行爬虫
+ String url = "https://4701268539-esh.qdk63ayw8g.com/member/bets?settled=true";
+
+ Spider.create(crawler)
+ .addUrl(url)
+ .thread(1)
+ .run();
+ }
+ return "";
+ }
+
/**
* 单次登录尝试
*/
diff --git a/src/main/java/com/tem/bocai/util/CompletedTodayCrawler.java b/src/main/java/com/tem/bocai/util/CompletedTodayCrawler.java
new file mode 100644
index 0000000..8a1b752
--- /dev/null
+++ b/src/main/java/com/tem/bocai/util/CompletedTodayCrawler.java
@@ -0,0 +1,396 @@
+package com.tem.bocai.util;
+
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import us.codecraft.webmagic.Page;
+import us.codecraft.webmagic.Site;
+import us.codecraft.webmagic.Spider;
+import us.codecraft.webmagic.processor.PageProcessor;
+import us.codecraft.webmagic.selector.Html;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CompletedTodayCrawler implements PageProcessor {
+
+ private final String token;
+ private Site site;
+ private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+ public CompletedTodayCrawler(String token) {
+ this.token = token;
+ initSite();
+ }
+
+ private void initSite() {
+ site = Site.me()
+ .setRetryTimes(3)
+ .setSleepTime(2000) // 增加等待时间
+ .setTimeOut(15000) // 增加超时时间
+ .setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36")
+ .addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8")
+ .addHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
+ .addHeader("Accept-Encoding", "gzip, deflate, br")
+ .addHeader("Connection", "keep-alive")
+ .addHeader("Upgrade-Insecure-Requests", "1")
+ .addHeader("Sec-Fetch-Dest", "document")
+ .addHeader("Sec-Fetch-Mode", "navigate")
+ .addHeader("Sec-Fetch-Site", "same-origin")
+ .addHeader("Sec-Fetch-User", "?1");
+
+ // 设置cookie
+ if (token != null && !token.isEmpty()) {
+ site.addHeader("cookie", "token=" + token);
+ }
+ }
+
+ @Override
+ public void process(Page page) {
+ String url = page.getUrl().toString();
+ System.out.println("处理页面: " + url);
+
+ Html html = page.getHtml();
+ String content = html.toString();
+
+ // 打印一些基本信息
+ System.out.println("页面标题: " + html.xpath("//title/text()").get());
+ System.out.println("页面大小: " + content.length() + " 字符");
+
+ // 检查是否有"暂无数据"提示
+ if (content.contains("暂无数据")) {
+ System.out.println("警告: 页面显示'暂无数据'");
+ return;
+ }
+ // 解析注单数据
+ List