Merge branch '139login' into multiThread

# Conflicts:
#	jar/custom_spider.jar
#	jar/custom_spider.jar.md5
#	json/test.json
This commit is contained in:
lushunming 2025-07-08 11:32:22 +08:00
commit 82e60f9db7
7 changed files with 247 additions and 16 deletions

View File

@ -1,25 +1,34 @@
package com.github.catvod.api; package com.github.catvod.api;
import com.github.catvod.crawler.SpiderDebug;
import com.github.catvod.net.OkHttp; import com.github.catvod.net.OkHttp;
import com.github.catvod.net.OkResult; import com.github.catvod.net.OkResult;
import com.github.catvod.utils.Json; import com.github.catvod.utils.Json;
import com.github.catvod.utils.Util;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class YunDrive { public class YunDrive {
private final Pattern regex = Pattern.compile("https://yun\\.139\\.com/shareweb/#/w/i/([^&]+)"); private final Pattern regex = Pattern.compile("https://yun\\.139\\.com/shareweb/#/w/i/([^&]+)");
private final SecretKeySpec secretKey; private final SecretKeySpec secretKey;
@ -76,6 +85,14 @@ public class YunDrive {
matcher = Pattern.compile("https://caiyun\\.139\\.com/m/i\\?([^&]+)").matcher(url); matcher = Pattern.compile("https://caiyun\\.139\\.com/m/i\\?([^&]+)").matcher(url);
finded = matcher.find(); finded = matcher.find();
} }
if (!finded) {
matcher = Pattern.compile("https://yun.139.com/shareweb/#/w/i/([\\w-]+)").matcher(url);
finded = matcher.find();
}
if (!finded) {
matcher = Pattern.compile("https://caiyun.139.com/w/i/([\\w-]+)").matcher(url);
finded = matcher.find();
}
if (finded) linkID = matcher.group(1); if (finded) linkID = matcher.group(1);
return linkID; return linkID;
@ -169,7 +186,7 @@ public class YunDrive {
for (JsonElement element : response.getAsJsonArray("coLst")) { for (JsonElement element : response.getAsJsonArray("coLst")) {
JsonObject entry = element.getAsJsonObject(); JsonObject entry = element.getAsJsonObject();
if (entry.get("coType").getAsInt() == 3) { if (entry.get("coType").getAsInt() == 3) {
items.add(Map.of("name", entry.get("coName").getAsString(), "contentId", entry.get("coID").getAsString(), "linkID", linkID)); items.add(Map.of("name", entry.get("coName").getAsString(), "contentId", entry.get("coID").getAsString(), "linkID", linkID, "path", entry.get("path").getAsString()));
} }
} }
} else if (response.has("caLst")) { } else if (response.has("caLst")) {
@ -195,8 +212,66 @@ public class YunDrive {
break; break;
} }
} }
return m3u8.split("playlist.m3u8")[0]+resultUrl; return m3u8.split("playlist.m3u8")[0] + resultUrl;
} }
public String get4kVideoInfo(String fid, String linkID) throws Exception {
String auth = YunTokenHandler.get().getToken();
SpiderDebug.log("auth:" + auth);
String phone = StringUtils.split(Util.base64Decode(auth), ":")[1];
SpiderDebug.log("phone:" + phone);
// 构建 JSON 请求体
Map<String, Object> requestBody = new HashMap<>();
Map<String, Object> dlFromOutLinkReqV3 = new HashMap<>();
Map<String, Object> commonAccountInfo = new HashMap<>();
dlFromOutLinkReqV3.put("linkID", linkID);
dlFromOutLinkReqV3.put("account", phone);
Map<String, Object> coIDLst = new HashMap<>();
coIDLst.put("item", Collections.singletonList(fid));
dlFromOutLinkReqV3.put("coIDLst", coIDLst);
commonAccountInfo.put("account", phone);
commonAccountInfo.put("accountType", 1);
requestBody.put("dlFromOutLinkReqV3", dlFromOutLinkReqV3);
requestBody.put("commonAccountInfo", commonAccountInfo);
/* {
"dlFromOutLinkReqV3" : {
"linkID" : "105CpbaJQFYc6",
"account" : "18896781601",
"coIDLst" : {
"item" : [ "DFTOdJkuAEwA1011ZpAcj1pl039202404112124392cb/Fkco6TgMKlnJwKbVul0ZKeYT5p2hIioVy" ]
}
},
"commonAccountInfo" : {
"account" : "18896781601",
"accountType" : 1
}
}*/
// 构建请求
Map<String, String> header = new HashMap<>();
header.put("X-Deviceinfo", "||3|12.27.0|safari|13.1.2|1||macos 10.15.6|1324X381|zh-cn|||");
header.put("hcy-cool-flag", "1");
header.put("Authorization", "Basic " + auth);
header.put("Content-Type", "application/json");
OkResult okResult = OkHttp.post(baseUrl + "dlFromOutLinkV3", encrypt(Json.toJson(requestBody)), header);
JsonObject resultJson = Json.safeObject(decrypt(okResult.getBody()));
if (resultJson.get("resultCode").getAsInt() == 0) {
return resultJson.getAsJsonObject("data").get("redrUrl").getAsString();
}
// 解析 JSON 响应
return null;
}
} }

