自动抓评论

This commit is contained in:
Van0313
2025-06-01 17:11:14 +08:00
parent f4d72b4335
commit 24c196c8a3
2 changed files with 116 additions and 8 deletions

View File

@@ -1,6 +1,10 @@
package cn.van.business.util;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.van.business.model.jd.OrderRow;
import cn.van.business.model.pl.Comment;
import cn.van.business.repository.CommentRepository;
import cn.van.business.repository.OrderRowRepository;
import cn.van.business.util.jdReq.*;
import com.alibaba.fastjson2.util.DateUtils;
@@ -23,9 +27,8 @@ import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import static cn.van.business.util.JDUtil.DATE_TIME_FORMATTER;
import static cn.van.business.util.WXUtil.super_admins;
@@ -48,6 +51,10 @@ public class JDScheduleJob {
private final StringRedisTemplate redisTemplate;
private final OrderRowRepository orderRowRepository;
private final OrderUtil orderUtil;
private final JDUtil jdUtil;
private final CommentRepository commentRepository;
@Getter
@Value("${isRunning.wx}")
private String isRunning_wx;
@@ -55,13 +62,17 @@ public class JDScheduleJob {
@Getter
@Value("${isRunning.jd}")
private String isRunning_jd;
// 构造函数中注入StringRedisTemplate
@Autowired
public JDScheduleJob(StringRedisTemplate redisTemplate, OrderRowRepository orderRowRepository, OrderUtil orderUtil) {
public JDScheduleJob(StringRedisTemplate redisTemplate, OrderRowRepository orderRowRepository, OrderUtil orderUtil, JDUtil jdUtil, CommentRepository commentRepository) {
this.redisTemplate = redisTemplate;
this.orderRowRepository = orderRowRepository;
this.orderUtil = orderUtil;
this.jdUtil = jdUtil;
this.commentRepository = commentRepository;
}
/**
* 将 响应参数转化为 OrderRow并返回
*/
@@ -136,6 +147,7 @@ public class JDScheduleJob {
orderRow.setTraceType(orderRowResp.getTraceType());
return orderRow;
}
/**
* 根据指定的日期时间拉取订单
*
@@ -197,6 +209,7 @@ public class JDScheduleJob {
private void processOrderResponse(UnionOpenOrderRowQueryResponse response, WXUtil.SuperAdmin admin) {
Arrays.stream(response.getQueryResult().getData()).parallel().map(this::createOrderRow).forEach(orderRowRepository::save);
}
public int fetchOrders(OrderFetchStrategy strategy, String appKey, String secretKey) {
TimeRange range = strategy.calculateRange(LocalDateTime.now());
@@ -270,6 +283,7 @@ public class JDScheduleJob {
});
}
}
/**
* 扫描订单发送到微信
* 每分钟的30秒执行一次
@@ -285,7 +299,7 @@ public class JDScheduleJob {
for (OrderRow orderRow : orderRows) {
orderUtil.orderToWx(orderRow, true,false);
orderUtil.orderToWx(orderRow, true, false);
}
@@ -305,7 +319,7 @@ public class JDScheduleJob {
OrderFetchStrategy strategy = new Days3090Strategy();
for (WXUtil.SuperAdmin admin : super_admins.values()) {
try {
if (Util.isAnyEmpty(admin.getAppKey(), admin.getSecretKey())){
if (Util.isAnyEmpty(admin.getAppKey(), admin.getSecretKey())) {
continue;
}
int count = fetchOrders(strategy, admin.getAppKey(), admin.getSecretKey());
@@ -332,7 +346,7 @@ public class JDScheduleJob {
OrderFetchStrategy strategy = new Days1430Strategy(); // 需补充Days1430Strategy实现
for (WXUtil.SuperAdmin admin : super_admins.values()) {
try {
if (Util.isAnyEmpty(admin.getAppKey(), admin.getSecretKey())){
if (Util.isAnyEmpty(admin.getAppKey(), admin.getSecretKey())) {
continue;
}
int count = fetchOrders(strategy, admin.getAppKey(), admin.getSecretKey());
@@ -398,6 +412,7 @@ public class JDScheduleJob {
}
}
/**
* 获取订单列表
*
@@ -435,4 +450,94 @@ public class JDScheduleJob {
return client.execute(request);
}
@Scheduled(cron = "0 0 8-20 * * ?") // 每天从 8:00 到 20:00每小时执行一次
public void fetchPL() {
// 设置每天最多执行 3 次
String cacheKey = "fetchPL:executedHours";
Set<String> executedHours = getExecutedHoursFromRedis(); // 从 Redis 获取已执行的小时数
LocalDateTime now = LocalDateTime.now();
String currentHour = String.valueOf(now.getHour());
// 如果今天已经执行了3次则跳过
if (executedHours.size() >= 3) {
return;
}
// 随机决定是否执行本次任务(例如 50% 概率)
if (new Random().nextBoolean()) {
// 执行任务逻辑
executeFetchPL();
// 记录该小时已执行
executedHours.add(currentHour);
saveExecutedHoursToRedis(executedHours); // 存入 Redis
}
}
private void executeFetchPL() {
HashMap<String, String> productTypeMap = jdUtil.getProductTypeMap();
int allCommentCount = 0;
int usedCommentCount = 0;
int canUseComentCount = 0;
int addCommentCount = 0;
for (Map.Entry<String, String> entry : productTypeMap.entrySet()) {
// 随机睡眠1-5分钟
int sleepTime = new Random().nextInt(300) + 60;
try {
Thread.sleep(sleepTime * 1000);
} catch (InterruptedException e) {
logger.error("线程中断", e);
}
String product_id = entry.getKey();
List<Comment> availableComments = commentRepository.findByProductIdAndIsUseNotAndPictureUrlsIsNotNull(product_id, 1);
List<Comment> usedComments = commentRepository.findByProductIdAndIsUseNotAndPictureUrlsIsNotNull(product_id, 0);
canUseComentCount = availableComments.size();
usedCommentCount = usedComments.size();
if (canUseComentCount > 5){
logger.info("商品{} 评论可用数量大于5{}", product_id, canUseComentCount);
return;
}
try {
String fetchUrl = "http://192.168.8.6:5000/fetch_comments?product_id=" + product_id;
// 用hutool发起post请求
HttpResponse response = HttpRequest.post(fetchUrl).timeout(60000).execute();
logger.info("fetchUrl: {}", fetchUrl);
// code = 200 表示成功,-200 表示失败
if (response.getStatus() == 200) {
// ✅ 关键修改:重新从数据库中查询,而不是使用内存中的 fetchedComments
availableComments = commentRepository.findByProductIdAndIsUseNotAndPictureUrlsIsNotNull(product_id, 1);
if (!availableComments.isEmpty()) {
addCommentCount = availableComments.size() - canUseComentCount;
logger.info("自动刷新并且获取评论成功");
logger.info("型号{} 总评论数量 {} 可用数量 {} 新增评论数量:{}", entry.getValue(), availableComments.size() + usedCommentCount, canUseComentCount, addCommentCount);
}
} else if (response.getStatus() == -200) {
return;
}
} catch (Exception e) {
logger.error("调用外部接口获取评论失败", e);
return;
}
}
}
private Set<String> getExecutedHoursFromRedis() {
String key = "fetchPL:executedHours";
HashOperations<String, String, String> hashOps = redisTemplate.opsForHash();
return hashOps.entries(key).keySet();
}
private void saveExecutedHoursToRedis(Set<String> hours) {
String key = "fetchPL:executedHours";
HashOperations<String, String, String> hashOps = redisTemplate.opsForHash();
hashOps.putAll(key, hours.stream().collect(Collectors.toMap(h -> h, h -> "1")));
}
}

View File

@@ -1771,7 +1771,7 @@ public class JDUtil {
}
//getProductTypeMap 从redis中获取PRODUCT_TYPE_MAP_PREFIX
public void getProductTypeMap() {
public HashMap<String, String> getProductTypeMap() {
Map<Object, Object> rawMap = redisTemplate.opsForHash().entries(PRODUCT_TYPE_MAP_PREFIX);
if (!rawMap.isEmpty()) {
@@ -1781,9 +1781,11 @@ public class JDUtil {
}
// 排序
productTypeMap = productTypeMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
return productTypeMap;
} else {
logger.warn("Redis 中未找到键为 {} 的 Hash 数据", PRODUCT_TYPE_MAP_PREFIX);
}
return null;
}
public void addProductTypeMap(String key, String value) {
@@ -1819,6 +1821,7 @@ public class JDUtil {
* 生成评论内容
*/
private synchronized void generateComment(String fromWxid, String productType) {
//wxUtil.sendTextMessage(fromWxid, "已接收到评论生成指令,等候过程请勿重复输入", 1, fromWxid, true);
int allCommentCount = 0;
int usedCommentCount = 0;