feat(crawler): 新增美团首次接入功能
- 添加 CrawlerConfigAppriaisalAddDTO 类用于配置爬虫参数 - 实现 FtbCrawlNetFirstMt 类处理美团和大众点评的 Cookie 拦截 - 配置新增的 configInterfaceAddress 地址用于发送配置信息 - 更新 GlobalConfig 类添加租户名称和门店列表接口地址 - 在 PlatformSelectionView 页面增加“美团接入”选项 - 修改模块依赖引入 checkerframework 注解库 - 调整 BASE_NET_URL 默认指向本地开发环境地址
This commit is contained in:
@@ -7,8 +7,8 @@ public class GlobalConfig {
|
|||||||
/**
|
/**
|
||||||
* 基础网络地址
|
* 基础网络地址
|
||||||
*/
|
*/
|
||||||
//public static final String BASE_NET_URL = "http://127.0.0.1:9606";
|
public static final String BASE_NET_URL = "http://127.0.0.1:9606";
|
||||||
public static final String BASE_NET_URL = "http://139.155.27.186:9607";
|
//public static final String BASE_NET_URL = "http://139.155.27.186:9607";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录接口地址
|
* 登录接口地址
|
||||||
@@ -24,6 +24,12 @@ public class GlobalConfig {
|
|||||||
* 更新cookie地址
|
* 更新cookie地址
|
||||||
*/
|
*/
|
||||||
public static final String updateCookieInterfaceAddress = BASE_NET_URL+"/crawler/appraisal/update-user-cookie";
|
public static final String updateCookieInterfaceAddress = BASE_NET_URL+"/crawler/appraisal/update-user-cookie";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置请求地址
|
||||||
|
*/
|
||||||
|
public static final String configInterfaceAddress = BASE_NET_URL+"/crawler/appraisal/config";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 网络图标接口地址
|
* 网络图标接口地址
|
||||||
*/
|
*/
|
||||||
@@ -34,6 +40,16 @@ public class GlobalConfig {
|
|||||||
*/
|
*/
|
||||||
public static String tenantId;
|
public static String tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户Id标识
|
||||||
|
*/
|
||||||
|
public static String tenantName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 门店列表接口地址
|
||||||
|
*/
|
||||||
|
public static String mtShopListInterfaceAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 美团点评评价接口地址
|
* 美团点评评价接口地址
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.fantaibao.model;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数配置vo
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CrawlerConfigAppriaisalAddDTO {
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
/**
|
||||||
|
* 请求urlName
|
||||||
|
*/
|
||||||
|
private String urlName;
|
||||||
|
/**
|
||||||
|
* 请求方式 0 get/ 1 post
|
||||||
|
*/
|
||||||
|
private Integer method;
|
||||||
|
/**
|
||||||
|
* 请求参数
|
||||||
|
*/
|
||||||
|
private Map<String,String> param;
|
||||||
|
/**
|
||||||
|
* 请求cookie
|
||||||
|
*/
|
||||||
|
private Map<String,String> cookie;
|
||||||
|
/**
|
||||||
|
* 租户标识
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kafka消息topic
|
||||||
|
*/
|
||||||
|
private String messageTopic;
|
||||||
|
/**
|
||||||
|
* 平台0美团开店宝,1抖音,2饿了么商家端3美团外卖商家版4京东
|
||||||
|
*/
|
||||||
|
private Integer platform;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 美团门店列表参数
|
||||||
|
*/
|
||||||
|
private JSONObject storeParam;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -48,11 +48,18 @@ public class PlatformSelectionView {
|
|||||||
platformOptions.setAlignment(Pos.CENTER);
|
platformOptions.setAlignment(Pos.CENTER);
|
||||||
platformOptions.setSpacing(60);
|
platformOptions.setSpacing(60);
|
||||||
|
|
||||||
// 美团开店宝选项
|
// 美团开店宝cookie选项
|
||||||
VBox meituanOption = createPlatformMtOption(
|
VBox meituanOption = createPlatformMtOption(
|
||||||
"美团开店宝",
|
"美团Cookie更新",
|
||||||
GlobalConfig.mtLogo,
|
GlobalConfig.mtLogo,
|
||||||
"#FFD700"
|
"#FFD700","ftbCrawlNetMt"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 美团首次接入
|
||||||
|
VBox meituanFirstOption = createPlatformMtOption(
|
||||||
|
"美团接入",
|
||||||
|
GlobalConfig.mtLogo,
|
||||||
|
"#FFD700","ftbCrawlNetFirstMt"
|
||||||
);
|
);
|
||||||
|
|
||||||
// 抖音来客选项
|
// 抖音来客选项
|
||||||
@@ -62,7 +69,7 @@ public class PlatformSelectionView {
|
|||||||
"#4A90E2"
|
"#4A90E2"
|
||||||
);
|
);
|
||||||
|
|
||||||
platformOptions.getChildren().addAll(meituanOption, douyinOption);
|
platformOptions.getChildren().addAll(meituanOption,meituanFirstOption, douyinOption);
|
||||||
|
|
||||||
// 添加组件到主容器
|
// 添加组件到主容器
|
||||||
root.getChildren().addAll(titleLabel, infoLabel, platformOptions);
|
root.getChildren().addAll(titleLabel, infoLabel, platformOptions);
|
||||||
@@ -73,7 +80,7 @@ public class PlatformSelectionView {
|
|||||||
primaryStage.show();
|
primaryStage.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private VBox createPlatformMtOption(String title, Image imageUrl, String buttonColor) {
|
private VBox createPlatformMtOption(String title, Image imageUrl, String buttonColor,String beanName) {
|
||||||
VBox option = new VBox();
|
VBox option = new VBox();
|
||||||
option.setAlignment(Pos.CENTER);
|
option.setAlignment(Pos.CENTER);
|
||||||
option.setSpacing(10);
|
option.setSpacing(10);
|
||||||
@@ -93,7 +100,7 @@ public class PlatformSelectionView {
|
|||||||
connectButton.setStyle("-fx-background-color: " + buttonColor + "; -fx-text-fill: white; -fx-padding: 10px 20px; -fx-border-radius: 4px;");
|
connectButton.setStyle("-fx-background-color: " + buttonColor + "; -fx-text-fill: white; -fx-padding: 10px 20px; -fx-border-radius: 4px;");
|
||||||
|
|
||||||
connectButton.setOnAction(event -> {
|
connectButton.setOnAction(event -> {
|
||||||
FtbCrawlNetBase ftbCrawlNetMt = SpringContext.getBean("ftbCrawlNetMt");
|
FtbCrawlNetBase ftbCrawlNetMt = SpringContext.getBean(beanName);
|
||||||
ThreadPoolTaskExecutor poolTaskExecutor = SpringContext.getBean(ThreadPoolTaskExecutor.class);
|
ThreadPoolTaskExecutor poolTaskExecutor = SpringContext.getBean(ThreadPoolTaskExecutor.class);
|
||||||
poolTaskExecutor.execute(() -> {
|
poolTaskExecutor.execute(() -> {
|
||||||
ftbCrawlNetMt.executeCookieIntercept();
|
ftbCrawlNetMt.executeCookieIntercept();
|
||||||
|
|||||||
187
src/main/java/com/fantaibao/service/FtbCrawlNetFirstMt.java
Normal file
187
src/main/java/com/fantaibao/service/FtbCrawlNetFirstMt.java
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
package com.fantaibao.service;
|
||||||
|
|
||||||
|
import cn.hutool.http.HttpUtil;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.fantaibao.base.FtbCrawlNetBase;
|
||||||
|
import com.fantaibao.config.BrowserStealthConfig;
|
||||||
|
import com.fantaibao.config.GlobalConfig;
|
||||||
|
import com.fantaibao.config.PlaywrightManager;
|
||||||
|
import com.fantaibao.model.CrawlerConfigAppriaisalAddDTO;
|
||||||
|
import com.microsoft.playwright.Browser;
|
||||||
|
import com.microsoft.playwright.BrowserContext;
|
||||||
|
import com.microsoft.playwright.Page;
|
||||||
|
import com.microsoft.playwright.Request;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.control.Alert;
|
||||||
|
import javafx.scene.control.ButtonType;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
@Component(value = "ftbCrawlNetFirstMt")
|
||||||
|
@Slf4j
|
||||||
|
public class FtbCrawlNetFirstMt extends AbstractFtbCrawlNetBase implements FtbCrawlNetBase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void executeCookieIntercept() {
|
||||||
|
// 启动可见浏览器
|
||||||
|
try (Browser browser = PlaywrightManager.getInstance().getPlaywright()
|
||||||
|
.chromium().launch(BrowserStealthConfig.getStealthLaunchOptions())) {
|
||||||
|
// 设置浏览器上下文选项以减少自动化检测
|
||||||
|
BrowserContext context = browser.newContext(BrowserStealthConfig.getStealthContextOptions());
|
||||||
|
|
||||||
|
// 添加反自动化检测脚本
|
||||||
|
BrowserStealthConfig.configureStealthContext(context);
|
||||||
|
|
||||||
|
// 门店抓取
|
||||||
|
AtomicBoolean isCrawlFinished = new AtomicBoolean(false);
|
||||||
|
// 美团cookie
|
||||||
|
AtomicBoolean mtCookie = new AtomicBoolean(false);
|
||||||
|
// 大众点评cookie
|
||||||
|
AtomicBoolean dzCookie = new AtomicBoolean(false);
|
||||||
|
AtomicReference<JSONObject> atomicReference = new AtomicReference<>();
|
||||||
|
// 监听网络请求
|
||||||
|
context.onRequest((request -> handleRequest(request,mtCookie,dzCookie,isCrawlFinished,atomicReference)));
|
||||||
|
|
||||||
|
Page page = context.newPage();
|
||||||
|
// 监听浏览器关闭事件释放资源
|
||||||
|
browser.onDisconnected((brow) -> {
|
||||||
|
if (page != null && !page.isClosed()) {
|
||||||
|
log.info("美团浏览器关闭事件");
|
||||||
|
page.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 导航到登录页面
|
||||||
|
page.navigate(GlobalConfig.mtLoginPage,
|
||||||
|
new Page.NavigateOptions().setTimeout(60000.0));
|
||||||
|
// 设置30分钟登录超时时间
|
||||||
|
Page.WaitForConditionOptions waitForConditionOptions = new Page.WaitForConditionOptions();
|
||||||
|
waitForConditionOptions.setTimeout(30*60*1000);
|
||||||
|
page.waitForCondition(() -> mtCookie.get() && dzCookie.get() && isCrawlFinished.get(),waitForConditionOptions);
|
||||||
|
// 关闭页面
|
||||||
|
showSuccessAlertAndCloset(page,"美团");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("执行打开浏览器时发生错误", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理网络请求,提取需要的cookie信息
|
||||||
|
*
|
||||||
|
* @param request 网络请求
|
||||||
|
* @param storeParam
|
||||||
|
*/
|
||||||
|
private void handleRequest(Request request, AtomicBoolean mtCookie, AtomicBoolean dzCookie, AtomicBoolean isCrawlFinished, AtomicReference<JSONObject> atomicReference) {
|
||||||
|
// 美团cookie
|
||||||
|
if (request.url().contains(GlobalConfig.mtDianPingInterfaceAddress)) {
|
||||||
|
// 打印请求URL
|
||||||
|
log.info("请求URL: {}", request.url());
|
||||||
|
// 获取请求头中的Cookie
|
||||||
|
String cookieHeader = request.headerValue("cookie");
|
||||||
|
if (cookieHeader != null && !cookieHeader.isEmpty()) {
|
||||||
|
log.info("获取到{}的Cookie","美团");
|
||||||
|
CrawlerConfigAppriaisalAddDTO userCookieDTO = new CrawlerConfigAppriaisalAddDTO();
|
||||||
|
userCookieDTO.setTenantId(GlobalConfig.tenantId);
|
||||||
|
userCookieDTO.setPlatform(0);
|
||||||
|
userCookieDTO.setMethod(1);
|
||||||
|
userCookieDTO.setMessageTopic("ftb-crawler-mt-evaluate-"+GlobalConfig.tenantId);
|
||||||
|
userCookieDTO.setUrlName(GlobalConfig.tenantName+"美团评价");
|
||||||
|
userCookieDTO.setUrl("https://ecom.meituan.com/emis/gw/rpc/TFeedbackEcomService/queryFeedback?_tm=1752304094520&yodaReady=h5&csecplatform=4&csecversion=3.2.1");
|
||||||
|
Map<String,String> param = new HashMap<>();
|
||||||
|
param.put("requestBody","{\"platform\":0,\"queryPara\":{\"platform\":0,\"referTag\":0,\"startTime\":1751990400000,\"endTime\":1752076799999,\"starTag\":-1,\"businessTag\":\"-1\",\"poiIdLong\":\"853401195\",\"poiIdStr\":\"853401195\"},\"pageInfo\":{\"offset\":0,\"limit\":10,\"total\":0}}");
|
||||||
|
userCookieDTO.setParam(param);
|
||||||
|
Map<String,String> cookie = new HashMap<>();
|
||||||
|
cookie.put("cookie",cookieHeader);
|
||||||
|
userCookieDTO.setCookie(cookie);
|
||||||
|
userCookieDTO.setStoreParam(atomicReference.get());
|
||||||
|
processCookiet(userCookieDTO, "美团",mtCookie);
|
||||||
|
}
|
||||||
|
} else if (request.url().contains(GlobalConfig.mtDaZhInterfaceAddress)) {
|
||||||
|
// 打印请求URL
|
||||||
|
log.info("请求URL: {}", request.url());
|
||||||
|
// 获取请求头中的Cookie
|
||||||
|
String cookieHeader = request.headerValue("cookie");
|
||||||
|
if (cookieHeader != null && !cookieHeader.isEmpty()) {
|
||||||
|
log.info("获取到{}的Cookie","大众点评");
|
||||||
|
CrawlerConfigAppriaisalAddDTO userCookieDTO = new CrawlerConfigAppriaisalAddDTO();
|
||||||
|
userCookieDTO.setTenantId(GlobalConfig.tenantId);
|
||||||
|
userCookieDTO.setPlatform(5);
|
||||||
|
userCookieDTO.setMethod(1);
|
||||||
|
userCookieDTO.setMessageTopic("ftb-crawler-mt-evaluate-"+GlobalConfig.tenantId);
|
||||||
|
userCookieDTO.setUrlName(GlobalConfig.tenantName+"美团评价");
|
||||||
|
userCookieDTO.setUrl("https://ecom.meituan.com/emis/gw/TDPFeedbackServiceV2/queryFeedbackPCV2?_tm=1752304359951&yodaReady=h5&csecplatform=4&csecversion=3.2.1");
|
||||||
|
Map<String,String> param = new HashMap<>();
|
||||||
|
param.put("requestBody","{\"platform\":1,\"queryPara\":{\"platform\":1,\"referTag\":0,\"startTime\":1752076800000,\"endTime\":1752163199999,\"starTag\":-1,\"businessTag\":\"-1\",\"poiIdLong\":\"853401195\",\"poiIdStr\":\"853401195\"},\"pageInfo\":{\"offset\":0,\"limit\":10,\"total\":0}}");
|
||||||
|
userCookieDTO.setParam(param);
|
||||||
|
Map<String,String> cookie = new HashMap<>();
|
||||||
|
cookie.put("cookie",cookieHeader);
|
||||||
|
userCookieDTO.setCookie(cookie);
|
||||||
|
userCookieDTO.setStoreParam(atomicReference.get());
|
||||||
|
processCookiet(userCookieDTO, "大众点评",dzCookie);
|
||||||
|
} else if (request.url().contains(GlobalConfig.mtShopListInterfaceAddress)) {
|
||||||
|
String text = request.response().text();
|
||||||
|
log.info("请求门店返回内容为: {}", text);
|
||||||
|
atomicReference.set(JSONObject.parseObject(text));
|
||||||
|
isCrawlFinished.set(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void showSuccessAlertAndCloset(Page page, String platformName) {
|
||||||
|
try {
|
||||||
|
// 在JavaFX线程中显示弹窗
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||||
|
alert.setTitle("美团接入完成");
|
||||||
|
alert.setHeaderText(null);
|
||||||
|
alert.setContentText(platformName+"数据已接入完成,请点击\"我已知晓\"关闭");
|
||||||
|
// 设置弹窗图标
|
||||||
|
Stage alertStage = (Stage) alert.getDialogPane().getScene().getWindow();
|
||||||
|
GlobalConfig.addIcon(alertStage);
|
||||||
|
// 添加自定义按钮
|
||||||
|
ButtonType acknowledgeButton = new ButtonType("我已知晓");
|
||||||
|
alert.getButtonTypes().setAll(acknowledgeButton);
|
||||||
|
|
||||||
|
// 显示弹窗并等待用户响应
|
||||||
|
Optional<ButtonType> result = alert.showAndWait();
|
||||||
|
if (result.isPresent() && result.get() == acknowledgeButton) {
|
||||||
|
// 用户点击了"我已知晓"按钮,关闭页面
|
||||||
|
try {
|
||||||
|
page.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("关闭页面时出错", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("显示弹窗或关闭页面时出错", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理cookie并发送到服务器
|
||||||
|
* @param platformName 平台名称,用于日志记录
|
||||||
|
*/
|
||||||
|
protected void processCookiet(CrawlerConfigAppriaisalAddDTO userCookieDTO, String platformName, AtomicBoolean isCrawlFinished) {
|
||||||
|
try {
|
||||||
|
String result = HttpUtil.post(GlobalConfig.configInterfaceAddress, JSON.toJSONString(userCookieDTO));
|
||||||
|
JSONObject parsed = JSON.parseObject(result);
|
||||||
|
if (parsed.getInteger("code") == 200) {
|
||||||
|
isCrawlFinished.set(true);
|
||||||
|
log.info("{} 接入成功", platformName);
|
||||||
|
} else {
|
||||||
|
log.warn("{} 接入成功: {}", platformName, parsed.getString("msg"));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("{} 接入异常", platformName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,11 +9,11 @@ module fantaibao.crawler.desktop {
|
|||||||
requires playwright;
|
requires playwright;
|
||||||
requires org.slf4j;
|
requires org.slf4j;
|
||||||
requires lombok;
|
requires lombok;
|
||||||
requires java.desktop;
|
|
||||||
requires jakarta.annotation;
|
requires jakarta.annotation;
|
||||||
requires cn.hutool;
|
requires cn.hutool;
|
||||||
requires fastjson;
|
requires fastjson;
|
||||||
requires java.sql;
|
requires java.sql;
|
||||||
|
requires org.checkerframework.checker.qual;
|
||||||
|
|
||||||
opens com.fantaibao to spring.core, spring.beans, spring.context,
|
opens com.fantaibao to spring.core, spring.beans, spring.context,
|
||||||
javafx.fxml, javafx.base, javafx.graphics, spring.boot, spring.boot.autoconfigure;
|
javafx.fxml, javafx.base, javafx.graphics, spring.boot, spring.boot.autoconfigure;
|
||||||
|
|||||||
Reference in New Issue
Block a user