View File

@ -0,0 +1,36 @@
package com.github.catvod.api;
import com.github.catvod.bean.yun.Cache;
import com.github.catvod.bean.yun.User;
import com.github.catvod.utils.Path;
import java.io.File;
public class YunTokenHandler {
private final Cache cache;
public File getCache() {
return Path.tv("yun139");
}
private YunTokenHandler() {
cache = Cache.objectFrom(Path.read(getCache()));
}
private static class Loader {
static volatile YunTokenHandler INSTANCE = new YunTokenHandler();
}
public static YunTokenHandler get() {
return YunTokenHandler.Loader.INSTANCE;
}
public String getToken() {
User user = cache.getUser();
return user.getCookie();
//return "cGM6MTg4OTY3ODE2MDE6eTM1Tjd1dG58MXxSQ1N8MTc1NDQ2OTgwNzEyOXxzMlN0T1VEV3lOVmF5V3pNbGFfM2tJbVp1ZmlqSHBqaEhTSzVyNHZqVXNRLmlhV3loSUxHNDFkMUI5N1BqXzhWN0dtVWtKLnBTclhpNGpZU1EuTGZWMTV3MVFoZmNpcEVoZkxUV2tvYjB0bkFTYV9RTUhhaHhveWx6YkdmcEhQdjNCS1lrbnp1LkxaWDdKOE40YkNNRjkzT3piNmx2Y0d3TWdVUkl5b18ubVUt";
}
}

View File

@ -0,0 +1,39 @@
package com.github.catvod.bean.yun;
import com.github.catvod.api.YunTokenHandler;
import com.github.catvod.spider.Init;
import com.github.catvod.utils.Path;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
public class Cache {
@SerializedName("user")
private User user;
public static Cache objectFrom(String str) {
Cache item = new Gson().fromJson(str, Cache.class);
return item == null ? new Cache() : item;
}
public User getUser() {
return user == null ? new User("") : user;
}
public void setUser(User user) {
this.user = user;
this.save();
}
public void save() {
Init.execute(() -> Path.write(YunTokenHandler.get().getCache(), toString()));
}
@Override
public String toString() {
return new Gson().toJson(this);
}
}

View File

@ -0,0 +1,30 @@
package com.github.catvod.bean.yun;
import com.google.gson.annotations.SerializedName;
public class User {
public User(String cookie) {
this.cookie = cookie;
}
@SerializedName("cookie")
private String cookie;
public String getCookie() {
return cookie;
}
public void setCookie(String cookie) {
this.cookie = cookie;
}
public static User objectFrom(String cookie) {
return new User(cookie);
}
public void clean() {
this.cookie = "";
}
}

View File

