diff --git a/app/src/main/java/com/github/catvod/api/BaiduDrive.kt b/app/src/main/java/com/github/catvod/api/BaiduDrive.kt index 48f44ea4..71e30354 100644 --- a/app/src/main/java/com/github/catvod/api/BaiduDrive.kt +++ b/app/src/main/java/com/github/catvod/api/BaiduDrive.kt @@ -9,6 +9,7 @@ import com.github.catvod.utils.ProxyServer.buildProxyUrl import com.github.catvod.utils.Util import com.github.catvod.utils.Util.MEDIA import com.google.gson.JsonObject +import java.net.URLEncoder import java.util.* object BaiduDrive { @@ -164,7 +165,7 @@ object BaiduDrive { // 处理items items.forEach { item -> if (item.asJsonObject["isdir"].asInt == 1) { - val folderPath = "/sharelink$uk-$shareid/${item.asJsonObject["server_filename"].asString}" + val folderPath = "/sharelink$uk-${item.asJsonObject["fs_id"].asString}/${item.asJsonObject["server_filename"].asString}" if (folderPath !in seenFolders) { seenFolders.add(folderPath) pendingFolders.add( @@ -298,7 +299,7 @@ object BaiduDrive { "shareid" to folderInfo["shareid"]!!.toString(), "page" to folderInfo["page"].toString(), "num" to "9999", - "dir" to folderInfo["dir"]!!.toString(), + "dir" to URLEncoder.encode(folderInfo["dir"]!!.toString()), "desc" to "0", "order" to "name", ) diff --git a/app/src/main/java/com/github/catvod/spider/Qupans.java b/app/src/main/java/com/github/catvod/spider/Qupans.java new file mode 100644 index 00000000..2267a975 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Qupans.java @@ -0,0 +1,262 @@ +package com.github.catvod.spider; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Pair; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.github.catvod.bean.Result; +import com.github.catvod.bean.Vod; +import com.github.catvod.net.OkHttp; +import com.github.catvod.utils.Util; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + + +public class Qupans extends Cloud { + + private static final String BASE_URL = "https://www.qupanshe.com"; + private static final String DEFAULT_COVER_URL = "https://fs-im-kefu.7moor-fs1.com/ly/4d2c3f00-7d4c-11e5-af15-41bf63ae4ea0/1743950734122/baidu.jpg"; + private static final String BAIDU_PAN_REGEX = "https?:\\/\\/(?:pan\\.)?baidu\\.com\\/(?:s\\/|share\\/link\\?)[^\\s]+"; + private static final String PASSWORD_REGEX = "提取码[::]\\s*([a-zA-Z0-9]{4})"; + + public Qupans() { + super(); + } + + @Override + public void init(Context context, String extend) { + try { + super.init(context, extend); + if (!TextUtils.isEmpty(extend)) { + try { + JSONObject json = new JSONObject(extend); + String customUrl = json.optString("url"); + if (!TextUtils.isEmpty(customUrl)) { + } + } catch (Exception e) { + } + } + } catch (Exception e) { + } + } + + private String requestWithHeaders(String url) { + Map headers = new HashMap<>(); + headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"); + headers.put("Referer", BASE_URL); + return OkHttp.string(url, headers); + } + + @Override + public String homeContent(boolean filter) { + try { + JSONObject result = new JSONObject(); + JSONArray classArray = new JSONArray(); + JSONObject json = new JSONObject("{\"电影\":\"3\",\"电视剧\":\"2\",\"综艺\":\"4\",\"动漫\":\"5\",\"纪录片\":\"6\"}"); + Iterator keys = json.keys(); + + while (keys.hasNext()) { + String key = keys.next(); + JSONObject category = new JSONObject(); + category.put("type_id", json.optString(key)); + category.put("type_name", key); + classArray.put(category); + } + + result.put("class", classArray); + return result.toString(); + } catch (Exception e) { + return "{\"class\":[]}"; + } + } + + @Override + public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { + String url = String.format("%s/forum.php?mod=forumdisplay&fid=%s&page=%s", BASE_URL, tid, pg); + String response = requestWithHeaders(url); + Document doc = Jsoup.parse(response); + List> list = new ArrayList<>(); + + Elements items = doc.select("div.tit_box > a.s"); + for (Element item : items) { + String title = item.text(); + if (!title.contains("公告") && !title.contains("求")) { + list.add(new Pair<>(item.attr("href"), title)); + } + } + + try { + JSONObject result = new JSONObject(); + JSONArray listArray = new JSONArray(); + for (Pair item : list) { + JSONObject vod = new JSONObject(); + vod.put("vod_id", item.first); + vod.put("vod_name", item.second); + vod.put("vod_pic", DEFAULT_COVER_URL); + vod.put("vod_remarks", ""); + listArray.put(vod); + } + result.put("list", listArray); + result.put("page", pg); + result.put("pagecount", "0"); + result.put("total", "0"); + return result.toString(); + } catch (Exception e) { + return "{\"list\":[],\"page\":\"1\",\"pagecount\":\"0\",\"total\":\"0\"}"; + } + } + + @Override + public String detailContent(List ids) throws Exception { + String vodId = ids.get(0); + String url = vodId.startsWith("http") ? vodId : BASE_URL + "/" + vodId; + String html = requestWithHeaders(url); + Document doc = Jsoup.parse(html); + + Vod item = new Vod(); + item.setVodId(vodId); + + Element titleElement = doc.select("h1").first(); + String title = titleElement != null ? titleElement.text() : doc.title(); + item.setVodName(title); + item.setVodPic(DEFAULT_COVER_URL); + + List shareLinks = extractBaiduPanLinks(doc); + + if (!shareLinks.isEmpty()) { + String pwd = Util.findByRegex(doc.text(), PASSWORD_REGEX, 1); + if (!TextUtils.isEmpty(pwd)) { + for (int i = 0; i < shareLinks.size(); i++) { + String link = shareLinks.get(i); + if (!link.contains("pwd=")) { + shareLinks.set(i, link + (link.contains("?") ? "&" : "?") + "pwd=" + pwd); + } + } + } + + String playFrom = super.detailContentVodPlayFrom(shareLinks); + String playUrl = super.detailContentVodPlayUrl(shareLinks); + item.setVodPlayFrom(playFrom); + item.setVodPlayUrl(playUrl); + } + + return Result.string(item); + } + + private List extractBaiduPanLinks(Document doc) { + List shareLinks = new ArrayList<>(); + + for (Element link : doc.select("a")) { + String href = link.attr("href"); + if (href.contains("baidu.com") || href.contains("pan.baidu")) { + if (!href.startsWith("http")) { + if (href.startsWith("/")) { + href = BASE_URL + href; + } + } + if (!shareLinks.contains(href)) { + shareLinks.add(href); + } + } + } + + for (Element content : doc.select("td.t_f, .content, .post-content")) { + String foundLink = Util.findByRegex(content.text(), BAIDU_PAN_REGEX, 0); + if (!TextUtils.isEmpty(foundLink) && !shareLinks.contains(foundLink)) { + shareLinks.add(foundLink); + } + } + + if (shareLinks.isEmpty()) { + String foundLink = Util.findByRegex(doc.text(), BAIDU_PAN_REGEX, 0); + if (!TextUtils.isEmpty(foundLink) && !shareLinks.contains(foundLink)) { + shareLinks.add(foundLink); + } + } + + return shareLinks; + } + + @Override + public String searchContent(String key, boolean quick) { + return searchWithKeyword(key); + } + + @Override + public String searchContent(String key, boolean quick, String pg) { + return searchWithKeyword(key); + } + + private String searchWithKeyword(String keyword) { + String url = BASE_URL + "/search.php?mod=forum"; + + Map params = new HashMap<>(); + params.put("srchuname", ""); + params.put("srchfilter", "all"); + params.put("srchfrom", "0"); + params.put("before", ""); + params.put("orderby", "lastpost"); + params.put("ascdesc", "desc"); + params.put("searchsubmit", "yes"); + params.put("srchtxt", keyword); + + String[] forumIds = {"2", "3", "4", "5", "6"}; + for (int i = 0; i < forumIds.length; i++) { + params.put("srchfid[" + i + "]", forumIds[i]); + } + + Map headers = new HashMap<>(); + headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"); + headers.put("content-type", "application/x-www-form-urlencoded"); + headers.put("Cookie", "X_CACHE_KEY=4ea0277e01b1880d76edcdb5deaf7d38; f3ll_2132_saltkey=pbaZTtWt; f3ll_2132_lastvisit=1750900013; f3ll_2132_seccodecSKQwk6G=516.5c6d6036e45acc7725; f3ll_2132_sid=pS5p3e; f3ll_2132_ulastactivity=4e54n6SBOHeGXpFs4y2pmBVIZ99rNTklZ8bmLQzNerUezlIdu4SI; f3ll_2132_auth=b46bRtQ%2FO7ckeivggteyEs2twb%2B3HHbhT0FlBF4IlO%2BSb1ndi5elO0d7KDFhy15UqCC9nKGyGUmA9fYu8SWezxcK; f3ll_2132_sendmail=1; f3ll_2132_lastact=1752292107%09home.php%09spacecp; f3ll_2132_lastcheckfeed=3141%7C1752292107"); + + String response = OkHttp.post(url, params, headers).getBody(); + Document doc = Jsoup.parse(response); + Elements items = doc.select("#threadlist ul li"); + + List> list = new ArrayList<>(); + for (Element item : items) { + Elements aElements = item.select("h3 > a"); + if (!aElements.isEmpty()) { + String href = aElements.first().attr("href"); + String title = aElements.first().text(); + if (title != null && !title.isEmpty()) { + title = title.replaceAll("<[^>]+>", ""); + } + list.add(new Pair<>(href, title)); + } + } + + try { + JSONObject result = new JSONObject(); + JSONArray listArray = new JSONArray(); + for (Pair item : list) { + JSONObject vod = new JSONObject(); + vod.put("vod_id", item.first); + vod.put("vod_name", item.second); + vod.put("vod_pic", DEFAULT_COVER_URL); + vod.put("vod_remarks", ""); + listArray.put(vod); + } + result.put("list", listArray); + result.put("page", "1"); + result.put("pagecount", "1"); + result.put("total", String.valueOf(listArray.length())); + return result.toString(); + } catch (Exception e) { + return "{\"list\":[],\"page\":\"1\",\"pagecount\":\"1\",\"total\":\"0\"}"; + } + } +} \ No newline at end of file diff --git a/app/src/test/java/com/github/catvod/api/BaiduDriveTest.kt b/app/src/test/java/com/github/catvod/api/BaiduDriveTest.kt index d636d4be..c24fe982 100644 --- a/app/src/test/java/com/github/catvod/api/BaiduDriveTest.kt +++ b/app/src/test/java/com/github/catvod/api/BaiduDriveTest.kt @@ -15,7 +15,7 @@ class BaiduDriveTest { runBlocking { val reslut = - BaiduDrive.processShareLinks(listOf("https://pan.baidu.com/s/1Ov0S6S7rqnyW_S3AondhmQ?pwd=8888")) + BaiduDrive.processShareLinks(listOf("https://pan.baidu.com/s/1So5RhSmNts0rWKEzjqinhQ?pwd=9527")) System.out.println(Json.toJson(reslut)) } } @@ -51,7 +51,7 @@ class BaiduDriveTest { System.out.println(reslut) }*/ val jsonStr = - com.github.catvod.utils.Util.base64Decode("eyJ1ayI6IjExMDMyNzkxMjIzNDEiLCJzaGFyZWlkIjoiMjk1NzE4ODcyOTgiLCJmaWQiOjMxOTM5NTUxMTQyOTU4MCwicmFuZHNrIjoidkd4WXh4TVBRcXpucXZialRQeUQ2Q1FFT2VqemtJWmdFdXV2OUQ1Y3R6TSUzRCIsInBuYW1lIjoiRHJhZ29uIEJhbGwgREFJTUEuUzAxRTAxLjIwMjQuMTA4MHAuQ1IuV0VCLURMLngyNjQuQUFDLm1rdiIsInF0eXBlIjoib3JpZ2luYWwifQ==") + com.github.catvod.utils.Util.base64Decode("eyJ1ayI6IjI0MDAxMjE2NzIiLCJzaGFyZWlkIjoiMjc2NTk2OTA4MTAiLCJmaWQiOjcxNzUwMDM4OTg1MjYzOSwicmFuZHNrIjoiNEdjMzFTejVsZHNpdHcwRW12ZDNzam9XYWFuVjFEQlFsUHk3VkdESHklMkI0JTNEIiwicG5hbWUiOiJUaGUuUmV0dXJuLm9mLnRoZS5MYW1lLkhlcm8uMjAyNS4yMTYwcC5XRUItREwuSDI2NS5IRFIuNjBmcHMuRERQNS4xLURyZWFtSEQubWt2IiwicXR5cGUiOiJvcmlnaW5hbCJ9") val obj = Json.safeObject(jsonStr) runBlocking { val reslut = BaiduDrive.getVideoUrl(obj, "BD原画1") diff --git a/jar/custom_spider.jar b/jar/custom_spider.jar index 51ab9903..ff7309ce 100644 Binary files a/jar/custom_spider.jar and b/jar/custom_spider.jar differ diff --git a/jar/custom_spider.jar.md5 b/jar/custom_spider.jar.md5 index 601eaa95..b498b2ac 100644 --- a/jar/custom_spider.jar.md5 +++ b/jar/custom_spider.jar.md5 @@ -1 +1 @@ -e08d2ec17471fa6606811286d60a1087 +442e28f56e42d29e8ced7debc6e2b7d3 diff --git a/json/index.json b/json/index.json index 7f1601cd..f999ab8c 100644 --- a/json/index.json +++ b/json/index.json @@ -1,5 +1,5 @@ { - "spider": "https://andoridspidermt.netlify.app/jar/custom_spider.jar;md5;e08d2ec17471fa6606811286d60a1087", + "spider": "https://andoridspidermt.netlify.app/jar/custom_spider.jar;md5;442e28f56e42d29e8ced7debc6e2b7d3", "lives": [ { "name": "电视直播", @@ -94,6 +94,14 @@ "ext": {} }, { + "key": "Qupans", + "name": "Qupans|Pan", + "type": 3, + "api": "csp_Qupans", + "searchable": 1, + "changeable": 1, + "ext": {} + },{ "key": "TgSearch", "name": "TgSearch|Pan", "type": 3,