|
@@ -1,65 +1,217 @@
|
|
|
package com.tzld.piaoquan.longarticle.utils.other;
|
|
package com.tzld.piaoquan.longarticle.utils.other;
|
|
|
|
|
|
|
|
-import cn.hutool.crypto.digest.DigestUtil;
|
|
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import okhttp3.*;
|
|
import okhttp3.*;
|
|
|
import com.tzld.piaoquan.longarticle.common.constants.CrawlerConstant;
|
|
import com.tzld.piaoquan.longarticle.common.constants.CrawlerConstant;
|
|
|
import com.tzld.piaoquan.longarticle.model.po.longarticle.CrawlerVideo;
|
|
import com.tzld.piaoquan.longarticle.model.po.longarticle.CrawlerVideo;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-import java.net.*;
|
|
|
|
|
-import okhttp3.Authenticator;
|
|
|
|
|
-
|
|
|
|
|
-import java.security.MessageDigest;
|
|
|
|
|
-import java.security.NoSuchAlgorithmException;
|
|
|
|
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
|
|
-import static com.tzld.piaoquan.longarticle.common.constants.ProxyConstant.*;
|
|
|
|
|
-
|
|
|
|
|
@Slf4j
|
|
@Slf4j
|
|
|
|
|
+@Service
|
|
|
public class HkspSearch {
|
|
public class HkspSearch {
|
|
|
|
|
|
|
|
- private static OkHttpClient okHttpClient;
|
|
|
|
|
|
|
+ @Value("${spider.api.base-url:http://crawapi.piaoquantv.com}")
|
|
|
|
|
+ private String spiderBaseUrl;
|
|
|
|
|
|
|
|
- static {
|
|
|
|
|
- createClient();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ @Value("${spider.api.timeout-minutes:5}")
|
|
|
|
|
+ private int spiderTimeoutMinutes;
|
|
|
|
|
+
|
|
|
|
|
+ private OkHttpClient spiderOkHttpClient;
|
|
|
|
|
|
|
|
- private static synchronized void createClient() {
|
|
|
|
|
|
|
+ private static final int MAX_RETRIES = 5;
|
|
|
|
|
+ private static final long RETRY_DELAY_MS = 1000;
|
|
|
|
|
+
|
|
|
|
|
+ @PostConstruct
|
|
|
|
|
+ public void init() {
|
|
|
try {
|
|
try {
|
|
|
- Proxy proxy = new Proxy(
|
|
|
|
|
- Proxy.Type.HTTP,
|
|
|
|
|
- new InetSocketAddress(PROXY_HOST, PROXY_PORT)
|
|
|
|
|
- );
|
|
|
|
|
- Authenticator authenticator = (route, response) -> {
|
|
|
|
|
- String credential = Credentials.basic(USERNAME, PASSWORD);
|
|
|
|
|
- return response.request().newBuilder()
|
|
|
|
|
- .header("Proxy-Authorization", credential)
|
|
|
|
|
- .build();
|
|
|
|
|
- };
|
|
|
|
|
- okHttpClient = new OkHttpClient.Builder()
|
|
|
|
|
- .proxy(proxy)
|
|
|
|
|
- .proxyAuthenticator(authenticator)
|
|
|
|
|
- .connectTimeout(15, TimeUnit.MINUTES)
|
|
|
|
|
- .readTimeout(15, TimeUnit.MINUTES)
|
|
|
|
|
- .writeTimeout(15, TimeUnit.MINUTES)
|
|
|
|
|
- .connectionPool(new ConnectionPool(0, 1, TimeUnit.MILLISECONDS))
|
|
|
|
|
|
|
+ spiderOkHttpClient = new OkHttpClient.Builder()
|
|
|
|
|
+ .connectTimeout(spiderTimeoutMinutes, TimeUnit.MINUTES)
|
|
|
|
|
+ .readTimeout(spiderTimeoutMinutes, TimeUnit.MINUTES)
|
|
|
|
|
+ .writeTimeout(spiderTimeoutMinutes, TimeUnit.MINUTES)
|
|
|
.build();
|
|
.build();
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.error("Failed to create HkspSearch client {}", e.getMessage());
|
|
log.error("Failed to create HkspSearch client {}", e.getMessage());
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public static CrawlerVideo baiduVideoProduce(JSONObject jsonObject) {
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 带重试的 HTTP 调用执行一次请求,返回响应体字符串。
|
|
|
|
|
+ * code != 0 或异常时重试,最多 MAX_RETRIES 次。
|
|
|
|
|
+ */
|
|
|
|
|
+ private String executeRequest(Request request, String methodName) {
|
|
|
|
|
+ int retryCount = 0;
|
|
|
|
|
+ while (retryCount < MAX_RETRIES) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Response response = spiderOkHttpClient.newCall(request).execute();
|
|
|
|
|
+ String body = response.body().string();
|
|
|
|
|
+ JSONObject jsonResponse = JSONObject.parseObject(body);
|
|
|
|
|
+ int code = jsonResponse.getIntValue("code");
|
|
|
|
|
+ if (code == 0) {
|
|
|
|
|
+ return body;
|
|
|
|
|
+ }
|
|
|
|
|
+ log.error("{} business error, code={}, retry={}/{}", methodName, code, retryCount + 1, MAX_RETRIES);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("{} exception, retry={}/{}: {}", methodName, retryCount + 1, MAX_RETRIES, e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ retryCount++;
|
|
|
|
|
+ if (retryCount < MAX_RETRIES) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ TimeUnit.MILLISECONDS.sleep(RETRY_DELAY_MS);
|
|
|
|
|
+ } catch (InterruptedException ie) {
|
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ log.error("{} failed after {} retries", methodName, MAX_RETRIES);
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 搜索好看视频(通过爬虫服务)
|
|
|
|
|
+ */
|
|
|
|
|
+ public List<JSONObject> searchVideo(String key, List<String> sensitiveWords) {
|
|
|
|
|
+ String url = spiderBaseUrl + "/crawler/hao_kan_shi_pin/keyword";
|
|
|
|
|
+ JSONObject param = new JSONObject();
|
|
|
|
|
+ param.put("keyword", key);
|
|
|
|
|
+ RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), param.toJSONString());
|
|
|
|
|
+ Request request = new Request.Builder()
|
|
|
|
|
+ .url(url)
|
|
|
|
|
+ .post(body)
|
|
|
|
|
+ .build();
|
|
|
|
|
+
|
|
|
|
|
+ String result = executeRequest(request, "searchVideo");
|
|
|
|
|
+ if (result == null) {
|
|
|
|
|
+ return new ArrayList<>();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ JSONObject jsonResponse = JSONObject.parseObject(result);
|
|
|
|
|
+ JSONObject dataObj = jsonResponse.getJSONObject("data");
|
|
|
|
|
+ if (dataObj == null) {
|
|
|
|
|
+ return new ArrayList<>();
|
|
|
|
|
+ }
|
|
|
|
|
+ JSONArray dataList = dataObj.getJSONArray("data");
|
|
|
|
|
+ if (dataList == null || dataList.isEmpty()) {
|
|
|
|
|
+ return new ArrayList<>();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<JSONObject> resultList = new ArrayList<>();
|
|
|
|
|
+ for (int i = 0; i < dataList.size(); i++) {
|
|
|
|
|
+ JSONObject item = dataList.getJSONObject(i);
|
|
|
|
|
+ String videoId = item.getString("vid");
|
|
|
|
|
+ String title = item.getString("title");
|
|
|
|
|
+ String durationStr = item.getString("duration");
|
|
|
|
|
+ int duration = 0;
|
|
|
|
|
+ if (durationStr != null && durationStr.contains(":")) {
|
|
|
|
|
+ duration = parseDuration(durationStr);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (sensitiveFlag(sensitiveWords, title) && duration <= CrawlerConstant.MAX_VIDEO_DURATION) {
|
|
|
|
|
+ JSONObject res = getVideoDetail(videoId);
|
|
|
|
|
+ if (res != null) {
|
|
|
|
|
+ resultList.add(res);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return resultList;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取视频详情(通过爬虫服务),包装为统一字段,调用方无需关心原始结构
|
|
|
|
|
+ * 返回字段: id, title, playurl, poster, like, playcnt, publish_time(毫秒), duration(秒)
|
|
|
|
|
+ * 关键字段缺失时返回 null
|
|
|
|
|
+ */
|
|
|
|
|
+ public JSONObject getVideoDetail(String videoId) {
|
|
|
|
|
+ String url = spiderBaseUrl + "/crawler/hao_kan_shi_pin/detail";
|
|
|
|
|
+ JSONObject param = new JSONObject();
|
|
|
|
|
+ param.put("content_id", videoId);
|
|
|
|
|
+ RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), param.toJSONString());
|
|
|
|
|
+ Request request = new Request.Builder()
|
|
|
|
|
+ .url(url)
|
|
|
|
|
+ .post(body)
|
|
|
|
|
+ .build();
|
|
|
|
|
+
|
|
|
|
|
+ String responseBody = executeRequest(request, "getVideoDetail");
|
|
|
|
|
+ if (responseBody == null) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ return parseDetailResponse(responseBody, videoId);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 解析详情响应,包装为统一字段
|
|
|
|
|
+ */
|
|
|
|
|
+ private JSONObject parseDetailResponse(String responseBody, String videoId) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ JSONObject jsonResponse = JSONObject.parseObject(responseBody);
|
|
|
|
|
+ JSONObject dataObj = jsonResponse.getJSONObject("data");
|
|
|
|
|
+ if (dataObj == null) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ JSONObject raw = dataObj.getJSONObject("data");
|
|
|
|
|
+ if (raw == null) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 播放地址(必需)
|
|
|
|
|
+ JSONArray videoUrlList = raw.getJSONArray("video_url_list");
|
|
|
|
|
+ if (videoUrlList == null || videoUrlList.isEmpty()) {
|
|
|
|
|
+ log.error("getVideoDetail video_url_list empty, videoId={}", videoId);
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ JSONObject result = new JSONObject();
|
|
|
|
|
+ result.put("id", raw.getString("channel_content_id"));
|
|
|
|
|
+ result.put("title", raw.getString("title"));
|
|
|
|
|
+ result.put("playurl", videoUrlList.getJSONObject(0).getString("video_url"));
|
|
|
|
|
+ if (videoUrlList.getJSONObject(0).getLong("video_duration") != null) {
|
|
|
|
|
+ result.put("duration", videoUrlList.getJSONObject(0).getLong("video_duration").intValue());
|
|
|
|
|
+ }
|
|
|
|
|
+ result.put("publish_time", raw.getLong("publish_timestamp"));
|
|
|
|
|
+
|
|
|
|
|
+ // 封面图(可选)
|
|
|
|
|
+ JSONArray imageUrlList = raw.getJSONArray("image_url_list");
|
|
|
|
|
+ if (imageUrlList != null && !imageUrlList.isEmpty()) {
|
|
|
|
|
+ result.put("poster", imageUrlList.getJSONObject(0).getString("image_url"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 统计数据
|
|
|
|
|
+ Long likeCount = raw.getLong("like_count");
|
|
|
|
|
+ result.put("like", likeCount != null ? likeCount.intValue() : 0);
|
|
|
|
|
+
|
|
|
|
|
+ Object playCntObj = raw.get("play_count");
|
|
|
|
|
+ if (playCntObj instanceof Integer) {
|
|
|
|
|
+ result.put("playcnt", playCntObj);
|
|
|
|
|
+ } else if (playCntObj instanceof Long) {
|
|
|
|
|
+ result.put("playcnt", ((Long) playCntObj).intValue());
|
|
|
|
|
+ }
|
|
|
|
|
+ Object viewCntObj = raw.get("view_count");
|
|
|
|
|
+ if (!result.containsKey("playcnt") && viewCntObj instanceof Integer) {
|
|
|
|
|
+ result.put("playcnt", viewCntObj);
|
|
|
|
|
+ } else if (!result.containsKey("playcnt") && viewCntObj instanceof Long) {
|
|
|
|
|
+ result.put("playcnt", ((Long) viewCntObj).intValue());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("parseDetailResponse error:{}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public CrawlerVideo baiduVideoProduce(JSONObject jsonObject) {
|
|
|
CrawlerVideo crawlerVideo = new CrawlerVideo();
|
|
CrawlerVideo crawlerVideo = new CrawlerVideo();
|
|
|
crawlerVideo.setPlatform(jsonObject.getString("platform"));
|
|
crawlerVideo.setPlatform(jsonObject.getString("platform"));
|
|
|
crawlerVideo.setVideoTitle(jsonObject.getString("title"));
|
|
crawlerVideo.setVideoTitle(jsonObject.getString("title"));
|
|
|
crawlerVideo.setOutVideoId(jsonObject.getString("id"));
|
|
crawlerVideo.setOutVideoId(jsonObject.getString("id"));
|
|
|
if (jsonObject.getLong("publish_time") != null) {
|
|
if (jsonObject.getLong("publish_time") != null) {
|
|
|
- crawlerVideo.setPublishTime(new Date(jsonObject.getLong("publish_time") * 1000));
|
|
|
|
|
|
|
+ crawlerVideo.setPublishTime(new Date(jsonObject.getLong("publish_time")));
|
|
|
}
|
|
}
|
|
|
crawlerVideo.setVideoUrl(jsonObject.getString("playurl"));
|
|
crawlerVideo.setVideoUrl(jsonObject.getString("playurl"));
|
|
|
crawlerVideo.setCoverUrl(jsonObject.getString("poster"));
|
|
crawlerVideo.setCoverUrl(jsonObject.getString("poster"));
|
|
@@ -70,101 +222,28 @@ public class HkspSearch {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
public static void main(String[] args) {
|
|
|
- // 这行代码是身份验证的关键配置,不然身份验证不起作用
|
|
|
|
|
- System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
|
|
|
|
|
- // 身份验证
|
|
|
|
|
|
|
+ HkspSearch search = new HkspSearch();
|
|
|
|
|
+ search.spiderBaseUrl = "http://crawapi.piaoquantv.com";
|
|
|
|
|
+ search.spiderTimeoutMinutes = 5;
|
|
|
|
|
+ search.init();
|
|
|
|
|
|
|
|
List<String> sensitiveWords = new ArrayList<>();
|
|
List<String> sensitiveWords = new ArrayList<>();
|
|
|
- List<JSONObject> list = hkspSearch("\uD83D\uDD25中国海军震撼世界!一天服役7艘巨舰,总吨位近半个法国海军!", sensitiveWords, "");
|
|
|
|
|
|
|
+ List<JSONObject> list = search.searchVideo("中国海军震撼世界", sensitiveWords);
|
|
|
for (JSONObject jsonObject : list) {
|
|
for (JSONObject jsonObject : list) {
|
|
|
- CrawlerVideo crawlerVideo = baiduVideoProduce(jsonObject);
|
|
|
|
|
|
|
+ CrawlerVideo crawlerVideo = search.baiduVideoProduce(jsonObject);
|
|
|
System.out.println(jsonObject);
|
|
System.out.println(jsonObject);
|
|
|
System.out.println(crawlerVideo);
|
|
System.out.println(crawlerVideo);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public static List<JSONObject> hkspSearch(String key, List<String> sensitiveWords, String traceId) {
|
|
|
|
|
- try {
|
|
|
|
|
|
|
+ // ==================== 工具方法 ====================
|
|
|
|
|
|
|
|
- String encodedKey = URLEncoder.encode(key, "UTF-8");
|
|
|
|
|
- long timestampMilliseconds = System.currentTimeMillis();
|
|
|
|
|
- String strings = String.format("%d_%s_%d_%d_%d", 1, encodedKey, 10, timestampMilliseconds, 1);
|
|
|
|
|
- String sign = DigestUtil.md5Hex(strings);
|
|
|
|
|
-
|
|
|
|
|
- HttpUrl url = HttpUrl.parse("https://haokan.baidu.com/haokan/ui-search/pc/search/video")
|
|
|
|
|
- .newBuilder()
|
|
|
|
|
- .addQueryParameter("pn", "1")
|
|
|
|
|
- .addQueryParameter("rn", "10")
|
|
|
|
|
- .addQueryParameter("type", "video")
|
|
|
|
|
- .addQueryParameter("query", key)
|
|
|
|
|
- .addQueryParameter("sign", sign)
|
|
|
|
|
- .addQueryParameter("version", "1")
|
|
|
|
|
- .addQueryParameter("timestamp", String.valueOf(timestampMilliseconds))
|
|
|
|
|
- .build();
|
|
|
|
|
- Headers headers = Headers.of(
|
|
|
|
|
- "accept", "*/*",
|
|
|
|
|
- "accept-language", "zh,en;q=0.9,zh-CN;q=0.8",
|
|
|
|
|
- "cookie", String.format("BIDUPSID=%s", Base64.getEncoder().encodeToString(UUID.randomUUID().toString().getBytes())),
|
|
|
|
|
- "user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
|
|
|
|
|
- "Connection", "close"
|
|
|
|
|
- );
|
|
|
|
|
- Request request = new Request.Builder()
|
|
|
|
|
- .url(url)
|
|
|
|
|
- .headers(headers)
|
|
|
|
|
- .get()
|
|
|
|
|
- .build();
|
|
|
|
|
-
|
|
|
|
|
- Response response = okHttpClient.newCall(request).execute();
|
|
|
|
|
- String result = response.body().string();
|
|
|
|
|
-
|
|
|
|
|
- List<JSONObject> resultList = new ArrayList<>();
|
|
|
|
|
- log.info("hkspSearch response:{}", result);
|
|
|
|
|
- JSONObject jsonResponse = JSONObject.parseObject(result);
|
|
|
|
|
- JSONArray dataList = jsonResponse.getJSONObject("data").getJSONArray("list");
|
|
|
|
|
-
|
|
|
|
|
- if (Objects.nonNull(dataList)) {
|
|
|
|
|
- for (int i = 0; i < dataList.size(); i++) {
|
|
|
|
|
- JSONObject data = dataList.getJSONObject(i);
|
|
|
|
|
- String videoId = data.getString("vid");
|
|
|
|
|
- String title = data.getString("title");
|
|
|
|
|
- int duration = parseDuration(data.getString("duration"));
|
|
|
|
|
- if (sensitiveFlag(sensitiveWords, title) && duration <= CrawlerConstant.MAX_VIDEO_DURATION) {
|
|
|
|
|
- JSONObject res = getVideoDetail(videoId);
|
|
|
|
|
- if (res != null) {
|
|
|
|
|
- resultList.add(res);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return resultList;
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("hkspSearch error:{}", e.getMessage());
|
|
|
|
|
- }
|
|
|
|
|
- return new ArrayList<>();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private static int parseDuration(String duration) {
|
|
|
|
|
|
|
+ private int parseDuration(String duration) {
|
|
|
String[] parts = duration.split(":");
|
|
String[] parts = duration.split(":");
|
|
|
return Integer.parseInt(parts[0]) * 60 + Integer.parseInt(parts[1]);
|
|
return Integer.parseInt(parts[0]) * 60 + Integer.parseInt(parts[1]);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static String md5(String input) {
|
|
|
|
|
- try {
|
|
|
|
|
- MessageDigest md = MessageDigest.getInstance("MD5");
|
|
|
|
|
- byte[] messageDigest = md.digest(input.getBytes());
|
|
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
|
|
- for (byte b : messageDigest) {
|
|
|
|
|
- sb.append(String.format("%02x", b));
|
|
|
|
|
- }
|
|
|
|
|
- return sb.toString();
|
|
|
|
|
- } catch (NoSuchAlgorithmException e) {
|
|
|
|
|
- log.error("HkspSearch md5 error:{}", e.getMessage());
|
|
|
|
|
- }
|
|
|
|
|
- return "";
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private static boolean sensitiveFlag(List<String> sensitiveWords, String title) {
|
|
|
|
|
- // 实现敏感词检查逻辑
|
|
|
|
|
|
|
+ private boolean sensitiveFlag(List<String> sensitiveWords, String title) {
|
|
|
for (String word : sensitiveWords) {
|
|
for (String word : sensitiveWords) {
|
|
|
if (title.contains(word)) {
|
|
if (title.contains(word)) {
|
|
|
return false;
|
|
return false;
|
|
@@ -173,51 +252,4 @@ public class HkspSearch {
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public static JSONObject getVideoDetail(String videoId) {
|
|
|
|
|
- try {
|
|
|
|
|
- // 构建URL并添加查询参数
|
|
|
|
|
- HttpUrl url = HttpUrl.parse("https://haokan.baidu.com/v")
|
|
|
|
|
- .newBuilder()
|
|
|
|
|
- .addQueryParameter("vid", videoId)
|
|
|
|
|
- .addQueryParameter("_format", "json")
|
|
|
|
|
- .build();
|
|
|
|
|
-
|
|
|
|
|
- // 生成BIDUPSID
|
|
|
|
|
- String base64String = Base64.getEncoder().encodeToString(UUID.randomUUID().toString().getBytes());
|
|
|
|
|
-
|
|
|
|
|
- // 构建请求头
|
|
|
|
|
- Headers headers = Headers.of(
|
|
|
|
|
- "Accept", "*/*",
|
|
|
|
|
- "cookie", "BIDUPSID=" + base64String,
|
|
|
|
|
- "Accept-Language", "en,zh;q=0.9,zh-CN;q=0.8",
|
|
|
|
|
- "Cache-Control", "no-cache",
|
|
|
|
|
- "Connection", "close",
|
|
|
|
|
- "Content-Type", "application/x-www-form-urlencoded",
|
|
|
|
|
- "Referer", "https://haokan.baidu.com",
|
|
|
|
|
- "User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- // 构建请求
|
|
|
|
|
- Request request = new Request.Builder()
|
|
|
|
|
- .url(url)
|
|
|
|
|
- .headers(headers)
|
|
|
|
|
- .get()
|
|
|
|
|
- .build();
|
|
|
|
|
-
|
|
|
|
|
- // 发送请求并获取响应
|
|
|
|
|
- Response response = okHttpClient.newCall(request).execute();
|
|
|
|
|
- String responseBody = response.body().string();
|
|
|
|
|
-
|
|
|
|
|
- // 解析响应
|
|
|
|
|
- return JSONObject.parseObject(responseBody)
|
|
|
|
|
- .getJSONObject("data")
|
|
|
|
|
- .getJSONObject("apiData")
|
|
|
|
|
- .getJSONObject("curVideoMeta");
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("getVideoDetail error:{}", e.getMessage());
|
|
|
|
|
- }
|
|
|
|
|
- return null;
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-}
|
|
|
|
|
|
|
+}
|