1
This commit is contained in:
@@ -32,7 +32,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static cn.van.business.util.JDUtil.*;
|
||||
|
||||
@@ -84,17 +84,29 @@ public class JDProductService {
|
||||
for (String url : urls) {
|
||||
try {
|
||||
String format = dateFormat.format(new Date());
|
||||
GoodsQueryResult productInfo = queryProductInfoByUJDUrl(url);
|
||||
String originalUrlInText = url;
|
||||
String normalizedUrl = normalizeJdUrl(originalUrlInText);
|
||||
if (normalizedUrl == null) {
|
||||
log.warn("检测到的链接无法识别为合法京东链接,跳过处理: {}", originalUrlInText);
|
||||
JSONObject errorObj = new JSONObject();
|
||||
errorObj.put("url", originalUrlInText);
|
||||
errorObj.put("error", "链接格式不支持或识别失败");
|
||||
resultArray.add(errorObj);
|
||||
continue;
|
||||
}
|
||||
|
||||
GoodsQueryResult productInfo = queryProductInfoByUJDUrl(normalizedUrl);
|
||||
if (productInfo == null || productInfo.getCode() != 200 || productInfo.getData() == null || productInfo.getData().length == 0) {
|
||||
JSONObject errorObj = new JSONObject();
|
||||
errorObj.put("url", url);
|
||||
errorObj.put("url", originalUrlInText);
|
||||
errorObj.put("error", "链接查询失败");
|
||||
resultArray.add(errorObj);
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONObject productObj = new JSONObject();
|
||||
productObj.put("originalUrl", url);
|
||||
productObj.put("originalUrl", originalUrlInText);
|
||||
productObj.put("normalizedUrl", normalizedUrl);
|
||||
|
||||
// 商品基本信息
|
||||
productObj.put("materialUrl", productInfo.getData()[0].getMaterialUrl());
|
||||
@@ -124,22 +136,24 @@ public class JDProductService {
|
||||
|
||||
// 生成转链后的短链
|
||||
try {
|
||||
String shortUrl = transfer(url, null);
|
||||
String shortUrl = transfer(normalizedUrl, null);
|
||||
String effectiveUrl = normalizedUrl;
|
||||
if (shortUrl != null && !shortUrl.isEmpty()) {
|
||||
productObj.put("shortUrl", shortUrl);
|
||||
productObj.put("transferSuccess", true);
|
||||
// 将短链替换原始链接,用于后续文案生成
|
||||
url = shortUrl;
|
||||
effectiveUrl = shortUrl;
|
||||
} else {
|
||||
productObj.put("shortUrl", url); // 如果转链失败,使用原链接
|
||||
productObj.put("shortUrl", normalizedUrl); // 如果转链失败,使用归一化后的链接
|
||||
productObj.put("transferSuccess", false);
|
||||
log.warn("转链失败,使用原链接: {}", url);
|
||||
log.warn("转链失败,使用原链接: {}", normalizedUrl);
|
||||
}
|
||||
productObj.put("effectiveUrl", effectiveUrl);
|
||||
} catch (Exception e) {
|
||||
log.error("生成转链时发生异常: {}", url, e);
|
||||
productObj.put("shortUrl", url); // 转链异常时使用原链接
|
||||
log.error("生成转链时发生异常: {}", normalizedUrl, e);
|
||||
productObj.put("shortUrl", normalizedUrl); // 转链异常时使用原链接
|
||||
productObj.put("transferSuccess", false);
|
||||
productObj.put("transferError", e.getMessage());
|
||||
productObj.put("effectiveUrl", normalizedUrl);
|
||||
}
|
||||
|
||||
// 文案信息
|
||||
@@ -194,7 +208,12 @@ public class JDProductService {
|
||||
JSONObject commonWenan = new JSONObject();
|
||||
commonWenan.put("type", "通用文案");
|
||||
// 将原始消息中的链接替换为转链后的短链
|
||||
String messageWithShortUrl = message.replace(productObj.getString("originalUrl"), url);
|
||||
String targetUrl = productObj.getString("effectiveUrl");
|
||||
String normalizedForReplace = productObj.getString("normalizedUrl");
|
||||
String messageWithShortUrl = message;
|
||||
if (normalizedForReplace != null && targetUrl != null) {
|
||||
messageWithShortUrl = message.replace(normalizedForReplace, targetUrl);
|
||||
}
|
||||
commonWenan.put("content", format + FANAN_COMMON + messageWithShortUrl);
|
||||
wenanArray.add(commonWenan);
|
||||
|
||||
@@ -547,4 +566,78 @@ public class JDProductService {
|
||||
log.info("批量创建礼金券完成 - 总数={}, 成功={}, 失败={}", batchSize, successCount, failCount);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static final Pattern UJD_LINK_PATTERN = Pattern.compile("^https?://u\\.jd\\.com/[A-Za-z0-9]+[A-Za-z0-9_-]*$", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern JINGFEN_LINK_PATTERN = Pattern.compile("^https?://jingfen\\.jd\\.com/detail/[A-Za-z0-9]+\\.html$", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern TRAILING_SYMBOLS_PATTERN = Pattern.compile("[))】>》。,;;!!??“”\"'、…—\\s]+$");
|
||||
|
||||
private static String normalizeJdUrl(String rawUrl) {
|
||||
if (rawUrl == null || rawUrl.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = rawUrl.trim();
|
||||
|
||||
// 截断常见中文/英文括号后的内容
|
||||
int cutoffIndex = findCutoffIndex(trimmed);
|
||||
if (cutoffIndex > -1) {
|
||||
trimmed = trimmed.substring(0, cutoffIndex);
|
||||
}
|
||||
|
||||
// 去掉末尾的标点符号
|
||||
trimmed = TRAILING_SYMBOLS_PATTERN.matcher(trimmed).replaceAll("");
|
||||
if (trimmed.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!trimmed.startsWith("http://") && !trimmed.startsWith("https://")) {
|
||||
trimmed = "https://" + trimmed;
|
||||
}
|
||||
|
||||
if (UJD_LINK_PATTERN.matcher(trimmed).matches() || JINGFEN_LINK_PATTERN.matcher(trimmed).matches()) {
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
// 针对 u.jd.com 链接,尝试进一步截断到第一个不合法字符
|
||||
if (trimmed.contains("u.jd.com/")) {
|
||||
int schemeEnd = trimmed.indexOf("u.jd.com/") + "u.jd.com/".length();
|
||||
StringBuilder sb = new StringBuilder(trimmed.substring(0, schemeEnd));
|
||||
for (int i = schemeEnd; i < trimmed.length(); i++) {
|
||||
char c = trimmed.charAt(i);
|
||||
if (isAllowedShortLinkChar(c)) {
|
||||
sb.append(c);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
String candidate = sb.toString();
|
||||
if (UJD_LINK_PATTERN.matcher(candidate).matches()) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int findCutoffIndex(String text) {
|
||||
char[] stopChars = new char[]{'(', '(', '[', '【', '<', '《', '「', '『'};
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
char c = text.charAt(i);
|
||||
if (Character.isWhitespace(c)) {
|
||||
return i;
|
||||
}
|
||||
for (char stopChar : stopChars) {
|
||||
if (c == stopChar) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static boolean isAllowedShortLinkChar(char c) {
|
||||
return (c >= 'A' && c <= 'Z')
|
||||
|| (c >= 'a' && c <= 'z')
|
||||
|| (c >= '0' && c <= '9')
|
||||
|| c == '-' || c == '_' || c == '.';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user