Просмотр исходного кода

好看视频爬取改为使用爬虫接口

wangyunpeng 4 дней назад
Родитель
Сommit
c947dc8628

+ 1 - 1
long-article-server/src/main/java/com/tzld/piaoquan/longarticle/component/ThreadPools.java

@@ -12,7 +12,7 @@ public class ThreadPools {
     public static final ThreadPoolExecutor newMatchKimiVideoPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);
 
     // 定义一个线程池,设置消费线程的数量
-    public static final ThreadPoolExecutor newMatchCrawlerVideoPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
+    public static final ThreadPoolExecutor newMatchCrawlerVideoPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);
 
     // 定义一个线程池,设置消费线程的数量
     public static final ThreadPoolExecutor newUploadCrawlerVideoPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(40);

+ 11 - 5
long-article-server/src/main/java/com/tzld/piaoquan/longarticle/service/local/impl/CrawlerVideoServiceImpl.java

@@ -48,6 +48,12 @@ public class CrawlerVideoServiceImpl {
     @Autowired
     private VideoService videoService;
 
+    @Autowired
+    private HkspSearch hkspSearch;
+
+    @Autowired
+    private VideoDownloader videoDownloader;
+
     private static final String default_user_id = "69637498";
 
     private static final Double NLP_SIMILARITY_THRESHOLD = 0.55;
@@ -157,7 +163,7 @@ public class CrawlerVideoServiceImpl {
         if (StringUtils.isNotEmpty(shareImgPath)) {
             String coverUrl = shareImgPath.substring(0, shareImgPath.indexOf("?"));
             crawlerVideo.setCoverUrl(coverUrl);
-            String coverPath = VideoDownloader.downloadCover(crawlerVideo.getOutVideoId(), crawlerVideo.getPlatform(), crawlerVideo.getCoverUrl());
+            String coverPath = videoDownloader.downloadCover(crawlerVideo.getOutVideoId(), crawlerVideo.getPlatform(), crawlerVideo.getCoverUrl());
             try {
                 String coverOssPath = OSSUploader.uploadToOSS(coverPath, "image");
                 crawlerVideo.setCoverOssPath(coverOssPath);
@@ -323,7 +329,7 @@ public class CrawlerVideoServiceImpl {
             }
             return res;
         }
-        res = HkspSearch.hkspSearch(text, sensitiveWords, "");
+        res = hkspSearch.searchVideo(text, sensitiveWords);
         if (!CollectionUtils.isEmpty(res)) {
             for (JSONObject jsonObject : res) {
                 jsonObject.put("platform", "baidu_search");
@@ -358,7 +364,7 @@ public class CrawlerVideoServiceImpl {
         crawlerVideo.setVideoTitle(jsonObject.getString("title"));
         crawlerVideo.setOutVideoId(jsonObject.getString("id"));
         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.setCoverUrl(jsonObject.getString("poster"));
@@ -384,8 +390,8 @@ public class CrawlerVideoServiceImpl {
         for (CrawlerVideo crawlerVideo : crawlerVideoList) {
             String platform = crawlerVideo.getPlatform();
             String outVideoId = crawlerVideo.getOutVideoId();
-            String videoPath = VideoDownloader.downloadVideo(outVideoId, platform, crawlerVideo.getVideoUrl());
-            String coverPath = VideoDownloader.downloadCover(outVideoId, platform, crawlerVideo.getCoverUrl());
+            String videoPath = videoDownloader.downloadVideo(outVideoId, platform, crawlerVideo.getVideoUrl());
+            String coverPath = videoDownloader.downloadCover(outVideoId, platform, crawlerVideo.getCoverUrl());
             if (StringUtils.isNotEmpty(videoPath)) {
                 String videoOssPath = OSSUploader.uploadToOSS(videoPath, "video");
                 log.info("OSSUploader.uploadToOSS videoPath={}", videoPath);

+ 195 - 163
long-article-server/src/main/java/com/tzld/piaoquan/longarticle/utils/other/HkspSearch.java

@@ -1,65 +1,217 @@
 package com.tzld.piaoquan.longarticle.utils.other;
 
-import cn.hutool.crypto.digest.DigestUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import okhttp3.*;
 import com.tzld.piaoquan.longarticle.common.constants.CrawlerConstant;
 import com.tzld.piaoquan.longarticle.model.po.longarticle.CrawlerVideo;
 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.concurrent.TimeUnit;
 
-import static com.tzld.piaoquan.longarticle.common.constants.ProxyConstant.*;
-
 @Slf4j
+@Service
 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 {
-            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();
         } catch (Exception e) {
             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.setPlatform(jsonObject.getString("platform"));
         crawlerVideo.setVideoTitle(jsonObject.getString("title"));
         crawlerVideo.setOutVideoId(jsonObject.getString("id"));
         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.setCoverUrl(jsonObject.getString("poster"));
@@ -70,101 +222,28 @@ public class HkspSearch {
     }
 
     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<JSONObject> list = hkspSearch("\uD83D\uDD25中国海军震撼世界!一天服役7艘巨舰,总吨位近半个法国海军!", sensitiveWords, "");
+        List<JSONObject> list = search.searchVideo("中国海军震撼世界", sensitiveWords);
         for (JSONObject jsonObject : list) {
-            CrawlerVideo crawlerVideo = baiduVideoProduce(jsonObject);
+            CrawlerVideo crawlerVideo = search.baiduVideoProduce(jsonObject);
             System.out.println(jsonObject);
             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(":");
         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) {
             if (title.contains(word)) {
                 return false;
@@ -173,51 +252,4 @@ public class HkspSearch {
         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;
-
-    }
-
-}
+}

+ 23 - 17
long-article-server/src/main/java/com/tzld/piaoquan/longarticle/utils/other/VideoDownloader.java

@@ -2,12 +2,13 @@ package com.tzld.piaoquan.longarticle.utils.other;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
-import com.tzld.piaoquan.longarticle.utils.ConfigUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
-
 import java.io.File;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -19,13 +20,18 @@ import java.util.UUID;
 import static com.tzld.piaoquan.longarticle.common.constants.ProxyConstant.*;
 
 @Slf4j
+@Service
 public class VideoDownloader {
 
-    private static final long READ_TIMEOUT_SECONDS = 60; // 读取超时时间(秒)
+    @Autowired
+    private HkspSearch hkspSearch;
+
+    @Value("${download.path:/download}")
+    private String downloadPath;
 
     private static final int MAX_RETRIES = 2;
 
-    public static String downloadCover(String outVideoId, String platform, String coverUrl) {
+    public String downloadCover(String outVideoId, String platform, String coverUrl) {
         String path = generateCoverPath(platform, outVideoId);
         if (download(path, coverUrl, platform) == 0) {
             return path;
@@ -33,7 +39,7 @@ public class VideoDownloader {
         return "";
     }
 
-    public static String downloadVideo(String outVideoId, String platform, String videoUrl) {
+    public String downloadVideo(String outVideoId, String platform, String videoUrl) {
         int retries = 0;
         while (retries < MAX_RETRIES) {
             log.info("downloadVideo outVideoId={} retries={}", outVideoId, retries);
@@ -47,7 +53,7 @@ public class VideoDownloader {
             }
             //百度重新获取链接
             if ((download == 403 || StringUtils.isEmpty(videoUrl)) && Objects.equals(platform, "baidu_search")) {
-                JSONObject videoDetail = HkspSearch.getVideoDetail(outVideoId);
+                JSONObject videoDetail = hkspSearch.getVideoDetail(outVideoId);
                 if (videoDetail != null) {
                     String newVideoUrl = videoDetail.getString("playurl");
                     if (newVideoUrl != null) {
@@ -74,7 +80,7 @@ public class VideoDownloader {
         return "";
     }
 
-    public static int download(String path, String videoUrl, String platform) {
+    public int download(String path, String videoUrl, String platform) {
         try {
             log.info("download video path={}", path);
             if (StringUtils.isEmpty(videoUrl)) {
@@ -124,28 +130,26 @@ public class VideoDownloader {
         return -1;
     }
 
-    private static String generateVideoPath(String platform, String videoId) {
+    private String generateVideoPath(String platform, String videoId) {
         String index = String.format("%s-%s-%s", platform, videoId, UUID.randomUUID());
         String md5Hash = DigestUtils.md5Hex(index);
         String fileName = String.format("%s.mp4", md5Hash);
-        String path = ConfigUtil.getConfig("download.path");
-        File uploadDir = new File(path);
+        File uploadDir = new File(downloadPath);
         if (!uploadDir.exists()) {
             uploadDir.mkdirs(); // 创建目录
         }
-        return String.join(File.separator, path, fileName); // 返回文件路径和封面路径
+        return String.join(File.separator, downloadPath, fileName);
     }
 
-    private static String generateCoverPath(String platform, String videoId) {
+    private String generateCoverPath(String platform, String videoId) {
         String index = String.format("%s-%s-%s", platform, videoId, UUID.randomUUID());
         String md5Hash = DigestUtils.md5Hex(index);
         String coverName = String.format("%s.png", md5Hash);
-        String path = ConfigUtil.getConfig("download.path");
-        File uploadDir = new File(path);
+        File uploadDir = new File(downloadPath);
         if (!uploadDir.exists()) {
             uploadDir.mkdirs(); // 创建目录
         }
-        return String.join(File.separator, path, coverName); // 返回文件路径和封面路径
+        return String.join(File.separator, downloadPath, coverName);
     }
 
     public static void main(String[] args) {
@@ -158,7 +162,9 @@ public class VideoDownloader {
                     }
                 }
         );
-        downloadVideo("2562802497357206175", "baidu_search", "https://vdept3.bdstatic.com/mda-qkt120240g2y8uka/cae_h264/1732792181901415854/mda-qkt120240g2y8uka.mp4?v_from_s=hkapp-haokan-suzhou&auth_key=1738759058-0-0-115429d241bdab4208d998b5f3f95507&bcevod_channel=searchbox_feed&cr=0&cd=0&pd=1&pt=3&logid=2258462520&vid=2562802497357206175&abtest=132219_1");
+        VideoDownloader videoDownloader = new VideoDownloader();
+        videoDownloader.downloadPath = "/download";
+        videoDownloader.downloadVideo("2562802497357206175", "baidu_search", "https://vdept3.bdstatic.com/mda-qkt120240g2y8uka/cae_h264/1732792181901415854/mda-qkt120240g2y8uka.mp4?v_from_s=hkapp-haokan-suzhou&auth_key=1738759058-0-0-115429d241bdab4208d998b5f3f95507&bcevod_channel=searchbox_feed&cr=0&cd=0&pd=1&pt=3&logid=2258462520&vid=2562802497357206175&abtest=132219_1");
     }
 
-}
+}