diff --git a/app/src/main/java/com/github/catvod/spider/XuanFeng.java b/app/src/main/java/com/github/catvod/spider/XuanFeng.java new file mode 100644 index 00000000..e0579a61 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/XuanFeng.java @@ -0,0 +1,165 @@ +package com.github.catvod.spider; + +import com.github.catvod.bean.Class; +import com.github.catvod.bean.Filter; +import com.github.catvod.bean.Result; +import com.github.catvod.bean.Vod; +import com.github.catvod.crawler.Spider; +import com.github.catvod.net.OkHttp; +import com.github.catvod.net.OkResult; +import com.github.catvod.utils.Json; +import com.github.catvod.utils.Util; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; + +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class XuanFeng extends Spider { + + private static final String siteUrl = "https://miao101.com"; + private static final String apiUrl = siteUrl + "/api"; + + + private HashMap getHeaders() { + return Util.webHeaders(siteUrl); + } + + @Override + public String homeContent(boolean filter) throws Exception { + List list = new ArrayList<>(); + List classes = new ArrayList<>(); + LinkedHashMap> filters = new LinkedHashMap<>(); + + Document doc = Jsoup.parse(OkHttp.string(siteUrl, getHeaders())); + + + for (Element element : doc.select("#navbarSupportedContent > ul > li ")) { + if (element.select("a.nav-link").attr("href").startsWith("/")) { + classes.add(new Class(element.select("a.nav-link").attr("href"), element.text())); + } else { + for (Element element1 : element.select("ul > li > a")) { + classes.add(new Class(element1.attr("href"), element1.text())); + } + + } + } + + for (Element element : doc.select("#container > div.row > div.col-md-2.col-6")) { + try { + String pic = element.select("img").attr("src"); + String url = element.select("div.cover-wrap > a").attr("href"); + String name = element.select("div.card-title").text(); + + + list.add(new Vod(url, name, pic)); + } catch (Exception ignored) { + } + } + return Result.string(classes, list); + } + + + @Override + public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception { + List list = new ArrayList<>(); + tid = tid.replaceAll("1", ""); + + String target = apiUrl + tid + "load.json"; + OkResult result = OkHttp.post(target, Map.of("page", pg), getHeaders()); + if (result.getCode() == 200) { + String body = result.getBody(); + Map>> obj = new HashMap<>(); + obj = Json.parseSafe(body, obj.getClass()); + ArrayList> videos = obj.get("videos"); + for (Map video : videos) { + list.add(new Vod("/video/" + video.get("ID").toString(), video.get("Title").toString(), video.get("Cover").toString())); + } + + Integer total = Integer.MAX_VALUE; + return Result.string(Integer.parseInt(pg), Integer.parseInt(pg) + 1, list.size(), total, list); + } + return null; + + } + + @Override + public String detailContent(List ids) throws Exception { + Document doc = Jsoup.parse(OkHttp.string(siteUrl.concat(ids.get(0)), getHeaders())); + String name = doc.select("#container > div.row.phone > div.col-md-8 > div:nth-child(3) > div.col-md-8 > h1").text(); + String pic = doc.select("#container > div.row.phone > div.col-md-8 > div.d-flex.mb-3 > div.flex-shrink-0 > img").attr("src"); + String year = doc.select("#container > div.row.phone > div.col-md-8 > div.d-flex.mb-3 > div.flex-grow-1 > p:nth-child(11)").text(); + String desc = doc.select("#container > div.row.phone > div.col-md-8 > div.text-break.ft14").text(); + String jsonStr = Util.findByRegex("JSON.parse\\(\"(.*?)\"\\)", doc.html(), 1); + Map map = Json.parseSafe(jsonStr.replaceAll("\\\\u0022", "\""), Map.class); + List> headers = (List>) map.get("headers"); + List> clips = (List>) map.get("clips"); + // 播放源 + + String PlayFrom = ""; + String PlayUrl = ""; + for (int i = 0; i < headers.size(); i++) { + String tabName = (String) headers.get(i).get("Name"); + if (!"".equals(PlayFrom)) { + PlayFrom = PlayFrom + "$$$" + tabName; + } else { + PlayFrom = PlayFrom + tabName; + } + String liUrl = ""; + for (List clip : clips) { + if (!"".equals(liUrl)) { + liUrl = liUrl + "#" + clip.get(0) + "$" + clip.get(1); + } else { + liUrl = liUrl + clip.get(0) + "$" + clip.get(1); + } + } + + if (!"".equals(PlayUrl)) { + PlayUrl = PlayUrl + "$$$" + liUrl; + } else { + PlayUrl = PlayUrl + liUrl; + } + } + + Vod vod = new Vod(); + vod.setVodId(ids.get(0)); + vod.setVodPic(pic); + vod.setVodYear(year); + vod.setVodName(name); + vod.setVodContent(desc); + vod.setVodPlayFrom(PlayFrom); + vod.setVodPlayUrl(PlayUrl); + return Result.string(vod); + + + } + + @Override + public String searchContent(String key, boolean quick) throws Exception { + + + List list = new ArrayList<>(); + Document doc = Jsoup.parse(OkHttp.string(siteUrl.concat("/search?q=").concat(URLEncoder.encode(key, "UTF-8")), getHeaders())); + for (Element element : doc.select("#container > div.row > div.col-md-2.col-6")) { + try { + String pic = element.select("img").attr("src"); + String url = element.select("div.cover-wrap > a").attr("href"); + String name = element.select("h6").text(); + list.add(new Vod(url, name, pic)); + } catch (Exception ignored) { + } + } + return Result.string(list); + } + + @Override + public String playerContent(String flag, String id, List vipFlags) throws Exception { + return Result.get().url(id).header(getHeaders()).string(); + } +} \ No newline at end of file diff --git a/app/src/test/java/XuanFengTest.java b/app/src/test/java/XuanFengTest.java new file mode 100644 index 00000000..6f2d4ada --- /dev/null +++ b/app/src/test/java/XuanFengTest.java @@ -0,0 +1,96 @@ +import android.app.Application; + +import com.github.catvod.spider.ChangZhang; +import com.github.catvod.spider.Init; +import com.github.catvod.spider.XuanFeng; +import com.github.catvod.utils.Json; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; + +import org.junit.Assert; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +import java.util.ArrayList; +import java.util.Arrays; + +@RunWith(RobolectricTestRunner.class) +public class XuanFengTest { + // @Mock + private Application mockContext; + + private XuanFeng spider; + + @org.junit.Before + public void setUp() throws Exception { + mockContext = RuntimeEnvironment.application; + Init.init(mockContext); + spider = new XuanFeng(); + spider.init(mockContext, "https://www.czzy.site/"); + } + + @org.junit.Test + public void homeContent() throws Exception { + String content = spider.homeContent(true); + JsonObject map = Json.safeObject(content); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + System.out.println("homeContent--" + gson.toJson(map)); + + //Assert.assertFalse(map.getAsJsonArray("list").isEmpty()); + } + + @org.junit.Test + public void homeVideoContent() throws Exception { + String content = spider.homeVideoContent(); + JsonObject map = Json.safeObject(content); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + System.out.println("homeVideoContent--" + gson.toJson(map)); + + //Assert.assertFalse(map.getAsJsonArray("list").isEmpty()); + } + + @org.junit.Test + public void categoryContent() throws Exception { + String content = spider.categoryContent("/tag/悬疑片/1", "2", true, null); + JsonObject map = Json.safeObject(content); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println("categoryContent--" + gson.toJson(map)); + Assert.assertFalse(map.getAsJsonArray("list").isEmpty()); + } + + @org.junit.Test + public void detailContent() throws Exception { + + String content = spider.detailContent(Arrays.asList("/video/8dFoErWcVsJJLsJd7sFPMQ")); + JsonObject map = Json.safeObject(content); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println("detailContent--" + gson.toJson(map)); + Assert.assertFalse(map.getAsJsonArray("list").isEmpty()); + } + + @org.junit.Test + public void playerContent() throws Exception { + String froms = "量子$$$淘片"; + String urls ="第01集$https://v.cdnlz3.com/20240731/25186_490331f6/index.m3u8#第02集$https://v.cdnlz3.com/20240731/25187_c7e06160/index.m3u8#第03集$https://v.cdnlz3.com/20240731/25189_28570e77/index.m3u8#第04集$https://v.cdnlz3.com/20240731/25188_a0d85819/index.m3u8#第05集$https://v.cdnlz3.com/20240801/25231_ffa23109/index.m3u8#第06集$https://v.cdnlz3.com/20240801/25232_7cdfc398/index.m3u8#第07集$https://v.cdnlz12.com/20240802/16173_42dcc85e/index.m3u8#第08集$https://v.cdnlz12.com/20240802/16174_ff0b89d2/index.m3u8#第09集$https://v.cdnlz3.com/20240803/25279_d5059500/index.m3u8#第10集$https://v.cdnlz3.com/20240803/25280_cda61290/index.m3u8#第11集$https://v.cdnlz12.com/20240804/16205_5bc22654/index.m3u8#第12集$https://v.cdnlz12.com/20240804/16206_3bcaf472/index.m3u8#第13集$https://v.cdnlz3.com/20240805/25321_bc51b2b3/index.m3u8#第14集$https://v.cdnlz3.com/20240805/25322_cadf8e24/index.m3u8#第15集$https://v.cdnlz12.com/20240806/16229_bee0732e/index.m3u8#第16集$https://v.cdnlz12.com/20240806/16228_a9b865e1/index.m3u8#第17集$https://v.cdnlz3.com/20240807/25396_52a2dde7/index.m3u8#第18集$https://v.cdnlz3.com/20240807/25397_4bf5838a/index.m3u8#第19集$https://v.cdnlz3.com/20240808/25421_08a90c9a/index.m3u8#第20集$https://v.cdnlz3.com/20240808/25422_d6341248/index.m3u8#第21集$https://v.cdnlz3.com/20240809/25447_34159679/index.m3u8#第22集$https://v.cdnlz3.com/20240809/25448_66e070eb/index.m3u8#第23集$https://v.cdnlz3.com/20240810/25478_d1ef4ec0/index.m3u8#第24集$https://v.cdnlz3.com/20240810/25479_c7db7c2b/index.m3u8#第25集$https://v.cdnlz3.com/20240811/25518_08a2d2dd/index.m3u8#第26集$https://v.cdnlz3.com/20240811/25519_dfeb62f9/index.m3u8#第27集$https://v.cdnlz3.com/20240812/25553_fc7bd8f6/index.m3u8#第28集$https://v.cdnlz3.com/20240812/25554_20b4b783/index.m3u8#第29集$https://v.cdnlz3.com/20240813/25575_7df14a3e/index.m3u8#第30集$https://v.cdnlz3.com/20240813/25576_a012c969/index.m3u8$$$第01集$https://v.cdnlz3.com/20240731/25186_490331f6/index.m3u8#第02集$https://v.cdnlz3.com/20240731/25187_c7e06160/index.m3u8#第03集$https://v.cdnlz3.com/20240731/25189_28570e77/index.m3u8#第04集$https://v.cdnlz3.com/20240731/25188_a0d85819/index.m3u8#第05集$https://v.cdnlz3.com/20240801/25231_ffa23109/index.m3u8#第06集$https://v.cdnlz3.com/20240801/25232_7cdfc398/index.m3u8#第07集$https://v.cdnlz12.com/20240802/16173_42dcc85e/index.m3u8#第08集$https://v.cdnlz12.com/20240802/16174_ff0b89d2/index.m3u8#第09集$https://v.cdnlz3.com/20240803/25279_d5059500/index.m3u8#第10集$https://v.cdnlz3.com/20240803/25280_cda61290/index.m3u8#第11集$https://v.cdnlz12.com/20240804/16205_5bc22654/index.m3u8#第12集$https://v.cdnlz12.com/20240804/16206_3bcaf472/index.m3u8#第13集$https://v.cdnlz3.com/20240805/25321_bc51b2b3/index.m3u8#第14集$https://v.cdnlz3.com/20240805/25322_cadf8e24/index.m3u8#第15集$https://v.cdnlz12.com/20240806/16229_bee0732e/index.m3u8#第16集$https://v.cdnlz12.com/20240806/16228_a9b865e1/index.m3u8#第17集$https://v.cdnlz3.com/20240807/25396_52a2dde7/index.m3u8#第18集$https://v.cdnlz3.com/20240807/25397_4bf5838a/index.m3u8#第19集$https://v.cdnlz3.com/20240808/25421_08a90c9a/index.m3u8#第20集$https://v.cdnlz3.com/20240808/25422_d6341248/index.m3u8#第21集$https://v.cdnlz3.com/20240809/25447_34159679/index.m3u8#第22集$https://v.cdnlz3.com/20240809/25448_66e070eb/index.m3u8#第23集$https://v.cdnlz3.com/20240810/25478_d1ef4ec0/index.m3u8#第24集$https://v.cdnlz3.com/20240810/25479_c7db7c2b/index.m3u8#第25集$https://v.cdnlz3.com/20240811/25518_08a2d2dd/index.m3u8#第26集$https://v.cdnlz3.com/20240811/25519_dfeb62f9/index.m3u8#第27集$https://v.cdnlz3.com/20240812/25553_fc7bd8f6/index.m3u8#第28集$https://v.cdnlz3.com/20240812/25554_20b4b783/index.m3u8#第29集$https://v.cdnlz3.com/20240813/25575_7df14a3e/index.m3u8#第30集$https://v.cdnlz3.com/20240813/25576_a012c969/index.m3u8"; + for (int i = 0; i < urls.split("\\$\\$\\$").length; i++) { + String content = spider.playerContent(froms.split("\\$\\$\\$")[i], urls.split("\\$\\$\\$")[i].split("\\$")[1], new ArrayList<>()); + JsonObject map = Json.safeObject(content); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println("playerContent--" + gson.toJson(map)); + Assert.assertFalse(map.getAsJsonPrimitive("url").getAsString().isEmpty()); + } + } + + @org.junit.Test + public void searchContent() throws Exception { + String content = spider.searchContent("红", false); + JsonObject map = Json.safeObject(content); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println("searchContent--" + gson.toJson(map)); + Assert.assertFalse(map.getAsJsonArray("list").isEmpty()); + } +} \ No newline at end of file diff --git a/jar/custom_spider.jar b/jar/custom_spider.jar index 24c750b2..ed2fb758 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 16ec2041..1585c6f7 100644 --- a/jar/custom_spider.jar.md5 +++ b/jar/custom_spider.jar.md5 @@ -1 +1 @@ -1f2e3362ef4ccefef998a9f4ea525924 +0dcb7bdf2bfb2e77fdea1d66f53d1d60 diff --git a/json/index.json b/json/index.json index b8259487..b6eee94e 100644 --- a/json/index.json +++ b/json/index.json @@ -1,5 +1,5 @@ { - "spider": "https://androidcatvodspider.pages.dev/jar/custom_spider.jar;md5;1f2e3362ef4ccefef998a9f4ea525924", + "spider": "https://androidcatvodspider.pages.dev/jar/custom_spider.jar;md5;0dcb7bdf2bfb2e77fdea1d66f53d1d60", "lives": [ { "name": "直播ipv6", @@ -51,6 +51,14 @@ "searchable": 1, "changeable": 1, "ext": {} + },{ + "key": "XuanFeng", + "name": "旋风影视", + "type": 3, + "api": "csp_XuanFeng", + "searchable": 1, + "changeable": 1, + "ext": {} }, { "key": "NCat", diff --git a/json/index1.json b/json/index1.json index 89ff844f..7c998d8f 100644 --- a/json/index1.json +++ b/json/index1.json @@ -1,5 +1,5 @@ { - "spider": "https://androidcatvodspider.pages.dev/jar/custom_spider.jar;md5;1f2e3362ef4ccefef998a9f4ea525924", + "spider": "https://androidcatvodspider.pages.dev/jar/custom_spider.jar;md5;0dcb7bdf2bfb2e77fdea1d66f53d1d60", "lives": [ { "name": "直播ipv6",