@ -2,11 +2,13 @@ package com.github.catvod.spider;
import android.content.Context; import android.content.Context;
import android.text.TextUtils; import android.text.TextUtils;
import com.github.catvod.api.YunDrive; import com.github.catvod.api.YunDrive;
import com.github.catvod.bean.Result; import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod; import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider; import com.github.catvod.crawler.Spider;
import com.github.catvod.crawler.SpiderDebug; import com.github.catvod.crawler.SpiderDebug;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
@ -49,7 +51,20 @@ public class YiDongYun extends Spider {
} }
} }
builder.append("移动", list); builder.append("移动(极速)", list);
List<Vod.VodPlayBuilder.PlayUrl> list2 = new ArrayList<>();
for (String s : result.keySet()) {
vodName = s;
for (Map<String, String> stringStringMap : result.get(s)) {
Vod.VodPlayBuilder.PlayUrl playUrl = new Vod.VodPlayBuilder.PlayUrl();
playUrl.url = stringStringMap.get("path") + "++" + stringStringMap.get("linkID");
playUrl.name = stringStringMap.get("name");
list2.add(playUrl);
}
}
builder.append("移动(原画)", list2);
Vod.VodPlayBuilder.BuildResult buildResult = builder.build(); Vod.VodPlayBuilder.BuildResult buildResult = builder.build();
Vod vod = new Vod(); Vod vod = new Vod();
vod.setVodId(ids.get(0)); vod.setVodId(ids.get(0));
@ -65,9 +80,17 @@ public class YiDongYun extends Spider {
@Override @Override
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception { public String playerContent(String flag, String id, List<String> vipFlags) throws Exception {
String playContent = "";
if (flag.contains("原画")) {
String contentId = id.split("\\+\\+")[0]; String contentId = id.split("\\+\\+")[0];
String linkID = id.split("\\+\\+")[1]; String linkID = id.split("\\+\\+")[1];
String playContent = YunDrive.get().fetchPlayUrl(contentId, linkID); playContent = YunDrive.get().get4kVideoInfo(contentId, linkID);
} else {
String contentId = id.split("\\+\\+")[0];
String linkID = id.split("\\+\\+")[1];
playContent = YunDrive.get().fetchPlayUrl(contentId, linkID);
}
SpiderDebug.log("playContent:" + playContent); SpiderDebug.log("playContent:" + playContent);
return Result.get().url(playContent).octet().string(); return Result.get().url(playContent).octet().string();
} }
@ -83,7 +106,10 @@ public class YiDongYun extends Spider {
List<String> playFrom = new ArrayList<>(); List<String> playFrom = new ArrayList<>();
int i = 0; int i = 0;
for (String id : ids) { for (String id : ids) {
playFrom.add("移动" + i++); i++;
playFrom.add("移动(极速)" + i);
playFrom.add("移动(原画)" + i);
} }

View File

@ -41,7 +41,7 @@ public class YiDongYunTest {
@org.junit.Test @org.junit.Test
public void detailContent() throws Exception { public void detailContent() throws Exception {
String content = spider.detailContent(Arrays.asList("https://yun.139.com/shareweb/#/w/i/165CkRwb9G885")); String content = spider.detailContent(Arrays.asList("https://caiyun.139.com/w/i/2nQQVZWCR24yf"));
System.out.println("detailContent--" + content); System.out.println("detailContent--" + content);
JsonObject map = Json.safeObject(content); JsonObject map = Json.safeObject(content);
Gson gson = new GsonBuilder().setPrettyPrinting().create(); Gson gson = new GsonBuilder().setPrettyPrinting().create();
@ -49,10 +49,15 @@ public class YiDongYunTest {
Assert.assertFalse(map.getAsJsonArray("list").isEmpty()); Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
} }
/**
* "vod_play_from": "移动(极速)$$$移动(原画)",
* "vod_play_url": "01.mp4$FtgoS0iBwhPFnG-daRU5HJKQ2yBYj8I3x++2nQQVZWCR24yf#02.mp4$FiPG4ttnS-78swp-1sTFG4prNYnLaUvK_++2nQQVZWCR24yf$$$01.mp4$FtB-r8kHUbJFKbzW_r9tJt6YjcTZCVGWR/FtgoS0iBwhPFnG-daRU5HJKQ2yBYj8I3x++2nQQVZWCR24yf#02.mp4$FtB-r8kHUbJFKbzW_r9tJt6YjcTZCVGWR/FiPG4ttnS-78swp-1sTFG4prNYnLaUvK_++2nQQVZWCR24yf"
* @throws Exception
*/
@org.junit.Test @org.junit.Test
public void playerContent() throws Exception { public void playerContent() throws Exception {
String content = spider.playerContent("普画","41ea9a50cbdd4e50b019bcd78687ebc1++22fc6fa8350d22e0eaecc49035368e81++38c5e16d71f7++WFcYTmRhjJpKTui56aleYdzBZi9R203GERBVzYNxDxI=",new ArrayList<>()); String content = spider.playerContent("移动(原画)","FtB-r8kHUbJFKbzW_r9tJt6YjcTZCVGWR/FiPG4ttnS-78swp-1sTFG4prNYnLaUvK_++2nQQVZWCR24yf",new ArrayList<>());
System.out.println("playerContent--" + content); System.out.println("playerContent--" + content);
JsonObject map = Json.safeObject(content); JsonObject map = Json.safeObject(content);
Gson gson = new GsonBuilder().setPrettyPrinting().create(); Gson gson = new GsonBuilder().setPrettyPrinting().create();

View File

@ -1,6 +1,7 @@
package com.github.catvod.api; package com.github.catvod.api;
import com.github.catvod.bean.tianyi.ShareData; import com.github.catvod.bean.tianyi.ShareData;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -27,14 +28,32 @@ public class YunDriveTest {
System.out.println(result); System.out.println(result);
for (String s : result.keySet()) { for (String s : result.keySet()) {
for (Map<String, String> stringStringMap : result.get(s)) { for (Map<String, String> stringStringMap : result.get(s)) {
String playUrl = yunDrive.fetchPlayUrl(stringStringMap.get("contentId"),""); String playUrl = yunDrive.fetchPlayUrl(stringStringMap.get("contentId"), "");
System.out.println(stringStringMap.get("name")+":"+playUrl); System.out.println(stringStringMap.get("name") + ":" + playUrl);
} }
} }
}
@Test
public void download() throws Exception {
Map<String, List<Map<String, String>>> result = yunDrive.processShareData("https://caiyun.139.com/w/i/2nQQVZWCR24yf");
System.out.println(result);
for (String s : result.keySet()) {
for (Map<String, String> stringStringMap : result.get(s)) {
String playUrl = yunDrive.fetchPlayUrl(stringStringMap.get("contentId"), stringStringMap.get("linkID"));
String url2 = yunDrive.get4kVideoInfo(stringStringMap.get("linkID"), stringStringMap.get("path"));
System.out.println(stringStringMap.get("name") + ":" + playUrl);
System.out.println(stringStringMap.get("url2") + ":" + url2);
}
}
//;
} }
@ -48,4 +67,5 @@ public class YunDriveTest {
} }
} }