在整合視頻平台資源時,常需根據視頻頁面 URL 自動抓取封面圖(縮略圖)用於列表展示。本文提供兩種純 Java 實作方案,均基於優酷公開的播放清單介面,無需官方 SDK 或 API Key。
videoId(如 id_XMjU0MjI2NzY0)。https://v.youku.com/player/getPlayList/VideoIDS/{videoId}/timezone/+08/version/5/source/out?password=&ran=2513&n=3。logo 欄位(封面圖 URL)。依賴 net.sf.json-lib (json-lib) 庫,需額外引入 ezmorph、commons-lang、commons-beanutils、commons-collections、commons-logging。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
public class YoukuThumbnailJson {
public static void main(String[] args) throws IOException {
String pageUrl = "https://v.youku.com/v_show/id_XMjU0MjI2NzY0.html";
// 1. 提取 videoId
int idIndex = pageUrl.indexOf("id_");
String videoId = pageUrl.substring(idIndex + 3, pageUrl.indexOf(".html"));
// 2. 請求播放清單介面
String apiUrl = "https://v.youku.com/player/getPlayList/VideoIDS/" + videoId
+ "/timezone/+08/version/5/source/out?password=&ran=2513&n=3";
URL url = new URL(apiUrl);
try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) {
String jsonText = br.readLine(); // 介面回傳單行 JSON
// 3. 解析 JSON
JSONObject root = JSONObject.fromObject(jsonText);
JSONArray dataArr = root.getJSONArray("data");
JSONObject videoInfo = JSONObject.fromObject(dataArr.get(0));
String logoUrl = videoInfo.getString("logo");
System.out.println("縮略圖 URL:" + logoUrl);
// 輸出範例:https://g2.ykimg.com/1100641F464D8FBF5FA3D90209C8DF96B67E2C-567E-AB53-C132-D7787FC966AB
}
}
}
利用回傳文本結構固定,直接以分隔符切分提取,不需任何第三方 JAR。但介面格式一旦變更極易失效,生產環境慎用。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
public class YoukuThumbnailSplit {
public static void main(String[] args) throws IOException {
String pageUrl = "https://v.youku.com/v_show/id_XMjU0MjI2NzY0.html";
int idIndex = pageUrl.indexOf("id_");
String videoId = pageUrl.substring(idIndex + 3, pageUrl.indexOf(".html"));
String apiUrl = "https://v.youku.com/player/getPlayList/VideoIDS/" + videoId
+ "/timezone/+08/version/5/source/out?password=&ran=2513&n=3";
URL url = new URL(apiUrl);
try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) {
// 回傳文本以 "\/" 為分隔符,第 4 段 (index 3) 包含 logo 路徑
String[] parts = br.readLine().split("\\\\/");
String target = parts[3]; // 形如 "1100641F464D8FBF5FA3D90209C8DF96B67E2C-567E-AB53-C132-D7787FC966AB\"
String imgId = target.substring(0, target.indexOf("\""));
String thumbnailUrl = "https://g2.ykimg.com/" + imgId;
System.out.println("縮略圖 URL:" + thumbnailUrl);
}
}
}
id_([^&/.]+) 擷取 videoId 更穩健。new InputStreamReader(url.openStream(), "UTF-8")。try-catch 並記錄日誌,避免單點失效拖垮主流程。robots.txt 與服務條款。相同思路可套用至 Bilibili、騰訊視頻、愛奇藝等:
pic/cover/logo 字段。方案一(JSON 解析)結構清晰、抗變化能力強,適合生產環境;方案二(字串分割)零依賴、代碼極簡,適合快速驗證或腳本任務。實務中建議封裝為通用 VideoThumbnailResolver 介面,針對不同平台實現具體 Strategy,配合緩存、熔斷、監控構建穩健的視頻資源聚合服務。