|
|
@@ -2,13 +2,17 @@ package com.jzg.quotation.zhongan.crawler.component;
|
|
|
|
|
|
import com.alibaba.fastjson2.JSON;
|
|
|
import com.alibaba.fastjson2.JSONObject;
|
|
|
+import com.fasterxml.jackson.databind.JsonNode;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
import com.jzg.commons.util.AssertionUtils;
|
|
|
import com.jzg.quotation.zhongan.crawler.client.LoginResult;
|
|
|
import com.jzg.quotation.zhongan.crawler.entity.request.ZhongAnCrawlerQueryInitInfoRequest;
|
|
|
import com.jzg.quotation.zhongan.crawler.entity.response.ZhongAnCrawlerPaymentResponse;
|
|
|
import com.jzg.quotation.zhongan.crawler.entity.response.ZhongAnCrawlerUploadInitDateResponse;
|
|
|
+import lombok.Data;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import okhttp3.*;
|
|
|
import org.apache.hc.core5.net.URIBuilder;
|
|
|
import org.apache.http.Header;
|
|
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
|
|
@@ -26,6 +30,7 @@ import org.springframework.stereotype.Component;
|
|
|
import java.net.URI;
|
|
|
import java.time.Duration;
|
|
|
import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.regex.Matcher;
|
|
|
import java.util.regex.Pattern;
|
|
|
@@ -111,107 +116,119 @@ public class ZhongAnCrawlerCacheComponent {
|
|
|
return JSON.parseObject(bucket1.get(), ZhongAnCrawlerPaymentResponse.ValueDTO.DatasDTO.InitInfoDTO.class);
|
|
|
}
|
|
|
|
|
|
- //登录
|
|
|
- private static final CloseableHttpClient HTTP_CLIENT =HttpClients.custom().disableRedirectHandling().build(); // 关闭自动重定向
|
|
|
+ private static final OkHttpClient session = new OkHttpClient.Builder()
|
|
|
+ .followRedirects(false)
|
|
|
+ .build();
|
|
|
|
|
|
- // 正则表达式 获取cookie、flowId
|
|
|
- private static final Pattern ZA_COOKIE_PATTERN = Pattern.compile("zaLoginCookieKey=(.*?);");
|
|
|
- private static final Pattern FLOW_ID_PATTERN = Pattern.compile("flowId=(.*?)&");
|
|
|
-
|
|
|
- // 构造 GET 请求
|
|
|
- private HttpGet buildGet(URI uri) {
|
|
|
- HttpGet get = new HttpGet(uri);
|
|
|
- get.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36");
|
|
|
- get.setHeader("Accept", "application/json, text/plain, */*");
|
|
|
- return get;
|
|
|
- }
|
|
|
-
|
|
|
- // 获取重定向 Location
|
|
|
- private String getLocationHeader(CloseableHttpResponse response) {
|
|
|
- Header header = response.getLastHeader("Location");
|
|
|
- return header != null ? header.getValue() : "";
|
|
|
- }
|
|
|
+ private static final ObjectMapper objectMapper = new ObjectMapper();
|
|
|
public LoginResult loginCookieCache(String zhongAnId,String productId) {
|
|
|
- HttpClientContext context = HttpClientContext.create();
|
|
|
try {
|
|
|
- String firstUrl = "http://zhongan.bjhfbx.cn/subao-proxy-customer/api/redirectToCoopUserProductExclusivePage";
|
|
|
- URI uri1 = new URIBuilder(firstUrl)
|
|
|
- .addParameter("coopUserId", zhongAnId)
|
|
|
- .addParameter("productId", productId)
|
|
|
- .addParameter("isOpenByPC", "N")
|
|
|
- .addParameter("promotionScene", "16")
|
|
|
- .addParameter("bizContent", "")
|
|
|
- .addParameter("insurePlaceCode", "140100")
|
|
|
+ // ========== 第一步 POST 请求 ==========
|
|
|
+ Headers.Builder postHeaderBuilder = new Headers.Builder();
|
|
|
+ postHeaderBuilder.add("Accept-Language", "zh-CN,zh;q=0.9");
|
|
|
+ postHeaderBuilder.add("Connection", "keep-alive");
|
|
|
+ postHeaderBuilder.add("Content-Type", "application/json");
|
|
|
+ postHeaderBuilder.add("Host", "www.yuanqingtech.com");
|
|
|
+ postHeaderBuilder.add("Referer", "https://servicewechat.com/wx46d2e1aaa28335ea/47/page-frame.html");
|
|
|
+ postHeaderBuilder.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf2541a1f) XWEB/19921");
|
|
|
+ postHeaderBuilder.add("accessKey", "");
|
|
|
+ postHeaderBuilder.add("appCode", "");
|
|
|
+ postHeaderBuilder.add("channel", "");
|
|
|
+ postHeaderBuilder.add("openIdToken", "");
|
|
|
+ postHeaderBuilder.add("platform", "MINI_WECHAT");
|
|
|
+ postHeaderBuilder.add("t", "ios");
|
|
|
+ postHeaderBuilder.add("unionId", "");
|
|
|
+ postHeaderBuilder.add("wxSDKVersion", "3.16.1");
|
|
|
+ postHeaderBuilder.add("wxVersion", "4.1.10.31");
|
|
|
+ postHeaderBuilder.add("xweb_xhr", "1");
|
|
|
+ postHeaderBuilder.add("zaLoginCookieKey", "");
|
|
|
+
|
|
|
+ Headers postHeaders = postHeaderBuilder.build();
|
|
|
+
|
|
|
+ String urlPost = "https://www.yuanqingtech.com/dmapi/dm-innovation-front/api/config-info/findIssuingLink";
|
|
|
+
|
|
|
+ FirstReqData reqData = new FirstReqData();
|
|
|
+ reqData.setInviterAccountId(zhongAnId);
|
|
|
+ reqData.setActivityCode(productId);
|
|
|
+
|
|
|
+ String jsonBody = objectMapper.writeValueAsString(reqData);
|
|
|
+ RequestBody body = RequestBody.create(jsonBody, MediaType.get("application/json; charset=utf-8"));
|
|
|
+ Request postReq = new Request.Builder()
|
|
|
+ .url(urlPost)
|
|
|
+ .headers(postHeaders)
|
|
|
+ .post(body)
|
|
|
.build();
|
|
|
- // 发送第一个请求,不跟随重定向
|
|
|
- HttpGet get1 = buildGet(uri1);
|
|
|
- CloseableHttpResponse resp1 = HTTP_CLIENT.execute(get1, context);
|
|
|
- AssertionUtils.isEmpty(resp1, "第一次请求失败,请联系管理员");
|
|
|
- String location1 = resp1.getFirstHeader("Location").getValue();
|
|
|
- resp1.close();
|
|
|
- // 发送第二个请求
|
|
|
- HttpGet get2 = buildGet(new URI(location1));
|
|
|
- CloseableHttpResponse resp2 = HTTP_CLIENT.execute(get2, context);
|
|
|
- AssertionUtils.isEmpty(resp2, "第二次请求失败,请联系管理员");
|
|
|
- String location2 = getLocationHeader(resp2);
|
|
|
- resp2.close();
|
|
|
- // 发送第三个请求
|
|
|
- HttpGet get3 = buildGet(new URI(location2));
|
|
|
- CloseableHttpResponse resp3 = HTTP_CLIENT.execute(get3, context);
|
|
|
- AssertionUtils.isEmpty(resp3, "第三次请求失败,请联系管理员");
|
|
|
- String location3 = resp3.getFirstHeader("Location").getValue();
|
|
|
- resp3.close();
|
|
|
- // 发送第四个请求
|
|
|
- HttpGet get4 = buildGet(new URI(location3));
|
|
|
- CloseableHttpResponse resp4 = HTTP_CLIENT.execute(get4, context);
|
|
|
- AssertionUtils.isEmpty(resp4, "第四次请求失败,请联系管理员");
|
|
|
- String location4 = resp4.getFirstHeader("Location").getValue();
|
|
|
- resp4.close();
|
|
|
- // 第五次请求,拿cookie
|
|
|
- HttpGet get5 = buildGet(new URI(location4));
|
|
|
- CloseableHttpResponse resp5 = HTTP_CLIENT.execute(get5, context);
|
|
|
- AssertionUtils.isEmpty(resp5, "第五次请求失败,请联系管理员");
|
|
|
- String location5 = resp5.getFirstHeader("Location").getValue();
|
|
|
- // 提取 zaLoginCookieKey
|
|
|
- String cookieKey = null;
|
|
|
- if (resp5.getHeaders("Set-Cookie") != null) {
|
|
|
- for (org.apache.http.Header h : resp5.getHeaders("Set-Cookie")) {
|
|
|
- Matcher m = ZA_COOKIE_PATTERN.matcher(h.getValue());
|
|
|
- if (m.find()) {
|
|
|
- cookieKey = m.group(1).trim();
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- resp5.close();
|
|
|
|
|
|
- if (cookieKey == null || cookieKey.isEmpty()) {
|
|
|
+ Response postResp = session.newCall(postReq).execute();
|
|
|
+ String respBody = postResp.body().string();
|
|
|
+ postResp.close();
|
|
|
+
|
|
|
+ JsonNode root = objectMapper.readTree(respBody);
|
|
|
+ JsonNode valueNode = root.path("value");
|
|
|
+ if (!valueNode.isArray() || valueNode.size() == 0) {
|
|
|
return new LoginResult(400, "账号错误", null, null);
|
|
|
}
|
|
|
|
|
|
- // 提取 flowId
|
|
|
- Matcher flowMatcher = FLOW_ID_PATTERN.matcher(location5);
|
|
|
- String flowId = flowMatcher.find() ? flowMatcher.group(1).trim() : "";
|
|
|
-
|
|
|
- String finalUrl = "https://c.zhongan.com/insure/index.html";
|
|
|
- URI finalUri = new URIBuilder(finalUrl)
|
|
|
- .addParameter("flowId", flowId)
|
|
|
- .addParameter("i", "e")
|
|
|
- .addParameter("insurePlaceCode", "140100")
|
|
|
- .addParameter("newPage", "1")
|
|
|
+ String linkUrl = valueNode.get(0).path("link").asText("");
|
|
|
+ Headers.Builder getHeaderBuilder = new Headers.Builder();
|
|
|
+ getHeaderBuilder.add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/wxpic,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
|
|
|
+ getHeaderBuilder.add("Accept-Encoding", "gzip, deflate, br");
|
|
|
+ getHeaderBuilder.add("Accept-Language", "zh-CN,zh;q=0.9");
|
|
|
+ getHeaderBuilder.add("Connection", "keep-alive");
|
|
|
+ getHeaderBuilder.add("Host", "c.zhongan.com");
|
|
|
+ getHeaderBuilder.add("Sec-Fetch-Dest", "document");
|
|
|
+ getHeaderBuilder.add("Sec-Fetch-Mode", "navigate");
|
|
|
+ getHeaderBuilder.add("Sec-Fetch-Site", "none");
|
|
|
+ getHeaderBuilder.add("Sec-Fetch-User", "?1");
|
|
|
+ getHeaderBuilder.add("Upgrade-Insecure-Requests", "1");
|
|
|
+ getHeaderBuilder.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf2541a1f) XWEB/19921 miniProgram/wx46d2e1aaa28335ea");
|
|
|
+
|
|
|
+ Headers getHeaders = getHeaderBuilder.build();
|
|
|
+ Request getReq = new Request.Builder()
|
|
|
+ .url(linkUrl)
|
|
|
+ .headers(getHeaders)
|
|
|
+ .get()
|
|
|
.build();
|
|
|
|
|
|
- HttpGet finalGet = buildGet(finalUri);
|
|
|
- finalGet.setHeader("Cookie", "zaLoginCookieKey=" + cookieKey);
|
|
|
- CloseableHttpResponse finalResp = HTTP_CLIENT.execute(finalGet, context);
|
|
|
- finalResp.close();
|
|
|
- cacheCookie(cookieKey, flowId, zhongAnId);
|
|
|
- return new LoginResult(200, "登录成功", cookieKey, flowId);
|
|
|
+ Response getResp = session.newCall(getReq).execute();
|
|
|
+ String flowIdUrl = getResp.header("Location", "");
|
|
|
+ getResp.close();
|
|
|
+
|
|
|
+ Pattern flowPattern = Pattern.compile("flowId=(.*?)&");
|
|
|
+ Matcher flowMatcher = null;
|
|
|
+ if (flowIdUrl != null) {
|
|
|
+ flowMatcher = flowPattern.matcher(flowIdUrl);
|
|
|
+ }
|
|
|
+ String flowId = "";
|
|
|
+ if (flowMatcher.find()) {
|
|
|
+ flowId = flowMatcher.group(1);
|
|
|
+ }
|
|
|
+ String zaLoginCookieKey = "";
|
|
|
+ List<String> setCookieList = getResp.headers("Set-Cookie");
|
|
|
+ for (String cookie : setCookieList) {
|
|
|
+ Pattern cookiePattern = Pattern.compile("zaLoginCookieKey=(.*?);", Pattern.DOTALL);
|
|
|
+ Matcher cookieMatcher = cookiePattern.matcher(cookie);
|
|
|
+ if (cookieMatcher.find()) {
|
|
|
+ zaLoginCookieKey = cookieMatcher.group(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ cacheCookie(zaLoginCookieKey, flowId, zhongAnId);
|
|
|
+ return new LoginResult(200, "登录成功", zaLoginCookieKey, flowId);
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
return new LoginResult(400, "登录异常:" + e.getMessage(), null, null);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+ @Data
|
|
|
+ public static class FirstReqData {
|
|
|
+ private String bizOrigin = "CAR_ZYHS_XXSYTG";
|
|
|
+ private String inviterAccountId;
|
|
|
+ private String activityCode;
|
|
|
+ private BizParams bizParams = new BizParams();
|
|
|
+ }
|
|
|
+ @Data
|
|
|
+ public static class BizParams {
|
|
|
+ private final String insurePlaceCode = "140100";
|
|
|
+ }
|
|
|
}
|