diff --git a/app/src/main/java/com/github/catvod/spider/Aidi.java b/app/src/main/java/com/github/catvod/spider/Aidi.java
new file mode 100644
index 0000000..d72c5f8
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Aidi.java
@@ -0,0 +1,466 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Demo for spider
+ *
+ * Author: CatVod
+ */
+public class Aidi extends Spider {
+ private static final String siteUrl = "https://aidi.tv";
+ private static final String siteHost = "aidi.tv";
+
+ /**
+ * 播放源配置
+ */
+ private JSONObject playerConfig;
+ /**
+ * 筛选配置
+ */
+ private JSONObject filterConfig;
+
+ private Pattern regexCategory = Pattern.compile("/v/(\\w+).html");
+ private Pattern regexVid = Pattern.compile("/movie/(\\w+).html");
+ private Pattern regexPlay = Pattern.compile("\\S+/play/(\\w+)-(\\d+)-(\\d+).html");
+ private Pattern regexPage = Pattern.compile("/show/(\\S+).html");
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ try {
+ playerConfig = new JSONObject("{\"xg_app_player\":{\"sh\":\"app全局解析\",\"pu\":\"\",\"sn\":0,\"or\":999},\"dplayer\":{\"sh\":\"dplayer\",\"pu\":\"\",\"sn\":0,\"or\":999},\"videojs\":{\"sh\":\"videojs-H5播放器\",\"pu\":\"\",\"sn\":0,\"or\":999},\"iva\":{\"sh\":\"iva-H5播放器\",\"pu\":\"\",\"sn\":0,\"or\":999},\"iframe\":{\"sh\":\"iframe外链数据\",\"pu\":\"\",\"sn\":0,\"or\":999},\"link\":{\"sh\":\"外链数据\",\"pu\":\"top.\",\"sn\":0,\"or\":999},\"swf\":{\"sh\":\"Flash文件\",\"pu\":\"\",\"sn\":0,\"or\":999},\"flv\":{\"sh\":\"Flv文件\",\"pu\":\"\",\"sn\":0,\"or\":999},\"qiepian\":{\"sh\":\"爱迪云播\",\"pu\":\"\",\"sn\":0,\"or\":999},\"ckm3u8\":{\"sh\":\"爱迪影视\",\"pu\":\"\",\"sn\":0,\"or\":999},\"xin\":{\"sh\":\"爱迪高速\",\"pu\":\"\",\"sn\":0,\"or\":999},\"ppyun\":{\"sh\":\"爱迪云链\",\"pu\":\"\",\"sn\":0,\"or\":999},\"jisu\":{\"sh\":\"极速路线\",\"pu\":\"\",\"sn\":0,\"or\":999},\"ppayun\":{\"sh\":\"pp云\",\"pu\":\"https://wy.ppayun.cn/api/ShowVideoWy/973ed6d6891c43269706718cb0aedb72/\",\"sn\":0,\"or\":999},\"yun3edu\":{\"sh\":\"爱迪云三\",\"pu\":\"\",\"sn\":0,\"or\":999},\"guoji\":{\"sh\":\"國際路線\",\"pu\":\"\",\"sn\":0,\"or\":999},\"ddyunp\":{\"sh\":\"蓝光线路\",\"pu\":\"\",\"sn\":0,\"or\":999},\"eduyun\":{\"sh\":\"爱迪云二\",\"pu\":\"\",\"sn\":0,\"or\":999},\"dbm3u8\":{\"sh\":\"720P线路\",\"pu\":\"\",\"sn\":0,\"or\":999},\"yjm3u8\":{\"sh\":\"备用线路\",\"pu\":\"\",\"sn\":0,\"or\":999}}");
+ filterConfig = new JSONObject("{\"dianying\":[{\"key\":0,\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"dianying\"},{\"n\":\"动作片\",\"v\":\"dongzuopian\"},{\"n\":\"喜剧片\",\"v\":\"xijupian\"},{\"n\":\"爱情片\",\"v\":\"aiqingpian\"},{\"n\":\"科幻片\",\"v\":\"kehuanpian\"},{\"n\":\"恐怖片\",\"v\":\"kongbupian\"},{\"n\":\"剧情片\",\"v\":\"juqingpian\"},{\"n\":\"战争片\",\"v\":\"zhanzhengpian\"},{\"n\":\"传记\",\"v\":\"zhuanji\"}]},{\"key\":3,\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"喜剧\",\"v\":\"喜剧\"},{\"n\":\"爱情\",\"v\":\"爱情\"},{\"n\":\"恐怖\",\"v\":\"恐怖\"},{\"n\":\"动作\",\"v\":\"动作\"},{\"n\":\"科幻\",\"v\":\"科幻\"},{\"n\":\"剧情\",\"v\":\"剧情\"},{\"n\":\"战争\",\"v\":\"战争\"},{\"n\":\"警匪\",\"v\":\"警匪\"},{\"n\":\"犯罪\",\"v\":\"犯罪\"},{\"n\":\"动画\",\"v\":\"动画\"},{\"n\":\"奇幻\",\"v\":\"奇幻\"},{\"n\":\"武侠\",\"v\":\"武侠\"},{\"n\":\"冒险\",\"v\":\"冒险\"},{\"n\":\"枪战\",\"v\":\"枪战\"},{\"n\":\"恐怖\",\"v\":\"恐怖\"},{\"n\":\"悬疑\",\"v\":\"悬疑\"},{\"n\":\"惊悚\",\"v\":\"惊悚\"},{\"n\":\"经典\",\"v\":\"经典\"},{\"n\":\"青春\",\"v\":\"青春\"},{\"n\":\"文艺\",\"v\":\"文艺\"},{\"n\":\"微电影\",\"v\":\"微电影\"},{\"n\":\"古装\",\"v\":\"古装\"},{\"n\":\"历史\",\"v\":\"历史\"},{\"n\":\"运动\",\"v\":\"运动\"},{\"n\":\"农村\",\"v\":\"农村\"},{\"n\":\"儿童\",\"v\":\"儿童\"},{\"n\":\"网络电影\",\"v\":\"网络电影\"},{\"n\":\"情色\",\"v\":\"情色\"}]},{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"大陆\",\"v\":\"大陆\"},{\"n\":\"香港\",\"v\":\"香港\"},{\"n\":\"台湾\",\"v\":\"台湾\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"法国\",\"v\":\"法国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"德国\",\"v\":\"德国\"},{\"n\":\"泰国\",\"v\":\"泰国\"},{\"n\":\"印度\",\"v\":\"印度\"},{\"n\":\"意大利\",\"v\":\"意大利\"},{\"n\":\"西班牙\",\"v\":\"西班牙\"},{\"n\":\"加拿大\",\"v\":\"加拿大\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]},{\"key\":4,\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"法语\",\"v\":\"法语\"},{\"n\":\"德语\",\"v\":\"德语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"lianxuju\":[{\"key\":0,\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"lianxuju\"},{\"n\":\"国产剧\",\"v\":\"guochanju\"},{\"n\":\"港台剧\",\"v\":\"gangtaiju\"},{\"n\":\"韩剧\",\"v\":\"hanju\"},{\"n\":\"美剧\",\"v\":\"meiju\"},{\"n\":\"日剧\",\"v\":\"riju\"},{\"n\":\"英剧\",\"v\":\"yingju\"},{\"n\":\"泰剧\",\"v\":\"taiju\"}]},{\"key\":3,\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"古装\",\"v\":\"古装\"},{\"n\":\"战争\",\"v\":\"战争\"},{\"n\":\"青春偶像\",\"v\":\"青春偶像\"},{\"n\":\"喜剧\",\"v\":\"喜剧\"},{\"n\":\"家庭\",\"v\":\"家庭\"},{\"n\":\"犯罪\",\"v\":\"犯罪\"},{\"n\":\"动作\",\"v\":\"动作\"},{\"n\":\"奇幻\",\"v\":\"奇幻\"},{\"n\":\"剧情\",\"v\":\"剧情\"},{\"n\":\"历史\",\"v\":\"历史\"},{\"n\":\"经典\",\"v\":\"经典\"},{\"n\":\"乡村\",\"v\":\"乡村\"},{\"n\":\"情景\",\"v\":\"情景\"},{\"n\":\"商战\",\"v\":\"商战\"},{\"n\":\"网剧\",\"v\":\"网剧\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"内地\",\"v\":\"内地\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"香港\",\"v\":\"香港\"},{\"n\":\"台湾\",\"v\":\"台湾\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"泰国\",\"v\":\"泰国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"新加坡\",\"v\":\"新加坡\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]},{\"key\":4,\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"zongyi\":[{\"key\":0,\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"zongyi\"},{\"n\":\"内地综艺\",\"v\":\"ndzy\"},{\"n\":\"港台综艺\",\"v\":\"gtzy\"},{\"n\":\"韩国综艺节目\",\"v\":\"variety\"},{\"n\":\"欧美综艺\",\"v\":\"oumeizongyi\"}]},{\"key\":3,\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"选秀\",\"v\":\"选秀\"},{\"n\":\"情感\",\"v\":\"情感\"},{\"n\":\"访谈\",\"v\":\"访谈\"},{\"n\":\"播报\",\"v\":\"播报\"},{\"n\":\"旅游\",\"v\":\"旅游\"},{\"n\":\"音乐\",\"v\":\"音乐\"},{\"n\":\"美食\",\"v\":\"美食\"},{\"n\":\"纪实\",\"v\":\"纪实\"},{\"n\":\"曲艺\",\"v\":\"曲艺\"},{\"n\":\"生活\",\"v\":\"生活\"},{\"n\":\"游戏互动\",\"v\":\"游戏互动\"},{\"n\":\"财经\",\"v\":\"财经\"},{\"n\":\"求职\",\"v\":\"求职\"}]},{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"内地\",\"v\":\"内地\"},{\"n\":\"港台\",\"v\":\"港台\"},{\"n\":\"日韩\",\"v\":\"日韩\"},{\"n\":\"欧美\",\"v\":\"欧美\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]},{\"key\":4,\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"dongman\":[{\"key\":0,\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"dongman\"},{\"n\":\"日韩动漫\",\"v\":\"rihan\"},{\"n\":\"国产动漫\",\"v\":\"guoman\"},{\"n\":\"欧美动漫\",\"v\":\"oumei\"},{\"n\":\"动漫电影\",\"v\":\"cartoon\"}]},{\"key\":3,\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"情感\",\"v\":\"情感\"},{\"n\":\"科幻\",\"v\":\"科幻\"},{\"n\":\"热血\",\"v\":\"热血\"},{\"n\":\"推理\",\"v\":\"推理\"},{\"n\":\"搞笑\",\"v\":\"搞笑\"},{\"n\":\"冒险\",\"v\":\"冒险\"},{\"n\":\"萝莉\",\"v\":\"萝莉\"},{\"n\":\"校园\",\"v\":\"校园\"},{\"n\":\"动作\",\"v\":\"动作\"},{\"n\":\"机战\",\"v\":\"机战\"},{\"n\":\"运动\",\"v\":\"运动\"},{\"n\":\"战争\",\"v\":\"战争\"},{\"n\":\"少年\",\"v\":\"少年\"},{\"n\":\"少女\",\"v\":\"少女\"},{\"n\":\"社会\",\"v\":\"社会\"},{\"n\":\"原创\",\"v\":\"原创\"},{\"n\":\"亲子\",\"v\":\"亲子\"},{\"n\":\"益智\",\"v\":\"益智\"},{\"n\":\"励志\",\"v\":\"励志\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国产\",\"v\":\"国产\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"欧美\",\"v\":\"欧美\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]},{\"key\":4,\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"jilu\":[{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]},{\"key\":4,\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}]}");
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ /**
+ * 爬虫headers
+ *
+ * @param url
+ * @return
+ */
+ protected HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("method", "GET");
+ headers.put("Host", siteHost);
+ headers.put("Upgrade-Insecure-Requests", "1");
+ headers.put("DNT", "1");
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
+ headers.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ return headers;
+ }
+
+ /**
+ * 获取分类数据 + 首页最近更新视频列表数据
+ *
+ * @param filter 是否开启筛选 关联的是 软件设置中 首页数据源里的筛选开关
+ * @return
+ */
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ Document doc = Jsoup.parse(OkHttpUtil.string(siteUrl, getHeaders(siteUrl)));
+ // 分类节点
+ Elements elements = doc.select("ul.nav_list > li a");
+ JSONArray classes = new JSONArray();
+ for (Element ele : elements) {
+ String name = ele.select("span").text();
+ if (name.equals("樱花动漫")) {
+ name = "动漫";
+ }
+ boolean show = name.equals("电影") ||
+ name.equals("连续剧") ||
+ name.equals("动漫") ||
+ name.equals("纪录片") ||
+ name.equals("综艺");
+ if (show) {
+ Matcher mather = regexCategory.matcher(ele.attr("href"));
+ if (!mather.find())
+ continue;
+ // 把分类的id和名称取出来加到列表里
+ String id = mather.group(1).trim();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_id", id);
+ jsonObject.put("type_name", name);
+ classes.put(jsonObject);
+ }
+ }
+ JSONObject result = new JSONObject();
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ result.put("class", classes);
+ try {
+ // 取首页推荐视频列表
+ Element homeList = doc.select("div.vod_row").get(1);
+ Elements list = homeList.select("div.cbox1 > ul.vodlist li a.vodlist_thumb");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.attr("title");
+ String cover = vod.attr("data-original");
+ String remark = vod.selectFirst("span.pic_text").text();
+ Matcher matcher = regexVid.matcher(vod.attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取分类信息数据
+ *
+ * @param tid 分类id
+ * @param pg 页数
+ * @param filter 同homeContent方法中的filter
+ * @param extend 筛选参数{k:v, k1:v1}
+ * @return
+ */
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ String[] urlParams = new String[]{"", "", "", "", "", "", "", "", "", "", "", ""};
+ urlParams[0] = tid;
+ urlParams[8] = pg;
+ if (extend != null && extend.size() > 0) {
+ for (Iterator it = extend.keySet().iterator(); it.hasNext(); ) {
+ String key = it.next();
+ String value = extend.get(key);
+ urlParams[Integer.parseInt(key)] = URLEncoder.encode(value);
+ }
+ }
+ // 获取分类数据的url
+ String url = siteUrl + "/show/" + TextUtils.join("-", urlParams) + ".html";
+ String html = OkHttpUtil.string(url, getHeaders(url));
+ Document doc = Jsoup.parse(html);
+ JSONObject result = new JSONObject();
+ int pageCount = 0;
+ int page = -1;
+
+ // 取页码相关信息
+ Elements pageInfo = doc.select("ul.page li");
+ if (pageInfo.size() == 0) {
+ page = Integer.parseInt(pg);
+ pageCount = page;
+ } else {
+ for (int i = 0; i < pageInfo.size(); i++) {
+ Element li = pageInfo.get(i);
+ Element a = li.selectFirst("a");
+ if (a == null)
+ continue;
+ String name = a.text();
+ if (page == -1 && li.hasClass("active")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ page = Integer.parseInt(matcher.group(1).split("-")[8]);
+ } else {
+ page = 0;
+ }
+ }
+ if (name.equals("尾页")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ pageCount = Integer.parseInt(matcher.group(1).split("-")[8]);
+ } else {
+ pageCount = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ JSONArray videos = new JSONArray();
+ if (!html.contains("没有找到您想要的结果哦")) {
+ // 取当前分类页的视频列表
+ Elements list = doc.select("ul.vodlist li a.vodlist_thumb");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.attr("title");
+ String cover = vod.attr("data-original");
+ String remark = vod.selectFirst("span.pic_text").text();
+ Matcher matcher = regexVid.matcher(vod.attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", 60);
+ result.put("total", pageCount <= 1 ? videos.length() : pageCount * 60);
+
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 视频详情信息
+ *
+ * @param ids 视频id
+ * @return
+ */
+ @Override
+ public String detailContent(List ids) {
+ try {
+ // 视频详情url
+ String url = siteUrl + "/movie/" + ids.get(0) + ".html";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+
+ // 取基本数据
+ String cover = doc.selectFirst("div.detail_list_box a.vodlist_thumb img").attr("data-original");
+ String title = doc.selectFirst("div.detail_list_box h2.title").text();
+ String desc = Jsoup.parse(doc.selectFirst("meta[name=description]").attr("content")).text();
+ String category = "", area = "", year = "", remark = "", director = "", actor = "";
+ Elements span_text_muted = doc.select("div.detail_list_box div.content_detail span");
+ for (int i = 0; i < span_text_muted.size(); i++) {
+ Element text = span_text_muted.get(i);
+ String info = text.text();
+ if (info.equals("类型:")) {
+ category = text.nextElementSibling().text();
+ } else if (info.equals("年份:")) {
+ year = text.nextElementSibling().text();
+ } else if (info.equals("地区:")) {
+ area = text.nextElementSibling().text();
+ } else if (info.equals("状态:")) {
+ remark = text.nextElementSibling().text();
+ } else if (info.equals("导演:")) {
+ List directors = new ArrayList<>();
+ Elements aa = text.parent().select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ directors.add(aa.get(j).text());
+ }
+ director = TextUtils.join(",", directors);
+ } else if (info.equals("主演:")) {
+ List actors = new ArrayList<>();
+ Elements aa = text.parent().select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ actors.add(aa.get(j).text());
+ }
+ actor = TextUtils.join(",", actors);
+ }
+ }
+
+ vodList.put("vod_id", ids.get(0));
+ vodList.put("vod_name", title);
+ vodList.put("vod_pic", cover);
+ vodList.put("type_name", category);
+ vodList.put("vod_year", year);
+ vodList.put("vod_area", area);
+ vodList.put("vod_remarks", remark);
+ vodList.put("vod_actor", actor);
+ vodList.put("vod_director", director);
+ vodList.put("vod_content", desc);
+
+ Map vod_play = new TreeMap<>(new Comparator() {
+ @Override
+ public int compare(String o1, String o2) {
+ try {
+ int sort1 = playerConfig.getJSONObject(o1).getInt("or");
+ int sort2 = playerConfig.getJSONObject(o2).getInt("or");
+
+ if (sort1 == sort2) {
+ return 1;
+ }
+ return sort1 - sort2 > 0 ? 1 : -1;
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ return 1;
+ }
+ });
+
+ // 取播放列表数据
+ Elements sources = doc.select("div.play_source_tab > a");
+ Elements sourceList = doc.select("div.play_list_box > div.playlist_full");
+
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ String sourceName = source.attr("alt");
+ boolean found = false;
+ for (Iterator it = playerConfig.keys(); it.hasNext(); ) {
+ String flag = it.next();
+ if (playerConfig.getJSONObject(flag).getString("sh").equals(sourceName)) {
+ sourceName = flag;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+ String playList = "";
+ Elements playListA = sourceList.get(i).select("li > a");
+ List vodItems = new ArrayList<>();
+
+ for (int j = 0; j < playListA.size(); j++) {
+ Element vod = playListA.get(j);
+ Matcher matcher = regexPlay.matcher(vod.attr("href"));
+ if (!matcher.find())
+ continue;
+ String playURL = matcher.group(1) + "-" + matcher.group(2) + "-" + matcher.group(3);
+ vodItems.add(vod.text() + "$" + playURL);
+ }
+ if (vodItems.size() > 0)
+ playList = TextUtils.join("#", vodItems);
+
+ if (playList.length() == 0)
+ continue;
+
+ vod_play.put(sourceName, playList);
+ }
+
+ if (vod_play.size() > 0) {
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+ }
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取视频播放信息
+ *
+ * @param flag 播放源
+ * @param id 视频id
+ * @param vipFlags 所有可能需要vip解析的源
+ * @return
+ */
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ // 播放页 url
+ String url = siteUrl + "/play/" + id + ".html";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ Elements allScript = doc.select("script");
+ JSONObject result = new JSONObject();
+ for (int i = 0; i < allScript.size(); i++) {
+ String scContent = allScript.get(i).html().trim();
+ if (scContent.startsWith("var player_")) { // 取直链
+ int start = scContent.indexOf('{');
+ int end = scContent.lastIndexOf('}') + 1;
+ String json = scContent.substring(start, end);
+ JSONObject player = new JSONObject(json);
+ if (playerConfig.has(player.getString("from"))) {
+ JSONObject pCfg = playerConfig.getJSONObject(player.getString("from"));
+ String videoUrl = player.getString("url");
+ String playUrl = pCfg.getString("pu");
+ result.put("parse", pCfg.getInt("sn"));
+ result.put("playUrl", playUrl);
+ result.put("url", videoUrl);
+ result.put("header", "");
+ }
+ break;
+ }
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 搜索
+ *
+ * @param key
+ * @param quick 是否播放页的快捷搜索
+ * @return
+ */
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ if (quick)
+ return "";
+ String url = siteUrl + "/vsearch/-------------.html?wd=" + URLEncoder.encode(key) + "&submit=";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+
+ JSONArray videos = new JSONArray();
+ Elements list = doc.select("div.search_box li.searchlist_item a.vodlist_thumb");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.attr("title");
+ String cover = vod.attr("data-original");
+ String remark = vod.selectFirst("span.pic_text").text();
+ Matcher matcher = regexVid.matcher(vod.attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Alist.java b/app/src/main/java/com/github/catvod/spider/Alist.java
new file mode 100644
index 0000000..7b5c16c
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Alist.java
@@ -0,0 +1,261 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.utils.okhttp.OKCallBack;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import okhttp3.Call;
+
+public class Alist extends Spider {
+ private JSONObject ext;
+ private String siteName;
+ private final static JSONObject version = new JSONObject();
+
+ public String categoryContent(String tid, String pg, boolean filter, HashMap hashMap) {
+ try {
+ int index = tid.indexOf('$');
+ String name = tid.substring(0, index);
+ String path = tid.substring(index+1);
+ siteName = name;
+ try {
+ if(!version.has(name) || version.getString(name).isEmpty()){
+ String ver = "2";
+ String url = this.ext.getString(name);
+ String versionUrl = url + "/api/public/settings";
+ String json = OkHttpUtil.string(versionUrl, null);
+ String data = new JSONObject(json).optString("data");
+ if (data.startsWith("{") && new JSONObject(data).getString("version").startsWith("v3.0")) ver = "3";
+ version.put(name, ver);
+ }
+ }catch (JSONException v){
+ v.printStackTrace();
+ version.put(name, "2");
+ }
+ String url;
+ if(version.getString(name).equals("3")){
+ url = this.ext.getString(name) + "/api/fs/list";
+ }else {
+ url = this.ext.getString(name) + "/api/public/path";
+ }
+ JSONObject params = new JSONObject();
+ params.put("path", path);
+
+ JSONArray jSONArray2 = new JSONArray();
+ OkHttpUtil.postJson(OkHttpUtil.defaultClient(), url, params.toString(), new OKCallBack.OKCallBackString() {
+ @Override
+ protected void onFailure(Call call, Exception e) {
+
+ }
+
+ @Override
+ protected void onResponse(String response) {
+ try {
+ JSONObject retval = new JSONObject(response);
+ JSONArray list = retval.getJSONObject("data").getJSONArray(version.getString(siteName).equals("3")?"content":"files");
+ for (int i =0; i < list.length(); ++i){
+ JSONObject o = list.getJSONObject(i);
+ String pic = o.getString(version.getString(siteName).equals("3")?"thumb":"thumbnail");
+ if(pic.isEmpty() && (o.getInt("type")==1) ){
+ pic = "http://img1.3png.com/281e284a670865a71d91515866552b5f172b.png";
+ }
+ JSONObject jSONObject2 = new JSONObject();
+ jSONObject2.put("vod_id", tid + (tid.charAt(tid.length()-1) == '/' ? "" : "/") + o.getString("name"));
+ jSONObject2.put("vod_name", o.getString("name"));
+ jSONObject2.put("vod_pic", pic);
+ jSONObject2.put("vod_tag",o.getInt("type")==1 ? "folder" : "file" );
+
+ double sz = o.getLong("size");
+ String filesize = "";
+ if(sz > 1024*1024*1024*1024.0){
+ sz /= (1024*1024*1024*1024.0);
+ filesize = "TB";
+ }
+ else if(sz > 1024*1024*1024.0){
+ sz /= (1024*1024*1024.0);
+ filesize = "GB";
+ }else if(sz > 1024*1024.0){
+ sz /= (1024*1024.0);
+ filesize = "MB";
+ }else{
+ sz /= 1024.0;
+ filesize = "KB";
+ }
+ String remark ="";
+ if(o.getLong("size") !=0){
+ remark = String.format("%.2f%s", sz, filesize);
+ }
+
+ jSONObject2.put("vod_remarks", o.getInt("type")==1 ? remark + " 文件夹" : remark);
+ jSONArray2.put(jSONObject2);
+
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+ });
+
+ JSONObject jSONObject3 = new JSONObject();
+ jSONObject3.put("page", 1);
+ jSONObject3.put("pagecount", 1);
+ jSONObject3.put("limit", jSONArray2.length());
+ jSONObject3.put("total", jSONArray2.length());
+ jSONObject3.put("list", jSONArray2);
+ return jSONObject3.toString();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ public String detailContent(List ids) {
+ try
+ {
+
+ String tid = ids.get(0);
+ int index = tid.indexOf('$');
+ String name = tid.substring(0, index);
+ String path = tid.substring(index+1);
+ String url;
+ if(version.getString(name).equals("3")){
+ url = this.ext.getString(name) + "/api/fs/get";
+ }else {
+ url = this.ext.getString(name) + "/api/public/path";
+ }
+
+ JSONObject params = new JSONObject();
+ params.put("path", path);
+
+ JSONObject result = new JSONObject();
+ JSONArray list = new JSONArray();
+
+ OkHttpUtil.postJson(OkHttpUtil.defaultClient(), url, params.toString(), new OKCallBack.OKCallBackString() {
+ @Override
+ protected void onFailure(Call call, Exception e) {
+
+ }
+
+ @Override
+ protected void onResponse(String response) {
+ try {
+ JSONObject retval = new JSONObject(response);
+ JSONObject o;
+ JSONObject data = retval.getJSONObject("data");
+ if(data.has("files")){
+ o=data.getJSONArray("files").getJSONObject(0);
+ }else {
+ o=data;
+ }
+ String url = o.getString(o.has("raw_url")?"raw_url":"url");
+ if(url.indexOf("//") == 0){
+ url = "http:"+url;
+ }
+ JSONObject jSONObject2 = new JSONObject();
+ jSONObject2.put("vod_id", tid + "/" + o.getString("name"));
+ jSONObject2.put("vod_name", o.getString("name"));
+ jSONObject2.put("vod_pic", o.getString(o.has("thumbnail")?"thumbnail":"thumb"));
+ jSONObject2.put("vod_tag",o.getInt("type") == 1 ? "folder" : "file" );
+ jSONObject2.put("vod_play_from", siteName);
+ jSONObject2.put("vod_play_url", o.getString("name")+"$"+url);
+ list.put(jSONObject2);
+
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+ });
+
+ result.put("list", list);
+ return result.toString();
+ }
+ catch (Exception e){
+ e.printStackTrace();
+ }
+ return "";
+
+ }
+
+
+ public String homeContent(boolean z) {
+ try {
+ JSONArray classes = new JSONArray();
+ Iterator keys = this.ext.keys();
+ while (keys.hasNext()) {
+ String k = keys.next();
+ JSONObject newCls = new JSONObject();
+ newCls.put("type_id", k+"$/"); // 使用$来分割站点名称+path
+ newCls.put("type_name", k);
+ newCls.put("type_flag", "1"); // 1 列表形式的文件夹 2 缩略图 0 或者不存在 表示正常
+ classes.put(newCls);
+ }
+
+ JSONObject jSONObject4 = new JSONObject();
+ jSONObject4.put("class", classes);
+ if(z) {
+ jSONObject4.put("filters", new JSONObject("{}"));
+ }
+ return jSONObject4.toString();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ public void init(Context context, String ext){
+ Alist.super.init(context);
+ try {
+ if(ext.startsWith("http")){
+ this.ext = new JSONObject(OkHttpUtil.string(ext,null));
+ }else {
+ this.ext = new JSONObject();
+ String vec[] = ext.split("#");
+ for (int i =0; i < vec.length; ++i){
+ String arr[] = vec[i].split("\\$");
+ if(arr.length ==1){
+ this.ext.put("alist", arr[0]);
+ } else if(arr.length == 2) {
+ this.ext.put(arr[0], arr[1]);
+ }
+ }
+ }
+
+ } catch (JSONException jsonException) {
+ jsonException.printStackTrace();
+ }
+ }
+
+ public String playerContent(String str, String str2, List list) {
+ try{
+ JSONObject result = new JSONObject();
+ result.put("parse", 0);
+ result.put("playUrl", "");
+ result.put("url", str2);
+ return result.toString();
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String searchContent(String str, boolean z) {
+ try {
+ return "";
+ } catch (Exception e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/catvod/spider/Alist3.java b/app/src/main/java/com/github/catvod/spider/Alist3.java
new file mode 100644
index 0000000..96dacc4
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Alist3.java
@@ -0,0 +1,232 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.utils.okhttp.OKCallBack;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import okhttp3.Call;
+
+public class Alist3 extends Spider {
+ private JSONObject ext;
+
+ public String categoryContent(String tid, String pg, boolean filter, HashMap hashMap) {
+ try {
+ int index = tid.indexOf('$');
+ String name = tid.substring(0, index);
+ String path = tid.substring(index+1);
+
+ String url = this.ext.getString(name) + "/api/fs/list";
+ JSONObject params = new JSONObject();
+ params.put("path", path);
+
+ JSONArray jSONArray2 = new JSONArray();
+ OkHttpUtil.postJson(OkHttpUtil.defaultClient(), url, params.toString(), new OKCallBack.OKCallBackString() {
+ @Override
+ protected void onFailure(Call call, Exception e) {
+
+ }
+
+ @Override
+ protected void onResponse(String response) {
+ try {
+ JSONObject retval = new JSONObject(response);
+ JSONArray list = retval.getJSONObject("data").getJSONArray("content");
+ for (int i =0; i < list.length(); ++i){
+ JSONObject o = list.getJSONObject(i);
+ String pic = o.getString("thumb");
+ if(pic.isEmpty() && (o.getInt("type")==1) ){
+ pic = "http://img1.3png.com/281e284a670865a71d91515866552b5f172b.png";
+ }
+ JSONObject jSONObject2 = new JSONObject();
+ jSONObject2.put("vod_id", tid + (tid.charAt(tid.length()-1) == '/' ? "" : "/") + o.getString("name"));
+ jSONObject2.put("vod_name", o.getString("name"));
+ jSONObject2.put("vod_pic", pic);
+ jSONObject2.put("vod_tag",o.getInt("type")==1 ? "folder" : "file" );
+
+ double sz = o.getLong("size");
+ String filesize = "";
+ if(sz > 1024*1024*1024*1024.0){
+ sz /= (1024*1024*1024*1024.0);
+ filesize = "TB";
+ }
+ else if(sz > 1024*1024*1024.0){
+ sz /= (1024*1024*1024.0);
+ filesize = "GB";
+ }else if(sz > 1024*1024.0){
+ sz /= (1024*1024.0);
+ filesize = "MB";
+ }else{
+ sz /= 1024.0;
+ filesize = "KB";
+ }
+ String remark ="";
+ if(o.getLong("size") !=0){
+ remark = String.format("%.2f%s", sz, filesize);
+ }
+
+ jSONObject2.put("vod_remarks", o.getInt("type")==1 ? remark + " 文件夹" : remark);
+ jSONArray2.put(jSONObject2);
+
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+ });
+
+ JSONObject jSONObject3 = new JSONObject();
+ jSONObject3.put("page", 1);
+ jSONObject3.put("pagecount", 1);
+ jSONObject3.put("limit", jSONArray2.length());
+ jSONObject3.put("total", jSONArray2.length());
+ jSONObject3.put("list", jSONArray2);
+ return jSONObject3.toString();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ public String detailContent(List ids) {
+ try
+ {
+
+ String tid = ids.get(0);
+ int index = tid.indexOf('$');
+ String name = tid.substring(0, index);
+ String path = tid.substring(index+1);
+
+
+ String url = this.ext.getString(name) + "/api/fs/get";
+ JSONObject params = new JSONObject();
+ params.put("path", path);
+
+ JSONObject result = new JSONObject();
+ JSONArray list = new JSONArray();
+
+ OkHttpUtil.postJson(OkHttpUtil.defaultClient(), url, params.toString(), new OKCallBack.OKCallBackString() {
+ @Override
+ protected void onFailure(Call call, Exception e) {
+
+ }
+
+ @Override
+ protected void onResponse(String response) {
+ try {
+ JSONObject retval = new JSONObject(response);
+ JSONObject files = retval.getJSONObject("data");
+ JSONObject o = files;
+ String url = o.getString("raw_url");
+ if(url.indexOf("//") == 0){
+ url = "http:"+url;
+ }
+
+ JSONObject jSONObject2 = new JSONObject();
+ jSONObject2.put("vod_id", tid + "/" + o.getString("name"));
+ jSONObject2.put("vod_name", o.getString("name"));
+ jSONObject2.put("vod_pic", "");
+ jSONObject2.put("vod_tag",o.getInt("type") == 1 ? "folder" : "file" );
+ jSONObject2.put("vod_play_from", "播放");
+ jSONObject2.put("vod_play_url", o.getString("name")+"$"+url);
+ list.put(jSONObject2);
+
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+ });
+
+ result.put("list", list);
+ return result.toString();
+ }
+ catch (Exception e){
+ e.printStackTrace();
+ }
+ return "";
+
+ }
+
+
+ public String homeContent(boolean z) {
+ try {
+ JSONArray classes = new JSONArray();
+ Iterator keys = this.ext.keys();
+ while (keys.hasNext()) {
+ String k = keys.next();
+ String url = this.ext.getString(k);
+ JSONObject newCls = new JSONObject();
+ newCls.put("type_id", k+"$/"); // 使用$来分割站点名称+path
+ newCls.put("type_name", k);
+ newCls.put("type_flag", "1"); // 1 列表形式的文件夹 2 缩略图 0 或者不存在 表示正常
+ classes.put(newCls);
+ }
+
+ JSONArray jSONArray3 = new JSONArray();
+ JSONObject jSONObject4 = new JSONObject();
+ jSONObject4.put("class", classes);
+ if(z) {
+ jSONObject4.put("filters", new JSONObject("{}"));
+ }
+ return jSONObject4.toString();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ public void init(Context context, String ext){
+ Alist3.super.init(context);
+ try {
+ if(ext.startsWith("http")){
+ this.ext = new JSONObject(OkHttpUtil.string(ext,null));
+ }else {
+ this.ext = new JSONObject();
+ String vec[] = ext.split("#");
+ for (int i =0; i < vec.length; ++i){
+ String arr[] = vec[i].split("\\$");
+ if(arr.length ==1){
+ this.ext.put("alist", arr[0]);
+ } else if(arr.length == 2) {
+ this.ext.put(arr[0], arr[1]);
+ }
+ }
+ }
+
+ } catch (JSONException jsonException) {
+ jsonException.printStackTrace();
+ }
+ }
+
+ public String playerContent(String str, String str2, List list) {
+ try{
+ JSONObject result = new JSONObject();
+ result.put("parse", 0);
+ result.put("playUrl", "");
+ result.put("url", str2);
+ return result.toString();
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String searchContent(String str, boolean z) {
+ try {
+ return "";
+ } catch (Exception e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/catvod/spider/Anfuns.java b/app/src/main/java/com/github/catvod/spider/Anfuns.java
new file mode 100644
index 0000000..7573ee1
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Anfuns.java
@@ -0,0 +1,376 @@
+package com.github.catvod.spider;
+
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Base64;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Anfuns extends Spider {
+ private static final String siteUrl = "https://www.anfuns.cc";
+ private static final String siteHost = "www.anfuns.cc";
+ private JSONObject filterConfig;
+ private String cookie="";
+ private String referer="";
+
+
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ try {
+ filterConfig = new JSONObject("{\"1\":[{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2022\",\"v\":\"2022\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"},{\"n\":\"2003\",\"v\":\"2003\"},{\"n\":\"2002\",\"v\":\"2002\"},{\"n\":\"2001\",\"v\":\"2001\"},{\"n\":\"2000\",\"v\":\"2000\"}]},{\"key\":\"order\",\"name\":\"排序\",\"value\":[{\"n\":\"最新\",\"v\":\"time\"},{\"n\":\"最热\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"2\":[{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2022\",\"v\":\"2022\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"},{\"n\":\"2003\",\"v\":\"2003\"},{\"n\":\"2002\",\"v\":\"2002\"},{\"n\":\"2001\",\"v\":\"2001\"},{\"n\":\"2000\",\"v\":\"2000\"}]},{\"key\":\"order\",\"name\":\"排序\",\"value\":[{\"n\":\"最新\",\"v\":\"time\"},{\"n\":\"最热\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"3\":[{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2022\",\"v\":\"2022\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"},{\"n\":\"2003\",\"v\":\"2003\"},{\"n\":\"2002\",\"v\":\"2002\"},{\"n\":\"2001\",\"v\":\"2001\"},{\"n\":\"2000\",\"v\":\"2000\"}]},{\"key\":\"order\",\"name\":\"排序\",\"value\":[{\"n\":\"最新\",\"v\":\"time\"},{\"n\":\"最热\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"4\":[{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2022\",\"v\":\"2022\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"},{\"n\":\"2003\",\"v\":\"2003\"},{\"n\":\"2002\",\"v\":\"2002\"},{\"n\":\"2001\",\"v\":\"2001\"},{\"n\":\"2000\",\"v\":\"2000\"}]},{\"key\":\"order\",\"name\":\"排序\",\"value\":[{\"n\":\"最新\",\"v\":\"time\"},{\"n\":\"最热\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}]}");
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+
+
+
+ protected HashMap getHeaders(String url, String ref) {
+ HashMap headers = new HashMap<>();
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ if(ref.length()>0){
+ headers.put("Referer", ref);
+ }
+ if(cookie.length()>0){
+ headers.put("Cookie", cookie);
+ }
+ headers.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ return headers;
+ }
+
+
+ protected HashMap getHeaders2(String url,String ref) {
+ HashMap headers = new HashMap<>();
+ String ss = url.replace("https://","").split("/")[0];
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Authority", ss);
+ headers.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ if (ref.contains("ref")){
+ headers.put("Referer", ref.replace("ref:",""));
+ } else if (ref.contains("origin")){
+ headers.put("Origin", ref.replace("origin:",""));
+ }
+ return headers;
+ }
+
+
+ protected void getCookie(){
+ cookie="";
+ String cookieurl="https://www.anfuns.cc/verify/index.html";
+ Map> cookies = new HashMap<>();
+ OkHttpUtil.string(cookieurl,getHeaders(cookieurl,""),cookies);
+ for( Map.Entry> entry : cookies.entrySet() ){
+ if(entry.getKey().equals("set-cookie")){
+ cookie = TextUtils.join(";",entry.getValue());
+ break;
+ }
+ }
+ }
+
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ Document doc = Jsoup.parse(OkHttpUtil.string(siteUrl, getHeaders(siteUrl,referer)));
+ referer=siteUrl+"/";
+ JSONObject result = new JSONObject();
+ JSONArray classes = new JSONArray();
+ String catestr ="{\"新旧番剧\": \"1\",\"蓝光无修\": \"2\",\"动漫剧场\": \"3\",\"欧美动漫\": \"4\"}";
+ JSONObject catedef = new JSONObject(catestr);
+ Iterator it = catedef.keys();
+ while(it.hasNext()){
+ JSONObject jsonObject = new JSONObject();
+ String key =(String) it.next();
+ jsonObject.put("type_name", key);
+ jsonObject.put("type_id", catedef.getString(key));
+ classes.put(jsonObject);
+ }
+ result.put("class", classes);
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ try {
+ Element homeList = doc.select("ul.hl-vod-list.swiper-wrapper").get(0);
+ Elements list = homeList.select("li");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst("a").attr("title");
+ String cover = vod.selectFirst("a" ).attr("data-original");
+ String remark = vod.selectFirst(" a > div.hl-pic-text > span").text();
+ String id =vod.selectFirst("a").attr("href");
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ String url = siteUrl + "/show/"+tid+"---{year}/by/{order}/page/"+pg+".html" ;
+ if (extend != null && extend.size() > 0 ) {
+ for (Iterator it = extend.keySet().iterator(); it.hasNext(); ) {
+ String key = it.next();
+ String value = extend.get(key);
+ if (value.length() > 0) {
+ url=url.replace("{"+key+"}", value);
+ }
+ }
+ }
+ for (int i=0 ;i<2;i++) {
+ if (url.contains("{year}")) {
+ url = url.replace("{year}", "");
+ } else if (url.contains("{order}")) {
+ url = url.replace("/by/{order}", "");
+ }
+ }
+ String html = OkHttpUtil.string(url, getHeaders(url,referer));
+ referer = url;
+ Document doc = Jsoup.parse(html);
+ JSONObject result = new JSONObject();
+ JSONArray videos = new JSONArray();
+ if (!html.contains("没有找到您想要的结果哦")) {
+ Elements list = doc.select("li.hl-list-item");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst("a").attr("title");
+ String cover = vod.selectFirst("a" ).attr("data-original");
+ String remark = vod.selectFirst(" a > div.hl-pic-text > span").text();
+ String id = vod.selectFirst("a").attr("href");
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ int page =Integer.parseInt(pg);
+ result.put("page", page);
+ result.put("pagecount", videos.length()== 36 ? page + 1 : page);
+ result.put("limit", 36);
+ result.put("total",Integer.MAX_VALUE );
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public String detailContent(List ids) {
+ try {
+ String url = siteUrl + ids.get(0);
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url,referer)));
+ referer=url;
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+ String cover = doc.selectFirst("span.hl-item-thumb").attr("data-original");
+ String title = doc.selectFirst("div.hl-dc-sub").text();
+ String desc = doc.selectFirst("a.hl-data-menu").text();
+ String vid = ids.get(0);
+ vodList.put("vod_id", vid);
+ vodList.put("vod_name", title);
+ vodList.put("vod_pic", cover);
+ vodList.put("vod_content", desc);
+ Map vod_play = new LinkedHashMap<>();
+ Elements sources = doc.select("div.hl-plays-wrap > div > a");
+ Elements sourceList = doc.select("div.hl-tabs-box.hl-fadeIn");
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ String sourceName = source.attr("alt");
+ String playList = "";
+ Element playListB = sourceList.get(i);
+ Elements playListA = playListB.select("li.hl-col-xs-4");
+ List vodItems = new ArrayList<>();
+ for (int j = 0; j < playListA.size(); j++) {
+ Element vod = playListA.get(j);
+ String playURL = vod.selectFirst("a").attr("href");
+ String playUrlName = vod.selectFirst("a").text();
+ vodItems.add(playUrlName + "$" + playURL);
+ }
+ if (vodItems.size() > 0) {
+ playList = TextUtils.join("#", vodItems);
+ vod_play.put(sourceName, playList);
+ }
+ }
+ if (vod_play.size() > 0) {
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+ }
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ getCookie();
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ String url = siteUrl + id ;
+ String htmlplay = OkHttpUtil.string(url, getHeaders(url,referer));
+ Document doc = Jsoup.parse(htmlplay);
+ Elements allScript = doc.select("script");
+ JSONObject result = new JSONObject();
+ String urlreq="";
+ for (int i = 0; i < allScript.size(); i++) {
+ String scContent = allScript.get(i).toString();
+ if (scContent.contains("var player_aaaa=")) {
+ int start = scContent.indexOf("{");
+ int end = scContent.lastIndexOf("}") + 1;
+ String urltmp = scContent.substring(start, end);
+ JSONObject urltmpobj = new JSONObject(urltmp);
+ String urlraw = urltmpobj.getString("url");
+ String urlnext= urltmpobj.optString("link_next");
+ urlreq = new String(Base64.decode(urlraw.getBytes(), Base64.DEFAULT));
+ urlreq = urlreq.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
+ urlreq = URLDecoder.decode(urlreq);
+ if(urlreq.contains("yanm")){
+ urlreq = "https://api.peizq.online/play/anfuns.php?url="+urlreq+"&next=//www.anfuns.cc"+urlnext;
+ }else {
+ if(urlreq.contains("%u")){
+ start = urlreq.indexOf("%u");
+ end = urlreq.lastIndexOf("%u")+6;
+ String urlreqtmp =urlreq.substring(start,end);
+ String urlreqtmps = urlreq.substring(0,start);
+ String urlreqtmpe = urlreq.substring(end,urlreq.length());
+ urlreqtmp = urlreqtmp.replace("%","\\");
+ Pattern pattern = Pattern.compile("(\\\\u(\\w{4}))");
+ Matcher matcher = pattern.matcher(urlreqtmp);
+ while (matcher.find()) {
+ String unicodeFull = matcher.group(1);
+ String unicodeNum = matcher.group(2);
+ char singleChar = (char) Integer.parseInt(unicodeNum, 16);
+ urlreqtmp = urlreqtmp.replace(unicodeFull, singleChar + "");
+ }
+ urlreq = urlreqtmps+urlreqtmp+urlreqtmpe;
+ }
+ urlreq = urlreq+"&next=//www.anfuns.cc"+urlnext;
+ }
+ break;
+ }
+ }
+
+ if(urlreq.contains("yanm")){
+ String htmlyanm = OkHttpUtil.string(urlreq, getHeaders2(urlreq,"ref:https://www.anfuns.cc/"));
+ Document docyanm = Jsoup.parse(htmlyanm);
+ Elements allScriptyanm = docyanm.select("script");
+ String urlreqyanm="";
+ for (int i = 0; i < allScriptyanm.size(); i++) {
+ String scContent = allScriptyanm.get(i).toString();
+ if (scContent.contains("var config =")) {
+ int start = scContent.indexOf("getrandom('")+11;
+ int end = scContent.indexOf("'),") ;
+ String getrandom = scContent.substring(start,end);
+ String getrandomb64 = new String(Base64.decode(getrandom.substring(8,getrandom.length()).getBytes(), Base64.DEFAULT));
+ String urlreqyanmtmp = URLDecoder.decode(getrandomb64.substring(8,getrandomb64.length()-8));
+ Map> respHeaders = new HashMap<>();
+ OkHttpUtil.stringNoRedirect(urlreqyanmtmp, getHeaders2(urlreqyanmtmp,"origin:https://api.peizq.online"), respHeaders);
+ String redirect = OkHttpUtil.getRedirectLocation(respHeaders);
+ String m3u8raw = OkHttpUtil.string(redirect, getHeaders2(redirect,"origin:https://api.peizq.online"));
+ start = m3u8raw.indexOf("/hls/");
+ String m3ubrawf1tmp =m3u8raw.substring(start,start+200);
+ end = m3ubrawf1tmp.indexOf("#EXTINF");
+ String m3ubrawf1req="https://fata.peizq.online"+m3ubrawf1tmp.substring(0,end);
+ OkHttpUtil.stringNoRedirect(m3ubrawf1req, getHeaders2(m3ubrawf1req,"origin:https://api.peizq.online"), respHeaders);
+ String m3ubrawf1 = OkHttpUtil.getRedirectLocation(respHeaders);
+ m3u8raw = m3u8raw.replace(m3u8raw.substring(start,start+end),m3ubrawf1);
+ String realm3u8b64=Base64.encodeToString(m3u8raw.getBytes(), 2);
+ result.put("url", "data:application/vnd.apple.mpegurl;base64,"+realm3u8b64);
+ result.put("header", new JSONObject(getHeaders2(m3ubrawf1,"origin:https://api.peizq.online")).toString());
+ break;
+ }
+ }
+ }else {
+ Map> respHeaders = new HashMap<>();
+ OkHttpUtil.stringNoRedirect(urlreq, getHeaders2(urlreq,""), respHeaders);
+ String redirect = OkHttpUtil.getRedirectLocation(respHeaders);
+ result.put("url", redirect);
+ result.put("header", getHeaders2(redirect,"").toString());
+ }
+ result.put("parse", 0);
+ result.put("playUrl", "");
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ String url = "https://www.anfuns.cc/search.html?wd="+URLEncoder.encode(key)+"&submit=";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url,getHeaders(url,referer)));
+ referer=url;
+ JSONObject result = new JSONObject();
+ JSONArray videos = new JSONArray();
+ Elements sourceList = doc.select("ul.hl-one-list");
+ if(sourceList.size()>0){
+ for (int i = 0; i < sourceList.size(); i++) {
+ Element sources = sourceList.get(i);
+ JSONObject v = new JSONObject();
+ String cover = sources.selectFirst("a").attr("data-original");
+ String title = sources.selectFirst("a").attr("title");
+ String id =sources.selectFirst("a").attr("href");
+ String remarks =sources.selectFirst("span.hl-lc-1.remarks ").text();
+ v.put("vod_name", title);
+ v.put("vod_remarks", remarks);
+ v.put("vod_id", id);
+ v.put("vod_pic", cover);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ return result.toString();
+ }
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Anime1.java b/app/src/main/java/com/github/catvod/spider/Anime1.java
new file mode 100644
index 0000000..034c3d5
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Anime1.java
@@ -0,0 +1,460 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.okhttp.OKCallBack;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+import okhttp3.Call;
+import okhttp3.Response;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.Calendar;
+import java.net.URLDecoder;
+
+
+
+
+public class Anime1 extends Spider {
+
+ private String cookies = "";
+ private String authority = "";
+ private JSONArray srcArray = new JSONArray();
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ }
+
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ long a = System.currentTimeMillis();
+ String srcurl = "https://d1zquzjgwo9yb.cloudfront.net/?_=" + a;
+ String srcOrignstr = OkHttpUtil.string(srcurl, getHeaders3(srcurl));
+ JSONArray srcOrign = new JSONArray(srcOrignstr);
+ int srclen = srcOrign.length();
+ for (int i = 0; i < srclen; i++){
+ JSONObject subobj= new JSONObject();
+ subobj.put("link", srcOrign.getJSONArray(i).get(0).toString());
+ subobj.put("name", srcOrign.getJSONArray(i).get(1).toString());
+ subobj.put("hit" , srcOrign.getJSONArray(i).get(2).toString());
+ subobj.put("year", srcOrign.getJSONArray(i).get(3).toString());
+ subobj.put("season", srcOrign.getJSONArray(i).get(4).toString());
+ subobj.put("team", srcOrign.getJSONArray(i).get(5).toString());
+ srcArray.put(subobj);
+ }
+ JSONObject result = new JSONObject();
+ JSONArray classes = new JSONArray();
+ Calendar cal = Calendar.getInstance();
+ int doy = cal.get(Calendar.YEAR) + 1;
+ for (int i = 0; i < 8; i++) {
+ JSONObject cateobj = new JSONObject();
+ String istr = Integer.toString(i);
+ if (i == 0) {
+ cateobj.put("type_name", "最近更新");
+ cateobj.put("type_id", istr);
+ } else if (i < 7) {
+ doy = doy - 1;
+ String year = Integer.toString(doy);
+ cateobj.put("type_name", year);
+ cateobj.put("type_id", istr);
+ } else {
+ cateobj.put("type_name", "更早");
+ cateobj.put("type_id", istr);
+ }
+ classes.put(cateobj);
+ }
+ result.put("class", classes);
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < 10; i++) {
+ JSONObject v = new JSONObject();
+ String id = srcArray.getJSONObject(i).getString("link");
+ String name = srcArray.getJSONObject(i).getString("name");
+ String mark = srcArray.getJSONObject(i).getString("hit");
+ v.put("vod_id", id);
+ v.put("vod_name", name);
+ v.put("vod_pic","https://sta.anicdn.com/playerImg/8.jpg");
+ v.put("vod_remarks", mark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ return result.toString();
+ } catch (
+ Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ JSONArray srccate = new JSONArray();
+ int cateId = Integer.parseInt( tid );
+ int srclen = srcArray.length();
+ Calendar cal = Calendar.getInstance();
+ int doy = cal.get(Calendar.YEAR) + 1;
+ if( cateId==0 ){
+ for (int i = 0; i < 100; i++) {
+ JSONObject subobj = srcArray.getJSONObject(i);
+ srccate.put(subobj);
+ }
+ } else if( cateId > 0 && cateId < 7 ){
+ int yearchk = doy - cateId;
+ for (int i = 0; i < srclen; i++) {
+ JSONObject subobj = srcArray.getJSONObject(i);
+ String yystr = subobj.getString("year");
+ if(yystr.contains("/")){
+ yystr=yystr.substring(5);
+ }
+ int yy = Integer.parseInt( yystr );
+ if( yy==yearchk ){
+ srccate.put(subobj);
+ }
+ }
+ } else {
+ int yy = doy - 6 ;
+ for (int i = 0; i < srclen; i++) {
+ JSONObject subobj = srcArray.getJSONObject(i);
+ String yearchk = subobj.getString("year");
+ if(yearchk.contains("/")){
+ yearchk=yearchk.substring(5);
+ }
+ int yearint = Integer.parseInt( yearchk );
+ if(yearint < yy){
+ srccate.put(subobj);
+ }
+ }
+ }
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < srccate.length() ; i++) {
+ JSONObject v = new JSONObject();
+ String id = srccate.getJSONObject(i).getString("link");
+ String name = srccate.getJSONObject(i).getString("name");
+ String mark = srccate.getJSONObject(i).getString("hit");
+ v.put("vod_id", id);
+ v.put("vod_name", name);
+ v.put("vod_pic", "https://sta.anicdn.com/playerImg/8.jpg");
+ v.put("vod_remarks", mark);
+ videos.put(v);
+ }
+ pg ="1";
+ JSONObject result = new JSONObject();
+ int limit = 20;
+ int page = Integer.parseInt(pg);
+ result.put("page", page);
+ int pageCount = videos.length() == limit ? page + 1 : page;
+ result.put("pagecount", pageCount);
+ result.put("limit", limit);
+ result.put("total", Integer.MAX_VALUE);
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public String detailContent(List ids) {
+ try {
+ String id = ids.get(0);
+ JSONObject dtinfo = new JSONObject();
+ for (int i = 0 ; i < srcArray.length() ; i++) {
+ JSONObject dtobj = srcArray.getJSONObject(i);
+ String objid = dtobj.getString("link");
+ if( objid.equals(id) ){
+ dtinfo = dtobj ;
+ }
+ }
+ String title = dtinfo.getString("name");
+ String mark = dtinfo.getString("hit");
+ String year = dtinfo.getString("year");
+ String season = dtinfo.getString("season");
+ String team = dtinfo.getString("team");
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+ vodList.put("vod_id", ids.get(0));
+ vodList.put("vod_name", title);
+ vodList.put("vod_pic", "https://sta.anicdn.com/playerImg/8.jpg");
+ vodList.put("vod_year", year);
+ vodList.put("type_name", season);
+ vodList.put("vod_area","日本" );
+ vodList.put("vod_actor", team);
+ vodList.put("vod_content", mark);
+
+ /**
+ * 播放源配置
+ */
+ String url = "https://anime1.me/?cat=" + id;
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders2(url)));
+ String nextPage = "";
+ Map vod_play_Order = new TreeMap<>();
+ do {
+ Element nextPageEle = doc.selectFirst("div.nav-previous a");
+ if( nextPageEle!=null ) {
+ nextPage = nextPageEle.attr("href");
+ }else{
+ nextPage ="";
+ }
+ Elements sources = doc.select("article");
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ Element sno =source.selectFirst("h2 > a");
+ String sourceNameori ="";
+ if( sno!=null ) {
+ sourceNameori = sno.text().trim();
+ }else {
+ Element sno2 =source.selectFirst("h2");
+ if (sno2 != null) {
+ sourceNameori = sno2.text().trim();
+ } else {
+ sourceNameori = "[No Title]";
+ }
+ }
+ int st = sourceNameori.indexOf("[") + 1;
+ int ed = sourceNameori.indexOf("]");
+ String sourceName = sourceNameori.substring(st, ed);
+ Elements playListA = source.select("div.vjscontainer video");
+ for (int j = 0; j < playListA.size(); j++) {
+ Element vod = playListA.get(j);
+ String playURL = vod.attr("data-apireq");
+ if (playURL.isEmpty()) {
+ continue;
+ }
+ if (playListA.size() > 1) {
+ if (j < 9) {
+ int jj = j + 1;
+ String nn = sourceName + "0" + Integer.toString(jj);
+ vod_play_Order.put(nn, playURL);
+ } else {
+ int jj = j + 1;
+ String nn = sourceName + Integer.toString(jj);
+ vod_play_Order.put(nn, playURL);
+ }
+ continue;
+ }
+ String regex=".*[a-zA-Z\\u4e00-\\u9fa5]+.*";
+ Matcher m=Pattern.compile(regex).matcher(sourceName);
+ if ( m.matches() == true ){
+ vod_play_Order.put(sourceName, playURL);
+ } else {
+ float count = Float.parseFloat(sourceName);
+ if(count < 100.0 ){
+ String nnn = "0" + sourceName;
+ vod_play_Order.put(nnn, playURL);
+ }else {
+ vod_play_Order.put(sourceName, playURL);
+ }
+ }
+ }
+ }
+ if(nextPage != ""){
+ doc = Jsoup.parse(OkHttpUtil.string(nextPage, getHeaders2(nextPage)));
+ }
+ }while(nextPage != "");
+ String playList = "";
+ List vodItems = new ArrayList<>();
+ Set> entrySet = vod_play_Order.entrySet();
+ for(Map.Entry entry : entrySet){
+ String key = entry.getKey();
+ String value = entry.getValue();
+ String pl = key + "$" + value;
+ vodItems.add(pl);
+ }
+ if (vodItems.size() > 0)
+ playList = TextUtils.join("#", vodItems);
+
+ if (playList.length() == 0)
+ playList = "nothing here";
+ Map vod_play = new TreeMap<>();
+ vod_play.put("Anime1", playList);
+ if (vod_play.size() > 0) {
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+ }
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ cookies = "";
+ authority = "";
+ String vlink = id ;
+ String url = "https://v.anime1.me/api";
+ JSONObject result = new JSONObject();
+ String apireq = vlink;
+ String jsonreq = URLDecoder.decode(apireq,"UTF-8");
+ HashMap reqpayload = new HashMap<>();
+ reqpayload.put("d", jsonreq);
+ OkHttpUtil.post(OkHttpUtil.defaultClient(), url, reqpayload, getHeaders2(url), new OKCallBack.OKCallBackString() {
+ @Override
+ public String onParseResponse(Call call, Response response) {
+ try {
+ Map> respHeader = new HashMap<>();
+ respHeader.clear();
+ respHeader.putAll(response.headers().toMultimap());
+ for (int i = 0; i < 3; i++) {
+ cookies = cookies + respHeader.get("set-cookie").get(i).split(";")[0];
+ if ( i < 2 ) {cookies = cookies + ";";}
+ }
+ return response.body().string();
+ } catch (IOException e) {
+ return "";
+ }
+ }
+
+ @Override
+ public void onFailure(Call call, Exception e) {
+ }
+
+ @Override
+ public void onResponse(String respbody) {
+ try {
+ JSONObject obj = new JSONObject(respbody);
+ JSONArray objarray = obj.getJSONArray("s");
+ JSONObject obj2 = objarray.getJSONObject(0);
+ String videolink = obj2.getString("src");
+ authority = videolink.split("/")[2];
+ videolink = "https:" + videolink;
+ result.put("url", videolink);
+ } catch (JSONException unused) {
+ }
+ }
+ });
+ result.put("header", new JSONObject(getHeaders1(url)).toString());
+ result.put("parse", 0);
+ result.put("playUrl", "");
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ private HashMap getHeaders3(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("Authority", "d1zquzjgwo9yb.cloudfront.net");
+ headers.put("Accept","application/json, text/javascript, */*; q=0.01");
+ headers.put("Accept-Encoding","gzip, deflate, br");
+ headers.put("Accept-Language","zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7,ja;q=0.6");
+ headers.put("Origin","https://anime1.me");
+ headers.put("Referer","https://anime1.me/");
+ headers.put("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.134 YaBrowser/22.7.1.755 (beta) Yowser/2.5 Safari/537.36");
+ headers.put("Sec-Fetch-Dest","empty");
+ headers.put("Sec-Fetch-Mode","cors");
+ headers.put("Sec-Fetch-Site","cross-site");
+ headers.put("sec-ch-ua-mobile","?0");
+ headers.put("sec-ch-ua-platform","\"Windows\"");
+ headers.put("sec-ch-ua"," \" Not A;Brand\";v=\"99\", \"Chromium\";v=\"102\" ");
+ return headers;
+ }
+
+ private HashMap getHeaders2(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("Authority", "v.anime1.me");
+ headers.put("Accept","*/*");
+ headers.put("Accept-Language","en,zh-TW;q=0.9,zh;q=0.8");
+ headers.put("Origin","https://anime1.me");
+ headers.put("Referer","https://anime1.me/");
+ headers.put("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.134 YaBrowser/22.7.1.755 (beta) Yowser/2.5 Safari/537.36");
+ headers.put("Sec-Fetch-Dest","empty");
+ headers.put("Sec-Fetch-Mode","cors");
+ headers.put("Sec-Fetch-Site","same-site");
+ headers.put("sec-ch-ua-mobile","?0");
+ headers.put("sec-ch-ua-platform","\"Windows\"");
+ headers.put("sec-ch-ua"," \" Not A;Brand\";v=\"99\", \"Chromium\";v=\"102\" ");
+ return headers;
+ }
+
+ private HashMap getHeaders1(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("Accept","*/*");
+ headers.put("Accept-encoding", "identity;q=1, *;q=0");
+ headers.put("Accept-language", "en,zh-TW;q=0.9,zh;q=0.8");
+ headers.put("Referer", "https://anime1.me");
+ headers.put("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.134 YaBrowser/22.7.1.755 (beta) Yowser/2.5 Safari/537.36");
+ headers.put("Sec-Fetch-Dest","video");
+ headers.put("Sec-Fetch-Mode","no-cors");
+ headers.put("Sec-Fetch-Site","same-site");
+ headers.put("sec-ch-ua-mobile","?0");
+ headers.put("sec-ch-ua-platform","\"Windows\"");
+ headers.put("sec-ch-ua"," \" Not A;Brand\";v=\"99\", \"Chromium\";v=\"102\" ");
+ headers.put("Authority", authority);
+ headers.put("cookie", cookies);
+ return headers;
+ }
+
+ /**
+ * 搜索
+ *
+ * @param key
+ * @param quick 是否播放页的快捷搜索
+ * @return
+ */
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ JSONArray searchResult = new JSONArray();
+ for (int i = 0; i < srcArray.length() ; i++) {
+ JSONObject srobj = srcArray.getJSONObject(i);
+ String kw = srobj.getString("name");
+ if(kw.contains(key)) {
+ searchResult.put(srobj);
+ }
+ }
+ JSONObject result = new JSONObject();
+ JSONArray videos = new JSONArray();
+ if (searchResult.length() > 0) {
+ int ch = searchResult.length() < 10 ? searchResult.length() : 10 ;
+ for (int i = 0; i < ch ; i++) {
+ String id = searchResult.getJSONObject(i).getString("link");
+ String name = searchResult.getJSONObject(i).getString("name");
+ String mark = searchResult.getJSONObject(i).getString("hit");
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", name);
+ v.put("vod_pic", "https://sta.anicdn.com/playerImg/8.jpg");
+ v.put("vod_remarks", mark);
+ videos.put(v);
+ }
+ }
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+}
diff --git a/app/src/main/java/com/github/catvod/spider/AppTT.java b/app/src/main/java/com/github/catvod/spider/AppTT.java
new file mode 100644
index 0000000..364e2ab
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/AppTT.java
@@ -0,0 +1,332 @@
+package com.github.catvod.spider;
+
+import static com.github.catvod.utils.Misc.CharsetUTF8;
+
+import android.content.Context;
+import android.os.Build;
+import android.text.TextUtils;
+import android.util.Base64;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.Misc;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Set;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+
+/**
+ * Author: @SDL
+ */
+public class AppTT extends Spider {
+ private static final String KEY = "SRK#e%4UYtU#KiEo*vsPqpr0cC4bxAQW";
+ private static final String IV = "o6sYmm*x5hn#rcCt";
+ private static final String siteUrl = "http://110.42.1.95:7788";
+
+ private String uAgent = "Dalvik/2.1.0 (Linux; U; Android " + Build.VERSION.RELEASE + "; " + Build.MODEL + " Build/" + Build.ID + ")";
+
+ private HashMap getHeaders(String url) {
+ HashMap hashMap = new HashMap();
+ hashMap.put("User-Agent", getUA(url));
+ return hashMap;
+ }
+
+ private String getUA(String str) {
+ if (!(str.contains("api.php/app") || str.contains("xgapp"))) {
+ if (!str.contains("freekan")) {
+ if (!(str.contains("zsb") || str.contains("fkxs") || str.contains("xays") || str.contains("xcys") || str.contains("szys") || str.contains("dxys") || str.contains("ytys"))) {
+ if (!str.contains("qnys")) {
+ return str.contains(".vod") ? "okhttp/4.1.0" : "Dalvik/2.1.0";
+ }
+ }
+ return "Dart/2.15 (dart:io)";
+ }
+ }
+ return "Dart/2.14 (dart:io)";
+ }
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ }
+
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+
+ JSONArray classes = new JSONArray();
+ JSONObject jSONObject1 = new JSONObject();
+ jSONObject1.put("type_id", 1);
+ jSONObject1.put("type_name", "电影");
+ classes.put(jSONObject1);
+
+ JSONObject jSONObject2 = new JSONObject();
+ jSONObject2.put("type_id", 2);
+ jSONObject2.put("type_name", "连续剧");
+ classes.put(jSONObject2);
+
+ JSONObject jSONObject3 = new JSONObject();
+ jSONObject3.put("type_id", 3);
+ jSONObject3.put("type_name", "动漫");
+ classes.put(jSONObject3);
+
+ JSONObject jSONObject4 = new JSONObject();
+ jSONObject4.put("type_id", 4);
+ jSONObject4.put("type_name", "综艺");
+ classes.put(jSONObject4);
+
+ JSONObject result = new JSONObject();
+ result.put("class", classes);
+
+ return result.toString();
+ } catch (Throwable th) {
+
+ }
+ return "";
+ }
+
+ @Override
+ public String homeVideoContent() {
+ try {
+ JSONArray videos = new JSONArray();
+ try {
+ String url = siteUrl + "/api.php/v1.vod/curnavitemlist?type_id=0";
+
+ String content = OkHttpUtil.string(url, getHeaders(url));
+ JSONObject jsonObject = new JSONObject(decryptResponse(content));
+ JSONArray jsonArray = jsonObject.getJSONObject("data").getJSONArray("swiperList");
+ for (int i = 0; i < jsonArray.length(); i++) {
+ JSONObject blockObj = jsonArray.getJSONObject(i);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", blockObj.getString("vod_id"));
+ v.put("vod_name", blockObj.getString("vod_name"));
+ v.put("vod_pic", blockObj.getString("vod_pic"));
+ v.put("vod_remarks", blockObj.getString("vod_remarks"));
+ videos.put(v);
+ }
+ } catch (Exception e) {
+ }
+ JSONObject result = new JSONObject();
+ result.put("list", videos);
+ return result.toString();
+ } catch (Throwable th) {
+
+ }
+ return "";
+ }
+
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ String url = siteUrl + "/api.php/v1.vod?type=" + tid + "&page=" + pg + "&pagesize=20";
+// Set keys = extend.keySet();
+// for (String key : keys) {
+// String val = extend.get(key).trim();
+// if (val.length() == 0)
+// continue;
+// url += "&" + key + "=" + URLEncoder.encode(val);
+// }
+ String content = OkHttpUtil.string(url, getHeaders(url));
+ JSONObject dataObject = new JSONObject(decryptResponse(content)).getJSONObject("data");
+ JSONArray jsonArray = dataObject.getJSONArray("list");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < jsonArray.length(); i++) {
+ JSONObject vObj = jsonArray.getJSONObject(i);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", vObj.getString("vod_id"));
+ v.put("vod_name", vObj.getString("vod_name"));
+ v.put("vod_pic", vObj.getString("vod_pic"));
+ v.put("vod_remarks", vObj.getString("vod_remarks"));
+ videos.put(v);
+ }
+ JSONObject result = new JSONObject();
+ int limit = 20;
+ int page = dataObject.getInt("page");
+ int total = dataObject.getInt("total");
+ int pageCount = videos.length();
+ result.put("page", page);
+ result.put("pagecount", total / 20);
+ result.put("limit", limit);
+ result.put("total", total);
+ result.put("list", videos);
+ return result.toString();
+ } catch (Throwable th) {
+
+ }
+ return "";
+ }
+
+ @Override
+ public String detailContent(List ids) {
+ try {
+ String url = siteUrl + "/api.php/v1.vod/detilldata?vod_id=" + ids.get(0);
+ String content = OkHttpUtil.string(url, getHeaders(url));
+ JSONObject dataObject = new JSONObject(decryptResponse(content));
+ JSONObject vObj = dataObject.getJSONObject("data");
+ JSONObject result = new JSONObject();
+ JSONArray list = new JSONArray();
+
+ JSONObject videoInfo = vObj.getJSONObject("videoInfo");
+
+ JSONObject vodAtom = new JSONObject();
+ String title = videoInfo.getString("vod_name");
+ vodAtom.put("vod_id", videoInfo.getString("vod_id"));
+ vodAtom.put("vod_name", videoInfo.getString("vod_name"));
+ vodAtom.put("vod_pic", videoInfo.getString("vod_pic"));
+ // vodAtom.put("type_name", videoInfo.getString("subCategory"));
+ vodAtom.put("vod_year", videoInfo.getString("vod_year"));
+ vodAtom.put("vod_area", videoInfo.getString("vod_area"));
+ vodAtom.put("vod_remarks", videoInfo.getString("vod_remarks"));
+ vodAtom.put("vod_actor", videoInfo.getString("vod_actor"));
+ vodAtom.put("vod_director", videoInfo.getString("vod_director"));
+ vodAtom.put("vod_content", videoInfo.getString("vod_content").trim());
+
+
+ JSONArray episodes = vObj.getJSONArray("source");
+ LinkedHashMap> playlist = new LinkedHashMap<>();
+ String show = null;
+ String parse = null;
+ for (int i = 0; i < episodes.length(); i++) {
+ JSONArray playurls = episodes.getJSONObject(i).getJSONArray("list");
+
+ show = episodes.getJSONObject(i).getJSONObject("player_info").getString("show");
+ parse = episodes.getJSONObject(i).getJSONObject("player_info").getString("parse");
+ ArrayList urls = playlist.get(show);
+ if (urls == null) {
+ urls = new ArrayList<>();
+ playlist.put(show, urls);
+ }
+
+ for (int j = 0; j < playurls.length(); j++) {
+ if (playurls.get(j).toString().contains(".m3u8") || playurls.get(j).toString().contains(".mp4")) {
+ urls.add(playurls.get(j).toString());
+ } else {
+ String name = playurls.get(j).toString().split("\\$")[0];
+ String pid = playurls.get(j).toString().split("\\$")[1];
+
+ urls.add(name + "$" + parse + pid);
+ }
+
+
+ }
+ }
+
+
+ String vod_play_from = TextUtils.join("$$$", playlist.keySet());
+ StringBuilder sb = new StringBuilder();
+ Iterator> iter = playlist.values().iterator();
+ short fromSize = (short) playlist.size();
+ while (iter.hasNext()) {
+ fromSize--;
+ ArrayList urls = iter.next();
+ sb.append(TextUtils.join("#", urls));
+ if (fromSize > 0)
+ sb.append("$$$");
+ }
+ vodAtom.put("vod_play_from", vod_play_from);
+ vodAtom.put("vod_play_url", sb.toString());
+ list.put(vodAtom);
+ result.put("list", list);
+ return result.toString();
+ } catch (Throwable th) {
+
+ }
+ return "";
+ }
+
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ String jxurl = null;
+ if (id.contains(".m3u8") || id.toString().contains(".mp4")) {
+ jxurl = id;
+ } else {
+ String url = id + "&sc=1&token=" + getToken();
+ String content = OkHttpUtil.string(url, getHeaders(url));
+ String decryptcontent = decrypt(content, "UTF-8", KEY, IV);
+ jxurl = new JSONObject(decryptcontent).getString("url");
+ }
+
+
+ JSONObject result = new JSONObject();
+ result.put("parse", 0);
+ result.put("playUrl", "");
+ result.put("url", jxurl);
+ return result.toString();
+ } catch (Throwable th) {
+
+ }
+ return "";
+ }
+
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ String url = siteUrl + "/api.php/v1.vod?wd=" + URLEncoder.encode(key);
+ String content = OkHttpUtil.string(url, getHeaders(url));
+ JSONObject dataObject = new JSONObject(decryptResponse(content));
+ JSONArray jsonArray = dataObject.getJSONObject("data").getJSONArray("list");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < jsonArray.length(); i++) {
+ JSONObject vObj = jsonArray.getJSONObject(i);
+ JSONObject v = new JSONObject();
+
+ v.put("vod_id", vObj.getString("vod_id"));
+ v.put("vod_name", vObj.getString("vod_name"));
+ v.put("vod_pic", vObj.getString("vod_pic"));
+ v.put("vod_remarks", vObj.getString("vod_remarks"));
+ videos.put(v);
+ }
+ JSONObject result = new JSONObject();
+ result.put("list", videos);
+ return result.toString();
+ } catch (Throwable th) {
+
+ }
+ return "";
+ }
+
+ protected String decryptResponse(String src) {
+ return src;
+ }
+
+ public String decrypt(String str, String str2, String str3, String str4) {
+ try {
+ SecretKeySpec secretKeySpec = new SecretKeySpec(str3.getBytes("UTF-8"), "AES");
+ Cipher instance = Cipher.getInstance("AES/CTR/PKCS5Padding");
+ instance.init(2, secretKeySpec, new IvParameterSpec(str4.getBytes()));
+ return new String(instance.doFinal(Base64.decode(str, 0)), str2);
+ } catch (Exception unused) {
+ return null;
+ }
+ }
+
+ public String encrypt(String str, String str2, String str3, String str4) {
+ try {
+ Cipher instance = Cipher.getInstance("AES/CTR/PKCS5Padding");
+ instance.init(1, new SecretKeySpec(str3.getBytes(), "AES"), new IvParameterSpec(str4.getBytes()));
+ return Base64.encodeToString(instance.doFinal(str.getBytes(str2)), 0);
+ } catch (Exception unused) {
+ return null;
+ }
+ }
+
+ public String getToken() {
+ return encrypt(Long.valueOf(new Date().getTime()).toString(), "UTF-8", KEY, IV);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/catvod/spider/Bdys01.java b/app/src/main/java/com/github/catvod/spider/Bdys01.java
new file mode 100644
index 0000000..e9763ef
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Bdys01.java
@@ -0,0 +1,559 @@
+package com.github.catvod.spider;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.os.Build;
+import android.text.TextUtils;
+import android.util.Base64;
+
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.Misc;
+import com.github.catvod.utils.gZip;
+import com.github.catvod.utils.okhttp.OKCallBack;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.TreeMap;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+import okhttp3.Call;
+import okhttp3.Response;
+
+
+
+
+public class Bdys01 extends Spider {
+ private static final String siteUrl = "https://www.bdys01.com";
+ private static final String siteHost = "www.bdys01.com";
+ private String cookie="";
+ private String referer="";
+
+ /**
+ * 筛选配置
+ */
+ private JSONObject filterConfig;
+
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ try {
+ filterConfig = new JSONObject("{\"0\":[{\"key\":\"s\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"all\"},{\"n\":\"动作\",\"v\":\"dongzuo\"},{\"n\":\"爱情\",\"v\":\"aiqing\"},{\"n\":\"喜剧\",\"v\":\"xiju\"},{\"n\":\"科幻\",\"v\":\"kehuan\"},{\"n\":\"恐怖\",\"v\":\"kongbu\"},{\"n\":\"战争\",\"v\":\"zhanzheng\"},{\"n\":\"武侠\",\"v\":\"wuxia\"},{\"n\":\"魔幻\",\"v\":\"mohuan\"},{\"n\":\"剧情\",\"v\":\"juqing\"},{\"n\":\"动画\",\"v\":\"donghua\"},{\"n\":\"惊悚\",\"v\":\"jingsong\"},{\"n\":\"3D\",\"v\":\"3D\"},{\"n\":\"灾难\",\"v\":\"zainan\"},{\"n\":\"悬疑\",\"v\":\"xuanyi\"},{\"n\":\"警匪\",\"v\":\"jingfei\"},{\"n\":\"文艺\",\"v\":\"wenyi\"},{\"n\":\"青春\",\"v\":\"qingchun\"},{\"n\":\"冒险\",\"v\":\"maoxian\"},{\"n\":\"犯罪\",\"v\":\"fanzui\"},{\"n\":\"纪录\",\"v\":\"jilu\"},{\"n\":\"古装\",\"v\":\"guzhuang\"},{\"n\":\"奇幻\",\"v\":\"qihuan\"},{\"n\":\"国语\",\"v\":\"guoyu\"},{\"n\":\"综艺\",\"v\":\"zongyi\"},{\"n\":\"历史\",\"v\":\"lishi\"},{\"n\":\"运动\",\"v\":\"yundong\"},{\"n\":\"原创压制\",\"v\":\"yuanchuang\"},{\"n\":\"美剧\",\"v\":\"meiju\"},{\"n\":\"韩剧\",\"v\":\"hanju\"},{\"n\":\"国产电视剧\",\"v\":\"guoju\"},{\"n\":\"日剧\",\"v\":\"riju\"},{\"n\":\"英剧\",\"v\":\"yingju\"},{\"n\":\"德剧\",\"v\":\"deju\"},{\"n\":\"俄剧\",\"v\":\"eju\"},{\"n\":\"巴剧\",\"v\":\"baju\"},{\"n\":\"加剧\",\"v\":\"jiaju\"},{\"n\":\"西剧\",\"v\":\"anish\"},{\"n\":\"意大利剧\",\"v\":\"yidaliju\"},{\"n\":\"泰剧\",\"v\":\"taiju\"},{\"n\":\"港台剧\",\"v\":\"gangtaiju\"},{\"n\":\"法剧\",\"v\":\"faju\"},{\"n\":\"澳剧\",\"v\":\"aoju\"}]},{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"不限\",\"v\":\"\"},{\"n\":\"中国大陆\",\"v\":\"中国大陆\"},{\"n\":\"中国香港\",\"v\":\"中国香港\"},{\"n\":\"中国台湾\",\"v\":\"中国台湾\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"法国\",\"v\":\"法国\"},{\"n\":\"印度\",\"v\":\"印度\"},{\"n\":\"德国\",\"v\":\"德国\"},{\"n\":\"西班牙\",\"v\":\"西班牙\"},{\"n\":\"意大利\",\"v\":\"意大利\"},{\"n\":\"澳大利亚\",\"v\":\"澳大利亚\"},{\"n\":\"比利时\",\"v\":\"比利时\"},{\"n\":\"瑞典\",\"v\":\"瑞典\"},{\"n\":\"荷兰\",\"v\":\"荷兰\"},{\"n\":\"丹麦\",\"v\":\"丹麦\"},{\"n\":\"加拿大\",\"v\":\"加拿大\"},{\"n\":\"俄罗斯\",\"v\":\"俄罗斯\"}]},{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2022\",\"v\":\"2022\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"},{\"n\":\"2003\",\"v\":\"2003\"},{\"n\":\"2002\",\"v\":\"2002\"},{\"n\":\"2001\",\"v\":\"2001\"},{\"n\":\"2000\",\"v\":\"2000\"}]},{\"key\":\"order\",\"name\":\"排序\",\"value\":[{\"n\":\"更新时间\",\"v\":\"0\"},{\"n\":\"豆瓣评分\",\"v\":\"1\"}]}],\"1\":[{\"key\":\"s\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"all\"},{\"n\":\"动作\",\"v\":\"dongzuo\"},{\"n\":\"爱情\",\"v\":\"aiqing\"},{\"n\":\"喜剧\",\"v\":\"xiju\"},{\"n\":\"科幻\",\"v\":\"kehuan\"},{\"n\":\"恐怖\",\"v\":\"kongbu\"},{\"n\":\"战争\",\"v\":\"zhanzheng\"},{\"n\":\"武侠\",\"v\":\"wuxia\"},{\"n\":\"魔幻\",\"v\":\"mohuan\"},{\"n\":\"剧情\",\"v\":\"juqing\"},{\"n\":\"动画\",\"v\":\"donghua\"},{\"n\":\"惊悚\",\"v\":\"jingsong\"},{\"n\":\"3D\",\"v\":\"3D\"},{\"n\":\"灾难\",\"v\":\"zainan\"},{\"n\":\"悬疑\",\"v\":\"xuanyi\"},{\"n\":\"警匪\",\"v\":\"jingfei\"},{\"n\":\"文艺\",\"v\":\"wenyi\"},{\"n\":\"青春\",\"v\":\"qingchun\"},{\"n\":\"冒险\",\"v\":\"maoxian\"},{\"n\":\"犯罪\",\"v\":\"fanzui\"},{\"n\":\"纪录\",\"v\":\"jilu\"},{\"n\":\"古装\",\"v\":\"guzhuang\"},{\"n\":\"奇幻\",\"v\":\"qihuan\"},{\"n\":\"国语\",\"v\":\"guoyu\"},{\"n\":\"综艺\",\"v\":\"zongyi\"},{\"n\":\"历史\",\"v\":\"lishi\"},{\"n\":\"运动\",\"v\":\"yundong\"},{\"n\":\"原创压制\",\"v\":\"yuanchuang\"},{\"n\":\"美剧\",\"v\":\"meiju\"},{\"n\":\"韩剧\",\"v\":\"hanju\"},{\"n\":\"国产电视剧\",\"v\":\"guoju\"},{\"n\":\"日剧\",\"v\":\"riju\"},{\"n\":\"英剧\",\"v\":\"yingju\"},{\"n\":\"德剧\",\"v\":\"deju\"},{\"n\":\"俄剧\",\"v\":\"eju\"},{\"n\":\"巴剧\",\"v\":\"baju\"},{\"n\":\"加剧\",\"v\":\"jiaju\"},{\"n\":\"西剧\",\"v\":\"anish\"},{\"n\":\"意大利剧\",\"v\":\"yidaliju\"},{\"n\":\"泰剧\",\"v\":\"taiju\"},{\"n\":\"港台剧\",\"v\":\"gangtaiju\"},{\"n\":\"法剧\",\"v\":\"faju\"},{\"n\":\"澳剧\",\"v\":\"aoju\"}]},{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"不限\",\"v\":\"\"},{\"n\":\"中国大陆\",\"v\":\"中国大陆\"},{\"n\":\"中国香港\",\"v\":\"中国香港\"},{\"n\":\"中国台湾\",\"v\":\"中国台湾\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"法国\",\"v\":\"法国\"},{\"n\":\"印度\",\"v\":\"印度\"},{\"n\":\"德国\",\"v\":\"德国\"},{\"n\":\"西班牙\",\"v\":\"西班牙\"},{\"n\":\"意大利\",\"v\":\"意大利\"},{\"n\":\"澳大利亚\",\"v\":\"澳大利亚\"},{\"n\":\"比利时\",\"v\":\"比利时\"},{\"n\":\"瑞典\",\"v\":\"瑞典\"},{\"n\":\"荷兰\",\"v\":\"荷兰\"},{\"n\":\"丹麦\",\"v\":\"丹麦\"},{\"n\":\"加拿大\",\"v\":\"加拿大\"},{\"n\":\"俄罗斯\",\"v\":\"俄罗斯\"}]},{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2022\",\"v\":\"2022\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"},{\"n\":\"2003\",\"v\":\"2003\"},{\"n\":\"2002\",\"v\":\"2002\"},{\"n\":\"2001\",\"v\":\"2001\"},{\"n\":\"2000\",\"v\":\"2000\"}]},{\"key\":\"order\",\"name\":\"排序\",\"value\":[{\"n\":\"更新时间\",\"v\":\"0\"},{\"n\":\"豆瓣评分\",\"v\":\"1\"}]}],\"a\":[{\"key\":\"s\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"all\"},{\"n\":\"动作\",\"v\":\"dongzuo\"},{\"n\":\"爱情\",\"v\":\"aiqing\"},{\"n\":\"喜剧\",\"v\":\"xiju\"},{\"n\":\"科幻\",\"v\":\"kehuan\"},{\"n\":\"恐怖\",\"v\":\"kongbu\"},{\"n\":\"战争\",\"v\":\"zhanzheng\"},{\"n\":\"武侠\",\"v\":\"wuxia\"},{\"n\":\"魔幻\",\"v\":\"mohuan\"},{\"n\":\"剧情\",\"v\":\"juqing\"},{\"n\":\"动画\",\"v\":\"donghua\"},{\"n\":\"惊悚\",\"v\":\"jingsong\"},{\"n\":\"3D\",\"v\":\"3D\"},{\"n\":\"灾难\",\"v\":\"zainan\"},{\"n\":\"悬疑\",\"v\":\"xuanyi\"},{\"n\":\"警匪\",\"v\":\"jingfei\"},{\"n\":\"文艺\",\"v\":\"wenyi\"},{\"n\":\"青春\",\"v\":\"qingchun\"},{\"n\":\"冒险\",\"v\":\"maoxian\"},{\"n\":\"犯罪\",\"v\":\"fanzui\"},{\"n\":\"纪录\",\"v\":\"jilu\"},{\"n\":\"古装\",\"v\":\"guzhuang\"},{\"n\":\"奇幻\",\"v\":\"qihuan\"},{\"n\":\"国语\",\"v\":\"guoyu\"},{\"n\":\"综艺\",\"v\":\"zongyi\"},{\"n\":\"历史\",\"v\":\"lishi\"},{\"n\":\"运动\",\"v\":\"yundong\"},{\"n\":\"原创压制\",\"v\":\"yuanchuang\"},{\"n\":\"美剧\",\"v\":\"meiju\"},{\"n\":\"韩剧\",\"v\":\"hanju\"},{\"n\":\"国产电视剧\",\"v\":\"guoju\"},{\"n\":\"日剧\",\"v\":\"riju\"},{\"n\":\"英剧\",\"v\":\"yingju\"},{\"n\":\"德剧\",\"v\":\"deju\"},{\"n\":\"俄剧\",\"v\":\"eju\"},{\"n\":\"巴剧\",\"v\":\"baju\"},{\"n\":\"加剧\",\"v\":\"jiaju\"},{\"n\":\"西剧\",\"v\":\"anish\"},{\"n\":\"意大利剧\",\"v\":\"yidaliju\"},{\"n\":\"泰剧\",\"v\":\"taiju\"},{\"n\":\"港台剧\",\"v\":\"gangtaiju\"},{\"n\":\"法剧\",\"v\":\"faju\"},{\"n\":\"澳剧\",\"v\":\"aoju\"}]},{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"不限\",\"v\":\"\"},{\"n\":\"中国大陆\",\"v\":\"中国大陆\"},{\"n\":\"中国香港\",\"v\":\"中国香港\"},{\"n\":\"中国台湾\",\"v\":\"中国台湾\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"法国\",\"v\":\"法国\"},{\"n\":\"印度\",\"v\":\"印度\"},{\"n\":\"德国\",\"v\":\"德国\"},{\"n\":\"西班牙\",\"v\":\"西班牙\"},{\"n\":\"意大利\",\"v\":\"意大利\"},{\"n\":\"澳大利亚\",\"v\":\"澳大利亚\"},{\"n\":\"比利时\",\"v\":\"比利时\"},{\"n\":\"瑞典\",\"v\":\"瑞典\"},{\"n\":\"荷兰\",\"v\":\"荷兰\"},{\"n\":\"丹麦\",\"v\":\"丹麦\"},{\"n\":\"加拿大\",\"v\":\"加拿大\"},{\"n\":\"俄罗斯\",\"v\":\"俄罗斯\"}]},{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2022\",\"v\":\"2022\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"},{\"n\":\"2003\",\"v\":\"2003\"},{\"n\":\"2002\",\"v\":\"2002\"},{\"n\":\"2001\",\"v\":\"2001\"},{\"n\":\"2000\",\"v\":\"2000\"}]},{\"key\":\"order\",\"name\":\"排序\",\"value\":[{\"n\":\"更新时间\",\"v\":\"0\"},{\"n\":\"豆瓣评分\",\"v\":\"1\"}]}]}");
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ /**
+ * 爬虫headers
+ *
+ * @param url
+ * @return
+ */
+ protected HashMap getHeaders(String url,String ref) {
+ HashMap headers = new HashMap<>();
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ if(!ref.equals("google")){
+ headers.put("Authority", "www.bdys01.com");
+ if(ref.length()>0){
+ headers.put("Referer", ref);
+ }
+ if(cookie.length()>0){
+ headers.put("Cookie", cookie);
+ }
+ }
+ headers.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ return headers;
+ }
+
+ protected HashMap getHeaders2(String url) {
+ HashMap headers = new HashMap<>();
+ String ss = url.replace("https://","").split("/")[0];
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Authority", ss);
+ headers.put("Origin", "www.bdys01.com");
+ headers.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ return headers;
+ }
+
+
+ protected String getCookie(){
+ cookie="";
+ String cookieurl="https://www.bdys01.com/zzzzz";
+ Map> respHeaders = new HashMap<>();
+ OkHttpUtil.stringNoRedirect(cookieurl, getHeaders(cookieurl,referer), respHeaders);
+ if(respHeaders.containsKey("set-cookie")){
+ cookie = respHeaders.get("set-cookie").get(0).split(";")[0];
+ }
+ return cookie;
+ }
+
+ /**
+ * 获取分类数据 + 首页最近更新视频列表数据
+ *
+ * @param filter 是否开启筛选 关联的是 软件设置中 首页数据源里的筛选开关
+ * @return
+ */
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ Document doc = Jsoup.parse(OkHttpUtil.string(siteUrl, getHeaders(siteUrl,referer)));
+ referer=siteUrl+"/";
+ // 分类节点
+ JSONObject result = new JSONObject();
+ JSONArray classes = new JSONArray();
+ String catestr ="{\"全部\": \"a\",\"电影\": \"0\",\"电视剧\": \"1\"}";
+ JSONObject catedef = new JSONObject(catestr);
+ Iterator it = catedef.keys();
+ while(it.hasNext()){
+ JSONObject jsonObject = new JSONObject();
+ String key =(String) it.next();
+ jsonObject.put("type_name", key);
+ jsonObject.put("type_id", catedef.getString(key));
+ classes.put(jsonObject);
+ }
+ result.put("class", classes);
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ try {
+ // 取首页推荐视频列表
+ Element homeList = doc.select("div.row.row-cards").get(0);
+ Elements list = homeList.select("div.col-4.rows-md-7");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst("h3.card-title").text();
+ String cover = vod.selectFirst("img.w-100" ).attr("data-src");
+ String remark = vod.selectFirst("p.text-muted").text();
+ String id =vod.selectFirst("a.d-block.cover").attr("href");
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ getCookie();
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取分类信息数据
+ *
+ * @param tid 分类id
+ * @param pg 页数
+ * @param filter 同homeContent方法中的filter
+ * @param extend 筛选参数{k:v, k1:v1}
+ * @return
+ */
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ String url = siteUrl + "/s/" ;
+ if (extend != null && extend.size() > 0 ) {
+ String urlformat= "";
+ if(tid.equals("a")){
+ urlformat= url +"{s}/"+ pg +"?&area={area}&year={year}&order={order}";
+ }else {
+ urlformat= url +"{s}/"+ pg +"?&type="+tid+"&area={area}&year={year}&order={order}";
+ }
+ for (Iterator it = extend.keySet().iterator(); it.hasNext(); ) {
+ String key = it.next();
+ String value = extend.get(key);
+ if (value.length() > 0) {
+ urlformat=urlformat.replace("{"+key+"}",URLEncoder.encode(value));
+ }
+ }
+ for (int i=0 ;i<4;i++) {
+ if (urlformat.contains("{s}")) {
+ urlformat = urlformat.replace("{s}", "all");
+ } else if (urlformat.contains("{area}")) {
+ urlformat = urlformat.replace("&area={area}", "");
+ } else if (urlformat.contains("{year}")) {
+ urlformat = urlformat.replace("&year={year}", "");
+ } else if (urlformat.contains("{order}")) {
+ urlformat = urlformat.replace("{order}", "0");
+ }
+ }
+ url = urlformat;
+ } else {
+ if(tid.equals("a")){
+ url += "all/" + pg + "?&order=0";
+ }else {
+ url += "all/" + pg + "?&type=" + tid + "&order=0";
+ }
+ }
+ referer=siteUrl+"/";
+ String html = OkHttpUtil.string(url, getHeaders(url,referer));
+ referer = url;
+ Document doc = Jsoup.parse(html);
+ JSONObject result = new JSONObject();
+ int pageCount = 0;
+ int page = -1;
+ Elements pageInfo = doc.select("a.page-link");
+ if (pageInfo.size() == 0) {
+ page = Integer.parseInt(pg);
+ pageCount = page;
+ } else {
+ for (int i = 0; i < pageInfo.size(); i++) {
+ Element a = pageInfo.get(i);
+ String name = a.text();
+ if (name.equals("尾页")) {
+ String gg =a.attr("href");
+ String hf ="";
+ if(gg.contains("JSESSIONID")){
+ int start = gg.lastIndexOf("/")+1;
+ int end = gg.indexOf(";");
+ hf =gg.substring(start,end);
+ }else{
+ int start = gg.lastIndexOf("/")+1;
+ int end = gg.indexOf("?");
+ hf =gg.substring(start,end);
+ }
+ if (!hf.isEmpty()) {
+ pageCount = Integer.parseInt(hf);
+ } else {
+ pageCount = 0;
+ }
+ break;
+ }
+ }
+ }
+ JSONArray videos = new JSONArray();
+ if (!html.contains("没有找到您想要的结果哦")) {
+ // 取当前分类页的视频列表
+ Elements list = doc.select("div.col-lg-8");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst("h3.mb-0").text();
+ String cover = vod.selectFirst("img.w-100").attr("src");
+ String remark = vod.selectFirst("p.mb-0").text();
+ String idtt = vod.selectFirst("a.d-block").attr("href");
+ String id ="";
+ if(idtt.contains("JSESSIONID")) {
+ int end = idtt.indexOf(";");
+ id = idtt.substring(0,end);
+ }else{
+ id =idtt;
+ }
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", 48);
+ result.put("total", pageCount <= 1 ? videos.length() : pageCount * 48);
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 视频详情信息
+ *
+ * @param ids 视频id
+ * @return
+ */
+ @Override
+ public String detailContent(List ids) {
+ try {
+ String url = siteUrl + ids.get(0);
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url,referer)));
+ referer=url;
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+ String cover = doc.selectFirst("div.col-md-auto img").attr("src");
+ String title = doc.selectFirst("h1.d-none.d-md-block").text();
+ String desc = doc.select("div.card.collapse > div.card-body").text();
+ String year = doc.select("span.badge.bg-purple-lt").text().replace("更新时间:","").split("-")[0];
+ String category = "", area = "", remark = "", director = "", actor = "";
+ Element details = doc.select("div.col.mb-2").get(0);
+ Elements allp = details.select("p");
+ for (int i = 0; i < allp.size(); i++) {
+ Element text = allp.get(i);
+ String info = text.selectFirst("strong").text();
+ if (info.equals("类型:")) {
+ List categorys = new ArrayList<>();
+ Elements aa = text.select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ categorys.add(aa.get(j).text());
+ }
+ category ="类型:"+TextUtils.join(",", categorys);
+ } else if (info.contains("地区")) {
+ int start= text.text().indexOf("[")+1;
+ int end = text.text().indexOf("]");
+ area = text.text().substring(start,end);
+ } else if (info.contains("豆瓣")) {
+ remark = "豆瓣:"+text.text();
+ } else if (info.contains("导演:")) {
+ director = text.selectFirst("a").text();
+ } else if (info.contains("主演:")) {
+ List actors = new ArrayList<>();
+ Elements aa = text.select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ actors.add(aa.get(j).text());
+ }
+ actor =TextUtils.join(",", actors);
+ }
+ }
+ String vid = ids.get(0);
+ vodList.put("vod_id", vid);
+ vodList.put("vod_name", title);
+ vodList.put("vod_pic", cover);
+ vodList.put("type_name", category);
+ vodList.put("vod_year", year);
+ vodList.put("vod_area", area);
+ vodList.put("vod_remarks", remark);
+ vodList.put("vod_actor", actor);
+ vodList.put("vod_director", director);
+ vodList.put("vod_content", desc);
+ Map vod_play = new TreeMap<>();
+ // 取播放列表数据
+ Elements playListA = doc.select("a.btn.btn-square");
+ String sourceName = "播放列表";
+ String playList = "";
+ List vodItems = new ArrayList<>();
+ for (int j = 0; j < playListA.size(); j++) {
+ Element vod = playListA.get(j);
+ String idtt = vod.attr("href");
+ String playURL ="";
+ if(idtt.contains("JSESSIONID")) {
+ int end = idtt.indexOf(";");
+ playURL = idtt.substring(0,end);
+ }else{
+ playURL =idtt;
+ }
+ vodItems.add(vod.text() + "$" + playURL);
+ }
+ if (vodItems.size() > 0)
+ playList = TextUtils.join("#", vodItems);
+ vod_play.put(sourceName, playList);
+ if (vod_play.size() > 0) {
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+ }
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取视频播放信息
+ *
+ * @param flag 播放源
+ * @param id 视频id
+ * @param vipFlags 所有可能需要vip解析的源
+ * @return
+ */
+ @TargetApi(Build.VERSION_CODES.KITKAT)
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ String url = siteUrl + id ;
+ String htmlplay = OkHttpUtil.string(url, getHeaders(url,referer));
+ Document doc = Jsoup.parse(htmlplay);
+ Elements allScript = doc.select("script");
+ JSONObject result = new JSONObject();
+ String pid="";
+ for (int i = 0; i < allScript.size(); i++) {
+ String scContent = allScript.get(i).toString();
+ if (scContent.contains("var pid =")) {
+ int start = scContent.indexOf("var pid =");
+ int end = scContent.lastIndexOf("var time") + 1;
+ String pidtmp = scContent.substring(start, end);
+ start = pidtmp.indexOf("=")+2;
+ end = pidtmp.lastIndexOf(";") ;
+ pid = pidtmp.substring(start, end);
+ break;
+ }
+ }
+ long t = System.currentTimeMillis();
+ String key = Misc.MD5(pid+"-"+t, StandardCharsets.UTF_8).substring(0,16);
+ String sg = encrypt(pid+"-"+t,key);
+ String geturl = siteUrl+"/lines?t="+t+"&sg="+sg+"&pid="+pid;
+ String urlsrc = OkHttpUtil.string(geturl, getHeaders(geturl,""));
+ JSONObject urlsrcobj = new JSONObject(urlsrc);
+ JSONObject urldb = urlsrcobj.getJSONObject("data");
+ List urldblist = new ArrayList<>();
+ if(!urldb.isNull("url3")){
+ String url3 = urldb.optString("url3");
+ urldblist.add(url3);
+ }
+ if(!urldb.isNull("m3u8")){
+ String m3u8 = urldb.optString("m3u8").replace("www.bde4.cc","www.bdys01.com");
+ urldblist.add(m3u8);
+ }
+ if(!urldb.isNull("m3u8_2")){
+ String m3u8_2 =urldb.optString("m3u8_2");
+ String[] m2=m3u8_2.split(",");
+ for(int i=0; i< m2.length ;i++){
+ urldblist.add(m2[i].replace("www.bde4.cc","www.bdys01.com"));
+ }
+ }
+ int index =new Random().nextInt(urldblist.size());
+ String videourl = urldblist.get(index);
+ if(videourl.contains("mp4")){
+ result.put("parse", 0);
+ result.put("playUrl", "");
+ result.put("url", videourl);
+ result.put("header", "");
+ return result.toString();
+ }
+ Map> respHeaders = new HashMap<>();
+ OkHttpUtil.stringNoRedirect(videourl, getHeaders(videourl,""), respHeaders);
+ String redirect = OkHttpUtil.getRedirectLocation(respHeaders);
+ String realm3u8="";
+ OKCallBack.OKCallBackDefault callBack = new OKCallBack.OKCallBackDefault() {
+ @Override
+ protected void onFailure(Call call, Exception e) {
+ }
+ @Override
+ protected void onResponse(Response response) {
+ }
+ };
+ OkHttpUtil.get(OkHttpUtil.defaultClient(), redirect, null, getHeaders2(redirect), callBack);
+ if (callBack.getResult().code() == 200) {
+ InputStream picsrc = callBack.getResult().body().byteStream();
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ int nRead;
+ byte[] data = new byte[4];
+ while ((nRead = picsrc.read(data, 0, data.length)) != -1) {
+ buffer.write(data, 0, nRead);
+ }
+ buffer.flush();
+ byte[] targetArray = buffer.toByteArray();
+ picsrc.close();
+ byte[] dep = Arrays.copyOfRange(targetArray,3354,targetArray.length);
+ String pp = gZip.KS(dep);
+ String[] m3u8ori = pp.split("\n");
+ for(int i=0;i0){
+ for (int i = 0; i < 1; i++) {
+ Element sourcess = sourceList.get(i);
+ String sourceName = sourcess.select("h3.LC20lb.MBeuO.DKV0Md").text();
+ String list1 = sourcess.attr("href");
+ if(list1.contains("/s/")||list1.contains("play")||list1.contains("performer")||list1.contains("search")||list1.contains("jsessionid")){
+ continue;
+ }
+ if (sourceName.contains(key)) {
+ Document ddrklink = Jsoup.parse(OkHttpUtil.string(list1, getHeaders(list1,referer)));
+ JSONObject v = new JSONObject();
+ String cover = ddrklink.selectFirst("div.col-md-auto img").attr("src");
+ String title = ddrklink.selectFirst("h2.d-sm-block.d-md-none").text();
+ String id =list1.replace("https://www.bdys01.com","");
+ v.put("vod_name", title);
+ v.put("vod_remarks", "");
+ v.put("vod_id", id);
+ v.put("vod_pic", cover);
+ videos.put(v);
+ }
+ }
+ result.put("list", videos);
+ return result.toString();
+ }
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ protected String encrypt(String src, String KEY) {
+ try {
+ Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
+ SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), "AES");
+ cipher.init(Cipher.ENCRYPT_MODE, keySpec);
+ return bytesToHexStr(cipher.doFinal(src.getBytes())).toUpperCase();
+ } catch (Exception exception) {
+ SpiderDebug.log(exception);
+ }
+ return null;
+ }
+
+ protected String bytesToHexStr(byte[] bytes) {
+ StringBuilder hexStr = new StringBuilder();
+ for (byte b : bytes) {
+ String hex = Integer.toHexString(b & 0xFF);
+ if (hex.length() == 1) {
+ hex = '0' + hex;
+ }
+ hexStr.append(hex);
+ }
+ return hexStr.toString();
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/catvod/spider/Buka.java b/app/src/main/java/com/github/catvod/spider/Buka.java
new file mode 100644
index 0000000..328c2ed
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Buka.java
@@ -0,0 +1,483 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 真不卡 播放好像还有问题 需要大佬继续修复
+ *
+ * Author: 小黄瓜
+ */
+public class Buka extends Spider {
+ private static final String siteUrl = "https://www.zhenbuka3.com";
+ private static final String siteHost = "www.zhenbuka3.com";
+ private static final String ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36";
+
+ /**
+ * 播放源配置
+ */
+ private JSONObject playerConfig;
+ /**
+ * 筛选配置
+ */
+ private JSONObject filterConfig;
+
+ private Pattern regexCategory = Pattern.compile("/vodtype/(\\w+)/");
+ private Pattern regexVid = Pattern.compile("/voddetail/(\\w+)/");
+ private Pattern regexPlay = Pattern.compile("/vodplay/(\\w+)-(\\d+)-(\\d+)/");
+ private Pattern regexPage = Pattern.compile("/vodshow/(\\S+)/");
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ try {
+ playerConfig = new JSONObject("{\"qqpic\":{\"sh\":\"不卡超清[推荐]\",\"pu\":\"http://good-vip.mmiyue.com/zhenbuka2/player/index.php?video_id=\",\"sn\":0,\"or\":999},\"niuxyun\":{\"sh\":\"不卡备用[推荐]\",\"pu\":\"http://good-vip.mmiyue.com/jiekou/zbk-bkby/jx.php?id=\",\"sn\":0,\"or\":999},\"vipjx\":{\"sh\":\"不卡备用③[推荐]\",\"pu\":\"https://cq.mmiyue.com/zhenbuka2/player/index.php?url=\",\"sn\":0,\"or\":999},\"bkm3u8\":{\"sh\":\"不卡备用②[推荐]\",\"pu\":\"http://good-vip.mmiyue.com/zhenbuka2/player/index.php?url=//good-vip.mmiyue.com/zhenbuka2/api/dymp4.php?video_id=\",\"sn\":0,\"or\":999},\"cy\":{\"sh\":\"动漫云\",\"pu\":\"https://cq.mmiyue.com/jiekou/zbk-bkby/jx.php?id=\",\"sn\":0,\"or\":999},\"mgtv\":{\"sh\":\"不卡芒果\",\"pu\":\"https://cq.mmiyue.com/zhenbuka2/player/index.php?url=\",\"sn\":0,\"or\":999},\"qiyi\":{\"sh\":\"不卡奇艺\",\"pu\":\"https://cq.mmiyue.com/zhenbuka2/player/index.php?url=\",\"sn\":0,\"or\":999},\"qq\":{\"sh\":\"不卡企鹅\",\"pu\":\"https://cq.mmiyue.com/zhenbuka2/player/index.php?url=\",\"sn\":0,\"or\":999},\"youku\":{\"sh\":\"不卡优酷\",\"pu\":\"https://cq.mmiyue.com/zhenbuka2/player/index.php?url=\",\"sn\":0,\"or\":999},\"dbm3u8\":{\"sh\":\"资源备用[不推荐]\",\"pu\":\"\",\"sn\":0,\"or\":999},\"niuyun\":{\"sh\":\"超清备用\",\"pu\":\"https://api.l32c.cn/danmu/niuyun.php?id=\",\"sn\":0,\"or\":999},\"123kum3u8\":{\"sh\":\"资源备用[不推荐]\",\"pu\":\"\",\"sn\":0,\"or\":999},\"sixpan\":{\"sh\":\"不卡备用②[推荐]\",\"pu\":\"https://cq.mmiyue.com/zhenbuka2/player/index.php?url=//cq.mmiyue.com/m3u8/buka/\",\"sn\":0,\"or\":999},\"qq1\":{\"sh\":\"超清云播\",\"pu\":\"https://api.nixingle.com/zhenbuka/player/index.php?id=\",\"sn\":0,\"or\":999}}");
+ filterConfig = new JSONObject("{\"1\":[{\"key\":0,\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"动作片\",\"v\":\"6\"},{\"n\":\"喜剧片\",\"v\":\"7\"},{\"n\":\"爱情片\",\"v\":\"8\"},{\"n\":\"科幻片\",\"v\":\"9\"},{\"n\":\"恐怖片\",\"v\":\"10\"},{\"n\":\"剧情片\",\"v\":\"11\"},{\"n\":\"战争片\",\"v\":\"12\"},{\"n\":\"动画片\",\"v\":\"23\"},{\"n\":\"纪录片\",\"v\":\"25\"},{\"n\":\"犯罪片\",\"v\":\"26\"}]},{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"中国大陆\",\"v\":\"中国大陆\"},{\"n\":\"中国香港\",\"v\":\"中国香港\"},{\"n\":\"中国台湾\",\"v\":\"中国台湾\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"法国\",\"v\":\"法国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"德国\",\"v\":\"德国\"},{\"n\":\"泰国\",\"v\":\"泰国\"},{\"n\":\"印度\",\"v\":\"印度\"},{\"n\":\"意大利\",\"v\":\"意大利\"},{\"n\":\"西班牙\",\"v\":\"西班牙\"},{\"n\":\"加拿大\",\"v\":\"加拿大\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]}],\"2\":[{\"key\":0,\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国产剧\",\"v\":\"13\"},{\"n\":\"港台剧\",\"v\":\"14\"},{\"n\":\"日韩剧\",\"v\":\"15\"},{\"n\":\"欧美剧\",\"v\":\"16\"},{\"n\":\"海外剧\",\"v\":\"20\"},{\"n\":\"纪录片\",\"v\":\"24\"}]},{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"中国大陆\",\"v\":\"中国大陆\"},{\"n\":\"中国香港\",\"v\":\"中国香港\"},{\"n\":\"中国台湾\",\"v\":\"中国台湾\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"泰国\",\"v\":\"泰国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"新加坡\",\"v\":\"新加坡\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]}],\"3\":[{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"中国大陆\",\"v\":\"中国大陆\"},{\"n\":\"中国香港\",\"v\":\"中国香港\"},{\"n\":\"中国台湾\",\"v\":\"中国台湾\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"英国\",\"v\":\"英国\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]}],\"4\":[{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"中国大陆\",\"v\":\"中国大陆\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"美国\",\"v\":\"美国\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]}]}");
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ /**
+ * 爬虫headers
+ *
+ * @param url
+ * @return
+ */
+ protected HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("method", "GET");
+ headers.put("Host", siteHost);
+ headers.put("Upgrade-Insecure-Requests", "1");
+ headers.put("DNT", "1");
+ headers.put("User-Agent", ua);
+ headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
+ headers.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ return headers;
+ }
+
+ /**
+ * 获取分类数据 + 首页最近更新视频列表数据
+ *
+ * @param filter 是否开启筛选 关联的是 软件设置中 首页数据源里的筛选开关
+ * @return
+ */
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ Document doc = Jsoup.parse(OkHttpUtil.string(siteUrl, getHeaders(siteUrl)));
+ // 分类节点
+ Elements elements = doc.select("ul.dropdown > li a");
+ JSONArray classes = new JSONArray();
+ for (Element ele : elements) {
+ String name = ele.text();
+ boolean show = true;
+ if (filter) {
+ show = name.equals("电影") ||
+ name.equals("剧集") ||
+ name.equals("动漫") ||
+ name.equals("综艺");
+ }
+ if (show) {
+ Matcher mather = regexCategory.matcher(ele.attr("href"));
+ if (!mather.find())
+ continue;
+ String id = mather.group(1).trim();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_id", id);
+ jsonObject.put("type_name", name);
+ classes.put(jsonObject);
+ }
+ }
+ JSONObject result = new JSONObject();
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ result.put("class", classes);
+ try {
+ Elements list = doc.select("div.stui-pannel_bd ul.stui-vodlist li div.stui-vodlist__box");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".stui-vodlist__thumb").attr("href"));
+ if (!matcher.find())
+ continue;
+ String title = vod.selectFirst(".title").text();
+ String cover = vod.selectFirst(".stui-vodlist__thumb").attr("data-original");
+ String remark = vod.selectFirst("span.pic-text").text();
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取分类信息数据
+ *
+ * @param tid 分类id
+ * @param pg 页数
+ * @param filter 同homeContent方法中的filter
+ * @param extend 筛选参数{k:v, k1:v1}
+ * @return
+ */
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ String[] urlParams = new String[]{"", "", "", "", "", "", "", "", "", "", "", ""};
+ urlParams[0] = tid;
+ urlParams[8] = pg;
+ if (extend != null && extend.size() > 0) {
+ for (Iterator it = extend.keySet().iterator(); it.hasNext(); ) {
+ String key = it.next();
+ String value = extend.get(key);
+ if (value.trim().length() == 0)
+ continue;
+ urlParams[Integer.parseInt(key)] = URLEncoder.encode(value);
+ }
+ }
+ // 获取分类数据的url
+ String url = siteUrl + "/vodshow/" + TextUtils.join("-", urlParams) + "/";
+ String html = OkHttpUtil.string(url, getHeaders(url));
+ Document doc = Jsoup.parse(html);
+ JSONObject result = new JSONObject();
+ int pageCount = 0;
+ int page = -1;
+
+ Elements pageInfo = doc.select(".stui-page li");
+ if (pageInfo.size() == 0) {
+ page = Integer.parseInt(pg);
+ pageCount = page;
+ } else {
+ for (int i = 0; i < pageInfo.size(); i++) {
+ Element li = pageInfo.get(i);
+ Element a = li.selectFirst("a");
+ if (a == null)
+ continue;
+ String name = a.text();
+ if (page == -1 && li.hasClass("active")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ page = Integer.parseInt(matcher.group(1).split("-")[8]);
+ } else {
+ page = 0;
+ }
+ }
+ if (name.equals("尾页")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ pageCount = Integer.parseInt(matcher.group(1).split("-")[8]);
+ } else {
+ pageCount = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ JSONArray videos = new JSONArray();
+ if (!html.contains("没有找到您想要的结果哦")) {
+ Elements list = doc.select("ul.stui-vodlist li div.stui-vodlist__box");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst(".title").text();
+ String cover = vod.selectFirst(".stui-vodlist__thumb").attr("data-original");
+ String remark = vod.selectFirst("span.pic-text").text();
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".stui-vodlist__thumb").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", 48);
+ result.put("total", pageCount <= 1 ? videos.length() : pageCount * 48);
+
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 视频详情信息
+ *
+ * @param ids 视频id
+ * @return
+ */
+ @Override
+ public String detailContent(List ids) {
+ try {
+ // 视频详情url
+ String url = siteUrl + "/voddetail/" + ids.get(0) + "/";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+
+ // 取基本数据
+ String cover = doc.selectFirst("a.stui-vodlist__thumb img").attr("data-original");
+ String title = doc.selectFirst("div.stui-content__detail h1.title").text();
+ String desc = Jsoup.parse(doc.selectFirst("meta[name=description]").attr("content")).text();
+ String category = "", area = "", year = "", remark = "", director = "", actor = "";
+ Elements span_text_muted = doc.select("div.stui-content__detail span.text-muted");
+ for (int i = 0; i < span_text_muted.size(); i++) {
+ Element text = span_text_muted.get(i);
+ String info = text.text();
+ if (info.equals("类型:")) {
+ category = text.nextElementSibling().text();
+ } else if (info.equals("年份:")) {
+ year = text.nextSibling().outerHtml().trim();
+ } else if (info.equals("地区:")) {
+ area = text.nextSibling().outerHtml().trim();
+ } else if (info.equals("更新:")) {
+ remark = text.nextSibling().outerHtml().trim();
+ } else if (info.equals("导演:")) {
+ List directors = new ArrayList<>();
+ Elements aa = text.parent().select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ directors.add(aa.get(j).text());
+ }
+ director = TextUtils.join(",", directors);
+ } else if (info.equals("主演:")) {
+ List actors = new ArrayList<>();
+ Elements aa = text.parent().select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ actors.add(aa.get(j).text());
+ }
+ actor = TextUtils.join(",", actors);
+ }
+ }
+
+ vodList.put("vod_id", ids.get(0));
+ vodList.put("vod_name", title);
+ vodList.put("vod_pic", cover);
+ vodList.put("type_name", category);
+ vodList.put("vod_year", year);
+ vodList.put("vod_area", area);
+ vodList.put("vod_remarks", remark);
+ vodList.put("vod_actor", actor);
+ vodList.put("vod_director", director);
+ vodList.put("vod_content", desc);
+
+ Map vod_play = new TreeMap<>(new Comparator() {
+ @Override
+ public int compare(String o1, String o2) {
+ try {
+ int sort1 = playerConfig.getJSONObject(o1).getInt("or");
+ int sort2 = playerConfig.getJSONObject(o2).getInt("or");
+
+ if (sort1 == sort2) {
+ return 1;
+ }
+ return sort1 - sort2 > 0 ? 1 : -1;
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ return 1;
+ }
+ });
+
+ Elements sources = doc.select("div.playlist");
+
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ String sourceName = source.selectFirst("h3.title").text().trim();
+ String tabHref = source.attr("href");
+ boolean found = false;
+ for (Iterator it = playerConfig.keys(); it.hasNext(); ) {
+ String flag = it.next();
+ if (playerConfig.getJSONObject(flag).getString("sh").equals(sourceName)) {
+ sourceName = flag;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+ String playList = "";
+ Elements playListA = source.select("ul.stui-content__playlist > li > a");
+ List vodItems = new ArrayList<>();
+
+ for (int j = 0; j < playListA.size(); j++) {
+ Element vod = playListA.get(j);
+ Matcher matcher = regexPlay.matcher(vod.attr("href"));
+ if (!matcher.find())
+ continue;
+ String playURL = matcher.group(1) + "-" + matcher.group(2) + "-" + matcher.group(3);
+ vodItems.add(vod.text() + "$" + playURL);
+ }
+ if (vodItems.size() > 0)
+ playList = TextUtils.join("#", vodItems);
+
+ if (playList.length() == 0)
+ continue;
+
+ vod_play.put(sourceName, playList);
+ }
+
+ if (vod_play.size() > 0) {
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+ }
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取视频播放信息
+ *
+ * @param flag 播放源
+ * @param id 视频id
+ * @param vipFlags 所有可能需要vip解析的源
+ * @return
+ */
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ // 播放页 url
+ String url = siteUrl + "/vodplay/" + id + "/";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ Elements allScript = doc.select("script");
+ JSONObject result = new JSONObject();
+ for (int i = 0; i < allScript.size(); i++) {
+ String scContent = allScript.get(i).html().trim();
+ if (scContent.startsWith("var player_")) {
+ int start = scContent.indexOf('{');
+ int end = scContent.lastIndexOf('}') + 1;
+ String json = scContent.substring(start, end);
+ JSONObject player = new JSONObject(json);
+ if (playerConfig.has(player.getString("from"))) {
+ JSONObject pCfg = playerConfig.getJSONObject(player.getString("from"));
+ String videoUrl = player.getString("url");
+ String playUrl = pCfg.getString("pu");
+ String from = player.getString("from");
+ if (from.equals("qqpic")) {
+ // 感谢猫大神的直连解密代码
+ HashMap hds = getHeaders(url);
+ hds.put("Host", "good-vip.mmiyue.com");
+ hds.put("Referer", url);
+ String content1 = OkHttpUtil.string(playUrl + videoUrl, hds);
+ Document doc1 = Jsoup.parse(content1);
+ String url2 = "https:" + doc1.selectFirst("iframe#player").attr("src");
+ hds.put("Host", "pcc.mmiyue.com");
+ hds.put("Referer", "http://good-vip.mmiyue.com/");
+ String content2 = OkHttpUtil.string(url2, hds);
+ String finder = "var id=\"";
+ start = content2.indexOf(finder) + finder.length();
+ end = content2.indexOf('\"', start);
+ String vvid = content2.substring(start, end);
+ finder = "var sk=\"";
+ start = content2.indexOf(finder) + finder.length();
+ end = content2.indexOf('\"', start);
+ String skey = content2.substring(start, end);
+ finder = "var pt=\"";
+ start = content2.indexOf(finder) + finder.length();
+ end = content2.indexOf('\"', start);
+ String pt = content2.substring(start, end);
+ finder = "var ti=\"";
+ start = content2.indexOf(finder) + finder.length();
+ end = content2.indexOf('\"', start);
+ String time = content2.substring(start, end);
+ int bkn = 0x195c;
+ for (int j = 0x0, all = skey.length(); all > j; ++j) {
+ bkn += ((bkn << 5) + (byte) skey.charAt(j));
+ }
+ bkn = 0x7fffffff & bkn;
+ int gtk1 = 0x0;
+ for (int j = 0x0; j < pt.length(); j += 0x4) {
+ gtk1 += Integer.parseInt(String.format("%c%c%c%c", pt.charAt(j), pt.charAt(j + 0x1), pt.charAt(j + 0x2), pt.charAt(j + 0x3)), 0x10);
+ gtk1 %= 0x400a;
+ }
+ int offset = gtk1 % 10;
+ int gtk = 0x0;
+ for (int j = 0x0; j < pt.length(); j++) {
+ gtk += ((byte) pt.charAt(j)) * (j + offset);
+ gtk %= gtk1;
+ }
+ String finalVideoUrl = "https://pcc.mmiyue.com/hls/play/" + vvid + "%7C" + time + "%7C" + skey + "%7C" + pt + "%7C" + bkn + "%7C" + gtk + ".m3u8";
+ result.put("parse", pCfg.getInt("sn"));
+ result.put("playUrl", "");
+ result.put("url", finalVideoUrl);
+ result.put("header", "");
+ } else {
+ result.put("parse", pCfg.getInt("sn"));
+ result.put("playUrl", playUrl);
+ result.put("url", videoUrl);
+ result.put("header", "");
+ }
+ }
+ break;
+ }
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 搜索
+ *
+ * @param key
+ * @param quick 是否播放页的快捷搜索
+ * @return
+ */
+ @Override
+ public String searchContent(String key, boolean quick) {
+ // 搜索有验证码 不支持
+ return "";
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Cokemv.java b/app/src/main/java/com/github/catvod/spider/Cokemv.java
index fc82c81..b194d98 100644
--- a/app/src/main/java/com/github/catvod/spider/Cokemv.java
+++ b/app/src/main/java/com/github/catvod/spider/Cokemv.java
@@ -429,7 +429,7 @@ public class Cokemv extends Spider {
@Override
public String searchContent(String key, boolean quick) {
try {
- String url = "https://shitu.paodekuaiweixinqun.com/search?q=site%3Acokemv.me%2Fvoddetail+" + URLEncoder.encode(key);
+ String url = "https://www.sogou.com/web?query=site%3Acokemv.me%2Fvoddetail+" + URLEncoder.encode(key);
Document docs = Jsoup.parse(OkHttpUtil.string(url, sHeaders()));
JSONObject result = new JSONObject();
JSONArray videos = new JSONArray();
diff --git a/app/src/main/java/com/github/catvod/spider/Ddrk.java b/app/src/main/java/com/github/catvod/spider/Ddrk.java
new file mode 100644
index 0000000..8b70afb
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Ddrk.java
@@ -0,0 +1,581 @@
+package com.github.catvod.spider;
+
+import android.text.TextUtils;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.AES;
+import com.github.catvod.utils.CBC;
+import com.github.catvod.utils.gZip;
+import com.github.catvod.utils.okhttp.OKCallBack;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import okhttp3.Call;
+import okhttp3.OkHttpClient;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+
+/**
+ * Demo for self study
+ *
+ * Source from Author: CatVod
+ */
+
+public class Ddrk extends Spider {
+
+ private static final String siteUrl = "https://ddrk.tv";
+ private static final String siteHost = "ddrk.tv";
+
+ protected JSONObject filterConfig;
+
+ protected Pattern regexCategory = Pattern.compile("/category/(\\S+)/");
+ protected Pattern regexVid = Pattern.compile("https://ddrk.tv/(\\S+)/");
+
+ protected Pattern regexPage = Pattern.compile("\\S+/page/(\\S+)\\S+");
+ protected Pattern m = Pattern.compile("\\S+(http\\S+g)");
+ protected Pattern mark = Pattern.compile("\\S+(.*)");
+
+ // protected Pattern t = Pattern.compile("(\\S+)");
+
+
+ /**
+ * 爬虫headers
+ *
+ * @param url
+ * @return
+ */
+ protected HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.62 Safari/537.36");
+ headers.put("Referer", "https://ddrk.tv/");
+ return headers;
+ }
+
+ protected static HashMap Headers() {
+ HashMap headers = new HashMap<>();
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Referer", "https://ddrk.tv/");
+ return headers;
+ }
+
+ /**
+ * 获取分类数据 + 首页最近更新视频列表数据
+ *
+ * @param filter 是否开启筛选 关联的是 软件设置中 首页数据源里的筛选开关
+ * @return
+ */
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ String url = siteUrl + '/';
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ Elements elements = doc.select("li.menu-item a");
+ JSONArray classes = new JSONArray();
+ ArrayList allClass = new ArrayList<>();
+ for (Element ele : elements) {
+ String name = ele.attr("title");
+ boolean show = !filter || (name.equals("热映中")
+ || name.equals("欧美剧")
+ || name.equals("日剧")
+ || name.equals("韩剧")
+ || name.equals("华语剧")
+ || name.equals("其他地区")
+ || name.equals("全部")
+ || name.equals("欧美电影")
+ || name.equals("日韩电影")
+ || name.equals("华语电影")
+ || name.equals("新番")
+ || name.equals("动画")
+ || name.equals("纪录片")
+ || name.equals("综艺"));
+ if (allClass.contains(name))
+ show = false;
+ if (show) {
+ allClass.add(name);
+ Matcher mather = regexCategory.matcher(ele.attr("href"));
+ if (!mather.find())
+ continue;
+ // 把分类的id和名称取出来加到列表里
+ String id = mather.group(1).trim();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_id", id);
+ jsonObject.put("type_name", name);
+ classes.put(jsonObject);
+ }
+ }
+ JSONObject result = new JSONObject();
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ result.put("class", classes);
+ try {
+ // 取首页推荐视频列表
+ Elements list = doc.select("div.post-box-container");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String a = vod.selectFirst(".post-box-title a").text();
+ if (a.contains("(")) {
+ String[] item = a.split("\\(");
+ String title = item[0];
+ String remark = item[1].replace(")", "");
+ String cover = doReplaceRegex(m, vod.selectFirst(".post-box-image").attr("style"));
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".post-box-title a").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ } else {
+ String title = a;
+ String cover = doReplaceRegex(m, vod.selectFirst(".post-box-image").attr("style"));
+ String remark = doReplaceRegex(mark, vod.selectFirst(".post-box-title a").text());
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".post-box-title a").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ /**
+ * 获取分类信息数据
+ *
+ * @param tid 分类id
+ * @param pg 页数
+ * @param filter 同homeContent方法中的filter
+ * @param extend 筛选参数{k:v, k1:v1}
+ * @return
+ */
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ String url = "";
+ try {
+ if (extend != null && extend.size() > 0) {
+ for (Iterator it = extend.keySet().iterator(); it.hasNext(); ) {
+ String key = it.next();
+ String value = extend.get(key);
+ if (value != null && value.length() != 0 && value != " ") {
+ url = siteUrl + "/category/" + tid + "/" + value;
+ } else {
+ url = siteUrl + "/category/" + tid;
+ }
+ ;
+ }
+ } else {
+ url = siteUrl + "/category/" + tid;
+ }
+ ;
+ if (pg.equals("1")) {
+ url = url + "/";
+ } else {
+ url = url + "/page/" + pg + "/";
+ }
+ //System.out.println(url);
+ String html = OkHttpUtil.string(url, getHeaders(url));
+ Document doc = Jsoup.parse(html);
+ JSONObject result = new JSONObject();
+ int pageCount = 0;
+ int page = -1;
+
+ // 取页码相关信息
+ Elements pageInfo = doc.select("div.nav-links");
+ if (pageInfo.size() == 0) {
+ page = Integer.parseInt(pg);
+ pageCount = page;
+ } else {
+ for (int i = 0; i < pageInfo.size(); i++) {
+ Element li = pageInfo.get(i);
+ Element a = li.selectFirst("a");
+ if (a == null)
+ continue;
+ String wy = doc.select("div.nav-links a").last().attr("href");
+ String span = doc.select("span.current").text().trim();
+ if (page == -1) {
+ page = Integer.parseInt(span);
+ } else {
+
+ page = 0;
+ }
+ Matcher matcher = regexPage.matcher(wy);
+ if (matcher.find()) {
+ //System.out.println("尾页" + matcher.group(1));
+ pageCount = Integer.parseInt(matcher.group(1));
+ } else {
+ pageCount = 0;
+ }
+ break;
+ }
+ }
+
+ JSONArray videos = new JSONArray();
+ if (!html.contains("没有找到您想要的结果哦")) {
+ // 取当前分类页的视频列表
+ Elements list = doc.select("div.post-box-container");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String a = vod.selectFirst(".post-box-title a").text();
+ if (a.contains("(")) {
+ String[] item = a.split("\\(");
+ String title = item[0];
+ String remark = item[1].replace(")", "");
+ String cover = doReplaceRegex(m, vod.selectFirst(".post-box-image").attr("style"));
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".post-box-title a").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ } else {
+ String title = a;
+ String cover = doReplaceRegex(m, vod.selectFirst(".post-box-image").attr("style"));
+ String remark = doReplaceRegex(mark, vod.selectFirst(".post-box-title a").text());
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".post-box-title a").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ }
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", 24);
+ result.put("total", pageCount <= 1 ? videos.length() : pageCount * 24);
+
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 视频详情信息
+ *
+ * @param ids 视频id
+ * @return
+ */
+ @Override
+ public String detailContent(List ids) {
+ try {
+ // 视频详情url
+ String url = siteUrl + "/" + ids.get(0) + "/";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+
+ // 取基本数据
+ String cover = doc.select("div.post img").attr("src");
+ String ab = doc.select("h1.post-title").text();
+ if (ab.contains("(")) {
+ String[] b = ab.split("\\(");
+ String title = b[0];
+ String remark = b[1].replace("(", "");
+ vodList.put("vod_name", title);
+ vodList.put("vod_remarks", remark);
+ } else {
+ vodList.put("vod_name", ab);
+ String remark = doc.select("time").text().trim();
+ vodList.put("vod_remarks", "全");
+ }
+ String str2 = doc.select("div.abstract").text().replace(" ", "");
+ String replace = str2.replace("
", "");
+ String text = replace.replace("", "");
+ Pattern categorys = Pattern.compile("类型:(.*)制");
+ String category = doReplaceRegex(categorys, text);
+ Pattern a = Pattern.compile("年份:(.*)简");
+ String year = doReplaceRegex(a, text);
+ Pattern b = Pattern.compile("地区:(.*)年份");
+ String area = doReplaceRegex(b, text);
+ Pattern c = Pattern.compile("演员:(.*)类");
+ String actor = doReplaceRegex(c, text);
+ Pattern d = Pattern.compile("导演:(.*)演");
+ String director = doReplaceRegex(d, text);
+ Pattern e = Pattern.compile("简介:(.*)");
+ String desc = doReplaceRegex(e, text);
+
+
+ vodList.put("vod_id", ids.get(0));
+ vodList.put("vod_pic", cover);
+ vodList.put("type_name", category);
+ vodList.put("vod_year", year);
+ vodList.put("vod_area", area);
+ vodList.put("vod_actor", actor);
+ vodList.put("vod_director", director);
+ vodList.put("vod_content", desc);
+
+ List vodItems = new ArrayList<>();
+ List vodItems2 = new ArrayList<>();
+ Map vod_play = new LinkedHashMap<>();
+
+ Elements allScript = doc.select(".wp-playlist-script");
+ String sourceName = "第1季";
+ for (int j = 0; j < allScript.size(); j++) {
+ String scContent = allScript.get(j).html().trim();
+ int start = scContent.indexOf('{');
+ int end = scContent.lastIndexOf('}') + 1;
+ String json = scContent.substring(start, end);
+ JSONObject UJson = new JSONObject(json);
+ JSONArray Track = UJson.getJSONArray("tracks");
+ for (int k = 0; k < Track.length(); k++) {
+ JSONObject src = Track.getJSONObject(k);
+ String adk = src.getString("src1");
+ String vodName = src.getString("caption");
+ String playURL = "https://ddrk.tv/getvddr/video?id=" + adk + "&type=mix";
+ String zm = "https://ddrk.tv/subddr/" + src.getString("subsrc");
+ String pzm = playURL + "|" + zm;
+ vodItems.add(vodName + "$" + pzm);
+ }
+ vod_play.put(sourceName, TextUtils.join("#", vodItems));
+ }
+ Elements sources = doc.select(".post-page-numbers");
+ if (!sources.isEmpty())
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ sourceName = "第" + source.text() + "季";
+ String Purl = siteUrl + "/" + ids.get(0) + "/" + source.text() + "/";
+ Document docs = Jsoup.parse(OkHttpUtil.string(Purl, getHeaders(Purl)));
+ Elements allScripts = docs.select(".wp-playlist-script");
+ for (int j = 0; j < allScripts.size(); j++) {
+ String scContent = allScripts.get(j).html().trim();
+ int start = scContent.indexOf('{');
+ int end = scContent.lastIndexOf('}') + 1;
+ String json = scContent.substring(start, end);
+ JSONObject UJson = new JSONObject(json);
+ JSONArray Track = UJson.getJSONArray("tracks");
+ for (int k = 0; k < Track.length(); k++) {
+ JSONObject src = Track.getJSONObject(k);
+ String adk = src.getString("src1");
+ String vodName = src.getString("caption");
+ String playURL = "https://ddrk.tv/getvddr/video?id=" + adk + "&type=mix";
+ String zm = "https://ddrk.tv/subddr/" + src.getString("subsrc");
+ String pzm = playURL + "|" + zm;
+ vodItems2.add(vodName + "$" + pzm);
+ }
+ vod_play.put(sourceName, TextUtils.join("#", vodItems2));
+ }
+ vodItems2.removeAll(vodItems2);
+ }
+
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ public static Object[] loadsub(String sub) {
+ try {
+ OKCallBack.OKCallBackDefault callBack = new OKCallBack.OKCallBackDefault() {
+ @Override
+ protected void onFailure(Call call, Exception e) {
+
+ }
+
+ @Override
+ protected void onResponse(Response response) {
+
+ }
+ };
+ OkHttpClient YM = OkHttpUtil.defaultClient();
+ OkHttpUtil.get(YM, sub, null, Headers(), callBack);
+ Response result = callBack.getResult();
+ int code = result.code();
+ if (code == 404) {
+ return new Object[]{200, "application/octet-stream", new ByteArrayInputStream("WEBVTT".getBytes())};
+ }
+ ResponseBody body = result.body();
+ byte[] bytes = body.bytes();
+ byte[] tokenkey = Arrays.copyOfRange(bytes, 0, 16);
+ byte[] data = Arrays.copyOfRange(bytes, 16, bytes.length);
+ byte[] KS = CBC.CBC(data, tokenkey, tokenkey);
+ String vtt = gZip.KS(KS);
+
+
+ vtt = vtt.replaceAll("(\\d{2}:\\d{2}:\\d{2}.\\d{3}.+\\d{2}:\\d{2}:\\d{2}.\\d{3}).*", "$1");
+ vtt = vtt.replaceAll("(\\d{2}:\\d{2}.\\d{3}).*?( --> )(\\d{2}:\\d{2}.\\d{3}).*", "00:$1$200:$3");
+ BufferedReader br = new BufferedReader(new StringReader(vtt));
+ ArrayList lines = new ArrayList<>();
+ int captionNumber = 1;
+ String line = br.readLine();
+ while (line != null) {
+ if (line.matches("\\d{2}:\\d{2}:\\d{2}.\\d{3}.+\\d{2}:\\d{2}:\\d{2}.\\d{3}")) {
+ if (lines.get(lines.size() - 1).trim().isEmpty()) {
+ lines.add(captionNumber + "");
+ captionNumber++;
+ }
+ }
+ lines.add(line);
+ line = br.readLine();
+ }
+ String join = TextUtils.join("\n", lines);
+
+ return new Object[]{200, "application/octet-stream", new ByteArrayInputStream(join.getBytes())};
+ } catch (Exception e) {
+ e.printStackTrace();
+ SpiderDebug.log(e);
+ return null;
+ }
+ }
+
+
+ /**
+ * 获取视频播放信息
+ *
+ * @param flag 播放源
+ * @param id 视频id
+ * @param vipFlags 所有可能需要vip解析的源
+ * @return
+ */
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ String[] item = id.split("\\|");
+ String playUrl = item[0];
+ String ZiMu = item[1];
+
+ String content = OkHttpUtil.string(playUrl, getHeaders(playUrl));
+ JSONObject obj = new JSONObject(content);
+ String RealUrl = obj.optString("url");
+ JSONObject result = new JSONObject();
+ result.put("parse", 0);
+ result.put("playUrl", "");
+ result.put("url", RealUrl);
+ result.put("header", "");
+ // if (!TextUtils.isEmpty(str4)) {
+ result.put("subf", "/vtt/utf-8");
+ result.put("subt", Proxy.localProxyUrl() + "?do=ddrk&url=" + URLEncoder.encode(ZiMu));
+ // result.put("subt", ZiMu);
+ // }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ String url = "https://www.google.com/search?q=site%3Addrk.tv+" + URLEncoder.encode(key);
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONArray videos = new JSONArray();
+ String sourceName = doc.select("div.yuRUbf a h3").text();
+ if (sourceName.contains(key)) {
+ String list1 = doc.select("div.yuRUbf a").attr("href");
+ Document ddrklink = Jsoup.parse(OkHttpUtil.string(list1, getHeaders(list1)));
+ String DDlink = ddrklink.select("link[rel=canonical]").attr("href");
+ Matcher matcher = regexVid.matcher(DDlink);
+ if (matcher.find()) {
+ JSONObject v = new JSONObject();
+ String group = matcher.group(1);
+ String ab = ddrklink.select("h1.post-title").text();
+ String cover = ddrklink.select("div.post img").attr("src");
+ if (ab.contains("(")) {
+ String[] b = ab.split("\\(");
+ String title = b[0];
+ String remark = b[1].replace("(", "");
+ v.put("vod_name", title);
+ v.put("vod_remarks", remark);
+ } else {
+ v.put("vod_name", ab);
+ String remark = "全";
+ v.put("vod_remarks", remark);
+ }
+ v.put("vod_id", group);
+ v.put("vod_pic", cover);
+ videos.put(v);
+ }
+ }
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ private static String doReplaceRegex(Pattern pattern, String src) {
+ if (pattern == null)
+ return src;
+ try {
+ Matcher matcher = pattern.matcher(src);
+ if (matcher.find()) {
+ return matcher.group(1).trim();
+ }
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return src;
+ }
+
+
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Ddys.java b/app/src/main/java/com/github/catvod/spider/Ddys.java
new file mode 100644
index 0000000..784637b
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Ddys.java
@@ -0,0 +1,627 @@
+package com.github.catvod.spider;
+
+import android.text.TextUtils;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.AES;
+import com.github.catvod.utils.CBC;
+import com.github.catvod.utils.gZip;
+import com.github.catvod.utils.okhttp.OKCallBack;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import okhttp3.Call;
+import okhttp3.OkHttpClient;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+
+/**
+ * Demo for self study
+ *
+ * Source from Author: CatVod
+ */
+
+public class Ddys extends Spider {
+
+ private static final String siteUrl = "https://ddys.tv";
+ private static final String siteHost = "ddys.tv";
+ private String cookie="";
+
+ protected JSONObject filterConfig;
+
+ protected Pattern regexCategory = Pattern.compile("/category/(\\S+)/");
+ protected Pattern regexVid = Pattern.compile("https://ddys.tv/(\\S+)/");
+
+ protected Pattern regexPage = Pattern.compile("\\S+/page/(\\S+)\\S+");
+ protected Pattern m = Pattern.compile("\\S+(http\\S+g)");
+ protected Pattern mark = Pattern.compile("\\S+(.*)");
+
+ // protected Pattern t = Pattern.compile("(\\S+)");
+
+
+ /**
+ * 爬虫headers
+ *
+ * @param url
+ * @return
+ */
+ protected HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.62 Safari/537.36");
+ headers.put("Referer", "https://ddys.tv/");
+ if(cookie.length()>0 && !url.contains(("google"))){
+ headers.put("Cookie", cookie);
+ }
+ return headers;
+ }
+
+ protected static HashMap Headers() {
+ HashMap headers = new HashMap<>();
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Referer", "https://ddys.tv/");
+ return headers;
+ }
+
+ /**
+ * 获取分类数据 + 首页最近更新视频列表数据
+ *
+ * @param filter 是否开启筛选 关联的是 软件设置中 首页数据源里的筛选开关
+ * @return
+ */
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ String url = siteUrl + '/';
+ cookie="";
+ Map> cookies = new HashMap<>();
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url),cookies));
+ for( Map.Entry> entry : cookies.entrySet() ){
+ if(entry.getKey().equals("set-cookie")){
+ cookie = TextUtils.join(";",entry.getValue());
+ break;
+ }
+ }
+ Elements elements = doc.select("li.menu-item a");
+ JSONArray classes = new JSONArray();
+ ArrayList allClass = new ArrayList<>();
+ for (Element ele : elements) {
+ String name = ele.attr("title");
+ boolean show = !filter || (name.equals("热映中")
+ || name.equals("欧美剧")
+ || name.equals("日剧")
+ || name.equals("韩剧")
+ || name.equals("华语剧")
+ || name.equals("其他地区")
+ || name.equals("全部")
+ || name.equals("欧美电影")
+ || name.equals("日韩电影")
+ || name.equals("华语电影")
+ || name.equals("新番")
+ || name.equals("动画")
+ || name.equals("纪录片")
+ || name.equals("综艺"));
+ if (allClass.contains(name))
+ show = false;
+ if (show) {
+ allClass.add(name);
+ Matcher mather = regexCategory.matcher(ele.attr("href"));
+ if (!mather.find())
+ continue;
+ // 把分类的id和名称取出来加到列表里
+ String id = mather.group(1).trim();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_id", id);
+ jsonObject.put("type_name", name);
+ classes.put(jsonObject);
+ }
+ }
+ JSONObject result = new JSONObject();
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ result.put("class", classes);
+ try {
+ // 取首页推荐视频列表
+ Elements list = doc.select("div.post-box-container");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String a = vod.selectFirst(".post-box-title a").text();
+ if (a.contains("(")) {
+ String[] item = a.split("\\(");
+ String title = item[0];
+ String remark = item[1].replace(")", "");
+ String cover = doReplaceRegex(m, vod.selectFirst(".post-box-image").attr("style"));
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".post-box-title a").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ } else {
+ String title = a;
+ String cover = doReplaceRegex(m, vod.selectFirst(".post-box-image").attr("style"));
+ String remark = doReplaceRegex(mark, vod.selectFirst(".post-box-title a").text());
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".post-box-title a").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ /**
+ * 获取分类信息数据
+ *
+ * @param tid 分类id
+ * @param pg 页数
+ * @param filter 同homeContent方法中的filter
+ * @param extend 筛选参数{k:v, k1:v1}
+ * @return
+ */
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ String url = "";
+ try {
+ if (extend != null && extend.size() > 0) {
+ for (Iterator it = extend.keySet().iterator(); it.hasNext(); ) {
+ String key = it.next();
+ String value = extend.get(key);
+ if (value != null && value.length() != 0 && value != " ") {
+ url = siteUrl + "/category/" + tid + "/" + value;
+ } else {
+ url = siteUrl + "/category/" + tid;
+ }
+ ;
+ }
+ } else {
+ url = siteUrl + "/category/" + tid;
+ }
+ ;
+ if (pg.equals("1")) {
+ url = url + "/";
+ } else {
+ url = url + "/page/" + pg + "/";
+ }
+ //System.out.println(url);
+ String html = OkHttpUtil.string(url, getHeaders(url));
+ Document doc = Jsoup.parse(html);
+ JSONObject result = new JSONObject();
+ int pageCount = 0;
+ int page = -1;
+
+ // 取页码相关信息
+ Elements pageInfo = doc.select("div.nav-links");
+ if (pageInfo.size() == 0) {
+ page = Integer.parseInt(pg);
+ pageCount = page;
+ } else {
+ for (int i = 0; i < pageInfo.size(); i++) {
+ Element li = pageInfo.get(i);
+ Element a = li.selectFirst("a");
+ if (a == null)
+ continue;
+ String wy = doc.select("div.nav-links a").last().attr("href");
+ String span = doc.select("span.current").text().trim();
+ if (page == -1) {
+ page = Integer.parseInt(span);
+ } else {
+
+ page = 0;
+ }
+ Matcher matcher = regexPage.matcher(wy);
+ if (matcher.find()) {
+ //System.out.println("尾页" + matcher.group(1));
+ pageCount = Integer.parseInt(matcher.group(1));
+ } else {
+ pageCount = 0;
+ }
+ break;
+ }
+ }
+
+ JSONArray videos = new JSONArray();
+ if (!html.contains("没有找到您想要的结果哦")) {
+ // 取当前分类页的视频列表
+ Elements list = doc.select("div.post-box-container");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String a = vod.selectFirst(".post-box-title a").text();
+ if (a.contains("(")) {
+ String[] item = a.split("\\(");
+ String title = item[0];
+ String remark = item[1].replace(")", "");
+ String cover = doReplaceRegex(m, vod.selectFirst(".post-box-image").attr("style"));
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".post-box-title a").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ } else {
+ String title = a;
+ String cover = doReplaceRegex(m, vod.selectFirst(".post-box-image").attr("style"));
+ String remark = doReplaceRegex(mark, vod.selectFirst(".post-box-title a").text());
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".post-box-title a").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ }
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", 24);
+ result.put("total", pageCount <= 1 ? videos.length() : pageCount * 24);
+
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 视频详情信息
+ *
+ * @param ids 视频id
+ * @return
+ */
+ @Override
+ public String detailContent(List ids) {
+ try {
+ // 视频详情url
+ String url = siteUrl + "/" + ids.get(0) + "/";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+
+ // 取基本数据
+ String cover = doc.select("div.post img").attr("src");
+ String ab = doc.select("h1.post-title").text();
+ if (ab.contains("(")) {
+ String[] b = ab.split("\\(");
+ String title = b[0];
+ String remark = b[1].replace("(", "");
+ vodList.put("vod_name", title);
+ vodList.put("vod_remarks", remark);
+ } else {
+ vodList.put("vod_name", ab);
+ String remark = doc.select("time").text().trim();
+ vodList.put("vod_remarks", "全");
+ }
+ String str2 = doc.select("div.abstract").text().replace(" ", "");
+ String replace = str2.replace("
", "");
+ String text = replace.replace("", "");
+ Pattern categorys = Pattern.compile("类型:(.*)制");
+ String category = doReplaceRegex(categorys, text);
+ Pattern a = Pattern.compile("年份:(.*)简");
+ String year = doReplaceRegex(a, text);
+ Pattern b = Pattern.compile("地区:(.*)年份");
+ String area = doReplaceRegex(b, text);
+ Pattern c = Pattern.compile("演员:(.*)类");
+ String actor = doReplaceRegex(c, text);
+ Pattern d = Pattern.compile("导演:(.*)演");
+ String director = doReplaceRegex(d, text);
+ Pattern e = Pattern.compile("简介:(.*)");
+ String desc = doReplaceRegex(e, text);
+
+
+ vodList.put("vod_id", ids.get(0));
+ vodList.put("vod_pic", cover);
+ vodList.put("type_name", category);
+ vodList.put("vod_year", year);
+ vodList.put("vod_area", area);
+ vodList.put("vod_actor", actor);
+ vodList.put("vod_director", director);
+ vodList.put("vod_content", desc);
+
+ List vodItems = new ArrayList<>();
+ List vodItems2 = new ArrayList<>();
+ List vodItemsos = new ArrayList<>();
+ List vodItems2os = new ArrayList<>();
+ Map vod_play = new LinkedHashMap<>();
+
+ Elements allScript = doc.select(".wp-playlist-script");
+ String sourceName = "第1季";
+ for (int j = 0; j < allScript.size(); j++) {
+ String scContent = allScript.get(j).html().trim();
+ int start = scContent.indexOf('{');
+ int end = scContent.lastIndexOf('}') + 1;
+ String json = scContent.substring(start, end);
+ JSONObject UJson = new JSONObject(json);
+ JSONArray Track = UJson.getJSONArray("tracks");
+ for (int k = 0; k < Track.length(); k++) {
+ JSONObject src = Track.getJSONObject(k);
+ String adk = src.getString("src1");
+ String vodName = src.getString("caption");
+ String playURL = "https://ddys.tv/getvddr/video?id=" + adk +"&dim=1080P+&type=mix";
+ String zm = "https://ddys.tv/subddr/" + src.getString("subsrc");
+ String pzm = playURL + "|" + zm;
+ vodItems.add(vodName + "$" + pzm);
+ }
+ for (int k = 0; k < Track.length(); k++) {
+ JSONObject src = Track.getJSONObject(k);
+ String adksrc0 = src.getString("src0");
+ String adksrc2 = src.getString("src2");
+ String vodName = src.getString("caption");
+ String playURL = "https://w.ddys.tv" + adksrc0 +"?ddrkey=" + adksrc2;
+ String zm = "https://ddys.tv/subddr/" + src.getString("subsrc");
+ String pzm = playURL + "|" + zm;
+ vodItemsos.add(vodName + "$" + pzm);
+ }
+ vod_play.put(sourceName, TextUtils.join("#", vodItems));
+ vod_play.put(sourceName+":海外", TextUtils.join("#", vodItemsos));
+ }
+
+
+ Elements sources = doc.select(".post-page-numbers");
+ if (!sources.isEmpty())
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ sourceName = "第" + source.text() + "季";
+ String Purl = siteUrl + "/" + ids.get(0) + "/" + source.text() + "/";
+ Document docs = Jsoup.parse(OkHttpUtil.string(Purl, getHeaders(Purl)));
+ Elements allScripts = docs.select(".wp-playlist-script");
+ for (int j = 0; j < allScripts.size(); j++) {
+ String scContent = allScripts.get(j).html().trim();
+ int start = scContent.indexOf('{');
+ int end = scContent.lastIndexOf('}') + 1;
+ String json = scContent.substring(start, end);
+ JSONObject UJson = new JSONObject(json);
+ JSONArray Track = UJson.getJSONArray("tracks");
+ for (int k = 0; k < Track.length(); k++) {
+ JSONObject src = Track.getJSONObject(k);
+ String adk = src.getString("src1");
+ String vodName = src.getString("caption");
+ String playURL = "https://ddys.tv/getvddr/video?id=" + adk +"&dim=1080P+&type=mix";
+ String zm = "https://ddys.tv/subddr/" + src.getString("subsrc");
+ String pzm = playURL + "|" + zm;
+ vodItems2.add(vodName + "$" + pzm);
+ }
+ for (int k = 0; k < Track.length(); k++) {
+ JSONObject src = Track.getJSONObject(k);
+ String adksrc0 = src.getString("src0");
+ String adksrc2 = src.getString("src2");
+ String vodName = src.getString("caption");
+ String playURL = "https://w.ddys.tv" + adksrc0 +"?ddrkey=" + adksrc2;
+ String zm = "https://ddys.tv/subddr/" + src.getString("subsrc");
+ String pzm = playURL + "|" + zm;
+ vodItems2os.add(vodName + "$" + pzm);
+ }
+ vod_play.put(sourceName, TextUtils.join("#", vodItems2));
+ vod_play.put(sourceName+":海外", TextUtils.join("#", vodItems2os));
+ }
+ vodItems2.removeAll(vodItems2);
+ vodItems2os.removeAll(vodItems2os);
+ }
+
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ public static Object[] loadsub(String sub) {
+ try {
+ OKCallBack.OKCallBackDefault callBack = new OKCallBack.OKCallBackDefault() {
+ @Override
+ protected void onFailure(Call call, Exception e) {
+
+ }
+
+ @Override
+ protected void onResponse(Response response) {
+
+ }
+ };
+ OkHttpClient YM = OkHttpUtil.defaultClient();
+ OkHttpUtil.get(YM, sub, null, Headers(), callBack);
+ Response result = callBack.getResult();
+ int code = result.code();
+ if (code == 404) {
+ return new Object[]{200, "application/octet-stream", new ByteArrayInputStream("WEBVTT".getBytes())};
+ }
+ ResponseBody body = result.body();
+ byte[] bytes = body.bytes();
+ byte[] tokenkey = Arrays.copyOfRange(bytes, 0, 16);
+ byte[] data = Arrays.copyOfRange(bytes, 16, bytes.length);
+ byte[] KS = CBC.CBC(data, tokenkey, tokenkey);
+ String vtt = gZip.KS(KS);
+
+
+ vtt = vtt.replaceAll("(\\d{2}:\\d{2}:\\d{2}.\\d{3}.+\\d{2}:\\d{2}:\\d{2}.\\d{3}).*", "$1");
+ vtt = vtt.replaceAll("(\\d{2}:\\d{2}.\\d{3}).*?( --> )(\\d{2}:\\d{2}.\\d{3}).*", "00:$1$200:$3");
+ BufferedReader br = new BufferedReader(new StringReader(vtt));
+ ArrayList lines = new ArrayList<>();
+ int captionNumber = 1;
+ String line = br.readLine();
+ while (line != null) {
+ if (line.matches("\\d{2}:\\d{2}:\\d{2}.\\d{3}.+\\d{2}:\\d{2}:\\d{2}.\\d{3}")) {
+ if (lines.get(lines.size() - 1).trim().isEmpty()) {
+ lines.add(captionNumber + "");
+ captionNumber++;
+ }
+ }
+ lines.add(line);
+ line = br.readLine();
+ }
+ String join = TextUtils.join("\n", lines);
+
+ return new Object[]{200, "application/octet-stream", new ByteArrayInputStream(join.getBytes())};
+ } catch (Exception e) {
+ e.printStackTrace();
+ SpiderDebug.log(e);
+ return null;
+ }
+ }
+
+
+ /**
+ * 获取视频播放信息
+ *
+ * @param flag 播放源
+ * @param id 视频id
+ * @param vipFlags 所有可能需要vip解析的源
+ * @return
+ */
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ JSONObject result = new JSONObject();
+ String[] item = id.split("\\|");
+ String playUrl = item[0];
+ String ZiMu = item[1];
+ String RealUrl="";
+ if(playUrl.contains("ddrkey")){
+ Map> respHeaders = new HashMap<>();
+ OkHttpUtil.stringNoRedirect(playUrl, getHeaders(playUrl),respHeaders);
+ RealUrl = OkHttpUtil.getRedirectLocation(respHeaders);
+ } else {
+ String content = OkHttpUtil.string(playUrl, getHeaders(playUrl));
+ JSONObject obj = new JSONObject(content);
+ RealUrl = obj.optString("url");
+ }
+
+ result.put("parse", 0);
+ result.put("playUrl", "");
+ result.put("url", RealUrl);
+ result.put("header", "");
+ // if (!TextUtils.isEmpty(str4)) {
+ result.put("subf", "/vtt/utf-8");
+ result.put("subt", Proxy.localProxyUrl() + "?do=ddys&url=" + URLEncoder.encode(ZiMu));
+ // result.put("subt", ZiMu);
+ // }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ String url = "https://www.google.com/search?q=site%3Addys.tv+" + URLEncoder.encode(key);
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONArray videos = new JSONArray();
+ String sourceName = doc.select("div.yuRUbf a h3").text();
+ if (sourceName.contains(key)) {
+ String list1 = doc.select("div.yuRUbf a").attr("href");
+ Document ddrklink = Jsoup.parse(OkHttpUtil.string(list1, getHeaders(list1)));
+ String DDlink = ddrklink.select("link[rel=canonical]").attr("href");
+ Matcher matcher = regexVid.matcher(DDlink);
+ if (matcher.find()) {
+ JSONObject v = new JSONObject();
+ String group = matcher.group(1);
+ String ab = ddrklink.select("h1.post-title").text();
+ String cover = ddrklink.select("div.post img").attr("src");
+ if (ab.contains("(")) {
+ String[] b = ab.split("\\(");
+ String title = b[0];
+ String remark = b[1].replace("(", "");
+ v.put("vod_name", title);
+ v.put("vod_remarks", remark);
+ } else {
+ v.put("vod_name", ab);
+ String remark = "全";
+ v.put("vod_remarks", remark);
+ }
+ v.put("vod_id", group);
+ v.put("vod_pic", cover);
+ videos.put(v);
+ }
+ }
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ private static String doReplaceRegex(Pattern pattern, String src) {
+ if (pattern == null)
+ return src;
+ try {
+ Matcher matcher = pattern.matcher(src);
+ if (matcher.find()) {
+ return matcher.group(1).trim();
+ }
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return src;
+ }
+
+
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Dy555.java b/app/src/main/java/com/github/catvod/spider/Dy555.java
new file mode 100644
index 0000000..03017a2
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Dy555.java
@@ -0,0 +1,568 @@
+package com.github.catvod.spider;
+
+
+import static java.lang.System.*;
+
+import okhttp3.*;
+import okio.ByteString;
+
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.concurrent.TimeUnit;
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.net.URLEncoder;
+import java.security.Key;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Response;
+
+
+
+
+public class Dy555 extends Spider {
+
+ private static final String siteUrl = "https://www.555dianying.cc";
+
+ protected JSONObject playerConfig;
+ protected JSONObject filterConfig;
+
+ protected Pattern regexCategory = Pattern.compile("/vodtype/(\\d+).html");
+ protected Pattern regexVoddetail = Pattern.compile("/voddetail/(\\d+).html");
+ protected Pattern regexPlay = Pattern.compile("/vodplay/(\\S+).html");
+ protected Pattern regexPage = Pattern.compile("\\d+/(\\d+)");
+
+
+ private final String filterString = "{\"1\":[{\"name\":\"年份\",\"key\":\"year\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2022\",\"v\":\"2022\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]},{\"name\":\"地区\",\"key\":\"area\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"大陆\",\"v\":\"大陆\"},{\"n\":\"香港\",\"v\":\"香港\"},{\"n\":\"台湾\",\"v\":\"台湾\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"法国\",\"v\":\"法国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"德国\",\"v\":\"德国\"},{\"n\":\"泰国\",\"v\":\"泰国\"},{\"n\":\"印度\",\"v\":\"印度\"},{\"n\":\"意大利\",\"v\":\"意大利\"},{\"n\":\"西班牙\",\"v\":\"西班牙\"},{\"n\":\"加拿大\",\"v\":\"加拿大\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"name\":\"类型\",\"key\":\"class\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"动作\",\"v\":\"动作\"},{\"n\":\"喜剧\",\"v\":\"喜剧\"},{\"n\":\"爱情\",\"v\":\"爱情\"},{\"n\":\"科幻\",\"v\":\"科幻\"},{\"n\":\"恐怖\",\"v\":\"恐怖\"},{\"n\":\"剧情\",\"v\":\"剧情\"},{\"n\":\"战争\",\"v\":\"战争\"},{\"n\":\"悬疑\",\"v\":\"悬疑\"},{\"n\":\"冒险\",\"v\":\"冒险\"},{\"n\":\"犯罪\",\"v\":\"犯罪\"},{\"n\":\"奇幻\",\"v\":\"奇幻\"},{\"n\":\"惊悚\",\"v\":\"惊悚\"},{\"n\":\"青春\",\"v\":\"青春\"},{\"n\":\"动画\",\"v\":\"动画\"}]},{\"name\":\"排序\",\"key\":\"by\",\"value\":[{\"n\":\"最新\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"2\":[{\"name\":\"年份\",\"key\":\"year\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2022\",\"v\":\"2022\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]},{\"name\":\"地区\",\"key\":\"area\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"内地\",\"v\":\"内地\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"香港\",\"v\":\"香港\"},{\"n\":\"台湾\",\"v\":\"台湾\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"泰国\",\"v\":\"泰国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"新加坡\",\"v\":\"新加坡\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"name\":\"类型\",\"key\":\"class\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"古装\",\"v\":\"古装\"},{\"n\":\"战争\",\"v\":\"战争\"},{\"n\":\"青春偶像\",\"v\":\"青春偶像\"},{\"n\":\"喜剧\",\"v\":\"喜剧\"},{\"n\":\"家庭\",\"v\":\"家庭\"},{\"n\":\"犯罪\",\"v\":\"犯罪\"},{\"n\":\"动作\",\"v\":\"动作\"},{\"n\":\"奇幻\",\"v\":\"奇幻\"},{\"n\":\"剧情\",\"v\":\"剧情\"},{\"n\":\"历史\",\"v\":\"历史\"},{\"n\":\"经典\",\"v\":\"经典\"},{\"n\":\"乡村\",\"v\":\"乡村\"},{\"n\":\"情景\",\"v\":\"情景\"},{\"n\":\"商战\",\"v\":\"商战\"},{\"n\":\"网剧\",\"v\":\"网剧\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"name\":\"排序\",\"key\":\"by\",\"value\":[{\"n\":\"最新\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"3\":[{\"name\":\"年份\",\"key\":\"year\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2022\",\"v\":\"2022\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]},{\"name\":\"地区\",\"key\":\"area\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"内地\",\"v\":\"内地\"},{\"n\":\"港台\",\"v\":\"港台\"},{\"n\":\"日韩\",\"v\":\"日韩\"},{\"n\":\"欧美\",\"v\":\"欧美\"}]},{\"name\":\"排序\",\"key\":\"by\",\"value\":[{\"n\":\"最新\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"5\":[{\"name\":\"年份\",\"key\":\"year\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2022\",\"v\":\"2022\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]},{\"name\":\"类型\",\"key\":\"class\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"番剧\",\"v\":\"番剧\"},{\"n\":\"国创\",\"v\":\"国创\"},{\"n\":\"动画片\",\"v\":\"动画片\"}]},{\"name\":\"排序\",\"key\":\"by\",\"value\":[{\"n\":\"最新\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}]}";
+ private final String playerString = "{\"xg_app_player\":{\"show\":\"app全局解析\",\"des\":\"\",\"ps\":\"1\",\"parse\":\"https://www.x-n.cc/api.php?url=\"},\"duoduozy\":{\"show\":\"555蓝光\",\"des\":\"\",\"ps\":\"0\",\"api\":\"https://zyz.sdljwomen.com/newduoduo/555tZ4pvzHE3BpiO838.php\",\"parse\":\"https://zyz.sdljwomen.com/server_player/?url=\"},\"bilibili\":{\"show\":\"bilibili\",\"des\":\"\",\"ps\":\"0\",\"api\":\"https://jhpc.021huaying.com/newplayer/5348837768203767939.php\",\"parse\":\"https://jhpc.021huaying.com/newplayer/?url=\"},\"youku\":{\"show\":\"优酷\",\"des\":\"\",\"ps\":\"0\",\"api\":\"https://jhpc.021huaying.com/newplayer/5348837768203767939.php\",\"parse\":\"https://jhpc.021huaying.com/newplayer/?url=\"},\"qiyi\":{\"show\":\"爱奇艺\",\"des\":\"\",\"ps\":\"0\",\"api\":\"https://jhpc.021huaying.com/newplayer/5348837768203767939.php\",\"parse\":\"https://jhpc.021huaying.com/newplayer/?url=\"},\"mgtv\":{\"show\":\"芒果\",\"des\":\"\",\"ps\":\"0\",\"api\":\"https://jhpc.021huaying.com/newplayer/5348837768203767939.php\",\"parse\":\"https://jhpc.021huaying.com/newplayer/?url=\"},\"qq\":{\"show\":\"腾讯\",\"des\":\"\",\"ps\":\"0\",\"api\":\"https://jhpc.021huaying.com/newplayer/5348837768203767939.php\",\"parse\":\"https://jhpc.021huaying.com/newplayer/?url=\"},\"sohu\":{\"show\":\"搜狐\",\"des\":\"\",\"ps\":\"0\",\"api\":\"https://jhpc.021huaying.com/newplayer/5348837768203767939.php\",\"parse\":\"https://jhpc.021huaying.com/newplayer/?url=\"},\"pptv\":{\"show\":\"PPTV\",\"des\":\"\",\"ps\":\"0\",\"api\":\"https://jhpc.021huaying.com/newplayer/5348837768203767939.php\",\"parse\":\"https://jhpc.021huaying.com/newplayer/?url=\"},\"m1905\":{\"show\":\"m1905\",\"des\":\"\",\"ps\":\"0\",\"api\":\"https://jhpc.021huaying.com/newplayer/5348837768203767939.php\",\"parse\":\"https://jhpc.021huaying.com/newplayer/?url=\"},\"xigua\":{\"show\":\"西瓜视频\",\"des\":\"\",\"ps\":\"0\",\"api\":\"https://jhpc.021huaying.com/newplayer/5348837768203767939.php\",\"parse\":\"https://jhpc.021huaying.com/newplayer/?url=\"},\"fuckapp\":{\"show\":\"独家线路\",\"des\":\"555自建资源\",\"ps\":\"0\",\"parse\":\"https://dp.dd520.cc/p.php?url=\"},\"letv\":{\"show\":\"乐视\",\"des\":\"\",\"ps\":\"0\",\"api\":\"https://jhpc.021huaying.com/newplayer/5348837768203767939.php\",\"parse\":\"https://jhpc.021huaying.com/newplayer/?url=\"},\"yemao\":{\"show\":\"优质线路1\",\"des\":\"极速蓝光\",\"ps\":\"0\",\"parse\":\"https://jx.manduhu.com/?url=\"},\"sdm3u8\":{\"show\":\"闪电线路\",\"des\":\"闪电\",\"ps\":\"0\",\"api\":\"https://zyz.sdljwomen.com/newm3u8/5348837768203767939.php\",\"parse\":\"https://zyz.sdljwomen.com/newm3u8/?url=\"},\"fsm3u8\":{\"show\":\"飞速线路\",\"des\":\"飞速\",\"ps\":\"0\",\"api\":\"https://zyz.sdljwomen.com/newm3u8/5348837768203767939.php\",\"parse\":\"https://zyz.sdljwomen.com/newm3u8/?url=\"},\"wjm3u8\":{\"show\":\"无尽线路\",\"des\":\"无尽\",\"ps\":\"0\",\"api\":\"https://zyz.sdljwomen.com/newm3u8/5348837768203767939.php\",\"parse\":\"https://zyz.sdljwomen.com/newm3u8/?url=\"},\"dbm3u8\":{\"show\":\"百度线路\",\"des\":\"百度\",\"ps\":\"0\",\"api\":\"https://zyz.sdljwomen.com/newm3u8/5348837768203767939.php\",\"parse\":\"https://zyz.sdljwomen.com/newm3u8/?url=\"},\"tkm3u8\":{\"show\":\"天空线路\",\"des\":\"天空\",\"ps\":\"0\",\"api\":\"https://zyz.sdljwomen.com/newm3u8/5348837768203767939.php\",\"parse\":\"https://zyz.sdljwomen.com/newm3u8/?url=\"},\"kbm3u8\":{\"show\":\"快播线路\",\"des\":\"快播\",\"ps\":\"0\",\"api\":\"https://zyz.sdljwomen.com/newm3u8/5348837768203767939.php\",\"parse\":\"https://zyz.sdljwomen.com/newm3u8/?url=\"},\"zhibo\":{\"show\":\"直播\",\"des\":\"\",\"ps\":\"1\",\"parse\":\"http://suoyou.live/dplay/zb.php?url=\"},\"dujia\":{\"show\":\"独家专线\",\"des\":\"\",\"ps\":\"0\",\"api\":\"https://zyz.sdljwomen.com/newm3u8/5348837768203767939.php\",\"parse\":\"https://zyz.sdljwomen.com/newm3u8/?url=\"}}";
+ private String rs="";
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ try {
+ playerConfig = new JSONObject(playerString);
+ filterConfig = new JSONObject(filterString);
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ /**
+ * 爬虫headers
+ *
+ * @param refererUrl
+ * @return
+ */
+ protected HashMap getHeaders(String refererUrl) {
+ HashMap headers = new HashMap<>();
+ headers.put("method", "GET");
+ if (!TextUtils.isEmpty(refererUrl)) {
+ headers.put("Referer", refererUrl);
+ }
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
+ return headers;
+ }
+
+ /**
+ * 获取分类数据 + 首页最近更新视频列表数据
+ *
+ * @param filter 是否开启筛选 关联的是 软件设置中 首页数据源里的筛选开关
+ * @return
+ */
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ String url = siteUrl + '/';
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(siteUrl)));
+ Elements elements = doc.select("ul.navbar-items > li > a[href*='vodtype']");
+ JSONArray classes = new JSONArray();
+ for (Element ele : elements) {
+ String name = ele.text();
+ String href = ele.attr("href");
+ Matcher mather = regexCategory.matcher(href);
+ if (!mather.find() || name.contains("福利"))
+ continue;
+ // 把分类的id和名称取出来加到列表里
+ String id = mather.group(1).trim();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_id", id);
+ jsonObject.put("type_name", name);
+ classes.put(jsonObject);
+ }
+
+ JSONObject result = new JSONObject();
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ result.put("class", classes);
+ try {
+ // 取首页推荐视频列表
+ Elements list = doc.select("div.module-items> a[href*='voddetail']");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.attr("title");
+ String cover = vod.selectFirst("img").attr("data-original");
+ String remark = vod.selectFirst("div.module-item-note").text();
+ Matcher matcher = regexVoddetail.matcher(vod.attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ /**
+ * 获取分类信息数据
+ *
+ * @param tid 分类id
+ * @param pg 页数
+ * @param filter 同homeContent方法中的filter
+ * @param extend 筛选参数{k:v, k1:v1}
+ * @return
+ */
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ int page = 1;
+ if (!TextUtils.isEmpty(pg) && Integer.parseInt(pg.trim()) > 1) {
+ page = Integer.parseInt(pg.trim());
+ }
+ Map ext = new HashMap<>();
+ ext.put("id", tid);
+ ext.put("pg", "" + page);
+ if (extend != null && extend.size() > 0) {
+ ext.putAll(extend);
+ }
+// 13-内地-hits-古装-国语-A------2022.html
+ String id = ext.get("id") == null ? "" : ext.get("id");
+ String area = ext.get("area") == null ? "" : ext.get("area");
+ String by = ext.get("by") == null ? "" : ext.get("by");
+ String clazz = ext.get("class") == null ? "" : ext.get("class");
+ String lang = ext.get("lang") == null ? "" : ext.get("lang");
+ String spg = ext.get("pg") == null ? "" : ext.get("pg");
+ String year = ext.get("year") == null ? "" : ext.get("year");
+ String url = siteUrl + String.format("/vodshow/%s-%s-%s-%s-%s----%s---%s.html", id, area, by, clazz, lang, spg, year);
+ SpiderDebug.log(url);
+
+ String html = OkHttpUtil.string(url, getHeaders(siteUrl));
+ Document doc = Jsoup.parse(html);
+ JSONObject result = new JSONObject();
+ int pageCount = 1;
+
+ // 取页码相关信息
+ Elements pageInfo = doc.select("div[id='page'] > a:last-child");
+ if (pageInfo.size() > 0) {
+ String href = pageInfo.attr("href");
+ href = href.substring(9, href.length() - 4);
+ String pageCountNum = href.split("-")[9];
+ if (!TextUtils.isEmpty(pageCountNum)) {
+ pageCount = Integer.parseInt(pageCountNum);
+ }
+ }
+
+ JSONArray videos = new JSONArray();
+ // 取当前分类页的视频列表
+ Elements list = doc.select("div.module-items > a[href*='voddetail']");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.attr("title");
+ String cover = vod.selectFirst("img").attr("data-original");
+ String remark = vod.selectFirst("div.module-item-note").text();
+ Matcher matcher = regexVoddetail.matcher(vod.attr("href"));
+ if (matcher.find()) {
+ String vodId = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", vodId);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", 40);
+ result.put("total", pageCount <= 1 ? videos.length() : pageCount * 40);
+
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 视频详情信息
+ *
+ * @param ids 视频id
+ * @return
+ */
+ @Override
+ public String detailContent(List ids) {
+ try {
+ // 视频详情url
+ String url = siteUrl + "/voddetail/" + ids.get(0) + ".html";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(siteUrl)));
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+
+ // 取基本数据
+ String cover = doc.selectFirst("div.module-main img").attr("data-original");
+ String title = doc.selectFirst("div.module-main h1").text();
+ String desc = doc.selectFirst("div.module-main div.module-info-introduction-content >p").text();
+
+ vodList.put("vod_id", ids.get(0));
+ vodList.put("vod_name", title);
+ vodList.put("vod_pic", cover);
+ vodList.put("vod_content", desc);
+
+ Map vod_play = new LinkedHashMap<>();
+
+ // 取播放列表数据
+ Elements sources = doc.select("div[id='y-playList'] span");
+ Elements sourceList = doc.select("div.module-play-list");
+
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ String sourceName = source.text();
+ boolean found = false;
+ for (Iterator it = playerConfig.keys(); it.hasNext(); ) {
+ String flag = it.next();
+ if (playerConfig.getJSONObject(flag).getString("show").equals(sourceName)) {
+// sourceName = flag;
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ String playList = "";
+ Elements playListA = sourceList.get(i).select("a.module-play-list-link");
+ List vodItems = new ArrayList<>();
+
+ for (int j = 0; j < playListA.size(); j++) {
+ Element vod = playListA.get(j);
+ Matcher matcher = regexPlay.matcher(vod.attr("href"));
+ if (matcher.find()) {
+ String playURL = matcher.group(1);
+ String playUrlName = vod.text();
+ vodItems.add(playUrlName + "$" + playURL);
+ }
+ }
+ if (vodItems.size() > 0) {
+ playList = TextUtils.join("#", vodItems);
+ vod_play.put(sourceName, playList);
+ }
+ }
+ }
+
+ if (vod_play.size() > 0) {
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+ }
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+
+
+
+
+ /**
+ * 获取视频播放信息
+ *
+ * @param flag 播放源
+ * @param id 视频id
+ * @param vipFlags 所有可能需要vip解析的源
+ * @return
+ */
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ // 播放页 url
+ String url = siteUrl + "/vodplay/" + id + ".html";
+ JSONObject result = new JSONObject();
+ rs="";
+ SpiderDebug.log(url );
+
+ String htmlsrc = OkHttpUtil.string(url, getHeaders(url));
+ Document doc = Jsoup.parse(htmlsrc);
+ Elements allScript = doc.select("script");
+ String urlsrc=""; //加密url
+ for (int i = 0; i < allScript.size(); i++) {
+ String scContent = allScript.get(i).toString();
+ if (scContent.contains("var player_")) { // 取直链
+ int start = scContent.indexOf('{');
+ int end = scContent.lastIndexOf('}') + 1;
+ String json = scContent.substring(start, end);
+ JSONObject player = new JSONObject(json);
+ urlsrc = player.getString("url");
+ break;
+ }
+ }
+ String key="55ca5c48a943afdc";
+ String iv ="d11424dcecfe16c0";
+ String salt="55ca5c4d11424dcecfe16c08a943afdc";
+ String wssreqsrc="{\"type\":\"getUrl\",\"url\":\"\",\"sign\":\"\"}";
+ byte[] sasBytes = salt.getBytes();
+ Key hmacKey = new SecretKeySpec(sasBytes, "HmacSHA256");
+ Mac hmacSHA256 = Mac.getInstance("HmacSHA256");
+ hmacSHA256.init(hmacKey);
+ byte [] macData = hmacSHA256.doFinal(urlsrc.getBytes());
+ String sign = bytesToHexStr(macData) ;
+ JSONObject wssreq =new JSONObject(wssreqsrc);
+ wssreq.put("url",urlsrc);
+ wssreq.put("sign",sign);
+ String wssreqeny = encrypt(wssreq.toString(), key, iv);
+ String wss1="wss://player.sakurot.com:3458/wss";
+ String wss2="wss://player2.lscsfw.com:6723/wss";
+ int[] items = new int[]{1,2};
+ Random rand = new Random();
+ int wssurlint = items[rand.nextInt(items.length)];
+ String wssurl ="";
+ if( wssurlint==2 ){
+ wssurl =wss2;
+ }else{
+ wssurl =wss1;
+ }
+
+ wssClient(wssurl,wssreqeny);
+ Thread.sleep(100);
+ String wssrsp=rs;
+ String m3u8link = decrypt(wssrsp,key,iv);
+ JSONObject m3u8obj= new JSONObject(m3u8link);
+ String reallink = m3u8obj.getString("url");
+ if (reallink.length()>0){
+ result.put("parse", 0);
+ result.put("url", reallink);
+ result.put("header", new JSONObject(getHeaders2(url)).toString());
+ }else{
+ result.put("parse", 1);
+ result.put("url", url);
+ }
+ result.put("playUrl", "");
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public boolean manualVideoCheck() {
+ return true;
+ }
+
+ private String[] videoFormatList = new String[]{".m3u8", ".mp4", ".mpeg", ".flv"};
+
+ @Override
+ public boolean isVideoFormat(String url) {
+ url = url.toLowerCase();
+ if (url.contains("=http") || url.contains("=https") || url.contains("=https%3a%2f") || url.contains("=http%3a%2f")) {
+ return false;
+ }
+ for (String format : videoFormatList) {
+ if (url.contains(format)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ long currentTime = currentTimeMillis();
+ String url = siteUrl + "/index.php/ajax/suggest?mid=1&wd=" + URLEncoder.encode(key) + "&limit=10×tamp=" + currentTime;
+ JSONObject searchResult = new JSONObject(OkHttpUtil.string(url, getHeaders(siteUrl)));
+ JSONObject result = new JSONObject();
+ JSONArray videos = new JSONArray();
+ if (searchResult.getInt("total") > 0) {
+ JSONArray lists = new JSONArray(searchResult.getString("list"));
+ for (int i = 0; i < lists.length(); i++) {
+ JSONObject vod = lists.getJSONObject(i);
+ String id = vod.getString("id");
+ String title = vod.getString("name");
+ String cover = vod.getString("pic");
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", "");
+ videos.put(v);
+ }
+ }
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ protected String decrypt(String src, String KEY, String IV) {
+ try {
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
+ SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), "AES");
+ AlgorithmParameterSpec paramSpec = new IvParameterSpec(IV.getBytes());
+ cipher.init(Cipher.DECRYPT_MODE, keySpec, paramSpec);
+ return new String(cipher.doFinal(hex2byte(src)));
+ } catch (Exception exception) {
+ SpiderDebug.log(exception);
+ }
+ return null;
+ }
+ protected String encrypt(String src, String KEY, String IV) {
+ try {
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
+ SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), "AES");
+ AlgorithmParameterSpec paramSpec = new IvParameterSpec(IV.getBytes());
+ cipher.init(Cipher.ENCRYPT_MODE, keySpec, paramSpec);
+ return bytesToHexStr(cipher.doFinal(src.getBytes())).toUpperCase();
+ } catch (Exception exception) {
+ SpiderDebug.log(exception);
+ }
+ return null;
+ }
+
+ protected byte[] hex2byte(String hex) throws IllegalArgumentException {
+ if (hex.length() % 2 != 0){
+ throw new IllegalArgumentException("invalid hex string");
+ }
+ char[] arr = hex.toCharArray();
+ byte[] b = new byte[hex.length() / 2];
+ for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
+ String swap ="" + arr[i++] + arr[i];
+ int byteint = Integer.parseInt(swap, 16) & 0xFF;
+ b[j] = new Integer(byteint).byteValue();
+ }
+ return b;
+ }
+
+ protected String bytesToHexStr(byte[] bytes) {
+ StringBuilder hexStr = new StringBuilder();
+ for (byte b : bytes) {
+ String hex = Integer.toHexString(b & 0xFF);
+ if (hex.length() == 1) {
+ hex = '0' + hex;
+ }
+ hexStr.append(hex);
+ }
+ return hexStr.toString();
+ }
+
+ protected void wssClient(String url,String sendmsg) {
+ try {
+ OkHttpClient client;
+ client = new OkHttpClient.Builder()
+ .pingInterval(10, TimeUnit.SECONDS)
+ .writeTimeout(5, TimeUnit.SECONDS)
+ .readTimeout(5, TimeUnit.SECONDS)
+ .connectTimeout(10, TimeUnit.SECONDS)
+ .build();
+ Request request = new Request.Builder()
+ .addHeader("origin","https://player.sakurot.com:3458")
+ .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36")
+ .url(url)
+ .build();
+ final WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() {
+ @Override
+ public void onOpen(WebSocket webSocket, Response response) {
+ super.onOpen(webSocket, response);
+ webSocket.send(sendmsg);
+ }
+ @Override
+ public void onMessage(WebSocket webSocket, String text) {
+ super.onMessage(webSocket, text);
+ rs =text;
+ webSocket.close(1000, null);
+ }
+ @Override
+ public void onMessage(WebSocket webSocket, ByteString bytes) {
+ super.onMessage(webSocket, bytes);
+ }
+ @Override
+ public void onClosing(WebSocket webSocket, int code, String reason) {
+ super.onClosing(webSocket, code, reason);
+ webSocket.close(1000, null);
+ }
+ @Override
+ public void onClosed(WebSocket webSocket, int code, String reason) {
+ super.onClosed(webSocket, code, reason);
+ }
+ @Override
+ public void onFailure(WebSocket webSocket, Throwable t, Response response) {
+ super.onFailure(webSocket, t, response);
+ webSocket.close(1000, null);
+ }});
+
+
+ } catch (Exception exception) {
+ SpiderDebug.log(exception);
+ }
+ }
+
+ protected HashMap getHeaders2(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("Origin","https://player.sakurot.com:3458");
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
+ return headers;
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/EEEDY.java b/app/src/main/java/com/github/catvod/spider/EEEDY.java
new file mode 100644
index 0000000..3131bdb
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/EEEDY.java
@@ -0,0 +1,407 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.text.TextUtils;
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+public class EEEDY extends Spider {
+
+ private Pattern B = Pattern.compile("/vodtype/(\\d+).html");
+ private Pattern Pd = Pattern.compile("/vodplay/(\\d+)-(\\d+)-(\\d+).html");
+ private Pattern W = Pattern.compile("/voddetail/(\\d+).html");
+ private JSONObject u;
+ private Pattern u6 = Pattern.compile("/vodshow/(\\S+).html");
+ private JSONObject ue;
+
+ /* renamed from: com.github.catvod.spider.EEEDY$1 reason: invalid class name */
+ class AnonymousClass1 implements Comparator {
+ public int compare(String str, String str2) {
+ String $2 = "or";
+ try {
+ int i = EEEDY.this.ue.getJSONObject(str).getInt($2);
+ int i2 = EEEDY.this.ue.getJSONObject(str2).getInt($2);
+ if (i != i2 && i - i2 <= 0) {
+ return -1;
+ }
+ return 1;
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ return 1;
+ }
+ }
+ }
+
+ public String categoryContent(String str, String str2, boolean z, HashMap hashMap) {
+ int i;
+ int i2;
+ String $2 = "h4 > a";
+ String $3 = "-";
+ try {
+ int i3 = 1;
+ String[] strArr = {"", "", "", "", "", "", "", "", "", "", "", ""};
+ strArr[0] = str;
+ strArr[8] = str2;
+ if (hashMap != null && hashMap.size() > 0) {
+ for (String str3 : hashMap.keySet()) {
+ strArr[Integer.parseInt(str3)] = URLEncoder.encode(hashMap.get(str3));
+ }
+ }
+ String str4 = "https://www.3edy.com/vodshow/" + TextUtils.join($3, strArr) + ".html";
+ String h = OkHttpUtil.string(str4, u(str4));
+ Document ue2 = Jsoup.parse(h);
+ JSONObject jSONObject = new JSONObject();
+ Elements B1 = ue2.select("ul.pagination-lg>li");
+ int size = B1.size();
+ String $4 = "href";
+ if (size == 0) {
+ i2 = Integer.parseInt(str2);
+ i = i2;
+ } else {
+ int i4 = -1;
+ int i5 = -1;
+ int i6 = 0;
+ while (true) {
+ if (i6 >= B1.size()) {
+ i = i5;
+ break;
+ }
+ Element hq = (Element) B1.get(i6);
+ Element O = hq.selectFirst("a");
+ if (O != null) {
+ String pE = O.text();
+ if (i5 != i4 || !hq.hasClass("disabled")) {
+ i = i5;
+ } else {
+ Matcher matcher = this.u6.matcher(O.attr($4));
+ i = matcher.find() ? Integer.parseInt(matcher.group(1).split($3)[8]) : 0;
+ }
+ if (pE.contains("...")) {
+ Matcher matcher2 = this.u6.matcher(O.attr($4));
+ if (matcher2.find()) {
+ i2 = Integer.parseInt(matcher2.group(1).split($3)[8]);
+ }
+ } else {
+ i5 = i;
+ }
+ }
+ i6++;
+ i4 = -1;
+ }
+ i2 = 0;
+ }
+ JSONArray jSONArray = new JSONArray();
+ if (!h.contains("没有找到您想要的结果哦")) {
+ Elements B12 = ue2.select("ul.list-unstyled>li");
+ int i7 = 0;
+ while (i7 < B12.size()) {
+ Element hq2 = (Element) B12.get(i7);
+ String ue3 = hq2.select($2).attr("title");
+ String Pd2 = hq2.selectFirst("img").attr("data-original");
+ String jw = hq2.select("em.littplus").text();
+ Matcher matcher3 = this.W.matcher(hq2.select($2).attr($4));
+ if (matcher3.find()) {
+ String group = matcher3.group(i3);
+ JSONObject jSONObject2 = new JSONObject();
+ jSONObject2.put("vod_id", group);
+ jSONObject2.put("vod_name", ue3);
+ jSONObject2.put("vod_pic", Pd2);
+ jSONObject2.put("vod_remarks", jw);
+ jSONArray.put(jSONObject2);
+ }
+ i7++;
+ i3 = 1;
+ }
+ }
+ jSONObject.put("page", i);
+ jSONObject.put("pagecount", i2);
+ jSONObject.put("limit", 24);
+ jSONObject.put("total", i2 <= 1 ? jSONArray.length() : i2 * 24);
+ jSONObject.put("list", jSONArray);
+ return jSONObject.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ return "";
+ }
+ }
+
+ public String detailContent(List list) {
+ String str;
+ Exception e;
+ Elements exVar;
+ String str2;
+ String $2 = "-";
+ String $3 = ",";
+ String $4 = "a";
+ try {
+ String str3 = "https://www.3edy.com/voddetail/" + list.get(0) + ".html";
+ Document ue2 = Jsoup.parse(OkHttpUtil.string(str3, u(str3)));
+ JSONObject jSONObject = new JSONObject();
+ JSONObject jSONObject2 = new JSONObject();
+ Elements B1 = ue2.select("ul.vod-infos>li");
+ String ue3 = ((Element) B1.get(0)).select("img").attr("data-original");
+ String jw = ((Element) B1.get(1)).select("h4 > a").text();
+ Elements B12 = ue2.select("dl.dl-horizontal dd");
+ String jw2 = ((Element) B12.get(1)).select($4).text();
+ String pE = ((Element) B12.get(3)).text();
+ String pE2 = ((Element) B12.get(4)).text();
+ String pE3 = ((Element) B12.get(4)).text();
+ str = "";
+ try {
+ ArrayList arrayList = new ArrayList();
+ Elements B13 = ((Element) B12.get(0)).select($4);
+ String str4 = $2;
+ for (int i = 0; i < B13.size(); i++) {
+ arrayList.add(((Element) B13.get(i)).text());
+ }
+ String join = TextUtils.join($3, arrayList);
+ ArrayList arrayList2 = new ArrayList();
+ Elements B14 = ((Element) B12.get(2)).select($4);
+ String str5 = $4;
+ for (int i2 = 0; i2 < B14.size(); i2++) {
+ arrayList2.add(((Element) B14.get(i2)).text());
+ }
+ String join2 = TextUtils.join($3, arrayList2);
+ String pE4 = ((Element) B12.get(5)).text();
+ jSONObject2.put("vod_id", list.get(0));
+ jSONObject2.put("vod_name", jw);
+ jSONObject2.put("vod_pic", ue3);
+ jSONObject2.put("type_name", jw2);
+ jSONObject2.put("vod_year", pE2);
+ jSONObject2.put("vod_area", pE);
+ jSONObject2.put("vod_remarks", pE3);
+ jSONObject2.put("vod_actor", join);
+ jSONObject2.put("vod_director", join2);
+ jSONObject2.put("vod_content", pE4);
+ new TreeMap(new AnonymousClass1());
+ Elements u62 = ue2.select("ul#ff-tab").select("li");
+ String str6 = str;
+ String str7 = str6;
+ int i3 = 0;
+ while (i3 < u62.size()) {
+ str6 = ((Element) u62.get(i3)).selectFirst(str5).text().trim();
+ Elements B15 = ue2.select("ul.play-list > li > a");
+ ArrayList arrayList3 = new ArrayList();
+ int i4 = 0;
+ while (i4 < B15.size()) {
+ Element hq = (Element) B15.get(i4);
+ Matcher matcher = this.Pd.matcher(hq.attr("href"));
+ if (!matcher.find()) {
+ exVar = u62;
+ str2 = str4;
+ } else {
+ StringBuilder sb = new StringBuilder();
+ sb.append(matcher.group(1));
+ str2 = str4;
+ sb.append(str2);
+ exVar = u62;
+ sb.append(matcher.group(2));
+ sb.append(str2);
+ sb.append(matcher.group(3));
+ arrayList3.add(hq.text() + "$" + sb.toString());
+ }
+ i4++;
+ u62 = exVar;
+ str4 = str2;
+ }
+ if (arrayList3.size() > 0) {
+ str7 = TextUtils.join("#", arrayList3);
+ }
+ str7.length();
+ i3++;
+ u62 = u62;
+ str5 = str5;
+ str4 = str4;
+ }
+ if(str6.isEmpty() || str7.isEmpty())str6="暂无播放源";
+ jSONObject2.put("vod_play_from", str6);
+ jSONObject2.put("vod_play_url", str7);
+ JSONArray jSONArray = new JSONArray();
+ jSONArray.put(jSONObject2);
+ jSONObject.put("list", jSONArray);
+ return jSONObject.toString();
+ } catch (Exception e2) {
+ e = e2;
+ SpiderDebug.log(e);
+ return str;
+ }
+ } catch (Exception e3) {
+ e = e3;
+ str = "";
+ SpiderDebug.log(e);
+ return str;
+ }
+ }
+
+ public String homeContent(boolean z) {
+ int i;
+ String $2;
+ String $3 = "h4 > a";
+ String $4 = "https://www.3edy.com";
+ try {
+ Document ue2 = Jsoup.parse(OkHttpUtil.string($4, u($4)));
+ Elements B1 = ue2.select("ul.navbar-left>li a");
+ JSONArray jSONArray = new JSONArray();
+ Iterator it = B1.iterator();
+ while (true) {
+ boolean hasNext = it.hasNext();
+ i = 0;
+ $2 = "href";
+ if (!hasNext) {
+ break;
+ }
+ Element hq = (Element) it.next();
+ String pE = hq.text();
+ if (pE.equals("电影") || pE.equals("美剧") || pE.equals("韩剧") || pE.equals("国产剧") || pE.equals("日剧") || pE.equals("泰剧") || pE.equals("动漫") || pE.equals("综艺")) {
+ i = 1;
+ }
+ if (i != 0) {
+ Matcher matcher = this.B.matcher(hq.attr($2));
+ if (matcher.find()) {
+ String trim = matcher.group(1).trim();
+ JSONObject jSONObject = new JSONObject();
+ jSONObject.put("type_id", trim);
+ jSONObject.put("type_name", pE);
+ jSONArray.put(jSONObject);
+ }
+ }
+ }
+ JSONObject jSONObject2 = new JSONObject();
+ if (z) {
+ jSONObject2.put("filters", this.u);
+ }
+ jSONObject2.put("class", jSONArray);
+ try {
+ Elements B12 = ((Element) ue2.select("ul.list-unstyled-index").get(3)).select("li");
+ JSONArray jSONArray2 = new JSONArray();
+ while (i < B12.size()) {
+ Element hq2 = (Element) B12.get(i);
+ String ue3 = hq2.select($3).attr("title");
+ String Pd2 = hq2.selectFirst("img").attr("src");
+ String jw = hq2.select("em.littplus").text();
+ Matcher matcher2 = this.W.matcher(hq2.select($3).attr($2));
+ if (matcher2.find()) {
+ String group = matcher2.group(1);
+ JSONObject jSONObject3 = new JSONObject();
+ jSONObject3.put("vod_id", group);
+ jSONObject3.put("vod_name", ue3);
+ jSONObject3.put("vod_pic", Pd2);
+ jSONObject3.put("vod_remarks", jw);
+ jSONArray2.put(jSONObject3);
+ }
+ i++;
+ }
+ jSONObject2.put("list", jSONArray2);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return jSONObject2.toString();
+ } catch (Exception e2) {
+ SpiderDebug.log(e2);
+ return "";
+ }
+ }
+
+ public void init(Context context) {
+ EEEDY.super.init(context);
+ try {
+ this.ue = new JSONObject("{\"789pan\":{\"sh\":\" 飘花速播\",\"pu\":\"https://dp.jiexi.work/jsonno.php?url=\",\"sn\":1,\"or\":999}}");
+ this.u = new JSONObject("");
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ public String playerContent(String str, String str2, List list) {
+ String $2 = "url";
+ try {
+ String str3 = "https://www.3edy.com/vodplay/" + str2 + ".html";
+ Elements B1 = Jsoup.parse(OkHttpUtil.string(str3, u(str3))).select("div.ff-player script");
+ JSONObject jSONObject = new JSONObject();
+ System.out.println("scriptnum: "+B1.size());
+ for (int i = 0; i < B1.size(); i++) {
+ String trim = B1.get(i).html().trim();
+// System.out.println("trim: "+trim);
+ if (trim.startsWith("var player_")) {
+ JSONObject jSONObject2 = new JSONObject(trim.substring(trim.indexOf(123), trim.lastIndexOf(125) + 1));
+ String str4 = "https://dp.jiexi.work/jsonno.php?url=" + jSONObject2.getString($2);
+// System.out.println(str4);
+ String string = new JSONObject(OkHttpUtil.string(str4, u(str3))).getString($2);
+ jSONObject.put("parse", 0);
+ jSONObject.put("playUrl", "");
+ jSONObject.put($2, string);
+ }
+ }
+ return jSONObject.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ return "";
+ }
+ }
+
+ public String searchContent(String str, boolean z) {
+ if (z) {
+ return "";
+ }
+ try {
+ String str2 = "https://www.3edy.com/index.php/ajax/suggest?mid=1&wd=" + URLEncoder.encode(str) + "&limit=10×tamp=" + System.currentTimeMillis();
+ JSONObject jSONObject = new JSONObject(OkHttpUtil.string(str2, u(str2)));
+ JSONObject jSONObject2 = new JSONObject();
+ JSONArray jSONArray = new JSONArray();
+ int i = jSONObject.getInt("total");
+ String $2 = "list";
+ if (i > 0) {
+ JSONArray jSONArray2 = new JSONArray(jSONObject.getString($2));
+ for (int i2 = 0; i2 < jSONArray2.length(); i2++) {
+ JSONObject jSONObject3 = jSONArray2.getJSONObject(i2);
+ String string = jSONObject3.getString("id");
+ String string2 = jSONObject3.getString("name");
+ String string3 = jSONObject3.getString("pic");
+ JSONObject jSONObject4 = new JSONObject();
+ jSONObject4.put("vod_id", string);
+ jSONObject4.put("vod_name", string2);
+ jSONObject4.put("vod_pic", string3);
+ jSONObject4.put("vod_remarks", "");
+ jSONArray.put(jSONObject4);
+ }
+ }
+ jSONObject2.put($2, jSONArray);
+ return jSONObject2.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ return "";
+ }
+ }
+
+ /* access modifiers changed from: protected */
+ public HashMap u(String str) {
+ HashMap hashMap = new HashMap<>();
+ hashMap.put("method", "GET");
+ String $2 = "Upgrade-Insecure-Requests";
+ String $3 = "1";
+ hashMap.put($2, $3);
+ hashMap.put("DNT", $3);
+ hashMap.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ hashMap.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
+ hashMap.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ return hashMap;
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/EPang.java b/app/src/main/java/com/github/catvod/spider/EPang.java
new file mode 100644
index 0000000..a17f834
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/EPang.java
@@ -0,0 +1,463 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.crawler.SpiderReq;
+import com.github.catvod.crawler.SpiderReqResult;
+import com.github.catvod.crawler.SpiderUrl;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 阿房影视
+ *
+ * Author: 小黄瓜
+ */
+public class EPang extends Spider {
+ private static final String siteUrl = "https://www.bwl87.com";
+ private static final String siteHost = "www.bwl87.com";
+ private static final String ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36";
+
+ /**
+ * 播放源配置
+ */
+ private JSONObject playerConfig;
+ /**
+ * 筛选配置
+ */
+ private JSONObject filterConfig;
+
+ private Pattern regexCategory = Pattern.compile("/type/(\\w+)/");
+ private Pattern regexVid = Pattern.compile("/detail/(\\w+)/");
+ private Pattern regexPlay = Pattern.compile("/play/(\\w+)-(\\d+)-(\\d+)/");
+ private Pattern regexPage = Pattern.compile("/show/(\\S+)/");
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ try {
+ playerConfig = new JSONObject("{\"m3u8\":{\"sh\":\"大明宫\",\"pu\":\"\",\"sn\":0,\"or\":999},\"xin\":{\"sh\":\"阿房宫\",\"pu\":\"https://player.90mm.me/play.php?url=\",\"sn\":1,\"or\":999},\"mx771\":{\"sh\":\"未央宫\",\"pu\":\"\",\"sn\":0,\"or\":999}}");
+ filterConfig = new JSONObject("{\"1\":[{\"key\":0,\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"1\"},{\"n\":\"动作片\",\"v\":\"6\"},{\"n\":\"喜剧片\",\"v\":\"7\"},{\"n\":\"爱情片\",\"v\":\"8\"},{\"n\":\"科幻片\",\"v\":\"9\"},{\"n\":\"恐怖片\",\"v\":\"10\"},{\"n\":\"剧情片\",\"v\":\"11\"},{\"n\":\"战争片\",\"v\":\"12\"},{\"n\":\"奇幻片\",\"v\":\"22\"},{\"n\":\"悬疑片\",\"v\":\"23\"},{\"n\":\"犯罪片\",\"v\":\"24\"},{\"n\":\"动漫电影\",\"v\":\"26\"}]},{\"key\":3,\"name\":\"剧情\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"喜剧\",\"v\":\"喜剧\"},{\"n\":\"爱情\",\"v\":\"爱情\"},{\"n\":\"恐怖\",\"v\":\"恐怖\"},{\"n\":\"动作\",\"v\":\"动作\"},{\"n\":\"科幻\",\"v\":\"科幻\"},{\"n\":\"剧情\",\"v\":\"剧情\"},{\"n\":\"战争\",\"v\":\"战争\"},{\"n\":\"警匪\",\"v\":\"警匪\"},{\"n\":\"犯罪\",\"v\":\"犯罪\"},{\"n\":\"动画\",\"v\":\"动画\"},{\"n\":\"奇幻\",\"v\":\"奇幻\"},{\"n\":\"武侠\",\"v\":\"武侠\"},{\"n\":\"冒险\",\"v\":\"冒险\"},{\"n\":\"枪战\",\"v\":\"枪战\"},{\"n\":\"恐怖\",\"v\":\"恐怖\"},{\"n\":\"悬疑\",\"v\":\"悬疑\"},{\"n\":\"惊悚\",\"v\":\"惊悚\"},{\"n\":\"经典\",\"v\":\"经典\"},{\"n\":\"青春\",\"v\":\"青春\"},{\"n\":\"文艺\",\"v\":\"文艺\"},{\"n\":\"微电影\",\"v\":\"微电影\"},{\"n\":\"古装\",\"v\":\"古装\"},{\"n\":\"历史\",\"v\":\"历史\"},{\"n\":\"运动\",\"v\":\"运动\"},{\"n\":\"农村\",\"v\":\"农村\"},{\"n\":\"儿童\",\"v\":\"儿童\"},{\"n\":\"网络电影\",\"v\":\"网络电影\"}]},{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"大陆\",\"v\":\"大陆\"},{\"n\":\"香港\",\"v\":\"香港\"},{\"n\":\"台湾\",\"v\":\"台湾\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"法国\",\"v\":\"法国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"德国\",\"v\":\"德国\"},{\"n\":\"泰国\",\"v\":\"泰国\"},{\"n\":\"印度\",\"v\":\"印度\"},{\"n\":\"意大利\",\"v\":\"意大利\"},{\"n\":\"西班牙\",\"v\":\"西班牙\"},{\"n\":\"加拿大\",\"v\":\"加拿大\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":4,\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"法语\",\"v\":\"法语\"},{\"n\":\"德语\",\"v\":\"德语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"2\":[{\"key\":0,\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"2\"},{\"n\":\"国产剧\",\"v\":\"13\"},{\"n\":\"港台剧\",\"v\":\"14\"},{\"n\":\"韩日剧\",\"v\":\"15\"},{\"n\":\"欧美剧\",\"v\":\"16\"},{\"n\":\"泰国剧\",\"v\":\"21\"},{\"n\":\"日本剧\",\"v\":\"27\"}]},{\"key\":3,\"name\":\"剧情\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"古装\",\"v\":\"古装\"},{\"n\":\"战争\",\"v\":\"战争\"},{\"n\":\"青春偶像\",\"v\":\"青春偶像\"},{\"n\":\"喜剧\",\"v\":\"喜剧\"},{\"n\":\"家庭\",\"v\":\"家庭\"},{\"n\":\"犯罪\",\"v\":\"犯罪\"},{\"n\":\"动作\",\"v\":\"动作\"},{\"n\":\"奇幻\",\"v\":\"奇幻\"},{\"n\":\"剧情\",\"v\":\"剧情\"},{\"n\":\"历史\",\"v\":\"历史\"},{\"n\":\"经典\",\"v\":\"经典\"},{\"n\":\"乡村\",\"v\":\"乡村\"},{\"n\":\"情景\",\"v\":\"情景\"},{\"n\":\"商战\",\"v\":\"商战\"},{\"n\":\"网剧\",\"v\":\"网剧\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"内地\",\"v\":\"内地\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"香港\",\"v\":\"香港\"},{\"n\":\"台湾\",\"v\":\"台湾\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"泰国\",\"v\":\"泰国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"新加坡\",\"v\":\"新加坡\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":4,\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"3\":[{\"key\":3,\"name\":\"剧情\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"选秀\",\"v\":\"选秀\"},{\"n\":\"情感\",\"v\":\"情感\"},{\"n\":\"访谈\",\"v\":\"访谈\"},{\"n\":\"播报\",\"v\":\"播报\"},{\"n\":\"旅游\",\"v\":\"旅游\"},{\"n\":\"音乐\",\"v\":\"音乐\"},{\"n\":\"美食\",\"v\":\"美食\"},{\"n\":\"纪实\",\"v\":\"纪实\"},{\"n\":\"曲艺\",\"v\":\"曲艺\"},{\"n\":\"生活\",\"v\":\"生活\"},{\"n\":\"游戏互动\",\"v\":\"游戏互动\"},{\"n\":\"财经\",\"v\":\"财经\"},{\"n\":\"求职\",\"v\":\"求职\"}]},{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"内地\",\"v\":\"内地\"},{\"n\":\"港台\",\"v\":\"港台\"},{\"n\":\"日韩\",\"v\":\"日韩\"},{\"n\":\"欧美\",\"v\":\"欧美\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":4,\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"4\":[{\"key\":3,\"name\":\"剧情\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"情感\",\"v\":\"情感\"},{\"n\":\"科幻\",\"v\":\"科幻\"},{\"n\":\"热血\",\"v\":\"热血\"},{\"n\":\"推理\",\"v\":\"推理\"},{\"n\":\"搞笑\",\"v\":\"搞笑\"},{\"n\":\"冒险\",\"v\":\"冒险\"},{\"n\":\"萝莉\",\"v\":\"萝莉\"},{\"n\":\"校园\",\"v\":\"校园\"},{\"n\":\"动作\",\"v\":\"动作\"},{\"n\":\"机战\",\"v\":\"机战\"},{\"n\":\"运动\",\"v\":\"运动\"},{\"n\":\"战争\",\"v\":\"战争\"},{\"n\":\"少年\",\"v\":\"少年\"},{\"n\":\"少女\",\"v\":\"少女\"},{\"n\":\"社会\",\"v\":\"社会\"},{\"n\":\"原创\",\"v\":\"原创\"},{\"n\":\"亲子\",\"v\":\"亲子\"},{\"n\":\"益智\",\"v\":\"益智\"},{\"n\":\"励志\",\"v\":\"励志\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国产\",\"v\":\"国产\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"欧美\",\"v\":\"欧美\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":4,\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"20\":[{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}]}");
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ /**
+ * 爬虫headers
+ *
+ * @param url
+ * @return
+ */
+ protected HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("method", "GET");
+ headers.put("Host", siteHost);
+ headers.put("Upgrade-Insecure-Requests", "1");
+ headers.put("DNT", "1");
+ headers.put("User-Agent", ua);
+ headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
+ headers.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ return headers;
+ }
+
+ /**
+ * 获取分类数据 + 首页最近更新视频列表数据
+ *
+ * @param filter 是否开启筛选 关联的是 软件设置中 首页数据源里的筛选开关
+ * @return
+ */
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ SpiderUrl su = new SpiderUrl(siteUrl, getHeaders(siteUrl));
+ SpiderReqResult srr = SpiderReq.get(su);
+ Document doc = Jsoup.parse(srr.content);
+ // 分类节点
+ Elements elements = doc.select("ul.nav-list > li a");
+ JSONArray classes = new JSONArray();
+ for (Element ele : elements) {
+ String name = ele.text();
+ boolean show;
+ if (filter) {
+ show = name.equals("电影") ||
+ name.equals("连续剧") ||
+ name.equals("动漫") ||
+ name.equals("综艺") ||
+ name.equals("纪录片");
+ } else {
+ show = !(name.equals("首页") ||
+ name.equals("资讯") ||
+ name.equals("公告") ||
+ name.equals("头条") ||
+ name.equals("专题") ||
+ name.equals("APP"));
+ }
+ if (show) {
+ Matcher mather = regexCategory.matcher(ele.attr("href"));
+ if (!mather.find())
+ continue;
+ String id = mather.group(1).trim();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_id", id);
+ jsonObject.put("type_name", name);
+ classes.put(jsonObject);
+ }
+ }
+ JSONObject result = new JSONObject();
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ result.put("class", classes);
+ try {
+ Elements list = doc.select("div.col-lg-wide-75 > ul.myui-vodlist li div.myui-vodlist__box");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst(".title").text();
+ String cover = vod.selectFirst(".myui-vodlist__thumb").attr("data-original");
+ String remark = vod.selectFirst("span.pic-text").text();
+
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".myui-vodlist__thumb").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取分类信息数据
+ *
+ * @param tid 分类id
+ * @param pg 页数
+ * @param filter 同homeContent方法中的filter
+ * @param extend 筛选参数{k:v, k1:v1}
+ * @return
+ */
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ String[] urlParams = new String[]{"", "", "", "", "", "", "", "", "", "", "", ""};
+ urlParams[0] = tid;
+ urlParams[8] = pg;
+ if (extend != null && extend.size() > 0) {
+ for (Iterator it = extend.keySet().iterator(); it.hasNext(); ) {
+ String key = it.next();
+ String value = extend.get(key);
+ urlParams[Integer.parseInt(key)] = URLEncoder.encode(value);
+ }
+ }
+ // 获取分类数据的url
+ String url = siteUrl + "/show/" + TextUtils.join("-", urlParams) + "/";
+ SpiderUrl su = new SpiderUrl(url, getHeaders(url));
+ // 发起http请求
+ SpiderReqResult srr = SpiderReq.get(su);
+ String html = srr.content;
+ Document doc = Jsoup.parse(html);
+ JSONObject result = new JSONObject();
+ int pageCount = 0;
+ int page = -1;
+
+ Elements pageInfo = doc.select(".myui-page li a");
+ if (pageInfo.size() == 0) {
+ page = Integer.parseInt(pg);
+ pageCount = page;
+ } else {
+ for (int i = 0; i < pageInfo.size(); i++) {
+ Element a = pageInfo.get(i);
+ String name = a.text();
+ if (page == -1 && a.hasClass("btn-warm")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ page = Integer.parseInt(matcher.group(1).split("-")[8]);
+ } else {
+ page = 0;
+ }
+ }
+ if (name.equals("尾页")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ pageCount = Integer.parseInt(matcher.group(1).split("-")[8]);
+ } else {
+ pageCount = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ JSONArray videos = new JSONArray();
+ if (!html.contains("没有找到您想要的结果哦")) {
+ Elements list = doc.select("ul.myui-vodlist li div.myui-vodlist__box");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst(".title").text();
+ String cover = vod.selectFirst(".myui-vodlist__thumb").attr("data-original");
+ String remark = vod.selectFirst("span.pic-text").text();
+
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".myui-vodlist__thumb").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", 48);
+ result.put("total", pageCount <= 1 ? videos.length() : pageCount * 48);
+
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 视频详情信息
+ *
+ * @param ids 视频id
+ * @return
+ */
+ @Override
+ public String detailContent(List ids) {
+ try {
+ // 视频详情url
+ String url = siteUrl + "/detail/" + ids.get(0) + "/";
+ SpiderUrl su = new SpiderUrl(url, getHeaders(url));
+ SpiderReqResult srr = SpiderReq.get(su);
+ Document doc = Jsoup.parse(srr.content);
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+
+ // 取基本数据
+ String vid = doc.selectFirst("span.mac_hits").attr("data-id");
+
+ String cover = doc.selectFirst("a.myui-vodlist__thumb img").attr("data-original");
+ String title = doc.selectFirst("div.myui-content__detail h1.title").text();
+ String desc = Jsoup.parse(doc.selectFirst("meta[name=description]").attr("content")).text();
+ String category = "", area = "", year = "", remark = "", director = "", actor = "";
+ Elements span_text_muted = doc.select("div.myui-content__detail span.text-muted");
+ for (int i = 0; i < span_text_muted.size(); i++) {
+ Element text = span_text_muted.get(i);
+ String info = text.text();
+ if (info.equals("分类:")) {
+ category = text.nextElementSibling().text();
+ } else if (info.equals("年份:")) {
+ year = text.nextElementSibling().text();
+ } else if (info.equals("地区:")) {
+ area = text.nextElementSibling().text();
+ } else if (info.equals("更新:")) {
+ remark = text.nextElementSibling().text();
+ } else if (info.equals("导演:")) {
+ List directors = new ArrayList<>();
+ Elements aa = text.parent().select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ directors.add(aa.get(j).text());
+ }
+ director = TextUtils.join(",", directors);
+ } else if (info.equals("主演:")) {
+ List actors = new ArrayList<>();
+ Elements aa = text.parent().select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ actors.add(aa.get(j).text());
+ }
+ actor = TextUtils.join(",", actors);
+ }
+ }
+
+ vodList.put("vod_id", vid);
+ vodList.put("vod_name", title);
+ vodList.put("vod_pic", cover);
+ vodList.put("type_name", category);
+ vodList.put("vod_year", year);
+ vodList.put("vod_area", area);
+ vodList.put("vod_remarks", remark);
+ vodList.put("vod_actor", actor);
+ vodList.put("vod_director", director);
+ vodList.put("vod_content", desc);
+
+ Map vod_play = new TreeMap<>(new Comparator() {
+ @Override
+ public int compare(String o1, String o2) {
+ try {
+ int sort1 = playerConfig.getJSONObject(o1).getInt("or");
+ int sort2 = playerConfig.getJSONObject(o2).getInt("or");
+
+ if (sort1 == sort2) {
+ return 1;
+ }
+ return sort1 - sort2 > 0 ? 1 : -1;
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ return 1;
+ }
+ });
+
+ Elements sources = doc.select("a[data-toggle=tab]");
+
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ String sourceName = source.text();
+ String tabHref = source.attr("href");
+ boolean found = false;
+ for (Iterator it = playerConfig.keys(); it.hasNext(); ) {
+ String flag = it.next();
+ if (playerConfig.getJSONObject(flag).getString("sh").equals(sourceName)) {
+ sourceName = flag;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+ String playList = "";
+ Elements playListA = doc.select("div" + tabHref + " ul > li a");
+ List vodItems = new ArrayList<>();
+
+ for (int j = 0; j < playListA.size(); j++) {
+ Element vod = playListA.get(j);
+ Matcher matcher = regexPlay.matcher(vod.attr("href"));
+ if (!matcher.find())
+ continue;
+ String playURL = matcher.group(1) + "-" + matcher.group(2) + "-" + matcher.group(3);
+ vodItems.add(vod.text() + "$" + playURL);
+ }
+ if (vodItems.size() > 0)
+ playList = TextUtils.join("#", vodItems);
+
+ if (playList.length() == 0)
+ continue;
+
+ vod_play.put(sourceName, playList);
+ }
+
+ if (vod_play.size() > 0) {
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+ }
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取视频播放信息
+ *
+ * @param flag 播放源
+ * @param id 视频id
+ * @param vipFlags 所有可能需要vip解析的源
+ * @return
+ */
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ // 播放页 url
+ String url = siteUrl + "/play/" + id + "/";
+ SpiderUrl su = new SpiderUrl(url, getHeaders(url));
+ SpiderReqResult srr = SpiderReq.get(su);
+ Document doc = Jsoup.parse(srr.content);
+ Elements allScript = doc.select("script");
+ JSONObject result = new JSONObject();
+ for (int i = 0; i < allScript.size(); i++) {
+ String scContent = allScript.get(i).html().trim();
+ if (scContent.startsWith("var player_")) {
+ int start = scContent.indexOf('{');
+ int end = scContent.lastIndexOf('}') + 1;
+ String json = scContent.substring(start, end);
+ JSONObject player = new JSONObject(json);
+ if (playerConfig.has(player.getString("from"))) {
+ JSONObject pCfg = playerConfig.getJSONObject(player.getString("from"));
+ String videoUrl = player.getString("url");
+ String playUrl = pCfg.getString("pu");
+ result.put("parse", pCfg.getInt("sn"));
+ result.put("playUrl", playUrl);
+ result.put("url", videoUrl);
+ if (playUrl.contains("bwl87.com")) {
+ try {
+ JSONObject headers = new JSONObject();
+ headers.put("User-Agent", " " + ua);
+ headers.put("Accept", " */*");
+ headers.put("Accept-Language", " zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ headers.put("Accept-Encoding", " gzip, deflate, br");
+ result.put("header", headers.toString());
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ } else {
+ result.put("header", "");
+ }
+ }
+ break;
+ }
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 搜索
+ *
+ * @param key
+ * @param quick 是否播放页的快捷搜索
+ * @return
+ */
+ @Override
+ public String searchContent(String key, boolean quick) {
+ // 搜索有验证码 不支持
+ return "";
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Enlienli.java b/app/src/main/java/com/github/catvod/spider/Enlienli.java
new file mode 100644
index 0000000..a273cd4
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Enlienli.java
@@ -0,0 +1,252 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.net.URLEncoder;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 嗯哩嗯哩
+ *
+ * Author: 群友 不负此生
+ */
+public class Enlienli extends Spider {
+
+ private String siteUrl = "https://api.app.kongbuya.com";
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ }
+
+ private HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("Connection", "Keep-Alive");
+ headers.put("User-Agent", "okhttp/4.0.1");
+ return headers;
+ }
+
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ JSONArray jsonArray = new JSONArray(OkHttpUtil.string(siteUrl + "/api.php/provide/home_nav?", getHeaders(siteUrl)));
+ JSONArray classes = new JSONArray();
+ JSONObject filterConfig = new JSONObject();
+ for (int i = 0; i < jsonArray.length(); i++) {
+ JSONObject jObj = jsonArray.getJSONObject(i);
+ String typeName = jObj.getString("name");
+ String typeId = jObj.getString("id");
+ if (typeName.equals("推荐")) {
+ continue;
+ }
+ JSONObject newCls = new JSONObject();
+ newCls.put("type_id", typeId);
+ newCls.put("type_name", typeName);
+ classes.put(newCls);
+ try {
+ JSONArray typeExtend = jObj.getJSONArray("msg");
+ JSONArray extendsAll = new JSONArray();
+ for (int j = 0; j < typeExtend.length(); j++) {
+ JSONObject typeExtendObj = typeExtend.getJSONObject(j);
+ String typeExtendKey = typeExtendObj.getString("name");
+ JSONArray newTypeExtendKeys = typeExtendObj.getJSONArray("data");
+ if (newTypeExtendKeys.length() <= 1)
+ continue;
+ String typeExtendName = newTypeExtendKeys.getString(0);
+ JSONObject newTypeExtend = new JSONObject();
+ newTypeExtend.put("key", typeExtendKey);
+ newTypeExtend.put("name", typeExtendName);
+ JSONArray newTypeExtendKV = new JSONArray();
+ {
+ JSONObject kvAll = new JSONObject();
+ kvAll.put("n", "全部");
+ kvAll.put("v", "");
+ newTypeExtendKV.put(kvAll);
+ }
+ for (int k = 1; k < newTypeExtendKeys.length(); k++) {
+ JSONObject kv = new JSONObject();
+ kv.put("n", newTypeExtendKeys.getString(k));
+ kv.put("v", newTypeExtendKeys.getString(k));
+ newTypeExtendKV.put(kv);
+ }
+ newTypeExtend.put("value", newTypeExtendKV);
+ extendsAll.put(newTypeExtend);
+ }
+ filterConfig.put(typeId, extendsAll);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+
+ }
+ JSONObject result = new JSONObject();
+ result.put("class", classes);
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public String homeVideoContent() {
+ try {
+ String url = siteUrl + "/api.php/provide/home_data?page=1&id=0";
+ JSONObject jsonObject = new JSONObject(OkHttpUtil.string(url, getHeaders(url)));
+ JSONArray jsonArray = new JSONArray();
+ if (jsonObject.has("tv")) {
+ JSONArray data = jsonObject.getJSONObject("tv").getJSONArray("data");
+ for (int i = 0; i < data.length(); i++) {
+ jsonArray.put(data.getJSONObject(i));
+ }
+ }
+
+ if (jsonObject.has("video")) {
+ JSONArray vs = jsonObject.getJSONArray("video");
+ for (int i = 0; i < vs.length(); i++) {
+ JSONArray data = vs.getJSONObject(i).getJSONArray("data");
+ for (int j = 0; j < data.length(); j++) {
+ jsonArray.put(data.getJSONObject(j));
+ }
+ }
+ }
+
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < jsonArray.length(); i++) {
+ JSONObject vObj = jsonArray.getJSONObject(i);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", vObj.getString("id"));
+ v.put("vod_name", vObj.getString("name"));
+ v.put("vod_pic", vObj.getString("img"));
+ v.put("vod_remarks", vObj.getString("qingxidu"));
+ videos.put(v);
+ }
+ JSONObject result = new JSONObject();
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ String url = siteUrl + "/api.php/provide/vod_list?page=" + pg + "&id=" + tid;
+ Set keys = extend.keySet();
+ for (String key : keys) {
+ url += "&" + key + "=" + URLEncoder.encode(extend.get(key));
+ }
+ JSONArray jsonArray = new JSONArray(OkHttpUtil.string(url, getHeaders(url)));
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < jsonArray.length(); i++) {
+ JSONObject vObj = jsonArray.getJSONObject(i);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", vObj.getString("id"));
+ v.put("vod_name", vObj.getString("name"));
+ v.put("vod_pic", vObj.getString("img"));
+ v.put("vod_remarks", vObj.getString("qingxidu"));
+ videos.put(v);
+ }
+ JSONObject result = new JSONObject();
+ int limit = 20;
+ int page = Integer.parseInt(pg);
+ int total = Integer.MAX_VALUE;
+ int pageCount = videos.length() < 20 ? page : page + 1;
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", limit);
+ result.put("total", total);
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public String detailContent(List ids) {
+ try {
+ String url = siteUrl + "/api.php/provide/vod_detail?token=&id=" + ids.get(0) + "&ac=vod_detail";
+ JSONObject jsonObject = new JSONObject(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject vodList = new JSONObject();
+ vodList.put("vod_id", ids.get(0));
+ vodList.put("vod_name", jsonObject.getString("name"));
+ vodList.put("vod_pic", jsonObject.getString("img"));
+ vodList.put("type_name", jsonObject.getString("type"));
+ vodList.put("vod_year", "");
+ vodList.put("vod_area", "");
+ vodList.put("vod_remarks", jsonObject.getString("remarks"));
+ vodList.put("vod_actor", jsonObject.getString("actor"));
+ vodList.put("vod_director", jsonObject.getString("director"));
+ vodList.put("vod_content", jsonObject.getString("info"));
+
+ vodList.put("vod_play_from", jsonObject.getString("playcode"));
+ vodList.put("vod_play_url", jsonObject.getString("playlist"));
+
+ JSONObject result = new JSONObject();
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ JSONObject result = new JSONObject();
+ result.put("parse", 0);
+ result.put("playUrl", "");
+ result.put("url", id);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public String searchContent(String key, boolean quick) {
+ if (quick)
+ return "";
+ try {
+ String url = siteUrl + "/api.php/provide/search_result?video_name=" + URLEncoder.encode(key);
+ JSONObject jsonObject = new JSONObject(OkHttpUtil.string(url, getHeaders(url)));
+ JSONArray jsonArray = jsonObject.getJSONObject("result").getJSONArray("search_result");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < jsonArray.length(); i++) {
+ JSONObject vObj = jsonArray.getJSONObject(i);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", vObj.getString("id"));
+ v.put("vod_name", vObj.getString("video_name"));
+ v.put("vod_pic", vObj.getString("img"));
+ //v.put("vod_remarks", vObj.getString(""));
+ videos.put(v);
+ }
+ JSONObject result = new JSONObject();
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Fuli.java b/app/src/main/java/com/github/catvod/spider/Fuli.java
new file mode 100644
index 0000000..76bf5cf
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Fuli.java
@@ -0,0 +1,489 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.Misc;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+import com.github.catvod.xpath.XPathRule;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.jsoup.nodes.Element;
+import org.seimicrawler.xpath.JXDocument;
+import org.seimicrawler.xpath.JXNode;
+
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+public class Fuli extends XPath {
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ }
+
+ public void init(Context context, String extend) {
+ super.init(context, extend);
+ this.ext = extend;
+ }
+
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ fetchRule();
+ JSONObject result = new JSONObject();
+ JSONArray classes = new JSONArray();
+ if (rule.getCateManual().size() > 0) {
+ Set keys = rule.getCateManual().keySet();
+ for (String k : keys) {
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_name", k);
+ jsonObject.put("type_id", rule.getCateManual().get(k));
+ classes.put(jsonObject);
+ }
+ }
+ try {
+ String webUrl = rule.getHomeUrl();
+ JXDocument doc = JXDocument.create(fetch(webUrl));
+ if (rule.getCateManual().size() == 0) {
+ List navNodes = doc.selN(rule.getCateNode());
+ for (int i = 0; i < navNodes.size(); i++) {
+ String name = navNodes.get(i).selOne(rule.getCateName()).asString().trim();
+ name = rule.getCateNameR(name);
+ String id = navNodes.get(i).selOne(rule.getCateId()).asString().trim();
+ id = rule.getCateIdR(id);
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_id", id);
+ jsonObject.put("type_name", name);
+ classes.put(jsonObject);
+ }
+ }
+ if (!rule.getHomeVodNode().isEmpty()) {
+ try {
+ JSONArray videos = new JSONArray();
+ List vodNodes = doc.selN(rule.getHomeVodNode());
+ for (int i = 0; i < vodNodes.size(); i++) {
+ String name = vodNodes.get(i).selOne(rule.getHomeVodName()).asString().trim();
+ name = rule.getHomeVodNameR(name);
+ String id = vodNodes.get(i).selOne(rule.getHomeVodId()).asString().trim();
+ id = rule.getHomeVodIdR(id);
+ String pic = vodNodes.get(i).selOne(rule.getHomeVodImg()).asString().trim();
+ pic = rule.getHomeVodImgR(pic);
+ pic = Misc.fixUrl(webUrl, pic);
+ String mark = "";
+ if (!rule.getHomeVodMark().isEmpty()) {
+ try {
+ mark = vodNodes.get(i).selOne(rule.getHomeVodMark()).asString().trim();
+ mark = rule.getHomeVodMarkR(mark);
+ } catch (Exception e) {
+ SpiderDebug.log("homeContent"+e);
+ }
+ }
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", name);
+ v.put("vod_pic", pic);
+ v.put("vod_remarks", mark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log("homeContent"+e);
+ }
+ }
+ } catch (Exception e) {
+ SpiderDebug.log("homeContent"+e);
+ }
+ result.put("class", classes);
+ if (filter && rule.getFilter() != null) {
+ result.put("filters", rule.getFilter());
+ }
+ return result.toString();
+ } catch (
+ Exception e) {
+ SpiderDebug.log("homeContent"+e);
+ }
+ return "";
+ }
+
+ protected HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("User-Agent", rule.getUa().isEmpty()
+ ? "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36"
+ : rule.getUa());
+ return headers;
+ }
+
+ @Override
+ public String homeVideoContent() {
+ try {
+ fetchRule();
+ } catch (Exception e) {
+ SpiderDebug.log("homeVideoContent"+e);
+ }
+ return "";
+ }
+
+ protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) {
+ String url = rule.getCateUrl().replace("{cateId}", tid).replace("{catePg}", pg);
+ if(extend!=null) {
+ Set keys = extend.keySet();
+ for (String key : keys) {
+ url = url.replace(String.format("{%s}", key), extend.get(key));
+ }
+ }
+ SpiderDebug.log("categoryUrl"+String.format("categoryUrl -> url: %s", url));
+ return url;
+ }
+
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ fetchRule();
+ String webUrl = categoryUrl(tid, pg, filter, extend);
+ JSONArray videos = new JSONArray();
+ JXDocument doc = JXDocument.create(fetch(webUrl));
+ List vodNodes = doc.selN(rule.getCateVodNode());
+ for (int i = 0; i < vodNodes.size(); i++) {
+ String name = vodNodes.get(i).selOne(rule.getCateVodName()).asString().trim();
+ name = rule.getCateVodNameR(name);
+ String id = vodNodes.get(i).selOne(rule.getCateVodId()).asString().trim();
+ id = rule.getCateVodIdR(id);
+ String pic = vodNodes.get(i).selOne(rule.getCateVodImg()).asString().trim();
+ pic = rule.getCateVodImgR(pic);
+ pic = Misc.fixUrl(webUrl, pic);
+ String mark = "";
+ if (!rule.getCateVodMark().isEmpty()) {
+ try {
+ mark = vodNodes.get(i).selOne(rule.getCateVodMark()).asString().trim();
+ mark = rule.getCateVodMarkR(mark);
+ } catch (Exception e) {
+ SpiderDebug.log("categoryContent:"+e);
+ }
+ }
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", name);
+ v.put("vod_pic", pic);
+ v.put("vod_remarks", mark);
+ videos.put(v);
+ }
+ JSONObject result = new JSONObject();
+ result.put("page", pg);
+ result.put("pagecount", Integer.MAX_VALUE);
+ result.put("limit", 90);
+ result.put("total", Integer.MAX_VALUE);
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log("categoryContent:"+e);
+ }
+ return "";
+ }
+
+ protected void detailContentExt(String content, JSONObject vod) {
+
+ }
+
+ @Override
+ public String detailContent(List ids) {
+ try {
+ fetchRule();
+ String webUrl = rule.getDetailUrl().replace("{vid}", ids.get(0));
+ String webContent = fetch(webUrl);
+ JXDocument doc = JXDocument.create(webContent);
+ JXNode vodNode = doc.selNOne(rule.getDetailNode());
+
+ String cover = "", title = "", desc = "", category = "", area = "", year = "", remark = "", director = "", actor = "";
+
+ title = vodNode.selOne(rule.getDetailName()).asString().trim();
+ title = rule.getDetailNameR(title);
+
+ cover = vodNode.selOne(rule.getDetailImg()).asString().trim();
+ cover = rule.getDetailImgR(cover);
+ cover = Misc.fixUrl(webUrl, cover);
+
+ if (!rule.getDetailCate().isEmpty()) {
+ try {
+ category = vodNode.selOne(rule.getDetailCate()).asString().trim();
+ category = rule.getDetailCateR(category);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ }
+ if (!rule.getDetailYear().isEmpty()) {
+ try {
+ year = vodNode.selOne(rule.getDetailYear()).asString().trim();
+ year = rule.getDetailYearR(year);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ }
+ if (!rule.getDetailArea().isEmpty()) {
+ try {
+ area = vodNode.selOne(rule.getDetailArea()).asString().trim();
+ area = rule.getDetailAreaR(area);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ }
+ if (!rule.getDetailMark().isEmpty()) {
+ try {
+ remark = vodNode.selOne(rule.getDetailMark()).asString().trim();
+ remark = rule.getDetailMarkR(remark);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ }
+ if (!rule.getDetailActor().isEmpty()) {
+ try {
+ actor = vodNode.selOne(rule.getDetailActor()).asString().trim();
+ actor = rule.getDetailActorR(actor);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ }
+ if (!rule.getDetailDirector().isEmpty()) {
+ try {
+ director = vodNode.selOne(rule.getDetailDirector()).asString().trim();
+ director = rule.getDetailDirectorR(director);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ }
+ if (!rule.getDetailDesc().isEmpty()) {
+ try {
+ desc = vodNode.selOne(rule.getDetailDesc()).asString().trim();
+ desc = rule.getDetailDescR(desc);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ JSONObject vod = new JSONObject();
+ vod.put("vod_id", ids.get(0));
+ vod.put("vod_name", title);
+ vod.put("vod_pic", cover);
+ vod.put("type_name", category);
+ vod.put("vod_year", year);
+ vod.put("vod_area", area);
+ vod.put("vod_remarks", remark);
+ vod.put("vod_actor", actor);
+ vod.put("vod_director", director);
+ vod.put("vod_content", desc);
+
+ ArrayList playFrom = new ArrayList<>();
+
+ List fromNodes = doc.selN(rule.getDetailFromNode());
+ for (int i = 0; i < fromNodes.size(); i++) {
+ String name = fromNodes.get(i).selOne(rule.getDetailFromName()).asString().trim();
+ name = rule.getDetailFromNameR(name);
+ playFrom.add(name);
+ }
+ ArrayList playList = new ArrayList<>();
+ if (webUrl.contains("wzk666.xyz")) {
+ playFrom.add("自定义");
+ playList.add(String.format("正片$%s", ids.get(0)));
+ }else {
+ List urlListNodes = doc.selN(rule.getDetailUrlNode());
+ for (int i = 0; i < urlListNodes.size(); i++) {
+ List urlNodes = urlListNodes.get(i).sel(rule.getDetailUrlSubNode());
+ List vodItems = new ArrayList<>();
+ for (int j = 0; j < urlNodes.size(); j++) {
+ String name = urlNodes.get(j).selOne(rule.getDetailUrlName()).asString().trim();
+ name = rule.getDetailUrlNameR(name);
+ String id = urlNodes.get(j).selOne(rule.getDetailUrlId()).asString().trim();
+ id = rule.getDetailUrlIdR(id);
+ vodItems.add(name + "$" + id);
+ }
+ // 排除播放列表为空的播放源
+ if (vodItems.size() == 0 && playFrom.size() > i) {
+ playFrom.set(i, "");
+ }
+ playList.add(TextUtils.join("#", vodItems));
+ }
+ }
+ // 排除播放列表为空的播放源
+ for (int i = playFrom.size() - 1; i >= 0; i--) {
+ if (playFrom.get(i).isEmpty())
+ playFrom.remove(i);
+ }
+ for (int i = playList.size() - 1; i >= 0; i--) {
+ if (playList.get(i).isEmpty())
+ playList.remove(i);
+ }
+ for (int i = playList.size() - 1; i >= 0; i--) {
+ if (i >= playFrom.size())
+ playList.remove(i);
+ }
+ String vod_play_from = TextUtils.join("$$$", playFrom);
+ String vod_play_url = TextUtils.join("$$$", playList);
+ vod.put("vod_play_from", vod_play_from);
+ vod.put("vod_play_url", vod_play_url);
+
+ detailContentExt(webContent, vod);
+
+ JSONObject result = new JSONObject();
+ JSONArray list = new JSONArray();
+ list.put(vod);
+ result.put("list", list);
+ SpiderDebug.log("detailContent: "+result.toString());
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ fetchRule();
+ String webUrl = rule.getPlayUrl().isEmpty() ? id : rule.getPlayUrl().replace("{playUrl}", id);
+ SpiderDebug.log("playerContent: "+ webUrl);
+ JSONObject result = new JSONObject();
+ result.put("parse", 1);
+ result.put("playUrl", "");
+ if (!rule.getPlayUa().isEmpty()) {
+ result.put("ua", rule.getPlayUa());
+ }
+ result.put("url", webUrl);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log("playerContent: "+e);
+ }
+ return "";
+ }
+
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ fetchRule();
+ if (rule.getSearchUrl().isEmpty()) {
+ return "";
+ }
+ String webUrl = rule.getSearchUrl().replace("{wd}", URLEncoder.encode(key));
+ String webContent = fetch(webUrl);
+ JSONObject result = new JSONObject();
+ JSONArray videos = new JSONArray();
+ // add maccms suggest search api support
+ if (rule.getSearchVodNode().startsWith("json:")) {
+ String[] node = rule.getSearchVodNode().substring(5).split(">");
+ JSONObject data = new JSONObject(webContent);
+ for (int i = 0; i < node.length; i++) {
+ if (i == node.length - 1) {
+ JSONArray vodArray = data.getJSONArray(node[i]);
+ for (int j = 0; j < vodArray.length(); j++) {
+ JSONObject vod = vodArray.getJSONObject(j);
+ String name = vod.optString(rule.getSearchVodName()).trim();
+ name = rule.getSearchVodNameR(name);
+ String id = vod.optString(rule.getSearchVodId()).trim();
+ id = rule.getSearchVodIdR(id);
+ String pic = vod.optString(rule.getSearchVodImg()).trim();
+ pic = rule.getSearchVodImgR(pic);
+ pic = Misc.fixUrl(webUrl, pic);
+ String mark = vod.optString(rule.getSearchVodMark()).trim();
+ mark = rule.getSearchVodMarkR(mark);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", name);
+ v.put("vod_pic", pic);
+ v.put("vod_remarks", mark);
+ videos.put(v);
+ }
+ } else {
+ data = data.getJSONObject(node[i]);
+ }
+ }
+ } else {
+ JXDocument doc = JXDocument.create(webContent);
+ List vodNodes = doc.selN(rule.getSearchVodNode());
+ for (int i = 0; i < vodNodes.size(); i++) {
+ String name = vodNodes.get(i).selOne(rule.getSearchVodName()).asString().trim();
+ name = rule.getSearchVodNameR(name);
+ String id = vodNodes.get(i).selOne(rule.getSearchVodId()).asString().trim();
+ id = rule.getSearchVodIdR(id);
+ String pic = vodNodes.get(i).selOne(rule.getSearchVodImg()).asString().trim();
+ pic = rule.getSearchVodImgR(pic);
+ pic = Misc.fixUrl(webUrl, pic);
+ String mark = "";
+ if (!rule.getCateVodMark().isEmpty()) {
+ try {
+ mark = vodNodes.get(i).selOne(rule.getSearchVodMark()).asString().trim();
+ mark = rule.getSearchVodMarkR(mark);
+ } catch (Exception e) {
+ SpiderDebug.log("searchContent: "+e);
+ }
+ }
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", name);
+ v.put("vod_pic", pic);
+ v.put("vod_remarks", mark);
+ videos.put(v);
+ }
+ }
+ result.put("list", videos);
+ return result.toString();
+ } catch (
+ Exception e) {
+ SpiderDebug.log("searchContent: "+e);
+ }
+ return "";
+ }
+
+ @Override
+ public boolean manualVideoCheck() {
+ return false;
+ }
+
+ private String[] videoFormatList = new String[]{".m3u8", ".mp4", ".mpeg", ".flv"};
+
+ @Override
+ public boolean isVideoFormat(String url) {
+ url = url.toLowerCase();
+ if (url.contains("=http") || url.contains("=https") || url.contains("=https%3a%2f") || url.contains("=http%3a%2f")) {
+ return false;
+ }
+ for (String format : videoFormatList) {
+ if (url.contains(format)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected String ext = null;
+ protected XPathRule rule = null;
+
+ protected void fetchRule() {
+ if (rule == null) {
+ if (ext != null) {
+ if (ext.startsWith("http")) {
+ String json = OkHttpUtil.string(ext, null);
+ rule = XPathRule.fromJson(json);
+ loadRuleExt(json);
+ } else {
+ rule = XPathRule.fromJson(ext);
+ loadRuleExt(ext);
+ }
+ }
+ }
+ }
+
+ protected void loadRuleExt(String json) {
+
+ }
+
+ protected String fetch(String webUrl) {
+ SpiderDebug.log("fetch: "+webUrl);
+ return OkHttpUtil.string(webUrl, getHeaders(webUrl));
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Gitcafe.java b/app/src/main/java/com/github/catvod/spider/Gitcafe.java
index 71c97ec..d90ba7a 100644
--- a/app/src/main/java/com/github/catvod/spider/Gitcafe.java
+++ b/app/src/main/java/com/github/catvod/spider/Gitcafe.java
@@ -158,8 +158,9 @@ public class Gitcafe extends Spider {
for (Iterator iter = b.iterator(); iter.hasNext(); ) {
String element = iter.next();
String content = OkHttpUtil.string("https://gitcafe.net/alipaper/data/" + element + ".json", LT);
- JSONObject data = new JSONObject(content);
- JSONArray jSONArray = data.getJSONArray("data");
+// JSONObject data = new JSONObject(content);
+ JSONArray jSONArray = new JSONArray(content);
+ // data.getJSONArray("data");
for (int i = 0; i < jSONArray.length(); i++) {
JSONObject jSONObject = jSONArray.getJSONObject(i);
hashMap.put(jSONObject.getString("key"), jSONObject);
diff --git a/app/src/main/java/com/github/catvod/spider/IQIYI.java b/app/src/main/java/com/github/catvod/spider/IQIYI.java
new file mode 100644
index 0000000..a69082a
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/IQIYI.java
@@ -0,0 +1,324 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.net.Uri;
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import rxhttp.wrapper.annotations.NonNull;
+
+public class IQIYI extends Spider {
+ protected JSONObject a;
+ protected JSONArray xr;
+ protected JSONObject q = new JSONObject();
+ protected HashMap dn = new HashMap<>();
+
+ private String q(String str, String str2) {
+ String str3;
+ try {
+ if (str2.startsWith("//")) {
+ Uri parse = Uri.parse(str);
+ str3 = parse.getScheme() + ":" + str2;
+ } else if (str2.contains("://")) {
+ return str2;
+ } else {
+ Uri parse2 = Uri.parse(str);
+ str3 = parse2.getScheme() + "://" + parse2.getHost() + str2;
+ }
+ return str3;
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ return str2;
+ }
+ }
+
+ public String categoryContent(String str, String str2, boolean z, HashMap hashMap) {
+ IQIYI iqiyi = this;
+ try {
+ String str3 = "https://pcw-api.iqiyi.com/search/video/videolists?channel_id=" + str + "&is_purchase=&mode=24&pageNum=" + str2 + "&pageSize=24";
+ if (hashMap != null) {
+ Set keySet = hashMap.keySet();
+ ArrayList arrayList = new ArrayList();
+ for (String str4 : keySet) {
+ String trim = hashMap.get(str4).trim();
+ if (str4.matches("\\d+")) {
+ arrayList.add(trim + ";must");
+ } else {
+ str3 = str3 + "&" + str4 + "=" + trim;
+ }
+ }
+ str3 = str3 + "&three_category_id=" + iqiyi.join(",", arrayList);
+ }
+ String h = OkHttpUtil.string(str3, getHeaders(str3));
+ JSONObject jSONObject = new JSONObject();
+ try {
+ JSONArray optJSONArray = new JSONObject(h).optJSONObject("data").optJSONArray("list");
+ JSONArray jSONArray = new JSONArray();
+ int i = 0;
+ while (i < optJSONArray.length()) {
+ JSONObject optJSONObject = optJSONArray.optJSONObject(i);
+ String optString = optJSONObject.optString("name");
+ String q = iqiyi.q(str3, optJSONObject.optString("imageUrl"));
+ String optString2 = optJSONObject.optString("score");
+ String optString3 = optJSONObject.optString("playUrl");
+ if (!optJSONObject.optString("albumId").equals("")) {
+ if (optJSONObject.optInt("sourceId") != 0) {
+ optString3 = "/video/video/baseinfo/" + optJSONObject.optString("tvId") + "?userInfo=verify&jsonpCbName=videoInfo39";
+ } else {
+ optString3 = "/albums/album/avlistinfo?aid=" + optJSONObject.optString("albumId") + "&size=5000&page=1&url=" + optString3;
+ }
+ } else if (optJSONObject.optLong("tvId") != 0) {
+ optString3 = "/video/video/baseinfo/" + optJSONObject.optString("tvId") + "?userInfo=verify&jsonpCbName=videoInfo39";
+ }
+ JSONObject jSONObject2 = new JSONObject();
+ jSONObject2.put("vod_id", optString3);
+ jSONObject2.put("vod_name", optString);
+ jSONObject2.put("vod_pic", q);
+ jSONObject2.put("vod_remarks", optString2);
+ jSONArray.put(jSONObject2);
+ i++;
+ iqiyi = this;
+ optJSONArray = optJSONArray;
+ str3 = str3;
+ }
+ jSONObject.put("page", str2);
+ jSONObject.put("pagecount", Integer.MAX_VALUE);
+ jSONObject.put("limit", 90);
+ jSONObject.put("total", Integer.MAX_VALUE);
+ jSONObject.put("list", jSONArray);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return jSONObject.toString(4);
+ } catch (Exception e2) {
+ SpiderDebug.log(e2);
+ return "";
+ }
+ }
+
+ public String detailContent(List list) {
+ try {
+ String url = "https://pcw-api.iqiyi.com" + list.get(0);
+ JSONObject jSONObject = new JSONObject(OkHttpUtil.string(url, getHeaders(url))).getJSONObject("data");
+ JSONObject jSONObject2 = new JSONObject();
+ JSONObject optJSONObject = jSONObject.optJSONArray("epsodelist") != null ? jSONObject.optJSONArray("epsodelist").optJSONObject(0) : jSONObject;
+ jSONObject2.put("vod_id", list.get(0));
+ jSONObject2.put("vod_name", optJSONObject.optString("name").replaceAll("第\\d+(?:集|期)", ""));
+ jSONObject2.put("vod_pic", q(url, optJSONObject.optString("imageUrl")));
+ JSONObject optJSONObject2 = optJSONObject.optJSONObject("people");
+ JSONArray optJSONArray = optJSONObject2.optJSONArray("main_charactor");
+ if (optJSONArray == null) {
+ optJSONArray = optJSONObject2.optJSONArray("producer");
+ }
+ if (optJSONArray == null) {
+ optJSONArray = optJSONObject2.optJSONArray("guest");
+ }
+ if (optJSONArray == null) {
+ optJSONArray = optJSONObject2.optJSONArray("singer");
+ }
+ ArrayList arrayList = new ArrayList();
+ if (optJSONArray != null) {
+ for (int i = 0; i < optJSONArray.length(); i++) {
+ arrayList.add(optJSONArray.optJSONObject(i).optString("name"));
+ }
+ }
+ JSONArray optJSONArray2 = optJSONObject2.optJSONArray("director");
+ if (optJSONArray2 == null) {
+ optJSONArray2 = optJSONObject2.optJSONArray("screen_writer");
+ }
+ if (optJSONArray2 == null) {
+ optJSONArray2 = optJSONObject2.optJSONArray("host");
+ }
+ ArrayList arrayList2 = new ArrayList();
+ if (optJSONArray2 != null) {
+ for (int i2 = 0; i2 < optJSONArray2.length(); i2++) {
+ arrayList2.add(optJSONArray2.optJSONObject(i2).optString("name"));
+ }
+ }
+ jSONObject2.put("vod_remarks", optJSONObject.optString("duration"));
+ jSONObject2.put("vod_actor", join(",", arrayList));
+ jSONObject2.put("vod_director", join(",", arrayList2));
+ jSONObject2.put("vod_content", optJSONObject.optString("description"));
+ JSONArray optJSONArray3 = jSONObject.optJSONArray("epsodelist");
+ if (optJSONArray3 == null) {
+ optJSONArray3 = new JSONArray();
+ optJSONArray3.put(jSONObject);
+ }
+ ArrayList arrayList3 = new ArrayList();
+ for (int i3 = 0; i3 < optJSONArray3.length(); i3++) {
+ JSONObject optJSONObject3 = optJSONArray3.optJSONObject(i3);
+ arrayList3.add(optJSONObject3.optString("order") + " " + optJSONObject3.optString("subtitle") + "$" + optJSONObject3.optString("playUrl"));
+ }
+ jSONObject2.put("vod_play_from", "iqiyi");
+ jSONObject2.put("vod_play_url", join("#", arrayList3));
+ JSONObject jSONObject3 = new JSONObject();
+ JSONArray jSONArray = new JSONArray();
+ jSONArray.put(jSONObject2);
+ jSONObject3.put("list", jSONArray);
+ return jSONObject3.toString(4);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ return "";
+ }
+ }
+
+ protected HashMap getHeaders(String str) {
+ HashMap hashMap = new HashMap<>();
+ hashMap.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ return hashMap;
+ }
+
+ public String homeContent(boolean z) {
+ IQIYI iqiyi = this;
+ try {
+ String str = "https://pcw-api.iqiyi.com/search/video/videolists?channel_id=2&is_purchase=&mode=24&pageNum=1&pageSize=24&data_type=1&site=iqiyi";
+ String h = OkHttpUtil.string(str, iqiyi.getHeaders(str));
+ JSONObject jSONObject = new JSONObject();
+ jSONObject.put("class", iqiyi.xr);
+ if (z) {
+ jSONObject.put("filters", iqiyi.a);
+ }
+ try {
+ JSONArray optJSONArray = new JSONObject(h).optJSONObject("data").optJSONArray("list");
+ JSONArray jSONArray = new JSONArray();
+ int i = 0;
+ while (i < optJSONArray.length()) {
+ JSONObject optJSONObject = optJSONArray.optJSONObject(i);
+ String optString = optJSONObject.optString("name");
+ String q = iqiyi.q(str, optJSONObject.optString("imageUrl"));
+ String optString2 = optJSONObject.optString("score");
+ String optString3 = optJSONObject.optString("playUrl");
+ if (!optJSONObject.optString("albumId").equals("")) {
+ if (optJSONObject.optInt("sourceId") != 0) {
+ optString3 = "/video/video/baseinfo/" + optJSONObject.optString("tvId") + "?userInfo=verify&jsonpCbName=videoInfo39";
+ } else {
+ optString3 = "/albums/album/avlistinfo?aid=" + optJSONObject.optString("albumId") + "&size=5000&page=1&url=" + optString3;
+ }
+ } else if (optJSONObject.optLong("tvId") != 0) {
+ optString3 = "/video/video/baseinfo/" + optJSONObject.optString("tvId") + "?userInfo=verify&jsonpCbName=videoInfo39";
+ }
+ JSONObject jSONObject2 = new JSONObject();
+ jSONObject2.put("vod_id", optString3);
+ jSONObject2.put("vod_name", optString);
+ jSONObject2.put("vod_pic", q);
+ jSONObject2.put("vod_remarks", optString2);
+ jSONArray.put(jSONObject2);
+ i++;
+ iqiyi = this;
+ str = str;
+ }
+ jSONObject.put("list", jSONArray);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return jSONObject.toString(4);
+ } catch (Exception e2) {
+ SpiderDebug.log(e2);
+ return "";
+ }
+ }
+
+ public String homeVideoContent() {
+ try {
+ JSONArray jSONArray = new JSONObject(OkHttpUtil.string("https://pcw-api.iqiyi.com/api.php/app/index_video?token=", getHeaders("https://pcw-api.iqiyi.com/api.php/app/index_video?token="))).getJSONArray("list");
+ JSONArray jSONArray2 = new JSONArray();
+ for (int i = 0; i < jSONArray.length(); i++) {
+ JSONArray jSONArray3 = jSONArray.getJSONObject(i).getJSONArray("vlist");
+ int i2 = 0;
+ while (i2 < jSONArray3.length() && i2 < 6) {
+ JSONObject jSONObject = jSONArray3.getJSONObject(i2);
+ JSONObject jSONObject2 = new JSONObject();
+ jSONObject2.put("vod_id", jSONObject.optString("vod_id"));
+ jSONObject2.put("vod_name", jSONObject.optString("vod_name"));
+ jSONObject2.put("vod_pic", jSONObject.optString("vod_pic"));
+ jSONObject2.put("vod_remarks", jSONObject.optString("vod_remarks"));
+ jSONArray2.put(jSONObject2);
+ i2++;
+ }
+ }
+ JSONObject jSONObject3 = new JSONObject();
+ jSONObject3.put("list", jSONArray2);
+ return jSONObject3.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ return "";
+ }
+ }
+
+ public void init(Context context) {
+ IQIYI.super.init(context);
+ try {
+ this.xr = new JSONArray("[{\"type_name\":\"电视\",\"type_id\":\"2\"},{\"type_name\":\"电影\",\"type_id\":\"1\"},{\"type_name\":\"综艺\",\"type_id\":\"6\"},{\"type_name\":\"动漫\",\"type_id\":\"4\"},{\"type_name\":\"纪录\",\"type_id\":\"3\"},{\"type_name\":\"教育\",\"type_id\":\"12\"},{\"type_name\":\"游戏\",\"type_id\":\"8\"},{\"type_name\":\"资讯\",\"type_id\":\"25\"},{\"type_name\":\"娱乐\",\"type_id\":\"7\"},{\"type_name\":\"财经\",\"type_id\":\"24\"},{\"type_name\":\"网络\",\"type_id\":\"1\"},{\"type_name\":\"片花\",\"type_id\":\"10\"},{\"type_name\":\"音乐\",\"type_id\":\"5\"},{\"type_name\":\"军事\",\"type_id\":\"28\"},{\"type_name\":\"体育\",\"type_id\":\"17\"},{\"type_name\":\"儿童\",\"type_id\":\"15\"},{\"type_name\":\"旅游\",\"type_id\":\"9\"},{\"type_name\":\"时尚\",\"type_id\":\"13\"},{\"type_name\":\"生活\",\"type_id\":\"21\"},{\"type_name\":\"汽车\",\"type_id\":\"26\"},{\"type_name\":\"搞笑\",\"type_id\":\"22\"},{\"type_name\":\"广告\",\"type_id\":\"20\"},{\"type_name\":\"原创\",\"type_id\":\"27\"},{\"type_name\":\"母婴\",\"type_id\":\"29\"},{\"type_name\":\"科技\",\"type_id\":\"30\"},{\"type_name\":\"健康\",\"type_id\":\"32\"}]");
+ this.a = new JSONObject("{\"22\":[{\"name\":\"分类\",\"value\":[{\"v\":\"22169\",\"n\":\"欢乐精选\"},{\"v\":\"29115\",\"n\":\"娱乐八卦\"},{\"v\":\"29116\",\"n\":\"搞笑短片\"},{\"v\":\"29139\",\"n\":\"影视剧吐槽\"},{\"v\":\"22172\",\"n\":\"雷人囧事\"},{\"v\":\"22171\",\"n\":\"爆笑节目\"},{\"v\":\"1905\",\"n\":\"萌宠\"},{\"v\":\"1909\",\"n\":\"童趣\"},{\"v\":\"1900\",\"n\":\"奇闻趣事\"},{\"v\":\"1902\",\"n\":\"恶搞配音\"},{\"v\":\"22170\",\"n\":\"猎奇\"}],\"key\":\"18074\"},{\"name\":\"地域\",\"value\":[{\"v\":\"1907\",\"n\":\"国内\"},{\"v\":\"1908\",\"n\":\"国外\"}],\"key\":\"18075\"}],\"24\":[{\"name\":\"分类\",\"value\":[{\"v\":\"2233\",\"n\":\"宏观\"},{\"v\":\"2234\",\"n\":\"民生\"},{\"v\":\"2235\",\"n\":\"产经\"},{\"v\":\"2236\",\"n\":\"市场\"},{\"v\":\"2237\",\"n\":\"理财\"},{\"v\":\"2238\",\"n\":\"访谈\"}],\"key\":\"18079\"}],\"25\":[{\"name\":\"类型\",\"value\":[{\"v\":\"20031\",\"n\":\"社会\"},{\"v\":\"20321\",\"n\":\"科技\"},{\"v\":\"21314\",\"n\":\"军事\"},{\"v\":\"21315\",\"n\":\"评论\"},{\"v\":\"21739\",\"n\":\"国内\"},{\"v\":\"21740\",\"n\":\"国际\"}],\"key\":\"20030\"}],\"26\":[{\"name\":\"内容\",\"value\":[{\"v\":\"20529\",\"n\":\"资讯\"},{\"v\":\"20530\",\"n\":\"专访\"},{\"v\":\"20531\",\"n\":\"新车\"},{\"v\":\"20532\",\"n\":\"试驾\"},{\"v\":\"20533\",\"n\":\"用车\"},{\"v\":\"20534\",\"n\":\"赛事\"},{\"v\":\"20535\",\"n\":\"交通\"},{\"v\":\"20536\",\"n\":\"娱乐\"},{\"v\":\"20537\",\"n\":\"车模\"},{\"v\":\"20538\",\"n\":\"改装\"},{\"v\":\"20539\",\"n\":\"车微剧\"},{\"v\":\"20540\",\"n\":\"爱汽车制造\"},{\"v\":\"28463\",\"n\":\"品牌\"},{\"v\":\"28464\",\"n\":\"车展\"},{\"v\":\"28534\",\"n\":\"航空\"},{\"v\":\"28535\",\"n\":\"游艇\"},{\"v\":\"28536\",\"n\":\"轨道\"}],\"key\":\"20528\"},{\"name\":\"车型\",\"value\":[{\"v\":\"20542\",\"n\":\"微型车\"},{\"v\":\"20543\",\"n\":\"小型车\"},{\"v\":\"20544\",\"n\":\"紧凑型车\"},{\"v\":\"20545\",\"n\":\"中型车\"},{\"v\":\"20546\",\"n\":\"中高型车\"},{\"v\":\"20547\",\"n\":\"豪华车\"},{\"v\":\"20548\",\"n\":\"MPV\"},{\"v\":\"20549\",\"n\":\"SUV\"},{\"v\":\"20550\",\"n\":\"跑车\"},{\"v\":\"20551\",\"n\":\"皮卡\"},{\"v\":\"20552\",\"n\":\"微客\"},{\"v\":\"22179\",\"n\":\"新概念\"},{\"v\":\"28465\",\"n\":\"电动车\"},{\"v\":\"28466\",\"n\":\"摩托车\"}],\"key\":\"20541\"},{\"name\":\"地区\",\"value\":[{\"v\":\"20554\",\"n\":\"自主品牌\"},{\"v\":\"20555\",\"n\":\"欧洲品牌\"},{\"v\":\"20556\",\"n\":\"亚洲品牌\"},{\"v\":\"20557\",\"n\":\"北美品牌\"}],\"key\":\"20553\"}],\"27\":[{\"name\":\"分类\",\"value\":[{\"v\":\"21317\",\"n\":\"动画\"},{\"v\":\"27986\",\"n\":\"短片\"},{\"v\":\"28034\",\"n\":\"网络剧\"},{\"v\":\"28053\",\"n\":\"创意广告\"},{\"v\":\"21318\",\"n\":\"微电影\"}],\"key\":\"21316\"}],\"28\":[{\"name\":\"分类\",\"value\":[{\"v\":\"21789\",\"n\":\"军情\"},{\"v\":\"21790\",\"n\":\"深度\"},{\"v\":\"21791\",\"n\":\"兵器\"},{\"v\":\"21792\",\"n\":\"战史\"},{\"v\":\"21793\",\"n\":\"人物\"},{\"v\":\"30090\",\"n\":\"航空航天\"}],\"key\":\"21788\"}],\"29\":[{\"name\":\"类型\",\"value\":[{\"v\":\"24083\",\"n\":\"萌宝乐园\"},{\"v\":\"24084\",\"n\":\"孕期\"},{\"v\":\"24085\",\"n\":\"分娩\"},{\"v\":\"24086\",\"n\":\"妈咪饮食\"},{\"v\":\"24087\",\"n\":\"宝宝饮食\"},{\"v\":\"24088\",\"n\":\"早教课堂\"},{\"v\":\"24089\",\"n\":\"婴幼儿常见疾病\"},{\"v\":\"27345\",\"n\":\"时尚辣妈圈\"},{\"v\":\"27350\",\"n\":\"亲子生活馆\"},{\"v\":\"29619\",\"n\":\"宝宝养育\"},{\"v\":\"29746\",\"n\":\"趣味玩具\"},{\"v\":\"30086\",\"n\":\"行业动态\"}],\"key\":\"24082\"},{\"name\":\"年龄段\",\"value\":[{\"v\":\"24121\",\"n\":\"0-1岁\"},{\"v\":\"24122\",\"n\":\"1-3岁\"},{\"v\":\"24123\",\"n\":\"3-6岁\"},{\"v\":\"24124\",\"n\":\"6岁以上\"}],\"key\":\"24120\"}],\"30\":[{\"name\":\"类型\",\"value\":[{\"v\":\"27936\",\"n\":\"评测\"},{\"v\":\"27937\",\"n\":\"教程\"},{\"v\":\"27938\",\"n\":\"活动\"},{\"v\":\"27939\",\"n\":\"广告\"},{\"v\":\"27974\",\"n\":\"资讯\"},{\"v\":\"28522\",\"n\":\"专访\"},{\"v\":\"27975\",\"n\":\"其他\"}],\"key\":\"24125\"},{\"name\":\"地区\",\"value\":[{\"v\":\"24132\",\"n\":\"国内\"},{\"v\":\"24133\",\"n\":\"国际\"}],\"key\":\"24131\"},{\"name\":\"内容\",\"value\":[{\"v\":\"27972\",\"n\":\"IT业界\"},{\"v\":\"27973\",\"n\":\"互联网\"},{\"v\":\"28521\",\"n\":\"APP\"},{\"v\":\"27942\",\"n\":\"手机\"},{\"v\":\"27943\",\"n\":\"笔记本\"},{\"v\":\"27944\",\"n\":\"智能硬件\"},{\"v\":\"27945\",\"n\":\"平板电脑\"},{\"v\":\"27946\",\"n\":\"数码相机\"},{\"v\":\"27948\",\"n\":\"PC\"},{\"v\":\"27949\",\"n\":\"家电\"},{\"v\":\"27950\",\"n\":\"游戏机\"},{\"v\":\"27951\",\"n\":\"前沿技术\"},{\"v\":\"27952\",\"n\":\"科学探索\"},{\"v\":\"27953\",\"n\":\"爱科技出品\"}],\"key\":\"27940\"}],\"31\":[{\"name\":\"语言\",\"value\":[{\"v\":\"27515\",\"n\":\"普通话\"},{\"v\":\"27516\",\"n\":\"英语\"},{\"v\":\"27517\",\"n\":\"韩语\"},{\"v\":\"27518\",\"n\":\"日语\"}],\"key\":\"27499\"},{\"name\":\"类型\",\"value\":[{\"v\":\"27507\",\"n\":\"文化\"},{\"v\":\"27508\",\"n\":\"娱乐\"},{\"v\":\"27509\",\"n\":\"访谈\"},{\"v\":\"27510\",\"n\":\"社会\"},{\"v\":\"27511\",\"n\":\"搞笑\"},{\"v\":\"27512\",\"n\":\"财经\"},{\"v\":\"27513\",\"n\":\"时尚\"},{\"v\":\"27514\",\"n\":\"历史\"},{\"v\":\"29117\",\"n\":\"电台\"},{\"v\":\"30290\",\"n\":\"科技\"},{\"v\":\"31318\",\"n\":\"相声评书\"},{\"v\":\"31319\",\"n\":\"演讲\"}],\"key\":\"27500\"},{\"name\":\"地区\",\"value\":[{\"v\":\"27502\",\"n\":\"内地\"},{\"v\":\"27503\",\"n\":\"台湾地区\"},{\"v\":\"27504\",\"n\":\"香港地区\"},{\"v\":\"27505\",\"n\":\"日本\"},{\"v\":\"27506\",\"n\":\"韩国\"},{\"v\":\"27824\",\"n\":\"美国\"}],\"key\":\"27501\"}],\"10\":[{\"name\":\"内容分类\",\"value\":[{\"v\":\"1007\",\"n\":\"电影\"},{\"v\":\"1006\",\"n\":\"电视剧\"}],\"key\":\"18031\"},{\"name\":\"电影地区\",\"value\":[{\"v\":\"29801\",\"n\":\"华语\"},{\"v\":\"29802\",\"n\":\"美国\"},{\"v\":\"29811\",\"n\":\"印度\"},{\"v\":\"29805\",\"n\":\"其它\"}],\"key\":\"18032\"},{\"name\":\"电视剧地区\",\"value\":[{\"v\":\"29927\",\"n\":\"内地\"},{\"v\":\"29929\",\"n\":\"韩剧\"},{\"v\":\"29930\",\"n\":\"美剧\"},{\"v\":\"29932\",\"n\":\"日剧\"},{\"v\":\"29934\",\"n\":\"台湾地区\"}],\"key\":\"21260\"},{\"name\":\"电视剧类型\",\"value\":[{\"v\":\"29973\",\"n\":\"网剧\"}],\"key\":\"21238\"}],\"32\":[{\"name\":\"类型\",\"value\":[{\"v\":\"28068\",\"n\":\"资讯\"},{\"v\":\"28069\",\"n\":\"医疗\"},{\"v\":\"28081\",\"n\":\"两性\"},{\"v\":\"28082\",\"n\":\"养生\"},{\"v\":\"28441\",\"n\":\"健身\"},{\"v\":\"28449\",\"n\":\"美容\"},{\"v\":\"28450\",\"n\":\"心理\"},{\"v\":\"28451\",\"n\":\"常识\"},{\"v\":\"28452\",\"n\":\"儿科\"},{\"v\":\"28456\",\"n\":\"老年\"},{\"v\":\"28459\",\"n\":\"宠物\"},{\"v\":\"28462\",\"n\":\"交流分享\"}],\"key\":\"28067\"}],\"11\":[{\"name\":\"类型\",\"value\":[{\"v\":\"990\",\"n\":\"经济\"},{\"v\":\"991\",\"n\":\"人文\"},{\"v\":\"992\",\"n\":\"艺术\"},{\"v\":\"994\",\"n\":\"科技\"},{\"v\":\"995\",\"n\":\"社会\"},{\"v\":\"996\",\"n\":\"哲学\"},{\"v\":\"997\",\"n\":\"心理\"},{\"v\":\"998\",\"n\":\"其它\"}],\"key\":\"18030\"}],\"33\":[{\"name\":\"类型\",\"value\":[{\"v\":\"28900\",\"n\":\"资讯\"},{\"v\":\"28541\",\"n\":\"娱乐\"},{\"v\":\"28542\",\"n\":\"体育\"},{\"v\":\"28543\",\"n\":\"电影\"},{\"v\":\"28544\",\"n\":\"微电影\"},{\"v\":\"28545\",\"n\":\"纪录片\"},{\"v\":\"28546\",\"n\":\"综艺\"},{\"v\":\"28547\",\"n\":\"脱口秀\"},{\"v\":\"28548\",\"n\":\"片花\"},{\"v\":\"28549\",\"n\":\"广告\"},{\"v\":\"28550\",\"n\":\"音乐\"},{\"v\":\"28551\",\"n\":\"动漫\"},{\"v\":\"28552\",\"n\":\"少儿\"},{\"v\":\"28553\",\"n\":\"游戏\"},{\"v\":\"28554\",\"n\":\"教育\"},{\"v\":\"28555\",\"n\":\"生活\"},{\"v\":\"28556\",\"n\":\"原创\"},{\"v\":\"28557\",\"n\":\"搞笑\"},{\"v\":\"28558\",\"n\":\"旅游\"},{\"v\":\"28559\",\"n\":\"时尚\"},{\"v\":\"28560\",\"n\":\"财经\"},{\"v\":\"28561\",\"n\":\"科技\"},{\"v\":\"28562\",\"n\":\"健康\"},{\"v\":\"28563\",\"n\":\"母婴\"},{\"v\":\"28564\",\"n\":\"汽车\"}],\"key\":\"28537\"},{\"name\":\"性质\",\"value\":[{\"v\":\"28895\",\"n\":\"其他\"},{\"v\":\"28565\",\"n\":\"环保\"},{\"v\":\"28566\",\"n\":\"捐款\"},{\"v\":\"28567\",\"n\":\"大病救助\"},{\"v\":\"28568\",\"n\":\"救灾\"},{\"v\":\"28569\",\"n\":\"动物保护\"},{\"v\":\"28570\",\"n\":\"社会关注\"}],\"key\":\"28538\"},{\"name\":\"分类\",\"value\":[{\"v\":\"28595\",\"n\":\"公益资讯\"},{\"v\":\"28596\",\"n\":\"公益人物\"},{\"v\":\"28597\",\"n\":\"公益活动\"},{\"v\":\"28598\",\"n\":\"公益作品\"},{\"v\":\"28599\",\"n\":\"公益影像\"},{\"v\":\"28600\",\"n\":\"公益组织\"}],\"key\":\"28539\"},{\"name\":\"国家/地区\",\"value\":[{\"v\":\"28601\",\"n\":\"国内\"},{\"v\":\"28602\",\"n\":\"国外\"}],\"key\":\"28540\"}],\"12\":[{\"name\":\"分类\",\"value\":[{\"v\":\"32641\",\"n\":\"中小学\"},{\"v\":\"32655\",\"n\":\"大学\"},{\"v\":\"32659\",\"n\":\"职业考证\"},{\"v\":\"32669\",\"n\":\"外语\"},{\"v\":\"32674\",\"n\":\"职场\"},{\"v\":\"32684\",\"n\":\"IT/互联网\"},{\"v\":\"32692\",\"n\":\"财经\"},{\"v\":\"32697\",\"n\":\"文史\"},{\"v\":\"32704\",\"n\":\"艺术\"},{\"v\":\"32712\",\"n\":\"运动健身\"},{\"v\":\"32718\",\"n\":\"健康\"},{\"v\":\"32722\",\"n\":\"心理\"},{\"v\":\"32725\",\"n\":\"亲子\"},{\"v\":\"32732\",\"n\":\"生活\"},{\"v\":\"32890\",\"n\":\"党政\"}],\"key\":\"32640\"}],\"13\":[{\"name\":\"行业\",\"value\":[{\"v\":\"1208\",\"n\":\"服饰\"},{\"v\":\"1209\",\"n\":\"美容\"},{\"v\":\"1210\",\"n\":\"生活\"},{\"v\":\"1211\",\"n\":\"其它\"}],\"key\":\"18051\"},{\"name\":\"季节\",\"value\":[{\"v\":\"1224\",\"n\":\"早春\"},{\"v\":\"1225\",\"n\":\"春夏\"},{\"v\":\"1226\",\"n\":\"早秋\"},{\"v\":\"1227\",\"n\":\"秋冬\"},{\"v\":\"1228\",\"n\":\"其它\"}],\"key\":\"18053\"},{\"name\":\"类型\",\"value\":[{\"v\":\"1229\",\"n\":\"公告牌\"},{\"v\":\"1230\",\"n\":\"奇艺自制\"},{\"v\":\"1231\",\"n\":\"热门综艺\"},{\"v\":\"1232\",\"n\":\"名利场\"},{\"v\":\"1233\",\"n\":\"趋势报道\"},{\"v\":\"1234\",\"n\":\"本季流行\"},{\"v\":\"1235\",\"n\":\"秀场\"},{\"v\":\"1236\",\"n\":\"广告大片\"},{\"v\":\"1237\",\"n\":\"街拍\"},{\"v\":\"1238\",\"n\":\"人物\"},{\"v\":\"1240\",\"n\":\"乐活\"},{\"v\":\"1241\",\"n\":\"其它\"}],\"key\":\"18054\"}],\"14\":[{\"name\":\"地区\",\"value\":[{\"v\":\"1278\",\"n\":\"内地\"},{\"v\":\"1279\",\"n\":\"港台\"},{\"v\":\"1280\",\"n\":\"日韩\"},{\"v\":\"1281\",\"n\":\"欧美\"},{\"v\":\"1282\",\"n\":\"其它\"}],\"key\":\"18055\"},{\"name\":\"类型\",\"value\":[{\"v\":\"1247\",\"n\":\"播报\"},{\"v\":\"1248\",\"n\":\"访谈\"},{\"v\":\"1249\",\"n\":\"搞笑\"},{\"v\":\"1250\",\"n\":\"游戏\"},{\"v\":\"1251\",\"n\":\"选秀\"},{\"v\":\"1252\",\"n\":\"时尚\"},{\"v\":\"1253\",\"n\":\"杂谈\"},{\"v\":\"1254\",\"n\":\"情感\"},{\"v\":\"1255\",\"n\":\"盛会\"},{\"v\":\"1256\",\"n\":\"曲艺\"},{\"v\":\"1257\",\"n\":\"美食\"},{\"v\":\"1258\",\"n\":\"粤语\"},{\"v\":\"1276\",\"n\":\"时尚综艺\"}],\"key\":\"18056\"}],\"15\":[{\"name\":\"地区\",\"value\":[{\"v\":\"1261\",\"n\":\"欧美\"},{\"v\":\"1259\",\"n\":\"大陆\"},{\"v\":\"1260\",\"n\":\"港台\"},{\"v\":\"28933\",\"n\":\"韩国\"},{\"v\":\"1263\",\"n\":\"其它\"}],\"key\":\"18057\"},{\"name\":\"年龄段\",\"value\":[{\"v\":\"4489\",\"n\":\"0-3岁\"},{\"v\":\"28929\",\"n\":\"4-6岁\"},{\"v\":\"4493\",\"n\":\"7-10岁\"},{\"v\":\"4494\",\"n\":\"11-13岁\"}],\"key\":\"20288\"},{\"name\":\"课程类型\",\"value\":[{\"v\":\"28983\",\"n\":\"儿歌\"},{\"v\":\"28984\",\"n\":\"故事\"},{\"v\":\"28985\",\"n\":\"学英语\"},{\"v\":\"28986\",\"n\":\"百科\"},{\"v\":\"28987\",\"n\":\"国学\"},{\"v\":\"28988\",\"n\":\"手工\"},{\"v\":\"28989\",\"n\":\"识字\"},{\"v\":\"28990\",\"n\":\"数学\"},{\"v\":\"28991\",\"n\":\"美术\"},{\"v\":\"28993\",\"n\":\"舞蹈\"},{\"v\":\"30918\",\"n\":\"音乐\"},{\"v\":\"30919\",\"n\":\"诗词\"},{\"v\":\"28994\",\"n\":\"其他\"}],\"key\":\"28982\"}],\"16\":[{\"name\":\"类型\",\"value\":[{\"v\":\"1296\",\"n\":\"喜剧\"},{\"v\":\"1297\",\"n\":\"爱情\"},{\"v\":\"1298\",\"n\":\"动作\"}],\"key\":\"18061\"}],\"17\":[{\"name\":\"大项\",\"value\":[{\"v\":\"1673\",\"n\":\"足球\"},{\"v\":\"1688\",\"n\":\"篮球\"},{\"v\":\"1700\",\"n\":\"网球\"},{\"v\":\"1707\",\"n\":\"高尔夫\"},{\"v\":\"1708\",\"n\":\"赛车\"},{\"v\":\"1712\",\"n\":\"台球\"},{\"v\":\"32632\",\"n\":\"街舞\"},{\"v\":\"22178\",\"n\":\"健身\"},{\"v\":\"1715\",\"n\":\"综合\"}],\"key\":\"18067\"},{\"name\":\"类型\",\"value\":[{\"v\":\"1724\",\"n\":\"集锦\"},{\"v\":\"1725\",\"n\":\"花絮\"},{\"v\":\"1727\",\"n\":\"整场\"},{\"v\":\"1728\",\"n\":\"节目\"},{\"v\":\"1729\",\"n\":\"纪录片\"},{\"v\":\"1730\",\"n\":\"教学\"},{\"v\":\"1837\",\"n\":\"资讯\"},{\"v\":\"22180\",\"n\":\"瞬间\"},{\"v\":\"22182\",\"n\":\"球星\"},{\"v\":\"1731\",\"n\":\"其它\"}],\"key\":\"18066\"}],\"18\":[{\"name\":\"大项\",\"value\":[{\"v\":\"1322\",\"n\":\"足球\"},{\"v\":\"1323\",\"n\":\"网球\"},{\"v\":\"1324\",\"n\":\"曲棍球\"},{\"v\":\"1325\",\"n\":\"羽毛球\"},{\"v\":\"1326\",\"n\":\"手球\"},{\"v\":\"1327\",\"n\":\"排球\"},{\"v\":\"1328\",\"n\":\"乒乓球\"},{\"v\":\"1329\",\"n\":\"篮球\"},{\"v\":\"1330\",\"n\":\"游泳\"},{\"v\":\"1331\",\"n\":\"花样游泳\"},{\"v\":\"1332\",\"n\":\"跳水\"},{\"v\":\"1333\",\"n\":\"水球\"},{\"v\":\"1334\",\"n\":\"田径\"},{\"v\":\"1335\",\"n\":\"自行车\"},{\"v\":\"1336\",\"n\":\"体操\"},{\"v\":\"1337\",\"n\":\"马术\"},{\"v\":\"1338\",\"n\":\"射箭\"},{\"v\":\"1339\",\"n\":\"射击\"},{\"v\":\"1340\",\"n\":\"击剑\"},{\"v\":\"1341\",\"n\":\"举重\"},{\"v\":\"1342\",\"n\":\"拳击\"},{\"v\":\"1343\",\"n\":\"柔道\"},{\"v\":\"1344\",\"n\":\"摔跤\"},{\"v\":\"1345\",\"n\":\"跆拳道\"},{\"v\":\"1346\",\"n\":\"皮划艇\"},{\"v\":\"1347\",\"n\":\"赛艇\"},{\"v\":\"1348\",\"n\":\"帆船\"},{\"v\":\"1349\",\"n\":\"现代五项\"},{\"v\":\"1350\",\"n\":\"铁人三项\"}],\"key\":\"18062\"},{\"name\":\"类型\",\"value\":[{\"v\":\"1316\",\"n\":\"比赛\"},{\"v\":\"1317\",\"n\":\"花絮\"},{\"v\":\"1318\",\"n\":\"节目\"},{\"v\":\"1319\",\"n\":\"访谈\"},{\"v\":\"1320\",\"n\":\"资讯\"},{\"v\":\"1321\",\"n\":\"历史\"}],\"key\":\"18064\"}],\"1\":[{\"name\":\"地区\",\"value\":[{\"v\":\"1\",\"n\":\"华语\"},{\"v\":\"2\",\"n\":\"美国\"},{\"v\":\"3\",\"n\":\"欧洲\"},{\"v\":\"4\",\"n\":\"韩国\"},{\"v\":\"308\",\"n\":\"日本\"},{\"v\":\"28999\",\"n\":\"印度\"},{\"v\":\"5\",\"n\":\"其它\"}],\"key\":\"18000\"},{\"name\":\"类型\",\"value\":[{\"v\":\"8\",\"n\":\"喜剧\"},{\"v\":\"6\",\"n\":\"爱情\"},{\"v\":\"11\",\"n\":\"动作\"},{\"v\":\"131\",\"n\":\"枪战\"},{\"v\":\"291\",\"n\":\"犯罪\"},{\"v\":\"128\",\"n\":\"惊悚\"},{\"v\":\"10\",\"n\":\"恐怖\"},{\"v\":\"289\",\"n\":\"悬疑\"},{\"v\":\"12\",\"n\":\"动画\"},{\"v\":\"27356\",\"n\":\"家庭\"},{\"v\":\"1284\",\"n\":\"奇幻\"},{\"v\":\"9\",\"n\":\"科幻\"},{\"v\":\"7\",\"n\":\"战争\"},{\"v\":\"130\",\"n\":\"青春\"}],\"key\":\"18001\"},{\"name\":\"规格\",\"value\":[{\"v\":\"27397\",\"n\":\"巨制\"},{\"v\":\"27815\",\"n\":\"院线\"},{\"v\":\"30149\",\"n\":\"独播\"},{\"v\":\"27401\",\"n\":\"网络电影\"}],\"key\":\"27396\"}],\"2\":[{\"name\":\"地区\",\"value\":[{\"v\":\"15\",\"n\":\"内地\"},{\"v\":\"17\",\"n\":\"韩剧\"},{\"v\":\"18\",\"n\":\"美剧\"},{\"v\":\"309\",\"n\":\"日剧\"},{\"v\":\"1117\",\"n\":\"台湾地区\"}],\"key\":\"18002\"},{\"name\":\"类型\",\"value\":[{\"v\":\"24\",\"n\":\"古装\"},{\"v\":\"20\",\"n\":\"言情\"},{\"v\":\"23\",\"n\":\"武侠\"},{\"v\":\"30\",\"n\":\"偶像\"},{\"v\":\"1654\",\"n\":\"家庭\"},{\"v\":\"1653\",\"n\":\"青春\"},{\"v\":\"24064\",\"n\":\"都市\"},{\"v\":\"135\",\"n\":\"喜剧\"},{\"v\":\"32\",\"n\":\"悬疑\"},{\"v\":\"149\",\"n\":\"罪案\"},{\"v\":\"148\",\"n\":\"穿越\"},{\"v\":\"139\",\"n\":\"宫廷\"},{\"v\":\"21\",\"n\":\"历史\"},{\"v\":\"145\",\"n\":\"神话\"},{\"v\":\"34\",\"n\":\"科幻\"},{\"v\":\"27\",\"n\":\"年代\"},{\"v\":\"140\",\"n\":\"商战\"},{\"v\":\"24063\",\"n\":\"剧情\"},{\"v\":\"24065\",\"n\":\"网剧\"}],\"key\":\"18003\"}],\"3\":[{\"name\":\"地区\",\"value\":[{\"v\":\"20323\",\"n\":\"国内\"},{\"v\":\"20324\",\"n\":\"国外\"}],\"key\":\"20322\"},{\"name\":\"类型\",\"value\":[{\"v\":\"70\",\"n\":\"人文\"},{\"v\":\"33908\",\"n\":\"美食\"},{\"v\":\"33924\",\"n\":\"医疗\"},{\"v\":\"33933\",\"n\":\"自然\"},{\"v\":\"33945\",\"n\":\"萌宠\"},{\"v\":\"33953\",\"n\":\"财经\"},{\"v\":\"33960\",\"n\":\"罪案\"},{\"v\":\"33967\",\"n\":\"竞技\"},{\"v\":\"33974\",\"n\":\"灾难\"},{\"v\":\"74\",\"n\":\"历史\"},{\"v\":\"73\",\"n\":\"探险\"},{\"v\":\"71\",\"n\":\"社会\"},{\"v\":\"28119\",\"n\":\"科技\"},{\"v\":\"310\",\"n\":\"旅游\"}],\"key\":\"18004\"},{\"name\":\"出品方\",\"value\":[{\"v\":\"31283\",\"n\":\"爱奇艺出品\"}],\"key\":\"28467\"},{\"name\":\"片种\",\"value\":[{\"v\":\"29077\",\"n\":\"纪录电影\"},{\"v\":\"29078\",\"n\":\"系列纪录片\"},{\"v\":\"29082\",\"n\":\"网络纪录片\"},{\"v\":\"29083\",\"n\":\"纪实栏目\"}],\"key\":\"29076\"}],\"4\":[{\"name\":\"地区\",\"value\":[{\"v\":\"37\",\"n\":\"中国大陆\"},{\"v\":\"38\",\"n\":\"日本\"},{\"v\":\"30218\",\"n\":\"欧美\"}],\"key\":\"18005\"},{\"name\":\"版本\",\"value\":[{\"v\":\"30220\",\"n\":\"动画\"},{\"v\":\"32784\",\"n\":\"动画电影\"},{\"v\":\"33482\",\"n\":\"轻动画\"},{\"v\":\"33483\",\"n\":\"短剧\"}],\"key\":\"30219\"},{\"name\":\"风格\",\"value\":[{\"v\":\"30230\",\"n\":\"搞笑\"},{\"v\":\"30232\",\"n\":\"热血\"},{\"v\":\"30233\",\"n\":\"催泪\"},{\"v\":\"30234\",\"n\":\"治愈\"},{\"v\":\"30237\",\"n\":\"励志\"},{\"v\":\"30241\",\"n\":\"机战\"},{\"v\":\"30243\",\"n\":\"恋爱\"},{\"v\":\"30245\",\"n\":\"科幻\"},{\"v\":\"30247\",\"n\":\"奇幻\"},{\"v\":\"30248\",\"n\":\"推理\"},{\"v\":\"30249\",\"n\":\"校园\"},{\"v\":\"30252\",\"n\":\"日常\"},{\"v\":\"30255\",\"n\":\"美食\"},{\"v\":\"30256\",\"n\":\"职场\"},{\"v\":\"30258\",\"n\":\"偶像\"},{\"v\":\"30265\",\"n\":\"泡面\"},{\"v\":\"30267\",\"n\":\"冒险\"},{\"v\":\"30268\",\"n\":\"竞技\"},{\"v\":\"30270\",\"n\":\"合家欢\"},{\"v\":\"32792\",\"n\":\"武侠\"},{\"v\":\"32793\",\"n\":\"玄幻\"}],\"key\":\"30225\"},{\"name\":\"新类型\",\"value\":[{\"v\":\"32796\",\"n\":\"轻小说改编\"},{\"v\":\"32797\",\"n\":\"漫画改编\"},{\"v\":\"32798\",\"n\":\"游戏改编\"},{\"v\":\"32799\",\"n\":\"原创\"}],\"key\":\"32795\"}],\"5\":[{\"name\":\"地区\",\"value\":[{\"v\":\"221\",\"n\":\"内地\"},{\"v\":\"220\",\"n\":\"港台\"},{\"v\":\"219\",\"n\":\"欧美\"},{\"v\":\"218\",\"n\":\"日韩\"},{\"v\":\"217\",\"n\":\"拉美\"},{\"v\":\"216\",\"n\":\"亚洲地区\"},{\"v\":\"215\",\"n\":\"非洲\"}],\"key\":\"18008\"},{\"name\":\"语种\",\"value\":[{\"v\":\"91\",\"n\":\"普通话\"},{\"v\":\"92\",\"n\":\"粤语\"},{\"v\":\"93\",\"n\":\"闽南语\"},{\"v\":\"94\",\"n\":\"英语\"},{\"v\":\"95\",\"n\":\"日语\"},{\"v\":\"96\",\"n\":\"韩语\"},{\"v\":\"97\",\"n\":\"其它\"}],\"key\":\"18009\"}],\"6\":[{\"name\":\"地区\",\"value\":[{\"v\":\"151\",\"n\":\"内地\"},{\"v\":\"152\",\"n\":\"港台\"},{\"v\":\"33306\",\"n\":\"韩国\"},{\"v\":\"154\",\"n\":\"欧美\"},{\"v\":\"1113\",\"n\":\"其它\"}],\"key\":\"18013\"},{\"name\":\"类型\",\"value\":[{\"v\":\"155\",\"n\":\"播报\"},{\"v\":\"156\",\"n\":\"访谈\"},{\"v\":\"158\",\"n\":\"游戏\"},{\"v\":\"292\",\"n\":\"晚会\"},{\"v\":\"2118\",\"n\":\"脱口秀\"},{\"v\":\"2224\",\"n\":\"真人秀\"},{\"v\":\"33860\",\"n\":\"竞演\"}],\"key\":\"18014\"}],\"7\":[{\"name\":\"内容类型\",\"value\":[{\"v\":\"169\",\"n\":\"独家\"},{\"v\":\"170\",\"n\":\"热点\"},{\"v\":\"171\",\"n\":\"原创\"},{\"v\":\"175\",\"n\":\"八卦\"},{\"v\":\"176\",\"n\":\"选秀\"},{\"v\":\"180\",\"n\":\"搞笑\"},{\"v\":\"182\",\"n\":\"颁奖\"},{\"v\":\"183\",\"n\":\"活动\"},{\"v\":\"349\",\"n\":\"结婚\"},{\"v\":\"350\",\"n\":\"去世\"},{\"v\":\"351\",\"n\":\"生子\"},{\"v\":\"352\",\"n\":\"探班\"},{\"v\":\"353\",\"n\":\"事故\"},{\"v\":\"637\",\"n\":\"票房\"},{\"v\":\"951\",\"n\":\"纠纷\"},{\"v\":\"1001\",\"n\":\"星座\"},{\"v\":\"1088\",\"n\":\"演唱会\"},{\"v\":\"1658\",\"n\":\"慈善\"},{\"v\":\"32512\",\"n\":\"话剧\"},{\"v\":\"32513\",\"n\":\"舞蹈\"},{\"v\":\"32514\",\"n\":\"戏曲\"},{\"v\":\"32515\",\"n\":\"儿童剧\"},{\"v\":\"32516\",\"n\":\"歌剧\"},{\"v\":\"32517\",\"n\":\"音乐剧\"},{\"v\":\"32518\",\"n\":\"音乐会\"},{\"v\":\"32519\",\"n\":\"相声\"},{\"v\":\"32520\",\"n\":\"马戏\"},{\"v\":\"32521\",\"n\":\"魔术\"},{\"v\":\"32522\",\"n\":\"展览\"},{\"v\":\"32523\",\"n\":\"其它\"}],\"key\":\"18016\"},{\"name\":\"地区\",\"value\":[{\"v\":\"184\",\"n\":\"内地\"},{\"v\":\"185\",\"n\":\"港台\"},{\"v\":\"186\",\"n\":\"韩国\"},{\"v\":\"187\",\"n\":\"海外\"},{\"v\":\"188\",\"n\":\"其它\"}],\"key\":\"18017\"},{\"name\":\"类型\",\"value\":[{\"v\":\"1077\",\"n\":\"电影\"},{\"v\":\"1078\",\"n\":\"电视\"},{\"v\":\"1079\",\"n\":\"音乐\"},{\"v\":\"1080\",\"n\":\"演出\"},{\"v\":\"1081\",\"n\":\"明星\"},{\"v\":\"1082\",\"n\":\"综艺\"},{\"v\":\"1656\",\"n\":\"公益\"},{\"v\":\"32507\",\"n\":\"展览\"},{\"v\":\"32508\",\"n\":\"艺术节\"},{\"v\":\"32538\",\"n\":\"韩娱演出\"},{\"v\":\"1083\",\"n\":\"其它\"}],\"key\":\"18042\"}],\"8\":[{\"name\":\"类型\",\"value\":[{\"v\":\"21276\",\"n\":\"电子竞技\"},{\"v\":\"21275\",\"n\":\"网络游戏\"},{\"v\":\"21277\",\"n\":\"单机游戏\"},{\"v\":\"21278\",\"n\":\"手机游戏\"},{\"v\":\"30902\",\"n\":\"少儿游戏\"},{\"v\":\"21279\",\"n\":\"游戏美女\"}],\"key\":\"18024\"}],\"9\":[{\"name\":\"类型\",\"value\":[{\"v\":\"354\",\"n\":\"风光\"},{\"v\":\"355\",\"n\":\"饮食\"},{\"v\":\"356\",\"n\":\"住宿\"},{\"v\":\"357\",\"n\":\"新闻\"},{\"v\":\"30150\",\"n\":\"钓鱼\"},{\"v\":\"638\",\"n\":\"出行方式\"},{\"v\":\"29134\",\"n\":\"户外\"},{\"v\":\"29135\",\"n\":\"文化\"},{\"v\":\"639\",\"n\":\"奇趣\"}],\"key\":\"18029\"}],\"20\":[{\"name\":\"分类\",\"value\":[{\"v\":\"1859\",\"n\":\"明星\"},{\"v\":\"1860\",\"n\":\"公益\"},{\"v\":\"1861\",\"n\":\"欧美\"},{\"v\":\"1862\",\"n\":\"形象\"},{\"v\":\"1863\",\"n\":\"搞笑\"},{\"v\":\"1864\",\"n\":\"时尚\"},{\"v\":\"1865\",\"n\":\"儿童\"},{\"v\":\"1866\",\"n\":\"生活\"},{\"v\":\"1868\",\"n\":\"热门\"}],\"key\":\"18070\"},{\"name\":\"行业\",\"value\":[{\"v\":\"1883\",\"n\":\"IT数码\"},{\"v\":\"1884\",\"n\":\"汽车\"},{\"v\":\"1885\",\"n\":\"金融\"},{\"v\":\"1886\",\"n\":\"房地产\"},{\"v\":\"1887\",\"n\":\"化妆品\"},{\"v\":\"1888\",\"n\":\"食品饮料\"},{\"v\":\"1889\",\"n\":\"烟酒\"},{\"v\":\"1890\",\"n\":\"运动户外\"},{\"v\":\"1891\",\"n\":\"服装\"},{\"v\":\"1892\",\"n\":\"鞋包配件\"},{\"v\":\"1893\",\"n\":\"家具电器\"},{\"v\":\"1894\",\"n\":\"医药\"},{\"v\":\"1895\",\"n\":\"珠宝手表\"},{\"v\":\"1896\",\"n\":\"日化用品\"},{\"v\":\"28481\",\"n\":\"游戏\"},{\"v\":\"2295\",\"n\":\"其他\"}],\"key\":\"18073\"},{\"name\":\"版块\",\"value\":[{\"v\":\"2291\",\"n\":\"大赏\"},{\"v\":\"2292\",\"n\":\"微短片\"},{\"v\":\"2293\",\"n\":\"创意\"},{\"v\":\"2294\",\"n\":\"经典\"},{\"v\":\"29114\",\"n\":\"特约播映\"}],\"key\":\"18081\"}],\"21\":[{\"name\":\"分类\",\"value\":[{\"v\":\"2218\",\"n\":\"美食\"},{\"v\":\"31322\",\"n\":\"窍门\"},{\"v\":\"1879\",\"n\":\"家居\"},{\"v\":\"2228\",\"n\":\"宠物\"},{\"v\":\"1878\",\"n\":\"健康\"},{\"v\":\"2226\",\"n\":\"舞蹈\"},{\"v\":\"2230\",\"n\":\"情感\"},{\"v\":\"1876\",\"n\":\"奇闻\"},{\"v\":\"2227\",\"n\":\"休闲\"}],\"key\":\"18071\"},{\"name\":\"地域\",\"value\":[{\"v\":\"1881\",\"n\":\"国内\"},{\"v\":\"1882\",\"n\":\"国外\"}],\"key\":\"18072\"}]}");
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ public String join(@NonNull CharSequence charSequence, @NonNull Iterable iterable) {
+ Iterator it = iterable.iterator();
+ if (!it.hasNext()) {
+ return "";
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append(it.next());
+ while (it.hasNext()) {
+ sb.append(charSequence);
+ sb.append(it.next());
+ }
+ return sb.toString();
+ }
+
+ public String playerContent(String str, String str2, List list) {
+ try {
+ JSONObject jSONObject = new JSONObject();
+ try {
+ jSONObject.put("parse", 1);
+ jSONObject.put("jx", "1");
+ jSONObject.put("url", str2);
+ return jSONObject.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ return jSONObject.toString();
+ }
+ } catch (Exception e2) {
+ SpiderDebug.log(e2);
+ return "";
+ }
+ }
+
+ public String searchContent(String str, boolean quick) {
+ try {
+ String url = "https://search.video.iqiyi.com/o?if=html5&key=" + str + "&pageNum=1&pos=1&pageSize=20";
+ String json = OkHttpUtil.string(url, getHeaders(url));
+ JSONArray optJSONArray = new JSONObject(json).optJSONObject("data").optJSONArray("docinfos");
+
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < optJSONArray.length(); i++) {
+ JSONObject optJSONObject = optJSONArray.getJSONObject(i).optJSONObject("albumDocInfo");
+ JSONObject video = new JSONObject();
+ String optString = optJSONObject.optString("albumLink");
+ video.put("vod_id", "/albums/album/avlistinfo?aid=" + optJSONObject.optString("qipu_id") + "&size=5000&page=1&url=" + optString);
+ video.put("vod_name", optJSONObject.optString("albumTitle"));
+ video.put("vod_pic", optJSONObject.optString("albumImg"));
+ video.put("vod_remarks", optJSONObject.optString("releaseDate"));
+ videos.put(video);
+ }
+ JSONObject jSONObject2 = new JSONObject();
+ jSONObject2.put("list", videos);
+ return jSONObject2.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ return "";
+ }
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Imaple.java b/app/src/main/java/com/github/catvod/spider/Imaple.java
new file mode 100644
index 0000000..7779054
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Imaple.java
@@ -0,0 +1,465 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Demo for self study
+ *
+ * Source from Author: CatVod
+ */
+
+public class Imaple extends Spider {
+
+ private static final String siteUrl = "https://imaple.co/";
+ private static final String siteHost = "imaple.co";
+
+ protected JSONObject playerConfig;
+ protected JSONObject filterConfig;
+
+ protected Pattern regexCategory = Pattern.compile("/type/(\\S+).html");
+ protected Pattern regexVid = Pattern.compile("/vod/(\\d+).html");
+ protected Pattern regexPlay = Pattern.compile("/play/(\\d+)-(\\d+)-(\\d+).html");
+ protected Pattern regexPage = Pattern.compile("\\S+/page/(\\d+)\\S+");
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ try {
+ playerConfig = new JSONObject("{\"kbm3u8\":{\"sh\":\"秒播雲\",\"sn\":0,\"pu\":\"\",\"or\":999},\"bjm3u8\":{\"sh\":\"八戒雲\",\"sn\":0,\"pu\":\"\",\"or\":999},\"605m3u8\":{\"sh\":\"光速雲\",\"sn\":0,\"pu\":\"\",\"or\":999},\"mlm3u8\":{\"sh\":\"藍光線一\",\"sn\":0,\"pu\":\"\",\"or\":999},\"alizy\":{\"sh\":\"藍光線三\",\"sn\":1,\"pu\":\"https://player.imaple.tv/player/?url=\",\"or\":999},\"dplayer\":{\"sh\":\"動漫專線\",\"sn\":1,\"pu\":\"https://player.imaple.tv/player/?url=\",\"or\":999},\"qdyun\":{\"sh\":\"驱动云\",\"sn\":0,\"pu\":\"\",\"or\":999},\"wjm3u8\":{\"sh\":\"理想雲\",\"sn\":0,\"pu\":\"\",\"or\":999},\"fanqie\":{\"sh\":\"番茄资源\",\"sn\":1,\"pu\":\"https://player.imaple.tv/player/?url=\",\"or\":999},\"youku\":{\"sh\":\"奇藝雲\",\"sn\":1,\"pu\":\"https://player.imaple.tv/player/?url=\",\"or\":999},\"qq\":{\"sh\":\"騰訊雲\",\"sn\":1,\"pu\":\"https://player.imaple.tv/player/?url=\",\"or\":999},\"mgtv\":{\"sh\":\"芒果雲\",\"sn\":1,\"pu\":\"https://player.imaple.tv/player/?url=\",\"or\":999},\"sohu\":{\"sh\":\"搜狐雲\",\"sn\":1,\"pu\":\"https://player.imaple.tv/player/?url=\",\"or\":999},\"88zym3u8\":{\"sh\":\"優雅雲\",\"sn\":1,\"pu\":\"https://player.imaple.tv/player/?url=\",\"or\":999},\"bilibili\":{\"sh\":\"嗶哩雲\",\"sn\":1,\"pu\":\"https://player.imaple.tv/player/?url=\",\"or\":999},\"dbm3u8\":{\"sh\":\"急速雲\",\"sn\":0,\"pu\":\"\",\"or\":999},\"tkm3u8\":{\"sh\":\"天空雲\",\"sn\":0,\"pu\":\"\",\"or\":999}}");
+ filterConfig = new JSONObject("{\"1\":[{\"key\":\"tid\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"動作片\",\"v\":\"6\"},{\"n\":\"喜劇片\",\"v\":\"7\"},{\"n\":\"愛情片\",\"v\":\"8\"},{\"n\":\"科幻片\",\"v\":\"9\"},{\"n\":\"恐怖片\",\"v\":\"10\"},{\"n\":\"劇情片\",\"v\":\"11\"},{\"n\":\"戰爭片\",\"v\":\"12\"},{\"n\":\"紀錄片\",\"v\":\"20\"}]},{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"大陸\",\"v\":\"大陸\"},{\"n\":\"香港\",\"v\":\"香港\"},{\"n\":\"台灣\",\"v\":\"台灣\"},{\"n\":\"美國\",\"v\":\"美國\"},{\"n\":\"法國\",\"v\":\"法國\"},{\"n\":\"英國\",\"v\":\"英國\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韓國\",\"v\":\"韓國\"},{\"n\":\"德國\",\"v\":\"德國\"},{\"n\":\"泰國\",\"v\":\"泰國\"},{\"n\":\"印度\",\"v\":\"印度\"},{\"n\":\"意大利\",\"v\":\"意大利\"},{\"n\":\"西班牙\",\"v\":\"西班牙\"},{\"n\":\"加拿大\",\"v\":\"加拿大\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"2\":[{\"key\":\"tid\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"大陸劇\",\"v\":\"13\"},{\"n\":\"港劇\",\"v\":\"14\"},{\"n\":\"台劇\",\"v\":\"15\"},{\"n\":\"日劇\",\"v\":\"16\"},{\"n\":\"韓劇\",\"v\":\"23\"},{\"n\":\"美劇\",\"v\":\"24\"},{\"n\":\"海外劇\",\"v\":\"25\"}]},{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"3\":[{\"key\":\"tid\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"港台綜藝\",\"v\":\"29\"},{\"n\":\"日韓綜藝\",\"v\":\"30\"},{\"n\":\"大陸綜藝\",\"v\":\"31\"},{\"n\":\"歐美綜藝\",\"v\":\"32\"}]},{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"4\":[{\"key\":\"tid\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"港台動漫\",\"v\":\"33\"},{\"n\":\"日韓動漫\",\"v\":\"34\"},{\"n\":\"大陸動漫\",\"v\":\"35\"},{\"n\":\"歐美動漫\",\"v\":\"36\"},{\"n\":\"海外動漫\",\"v\":\"37\"}]},{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}]}");
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ /**
+ * 爬虫headers
+ *
+ * @param url
+ * @return
+ */
+ protected HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("method", "GET");
+ headers.put("Host", siteHost);
+ headers.put("Upgrade-Insecure-Requests", "1");
+ headers.put("DNT", "1");
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
+ headers.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ return headers;
+ }
+
+ /**
+ * 获取分类数据 + 首页最近更新视频列表数据
+ *
+ * @param filter 是否开启筛选 关联的是 软件设置中 首页数据源里的筛选开关
+ * @return
+ */
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ String url = siteUrl + '/';
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ Elements elements = doc.select("ul.myui-header__menu>li>a");
+ JSONArray classes = new JSONArray();
+ ArrayList allClass = new ArrayList<>();
+ for (Element ele : elements) {
+ String name = ele.text();
+ boolean show = !filter || (name.equals("電影") || name.equals("電視劇") || name.equals("綜藝") || name.equals("動漫"));
+ if (allClass.contains(name))
+ show = false;
+ if (show) {
+ allClass.add(name);
+ Matcher mather = regexCategory.matcher(ele.attr("href"));
+ if (!mather.find())
+ continue;
+ // 把分类的id和名称取出来加到列表里
+ String id = mather.group(1).trim();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_id", id);
+ jsonObject.put("type_name", name);
+ classes.put(jsonObject);
+ }
+ }
+ JSONObject result = new JSONObject();
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ result.put("class", classes);
+ try {
+ // 取首页推荐视频列表
+ Elements list = doc.select("li.col-lg-6 >div.myui-vodlist__box");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst(".title").text();
+ String cover = vod.selectFirst(".myui-vodlist__thumb").attr("data-original");
+ String remark = vod.selectFirst("span.pic-text").text();
+
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".myui-vodlist__thumb").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ /**
+ * 获取分类信息数据
+ *
+ * @param tid 分类id
+ * @param pg 页数
+ * @param filter 同homeContent方法中的filter
+ * @param extend 筛选参数{k:v, k1:v1}
+ * @return
+ */
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ String url = siteUrl + "/show/";
+ if (extend != null && extend.size() > 0 && extend.containsKey("tid") && extend.get("tid").length() > 0) {
+ url += extend.get("tid");
+ } else {
+ url += tid;
+ }
+ if (extend != null && extend.size() > 0) {
+ for (Iterator it = extend.keySet().iterator(); it.hasNext(); ) {
+ String key = it.next();
+ String value = extend.get(key);
+ if (value.length() > 0) {
+ url += "/" + key + "/" + URLEncoder.encode(value);
+ }
+ }
+ }
+ url += "/page/" + pg + ".html";
+ String html = OkHttpUtil.string(url, getHeaders(url));
+ Document doc = Jsoup.parse(html);
+ JSONObject result = new JSONObject();
+ int pageCount = 0;
+ int page = -1;
+
+ // 取页码相关信息
+ Elements pageInfo = doc.select(".myui-page li a");
+ if (pageInfo.size() == 0) {
+ page = Integer.parseInt(pg);
+ pageCount = page;
+ } else {
+ for (int i = 0; i < pageInfo.size(); i++) {
+ Element a = pageInfo.get(i);
+ String name = a.text();
+ if (page == -1 && a.hasClass("btn-warm")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ page = Integer.parseInt(matcher.group(1).trim());
+ } else {
+ page = 0;
+ }
+ }
+ if (name.equals("尾頁")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ pageCount = Integer.parseInt(matcher.group(1).trim());
+ } else {
+ pageCount = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ JSONArray videos = new JSONArray();
+ if (!html.contains("没有找到您想要的结果哦")) {
+ // 取当前分类页的视频列表
+ Elements list = doc.select("li.col-lg-6 >div.myui-vodlist__box");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst(".title").text();
+ String cover = vod.selectFirst(".myui-vodlist__thumb").attr("data-original");
+ String remark = vod.selectFirst("span.pic-text").text();
+
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".myui-vodlist__thumb").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", 48);
+ result.put("total", pageCount <= 1 ? videos.length() : pageCount * 48);
+
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 视频详情信息
+ *
+ * @param ids 视频id
+ * @return
+ */
+ @Override
+ public String detailContent(List ids) {
+ try {
+ // 视频详情url
+ String url = siteUrl + "/vod/" + ids.get(0) + ".html";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+
+ // 取基本数据
+ String vid = doc.selectFirst("span.mac_hits").attr("data-id");
+
+ String cover = doc.selectFirst("a.myui-vodlist__thumb img").attr("data-original");
+ String title = doc.selectFirst("div.myui-content__detail h1.title").text();
+ String desc = Jsoup.parse(doc.selectFirst("meta[name=description]").attr("content")).text();
+ String category = "", area = "", year = "", remark = "", director = "", actor = "";
+ Elements span_text_muted = doc.select("div.myui-content__detail span.text-muted");
+ for (int i = 0; i < span_text_muted.size(); i++) {
+ Element text = span_text_muted.get(i);
+ String info = text.text();
+ if (info.equals("分類:")) {
+ category = text.nextElementSibling().text();
+ } else if (info.equals("年份:")) {
+ year = text.nextElementSibling().text();
+ } else if (info.equals("地區:")) {
+ area = text.nextElementSibling().text();
+ } else if (info.equals("更新:")) {
+ remark = text.nextElementSibling().text();
+ } else if (info.equals("導演:")) {
+ List directors = new ArrayList<>();
+ Elements aa = text.parent().select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ directors.add(aa.get(j).text());
+ }
+ director = TextUtils.join(",", directors);
+ } else if (info.equals("主演:")) {
+ List actors = new ArrayList<>();
+ Elements aa = text.parent().select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ actors.add(aa.get(j).text());
+ }
+ actor = TextUtils.join(",", actors);
+ }
+ }
+
+ vodList.put("vod_id", vid);
+ vodList.put("vod_name", title);
+ vodList.put("vod_pic", cover);
+ vodList.put("type_name", category);
+ vodList.put("vod_year", year);
+ vodList.put("vod_area", area);
+ vodList.put("vod_remarks", remark);
+ vodList.put("vod_actor", actor);
+ vodList.put("vod_director", director);
+ vodList.put("vod_content", desc);
+
+ Map vod_play = new TreeMap<>(new Comparator() {
+ @Override
+ public int compare(String o1, String o2) {
+ try {
+ int sort1 = playerConfig.getJSONObject(o1).getInt("or");
+ int sort2 = playerConfig.getJSONObject(o2).getInt("or");
+
+ if (sort1 == sort2) {
+ return 1;
+ }
+ return sort1 - sort2 > 0 ? 1 : -1;
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ return 1;
+ }
+ });
+
+ // 取播放列表数据
+ Elements sources = doc.select("div.myui-panel__head>ul").get(0).select("li");
+ Elements sourceList = doc.select("div.tab-content>div.tab-pane");
+
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ String sourceName = source.text();
+ boolean found = false;
+ for (Iterator it = playerConfig.keys(); it.hasNext(); ) {
+ String flag = it.next();
+ if (playerConfig.getJSONObject(flag).getString("sh").equals(sourceName)) {
+ sourceName = flag;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+ String playList = "";
+ Elements playListA = sourceList.get(i).select("ul>li>a");
+ List vodItems = new ArrayList<>();
+
+ for (int j = 0; j < playListA.size(); j++) {
+ Element vod = playListA.get(j);
+ Matcher matcher = regexPlay.matcher(vod.attr("href"));
+ if (!matcher.find())
+ continue;
+ String playURL = matcher.group(1) + "-" + matcher.group(2) + "-" + matcher.group(3);
+ vodItems.add(vod.text() + "$" + playURL);
+ }
+ if (vodItems.size() > 0)
+ playList = TextUtils.join("#", vodItems);
+
+ if (playList.length() == 0)
+ continue;
+
+ vod_play.put(sourceName, playList);
+ }
+
+ if (vod_play.size() > 0) {
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+ }
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取视频播放信息
+ *
+ * @param flag 播放源
+ * @param id 视频id
+ * @param vipFlags 所有可能需要vip解析的源
+ * @return
+ */
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ //定义播放用的headers
+ JSONObject headers = new JSONObject();
+ //headers.put("Host", " cokemv.co");
+ headers.put("origin", " https://imaple.co");
+ headers.put("User-Agent", " Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Accept", " */*");
+ headers.put("Accept-Language", " zh-CN,zh;q=0.9,en-US;q=0.3,en;q=0.7");
+ headers.put("Accept-Encoding", " gzip, deflate");
+
+
+ // 播放页 url
+ String url = siteUrl + "/play/" + id + ".html";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ Elements allScript = doc.select("script");
+ JSONObject result = new JSONObject();
+ for (int i = 0; i < allScript.size(); i++) {
+ String scContent = allScript.get(i).html().trim();
+ if (scContent.startsWith("var player_")) { // 取直链
+ int start = scContent.indexOf('{');
+ int end = scContent.lastIndexOf('}') + 1;
+ String json = scContent.substring(start, end);
+ JSONObject player = new JSONObject(json);
+ if (playerConfig.has(player.getString("from"))) {
+ JSONObject pCfg = playerConfig.getJSONObject(player.getString("from"));
+ String videoUrl = player.getString("url");
+ String playUrl = pCfg.getString("pu");
+ result.put("parse", pCfg.getInt("sn"));
+ result.put("playUrl", playUrl);
+ result.put("url", videoUrl);
+ result.put("header", headers.toString());
+ }
+ break;
+ }
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ if (quick)
+ return "";
+ long currentTime = System.currentTimeMillis();
+ String url = siteUrl + "/index.php/ajax/suggest?mid=1&wd=" + URLEncoder.encode(key) + "&limit=10×tamp=" + currentTime;
+ JSONObject searchResult = new JSONObject(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONArray videos = new JSONArray();
+ if (searchResult.getInt("total") > 0) {
+ JSONArray lists = new JSONArray(searchResult.getString("list"));
+ for (int i = 0; i < lists.length(); i++) {
+ JSONObject vod = lists.getJSONObject(i);
+ String id = vod.getString("id");
+ String title = vod.getString("name");
+ String cover = vod.getString("pic");
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", "");
+ videos.put(v);
+ }
+ }
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Juhi.java b/app/src/main/java/com/github/catvod/spider/Juhi.java
new file mode 100644
index 0000000..8d33a94
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Juhi.java
@@ -0,0 +1,472 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.Misc;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Juhi extends Spider {
+
+ private static final String siteUrl = "https://www.juhi.cc/";
+ private static final String siteHost = "juhi.cc";
+
+ protected JSONObject playerConfig;
+ protected JSONObject filterConfig;
+
+ protected Pattern regexCategory = Pattern.compile("/vodtype/(\\d+)/");
+ protected Pattern regexVid = Pattern.compile("/voddetail/(\\d+)/");
+ protected Pattern regexPlay = Pattern.compile("/vodplay/(\\d+)-(\\d+)-(\\d+)/");
+ protected Pattern regexPage = Pattern.compile("/vodshow/(\\S+)/");
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ try {
+ playerConfig = new JSONObject("{\"tkm3u8\":{\"sh\":\"✦剧嗨专线\",\"pu\":\"https://jx.huishij.com/yun/?url=\",\"sn\":1,\"or\":999},\"if101\":{\"sh\":\"✦蓝光超清\",\"pu\":\"\",\"sn\":0,\"or\":999},\"dbm3u8\":{\"sh\":\"北美高清①\",\"pu\":\"\",\"sn\":0,\"or\":999},\"dbyun\":{\"sh\":\"北美高清②\",\"pu\":\"\",\"sn\":0,\"or\":999},\"wjm3u8\":{\"sh\":\"北美高清③\",\"pu\":\"\",\"sn\":0,\"or\":999},\"kbm3u8\":{\"sh\":\"全球线路①\",\"pu\":\"\",\"sn\":0,\"or\":999},\"hnyun\":{\"sh\":\"全球线路②\",\"pu\":\"\",\"sn\":0,\"or\":999},\"hnm3u8\":{\"sh\":\"全球线路③\",\"pu\":\"\",\"sn\":0,\"or\":999},\"kbzy\":{\"sh\":\"全球线路④\",\"pu\":\"\",\"sn\":0,\"or\":999},\"fanqie\":{\"sh\":\"全球线路⑤\",\"pu\":\"\",\"sn\":0,\"or\":999},\"kuaiyun\":{\"sh\":\"快速线路\",\"pu\":\"https://qimihe.com/?url=\",\"sn\":1,\"or\":999},\"leyum3u8\":{\"sh\":\"午夜专线1\",\"pu\":\"\",\"sn\":0,\"or\":999},\"lym3u8\":{\"sh\":\"午夜专线2\",\"pu\":\"\",\"sn\":0,\"or\":999},\"dplayer\":{\"sh\":\"DPlayer-H5播放器\",\"pu\":\"\",\"sn\":0,\"or\":999},\"videojs\":{\"sh\":\"videojs-H5播放器\",\"pu\":\"\",\"sn\":0,\"or\":999},\"iva\":{\"sh\":\"iva-H5播放器\",\"pu\":\"\",\"sn\":0,\"or\":999},\"iframe\":{\"sh\":\"iframe外链数据\",\"pu\":\"\",\"sn\":0,\"or\":999},\"link\":{\"sh\":\"外链数据\",\"pu\":\"\",\"sn\":0,\"or\":999},\"swf\":{\"sh\":\"Flash文件\",\"pu\":\"\",\"sn\":0,\"or\":999},\"flv\":{\"sh\":\"Flv文件\",\"pu\":\"\",\"sn\":0,\"or\":999},\"bjyun\":{\"sh\":\"bjyun\",\"pu\":\"\",\"sn\":0,\"or\":999},\"bjm3u8\":{\"sh\":\"bjm3u8\",\"pu\":\"\",\"sn\":0,\"or\":999},\"wasu\":{\"sh\":\"华数直连\",\"pu\":\"\",\"sn\":0,\"or\":999},\"funshion\":{\"sh\":\"风行直连\",\"pu\":\"\",\"sn\":0,\"or\":999},\"pptv\":{\"sh\":\"PPTV直连\",\"pu\":\"https://jx.m3u8.tv/jiexi/?url=\",\"sn\":1,\"or\":999},\"letv\":{\"sh\":\"乐视直连\",\"pu\":\"https://jx.m3u8.tv/jiexi/?url=\",\"sn\":1,\"or\":999},\"mgtv\":{\"sh\":\"芒果直连\",\"pu\":\"https://jx.m3u8.tv/jiexi/?url=\",\"sn\":1,\"or\":999},\"youku\":{\"sh\":\"优酷直连\",\"pu\":\"https://jx.m3u8.tv/jiexi/?url=\",\"sn\":1,\"or\":999},\"qiyi\":{\"sh\":\"爱奇艺直连\",\"pu\":\"https://jx.m3u8.tv/jiexi/?url=\",\"sn\":1,\"or\":999},\"qq\":{\"sh\":\"腾讯直连\",\"pu\":\"https://jx.m3u8.tv/jiexi/?url=\",\"sn\":1,\"or\":999},\"m1905\":{\"sh\":\"M1905直连\",\"pu\":\"https://jx.m3u8.tv/jiexi/?url=\",\"sn\":1,\"or\":999},\"sohu\":{\"sh\":\"搜狐直连\",\"pu\":\"https://jx.m3u8.tv/jiexi/?url=\",\"sn\":1,\"or\":999}}");
+ filterConfig = new JSONObject("{\"20\":[{\"key\":\"0\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"20\"},{\"n\":\"动作片\",\"v\":\"24\"},{\"n\":\"喜剧片\",\"v\":\"25\"},{\"n\":\"愛情片\",\"v\":\"26\"},{\"n\":\"科幻片\",\"v\":\"27\"},{\"n\":\"恐怖片\",\"v\":\"28\"},{\"n\":\"劇情片\",\"v\":\"11\"},{\"n\":\"戰爭片\",\"v\":\"30\"},{\"n\":\"动画电影\",\"v\":\"33\"}]},{\"key\":1,\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"大陆\",\"v\":\"大陆\"},{\"n\":\"香港\",\"v\":\"香港\"},{\"n\":\"台湾\",\"v\":\"台湾\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"法国\",\"v\":\"法国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"德国\",\"v\":\"德国\"},{\"n\":\"泰国\",\"v\":\"泰国\"},{\"n\":\"印度\",\"v\":\"印度\"},{\"n\":\"意大利\",\"v\":\"意大利\"},{\"n\":\"西班牙\",\"v\":\"西班牙\"},{\"n\":\"加拿大\",\"v\":\"加拿大\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"21\":[{\"key\":\"tid\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国产剧\",\"v\":\"34\"},{\"n\":\"港剧\",\"v\":\"35\"},{\"n\":\"韩剧\",\"v\":\"37\"},{\"n\":\"欧美剧\",\"v\":\"36\"},{\"n\":\"日本剧\",\"v\":\"38\"},{\"n\":\"台湾剧\",\"v\":\"39\"},{\"n\":\"海外剧\",\"v\":\"40\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"22\":[{\"key\":0,\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"22\"},{\"n\":\"大陆综艺\",\"v\":\"41\"},{\"n\":\"港台综艺\",\"v\":\"42\"},{\"n\":\"日韩综艺\",\"v\":\"43\"},{\"n\":\"欧美综艺\",\"v\":\"44\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"23\":[{\"key\":0,\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"23\"},{\"n\":\"国产动漫\",\"v\":\"45\"},{\"n\":\"日本动漫\",\"v\":\"46\"},{\"n\":\"欧美动漫\",\"v\":\"47\"}]},{\"key\":11,\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}]}");
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ /**
+ * 爬虫headers
+ *
+ * @param url
+ * @return
+ */
+ protected HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("method", "GET");
+ headers.put("Host", siteHost);
+ headers.put("Upgrade-Insecure-Requests", "1");
+ headers.put("DNT", "1");
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
+ headers.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ return headers;
+ }
+
+ /**
+ * 获取分类数据 + 首页最近更新视频列表数据
+ *
+ * @param filter 是否开启筛选 关联的是 软件设置中 首页数据源里的筛选开关
+ * @return
+ */
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ Document doc = Jsoup.parse(OkHttpUtil.string(siteUrl, getHeaders(siteUrl)));
+ // 分类节点
+ Elements elements = doc.select("ul.nav-menu > li > a");
+ JSONArray classes = new JSONArray();
+ for (Element ele : elements) {
+ //分类名
+ String name = ele.text();
+ boolean show = name.equals("电影") ||
+ name.equals("电视剧") ||
+ name.equals("综艺") ||
+ name.equals("动漫");
+ if (show) {
+ Matcher mather = regexCategory.matcher(ele.attr("href"));
+ if (!mather.find())
+ continue;
+ // 把分类的id和名称取出来加到列表里
+ String id = mather.group(1).trim();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_id", id);
+ jsonObject.put("type_name", name);
+ classes.put(jsonObject);
+ }
+ }
+ JSONObject result = new JSONObject();
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ result.put("class", classes);
+ try {
+ // 取首页推荐视频列表
+ Element homeList = doc.select("ul.myui-vodlist").get(0);
+ Elements list = homeList.select("li > div > a");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.attr("title");
+ String cover = vod.attr("data-original");
+ String remark = vod.selectFirst("span.pic-text").text();
+ Matcher matcher = regexVid.matcher(vod.attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取分类信息数据
+ *
+ * @param tid 分类id
+ * @param pg 页数
+ * @param filter 同homeContent方法中的filter
+ * @param extend 筛选参数{k:v, k1:v1}
+ * @return
+ */
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ String[] urlParams = new String[]{"", "", "", "", "", "", "", "", "", "", "", ""};
+ urlParams[0] = tid;
+ urlParams[8] = pg;
+ if (extend != null && extend.size() > 0) {
+ for (Iterator it = extend.keySet().iterator(); it.hasNext(); ) {
+ String key = it.next();
+ String value = extend.get(key);
+ urlParams[Integer.parseInt(key)] = URLEncoder.encode(value);
+ }
+ }
+ // 获取分类数据的url
+ String url = siteUrl + "/vodshow/" + TextUtils.join("-", urlParams) + "/";
+ String html = OkHttpUtil.string(url, getHeaders(url));
+ Document doc = Jsoup.parse(html);
+ JSONObject result = new JSONObject();
+ int pageCount = 0;
+ int page = -1;
+
+
+ // 取页码相关信息
+ Elements pageInfo = doc.select("ul.myui-page>li");
+ if (pageInfo.size() == 0) {
+ page = Integer.parseInt(pg);
+ pageCount = page;
+ } else {
+ for (int i = 0; i < pageInfo.size(); i++) {
+ Element li = pageInfo.get(i);
+ Element a = li.selectFirst("a");
+ if (a == null)
+ continue;
+ String name = a.text();
+ if (page == -1 && a.hasClass("btn-warm")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ page = Integer.parseInt(matcher.group(1).split("-")[8]);
+ } else {
+ page = 0;
+ }
+ }
+ if (name.equals("尾页")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ pageCount = Integer.parseInt(matcher.group(1).split("-")[8]);
+ } else {
+ pageCount = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ JSONArray videos = new JSONArray();
+ if (!html.contains("没有找到您想要的结果哦")) {
+ // 取当前分类页的视频列表
+ Elements list = doc.select("ul.myui-vodlist > li > div > a");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.attr("title");
+ String cover = vod.attr("data-original");
+ String remark = vod.selectFirst("span.pic-text").text();
+ Matcher matcher = regexVid.matcher(vod.attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", 48);
+ result.put("total", pageCount <= 1 ? videos.length() : pageCount * 48);
+
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 视频详情信息
+ *
+ * @param ids 视频id
+ * @return
+ */
+ @Override
+ public String detailContent(List ids) {
+ try {
+ // 视频详情url
+ String url = siteUrl + "/voddetail/" + ids.get(0) + "/";
+ //System.out.println(url);
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+
+ // 取基本数据
+ String cover = doc.selectFirst("div.myui-content__thumb > a > img").attr("src");
+ String title = doc.selectFirst("div.myui-content__thumb > a").attr("title");
+ String desc = Jsoup.parse(doc.selectFirst("meta[name=description]").attr("content")).text();
+ String category = "", area = "", year = "", remark = "", director = "", actor = "";
+ Elements span_text_muted = doc.select("div.myui-content__detail span.text-muted");
+ for (int i = 0; i < span_text_muted.size(); i++) {
+ Element text = span_text_muted.get(i);
+ String info = text.text();
+ if (info.equals("分类:")) {
+ category = text.nextElementSibling().text();
+ } else if (info.equals("年份:")) {
+ year = text.nextElementSibling().text();
+ } else if (info.equals("地区:")) {
+ area = text.nextElementSibling().text();
+ } else if (info.equals("更新:")) {
+ remark = text.nextElementSibling().text();
+ } else if (info.equals("导演:")) {
+ List directors = new ArrayList<>();
+ Elements aa = text.parent().select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ directors.add(aa.get(j).text());
+ }
+ director = TextUtils.join(",", directors);
+ } else if (info.equals("主演:")) {
+ List actors = new ArrayList<>();
+ Elements aa = text.parent().select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ actors.add(aa.get(j).text());
+ }
+ actor = TextUtils.join(",", actors);
+ }
+ }
+
+ vodList.put("vod_id", ids.get(0));
+ vodList.put("vod_name", title);
+ vodList.put("vod_pic", cover);
+ vodList.put("type_name", category);
+ vodList.put("vod_year", year);
+ vodList.put("vod_area", area);
+ vodList.put("vod_remarks", remark);
+ vodList.put("vod_actor", actor);
+ vodList.put("vod_director", director);
+ vodList.put("vod_content", desc);
+ //System.out.println(vodList.toString());
+ Map vod_play = new TreeMap<>(new Comparator() {
+ @Override
+ public int compare(String o1, String o2) {
+ try {
+ int sort1 = playerConfig.getJSONObject(o1).getInt("or");
+ int sort2 = playerConfig.getJSONObject(o2).getInt("or");
+
+ if (sort1 == sort2) {
+ return 1;
+ }
+ return sort1 - sort2 > 0 ? 1 : -1;
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ return 1;
+ }
+ });
+
+ // 取播放列表数据
+ Elements sources = doc.select("ul.nav-btn > li > a");
+ //System.out.println(sources.size());
+ Elements sourceList = doc.select("div.tab-content > div");
+ //System.out.println(sourceList.size());
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ //System.out.println(sources.text().split(":")[0].split("』")[1]);
+ String sourceName = source.text();
+ boolean found = false;
+ for (Iterator it = playerConfig.keys(); it.hasNext(); ) {
+ String flag = it.next();
+ if (playerConfig.getJSONObject(flag).getString("sh").equals(sourceName)) {
+ sourceName = flag;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+ String playList = "";
+ Elements playListA = sourceList.get(i).select("ul > li > a");
+ //System.out.println(playListA.size());
+ List vodItems = new ArrayList<>();
+
+ for (int j = 0; j < playListA.size(); j++) {
+ Element vod = playListA.get(j);
+ Matcher matcher = regexPlay.matcher(vod.attr("href"));
+ if (!matcher.find())
+ continue;
+ String playURL = matcher.group(1) + "-" + matcher.group(2) + "-" + matcher.group(3);
+ vodItems.add(vod.text() + "$" + playURL);
+ }
+ if (vodItems.size() > 0)
+ playList = TextUtils.join("#", vodItems);
+
+ if (playList.length() == 0)
+ continue;
+
+ vod_play.put(sourceName, playList);
+ }
+
+ if (vod_play.size() > 0) {
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+ }
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ /**
+ * 获取视频播放信息
+ *
+ * @param flag 播放源
+ * @param id 视频id
+ * @param vipFlags 所有可能需要vip解析的源
+ * @return
+ */
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ //定义播放用的headers
+ JSONObject headers = new JSONObject();
+ //headers.put("Host", " cokemv.co");
+ //headers.put("origin", " https://juhi.cc");
+ //headers.put("User-Agent", " Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ //headers.put("Accept", " */*");
+ //headers.put("Accept-Language", " zh-CN,zh;q=0.9,en-US;q=0.3,en;q=0.7");
+ //headers.put("Accept-Encoding", " gzip, deflate, br");
+
+
+ // 播放页 url
+ String url = siteUrl + "/vodplay/" + id + "/";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ Elements allScript = doc.select("script");
+ JSONObject result = new JSONObject();
+ for (int i = 0; i < allScript.size(); i++) {
+ String scContent = allScript.get(i).html().trim();
+ if (scContent.startsWith("var player_")) { // 取直链
+ int start = scContent.indexOf('{');
+ int end = scContent.lastIndexOf('}') + 1;
+ String json = scContent.substring(start, end);
+ JSONObject player = new JSONObject(json);
+ if (playerConfig.has(player.getString("from"))) {
+ JSONObject pCfg = playerConfig.getJSONObject(player.getString("from"));
+ String videoUrl = player.getString("url");
+ String playUrl = pCfg.getString("pu");
+ if (Misc.isVip(videoUrl)) { // 使用jx:1
+ try {
+ result.put("parse", 1);
+ result.put("jx", "1");
+ result.put("url", videoUrl);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ }
+ result.put("parse", pCfg.getInt("sn"));
+ result.put("playUrl", playUrl);
+ result.put("url", videoUrl);
+ result.put("header", headers.toString());
+ }
+ break;
+ }
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ if (quick)
+ return "";
+ long currentTime = System.currentTimeMillis();
+ String url = siteUrl + "/index.php/ajax/suggest?mid=1&wd=" + URLEncoder.encode(key) + "&limit=10×tamp=" + currentTime;
+ //Document doc = Jsoup.parse(srr.content);
+ JSONObject searchResult = new JSONObject(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONArray videos = new JSONArray();
+ if (searchResult.getInt("total") > 0) {
+ JSONArray lists = new JSONArray(searchResult.getString("list"));
+ for (int i = 0; i < lists.length(); i++) {
+ JSONObject vod = lists.getJSONObject(i);
+ String id = vod.getString("id");
+ String title = vod.getString("name");
+ String cover = vod.getString("pic");
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", "");
+ videos.put(v);
+ }
+ }
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Juhuang.java b/app/src/main/java/com/github/catvod/spider/Juhuang.java
new file mode 100644
index 0000000..1381ad5
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Juhuang.java
@@ -0,0 +1,406 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Base64;
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.okhttp.OKCallBack;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+
+public class Juhuang extends Spider {
+ private static final String siteUrl = "https://juhuang.tv";
+ private static final String siteHost = "juhuang.tv";
+
+ /**
+ * 播放源配置
+ */
+ private JSONObject playerConfig;
+ /**
+ * 筛选配置
+ */
+ private JSONObject filterConfig;
+
+ private Pattern regexCategory = Pattern.compile("/type/(\\d+)_type.html");
+ private Pattern regexVid = Pattern.compile("/play/(\\d+)_play_\\d+_\\d+.html");
+ private Pattern regexPlay = Pattern.compile("/play/(\\d+)_play_(\\d+)_(\\d+).html");
+ private Pattern regexPage = Pattern.compile("/type/\\d+_type_(\\d+).html");
+
+ public void init(Context context) {
+ Juhuang.super.init(context);
+ try {
+ playerConfig = new JSONObject("{\"xg\":{\"sh\":\"xg播放器\",\"or\":999,\"sn\":0,\"pu\":\"\"},\"dplayer\":{\"sh\":\"dplayer播放器\",\"or\":999,\"sn\":0,\"pu\":\"\"},\"videojs\":{\"sh\":\"videojs-H5播放器\",\"or\":999,\"sn\":0,\"pu\":\"\"},\"iva\":{\"sh\":\"iva-H5播放器\",\"or\":999,\"sn\":0,\"pu\":\"\"},\"iframe\":{\"sh\":\"iframe外链数据\",\"or\":999,\"sn\":0,\"pu\":\"\"},\"link\":{\"sh\":\"外链数据\",\"or\":999,\"sn\":0,\"pu\":\"\"},\"swf\":{\"sh\":\"Flash文件\",\"or\":999,\"sn\":0,\"pu\":\"\"},\"flv\":{\"sh\":\"Flv文件\",\"or\":999,\"sn\":0,\"pu\":\"\"},\"plyr\":{\"sh\":\"plyr\",\"or\":999,\"sn\":0,\"pu\":\"\"},\"H5player\":{\"sh\":\"H5player\",\"or\":999,\"sn\":0,\"pu\":\"\"},\"playerjs\":{\"sh\":\"playerjs\",\"or\":999,\"sn\":0,\"pu\":\"\"},\"aliplayer\":{\"sh\":\"阿里播放器\",\"or\":999,\"sn\":0,\"pu\":\"\"}}");
+ filterConfig = new JSONObject("{}");
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ protected HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("method", "GET");
+ headers.put("Host", "juhuang.tv");
+ headers.put("Upgrade-Insecure-Requests", "1");
+ headers.put("DNT", "1");
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
+ headers.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ return headers;
+ }
+
+ public String homeContent(boolean filter) {
+ try{
+ Document doc = Jsoup.parse(OkHttpUtil.string(siteUrl, getHeaders(siteUrl)));
+ // 分类节点
+ Elements elements = doc.select("ul.nav-menu-items > li > a");
+ JSONArray classes = new JSONArray();
+ for (Element ele : elements) {
+ //分类名
+ String name = ele.text();
+ boolean show = name.equals("Youtube精选") ||
+ name.equals("剧集") ||
+ name.equals("电影") ||
+ name.equals("综艺") ||
+ name.equals("动漫") ||
+ name.equals("纪录片");
+ if (show) {
+ Matcher mather = regexCategory.matcher(ele.attr("href"));
+ if (!mather.find())
+ continue;
+ // 把分类的id和名称取出来加到列表里
+ String id = mather.group(1).trim();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_id", id);
+ jsonObject.put("type_name", name);
+ classes.put(jsonObject);
+ }
+ }
+ JSONObject result = new JSONObject();
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ result.put("class", classes);
+ try {
+ // 取首页推荐视频列表
+ Element homeList = doc.select("div[class='module-items']").get(1);
+ Elements list = homeList.select("div.module-item");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst("div.module-item-cover > div.module-item-pic > a").attr("title");
+ String cover = vod.selectFirst("div.module-item-cover > div.module-item-pic > img").attr("data-src");
+ String remark = vod.selectFirst("div.module-item-text").text();
+ Matcher matcher = regexVid.matcher(vod.selectFirst("div.module-item-cover > div.module-item-pic > a").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取分类信息数据
+ *
+ * @param tid 分类id
+ * @param pg 页数
+ * @param filter 同homeContent方法中的filter
+ * @param extend 筛选参数{k:v, k1:v1}
+ * @return
+ */
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ int pageCount = 0;
+ int page = -1;
+ // 获取分类数据的url
+ String url = siteUrl + "/type/" + tid + "_type.html";
+
+ if (TextUtils.isEmpty(pg) || Integer.parseInt(pg.trim()) <= 1) {
+ page = 1;
+ } else {
+ url = siteUrl + String.format("/type/%s_type_%s.html", tid, pg);
+ page = Integer.parseInt(pg.trim());
+ }
+ String html = OkHttpUtil.string(url, getHeaders(url));
+ Document doc = Jsoup.parse(html);
+ JSONObject result = new JSONObject();
+ // 取页码相关信息
+ Elements pageInfo = doc.select("div.module-footer >div[id=page] > a");
+ if (pageInfo.size() == 0) {
+ page = Integer.parseInt(pg);
+ pageCount = page;
+ } else {
+ for (int i = 0; i < pageInfo.size(); i++) {
+ Element li = pageInfo.get(i);
+ Element a = li.selectFirst("a");
+ if (a == null)
+ continue;
+ String name = a.text();
+ if (name.equals("尾页")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ pageCount = Integer.parseInt(matcher.group(1));
+ } else {
+ pageCount = 0;
+ }
+ break;
+ }
+ }
+ }
+ JSONArray videos = new JSONArray();
+ if (!html.contains("没有找到您想要的结果哦")) {
+ Elements list = doc.select("div.module-items>div");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst("div.module-item-cover > div.module-item-pic > a").attr("title");
+ String cover = vod.selectFirst("div.module-item-cover > div.module-item-pic > img").attr("data-src");
+ String remark = "";
+ Element remarkElement = vod.selectFirst("div.module-item-text");
+ if (remarkElement != null) {
+ remark = remarkElement.text();
+ }
+ Matcher matcher = regexVid.matcher(vod.selectFirst("div.module-item-cover > div.module-item-pic > a").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", 48);
+ result.put("total", pageCount <= 1 ? videos.length() : pageCount * 48);
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+ /**
+ * 视频详情信息
+ *
+ * @param ids 视频id
+ * @return
+ */
+ @Override
+ public String detailContent(List ids) {
+ try {
+ // 视频详情url
+ String url = siteUrl + "/vod/" + ids.get(0) + "_vod.html";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+ // 取基本数据
+ String cover = doc.selectFirst("div.module-item-pic > img").attr("data-src");
+ String title = doc.selectFirst("div.video-info-header > h1.page-title").text();
+ String desc = doc.select("p.zkjj_a").text();
+ String category = "", area = "", year = "", remark = "", director = "", actor = "";
+
+ vodList.put("vod_id", ids.get(0));
+ vodList.put("vod_name", title);
+ vodList.put("vod_pic", cover);
+ vodList.put("type_name", category);
+ vodList.put("vod_year", year);
+ vodList.put("vod_area", area);
+ vodList.put("vod_remarks", remark);
+ vodList.put("vod_actor", actor);
+ vodList.put("vod_director", director);
+ vodList.put("vod_content", desc);
+ Map vod_play = new TreeMap<>(new Comparator() {
+ @Override
+ public int compare(String o1, String o2) {
+ try {
+ int sort1 = playerConfig.getJSONObject(o1).getInt("or");
+ int sort2 = playerConfig.getJSONObject(o2).getInt("or");
+
+ if (sort1 == sort2) {
+ return 1;
+ }
+ return sort1 - sort2 > 0 ? 1 : -1;
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ return 1;
+ }
+ });
+ // 取播放列表数据
+ Elements sources = doc.select("div.module");
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ String sourceName = source.select("div.module-heading > h2.module-title").text();
+
+ String playList = "";
+ Elements playListA = source.select("div.module-list > div.module-blocklist > div.scroll-content > a");
+ List vodItems = new ArrayList<>();
+
+ for (int j = 0; j < playListA.size(); j++) {
+ Element vod = playListA.get(j);
+ String href = vod.attr("href");
+ String playURL = href.substring(6, href.indexOf(".html"));
+ vodItems.add(vod.select("span").text() + "$" + playURL);
+ }
+ if (vodItems.size() > 0)
+ playList = TextUtils.join("#", vodItems);
+
+ if (playList.length() == 0)
+ continue;
+
+ vod_play.put(sourceName, playList);
+ }
+
+ if (vod_play.size() > 0) {
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+ }
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取视频播放信息
+ *
+ * @param flag 播放源
+ * @param id 视频id
+ * @param vipFlags 所有可能需要vip解析的源
+ * @return
+ */
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ JSONObject headers = new JSONObject();
+ //headers.put("Origin", " https://juhuang.tv");
+ headers.put("User-Agent", " Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ //headers.put("Accept", " */*");
+ //headers.put("Accept-Language", " zh-CN,zh;q=0.9,en-US;q=0.3,en;q=0.7");
+ //headers.put("Accept-Encoding", " gzip, deflate");
+ //headers.put("Referer", " https://juhuang.tv/");
+
+ // 播放页 url
+ String url = siteUrl + "/play/" + id + ".html";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ Elements allScript = doc.select("script");
+
+ JSONObject result = new JSONObject();
+ for (int i = 0; i < allScript.size(); i++) {
+ String scContent = allScript.get(i).html().trim();
+ if (scContent.startsWith("var player_aaaa")) {
+ int start = scContent.indexOf('{');
+ int end = scContent.lastIndexOf('}') + 1;
+ String json = scContent.substring(start, end);
+ JSONObject player = new JSONObject(json);
+ if (playerConfig.has(player.getString("from"))) {
+ String jxurl = player.getString("url");
+ if (player.has("encrypt")) {
+ int encrypt = player.getInt("encrypt");
+ if (encrypt == 1) {
+ jxurl = URLDecoder.decode(jxurl);
+ } else if (encrypt == 2) {
+ jxurl = URLEncoder.encode(new String(Base64.decode(URLDecoder.decode(new String(Base64.decode(jxurl, 0))),0)));
+ }
+ }
+ String directUrl = "https://web-webapi-tsjqsvyzyx.cn-shenzhen.fcapp.run/?url=" + jxurl;
+ HashMap hashMap = new HashMap();
+ hashMap.put("Referer", " https://juhuang.tv/");
+ hashMap.put("Origin", " https://juhuang.tv");
+ hashMap.put("User-Agent", " Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ result.put("url", new JSONObject(OkHttpUtil.string(directUrl, hashMap)).getString("play_url"));
+ result.put("parse", "0");
+ result.put("playUrl", "");
+ result.put("header", headers.toString());
+ //result.put("header", "{\"User-Agent\", \" Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36\"}");
+ }
+ }
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 搜索
+ *
+ * @param key
+ * @param quick 是否播放页的快捷搜索
+ * @return
+ */
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ if (quick)
+ return "";
+ String url = "https://so.juhuang.tv/soapi.php?&wd=" + URLEncoder.encode(key);
+ JSONObject searchResult = new JSONObject(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONArray videos = new JSONArray();
+ if (searchResult.getInt("count") > 0) {
+ JSONArray lists = new JSONArray(searchResult.getString("list"));
+ for (int i = 0; i < lists.length(); i++) {
+ JSONObject vod = lists.getJSONObject(i);
+ String id = vod.getString("vod_id");
+ String title = vod.getString("vod_name");
+ String cover = vod.getString("vod_pic");
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", "");
+ videos.put(v);
+ }
+ }
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Jumi.java b/app/src/main/java/com/github/catvod/spider/Jumi.java
new file mode 100644
index 0000000..1f3b010
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Jumi.java
@@ -0,0 +1,466 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Demo for self study
+ *
+ * Source from Author: CatVod
+ */
+
+public class Jumi extends Spider {
+
+ private static final String siteUrl = "https://jumi.tv/";
+ private static final String siteHost = "jumi.tv";
+
+ protected JSONObject playerConfig;
+ protected JSONObject filterConfig;
+
+ protected Pattern regexCategory = Pattern.compile("/type/(\\S+).html");
+ protected Pattern regexVid = Pattern.compile("/vod/(\\d+).html");
+ protected Pattern regexPlay = Pattern.compile("/play/(\\d+)-(\\d+)-(\\d+).html");
+ protected Pattern regexPage = Pattern.compile("\\S+/page/(\\d+)\\S+");
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ try {
+ playerConfig = new JSONObject("{\"mlm3u8\":{\"sh\":\"極速①線\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"alizy\":{\"sh\":\"極速③線\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"weiyun\":{\"sh\":\"1080P\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"dbm3u8\":{\"sh\":\"急速雲\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"tkm3u8\":{\"sh\":\"天空雲\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"wjm3u8\":{\"sh\":\"無盡雲\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"605m3u8\":{\"sh\":\"光速雲\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"kbm3u8\":{\"sh\":\"秒播雲\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"bjm3u8\":{\"sh\":\"八戒雲\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"hnm3u8\":{\"sh\":\"紅牛雲\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"bdxm3u8\":{\"sh\":\"北鬥雲\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"youku\":{\"sh\":\"優酷雲\",\"sn\":1,\"pu\":\"https://www.mgtv.com.jumi.tv/player/?url=\",\"or\":999},\"mgtv\":{\"sh\":\"芒果雲\",\"sn\":1,\"pu\":\"https://www.mgtv.com.jumi.tv/player/?url=\",\"or\":999},\"88zym3u8\":{\"sh\":\"88雲\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"qiyi\":{\"sh\":\"奇藝雲\",\"sn\":1,\"pu\":\"https://www.mgtv.com.jumi.tv/player/?url=\",\"or\":999},\"dplayer\":{\"sh\":\"動漫專線\",\"sn\":1,\"pu\":\"https://jx.parwix.com:4433/aliplayer/?url=\",\"or\":999},\"qq\":{\"sh\":\"騰訊雲\",\"sn\":1,\"pu\":\"https://www.mgtv.com.jumi.tv/player/?url=\",\"or\":999},\"bilibili\":{\"sh\":\"嗶哩雲\",\"sn\":1,\"pu\":\"https://www.mgtv.com.jumi.tv/player/?url=\",\"or\":999},\"sohu\":{\"sh\":\"搜狐雲\",\"sn\":1,\"pu\":\"https://www.mgtv.com.jumi.tv/player/?url=\",\"or\":999}}");
+ filterConfig = new JSONObject("{\"1\":[{\"key\":\"tid\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"動作片\",\"v\":\"6\"},{\"n\":\"喜劇片\",\"v\":\"7\"},{\"n\":\"愛情片\",\"v\":\"8\"},{\"n\":\"科幻片\",\"v\":\"9\"},{\"n\":\"恐怖片\",\"v\":\"10\"},{\"n\":\"劇情片\",\"v\":\"11\"},{\"n\":\"戰爭片\",\"v\":\"12\"},{\"n\":\"紀錄片\",\"v\":\"20\"}]},{\"key\":\"class\",\"name\":\"剧情\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"驚悚\",\"v\":\"驚悚\"},{\"n\":\"懸疑\",\"v\":\"懸疑\"},{\"n\":\"魔幻\",\"v\":\"魔幻\"},{\"n\":\"罪案\",\"v\":\"罪案\"},{\"n\":\"災難\",\"v\":\"災難\"},{\"n\":\"動畫\",\"v\":\"動畫\"},{\"n\":\"古裝\",\"v\":\"古裝\"},{\"n\":\"青春\",\"v\":\"青春\"},{\"n\":\"歌舞\",\"v\":\"歌舞\"},{\"n\":\"文藝\",\"v\":\"文藝\"},{\"n\":\"生活\",\"v\":\"生活\"},{\"n\":\"歷史\",\"v\":\"歷史\"},{\"n\":\"勵志\",\"v\":\"勵志\"},{\"n\":\"搞笑\",\"v\":\"搞笑\"},{\"n\":\"愛情\",\"v\":\"愛情\"},{\"n\":\"喜劇\",\"v\":\"喜劇\"},{\"n\":\"恐怖\",\"v\":\"恐怖\"},{\"n\":\"動作\",\"v\":\"動作\"},{\"n\":\"科幻\",\"v\":\"科幻\"},{\"n\":\"劇情\",\"v\":\"劇情\"},{\"n\":\"戰爭\",\"v\":\"戰爭\"},{\"n\":\"犯罪\",\"v\":\"犯罪\"},{\"n\":\"奇幻\",\"v\":\"奇幻\"},{\"n\":\"武俠\",\"v\":\"武俠\"},{\"n\":\"冒險\",\"v\":\"冒險\"},{\"n\":\"經典\",\"v\":\"經典\"},{\"n\":\"兒童\",\"v\":\"兒童\"}]},{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"大陸\",\"v\":\"大陸\"},{\"n\":\"香港\",\"v\":\"香港\"},{\"n\":\"台灣\",\"v\":\"台灣\"},{\"n\":\"美國\",\"v\":\"美國\"},{\"n\":\"法國\",\"v\":\"法國\"},{\"n\":\"英國\",\"v\":\"英國\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韓國\",\"v\":\"韓國\"},{\"n\":\"德國\",\"v\":\"德國\"},{\"n\":\"泰國\",\"v\":\"泰國\"},{\"n\":\"印度\",\"v\":\"印度\"},{\"n\":\"意大利\",\"v\":\"意大利\"},{\"n\":\"西班牙\",\"v\":\"西班牙\"},{\"n\":\"加拿大\",\"v\":\"加拿大\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"2\":[{\"key\":\"tid\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"陸劇\",\"v\":\"13\"},{\"n\":\"港劇\",\"v\":\"14\"},{\"n\":\"台劇\",\"v\":\"22\"},{\"n\":\"日劇\",\"v\":\"15\"},{\"n\":\"韓劇\",\"v\":\"23\"},{\"n\":\"美劇\",\"v\":\"16\"},{\"n\":\"海外劇\",\"v\":\"24\"}]},{\"key\":\"class\",\"name\":\"剧情\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"言情\",\"v\":\"言情\"},{\"n\":\"都市\",\"v\":\"都市\"},{\"n\":\"家庭\",\"v\":\"家庭\"},{\"n\":\"生活\",\"v\":\"生活\"},{\"n\":\"偶像\",\"v\":\"偶像\"},{\"n\":\"喜劇\",\"v\":\"喜劇\"},{\"n\":\"歷史\",\"v\":\"歷史\"},{\"n\":\"古裝\",\"v\":\"古裝\"},{\"n\":\"武俠\",\"v\":\"武俠\"},{\"n\":\"刑偵\",\"v\":\"刑偵\"},{\"n\":\"戰爭\",\"v\":\"戰爭\"},{\"n\":\"神話\",\"v\":\"神話\"},{\"n\":\"軍旅\",\"v\":\"軍旅\"},{\"n\":\"諜戰\",\"v\":\"諜戰\"},{\"n\":\"商戰\",\"v\":\"商戰\"},{\"n\":\"校園\",\"v\":\"校園\"},{\"n\":\"穿越\",\"v\":\"穿越\"},{\"n\":\"懸疑\",\"v\":\"懸疑\"},{\"n\":\"犯罪\",\"v\":\"犯罪\"},{\"n\":\"科幻\",\"v\":\"科幻\"},{\"n\":\"愛情\",\"v\":\"愛情\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"大陸\",\"v\":\"大陸\"},{\"n\":\"香港\",\"v\":\"香港\"},{\"n\":\"台灣\",\"v\":\"台灣\"},{\"n\":\"美國\",\"v\":\"美國\"},{\"n\":\"法國\",\"v\":\"法國\"},{\"n\":\"英國\",\"v\":\"英國\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韓國\",\"v\":\"韓國\"},{\"n\":\"德國\",\"v\":\"德國\"},{\"n\":\"泰國\",\"v\":\"泰國\"},{\"n\":\"印度\",\"v\":\"印度\"},{\"n\":\"意大利\",\"v\":\"意大利\"},{\"n\":\"西班牙\",\"v\":\"西班牙\"},{\"n\":\"加拿大\",\"v\":\"加拿大\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"3\":[{\"key\":\"class\",\"name\":\"剧情\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"选秀\",\"v\":\"选秀\"},{\"n\":\"情感\",\"v\":\"情感\"},{\"n\":\"访谈\",\"v\":\"访谈\"},{\"n\":\"播报\",\"v\":\"播报\"},{\"n\":\"旅游\",\"v\":\"旅游\"},{\"n\":\"音乐\",\"v\":\"音乐\"},{\"n\":\"美食\",\"v\":\"美食\"},{\"n\":\"纪实\",\"v\":\"纪实\"},{\"n\":\"曲艺\",\"v\":\"曲艺\"},{\"n\":\"生活\",\"v\":\"生活\"},{\"n\":\"游戏互动\",\"v\":\"游戏互动\"},{\"n\":\"财经\",\"v\":\"财经\"},{\"n\":\"求职\",\"v\":\"求职\"}]},{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"中国大陆\",\"v\":\"中国大陆\"},{\"n\":\"大陆\",\"v\":\"大陆\"},{\"n\":\"港台\",\"v\":\"港台\"},{\"n\":\"日韩\",\"v\":\"日韩\"},{\"n\":\"欧美\",\"v\":\"欧美\"}]},{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"4\":[{\"key\":\"class\",\"name\":\"剧情\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"情感\",\"v\":\"情感\"},{\"n\":\"科幻\",\"v\":\"科幻\"},{\"n\":\"热血\",\"v\":\"热血\"},{\"n\":\"推理\",\"v\":\"推理\"},{\"n\":\"搞笑\",\"v\":\"搞笑\"},{\"n\":\"冒险\",\"v\":\"冒险\"},{\"n\":\"萝莉\",\"v\":\"萝莉\"},{\"n\":\"校园\",\"v\":\"校园\"},{\"n\":\"动作\",\"v\":\"动作\"},{\"n\":\"机战\",\"v\":\"机战\"},{\"n\":\"运动\",\"v\":\"运动\"},{\"n\":\"战争\",\"v\":\"战争\"},{\"n\":\"少年\",\"v\":\"少年\"},{\"n\":\"少女\",\"v\":\"少女\"},{\"n\":\"社会\",\"v\":\"社会\"},{\"n\":\"原创\",\"v\":\"原创\"},{\"n\":\"亲子\",\"v\":\"亲子\"},{\"n\":\"益智\",\"v\":\"益智\"},{\"n\":\"励志\",\"v\":\"励志\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国产\",\"v\":\"国产\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"欧美\",\"v\":\"欧美\"},{\"n\":\"其他\",\"v\":\"其他\"}]},{\"key\":\"year\",\"name\":\"年份\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"2021\",\"v\":\"2021\"},{\"n\":\"2020\",\"v\":\"2020\"},{\"n\":\"2019\",\"v\":\"2019\"},{\"n\":\"2018\",\"v\":\"2018\"},{\"n\":\"2017\",\"v\":\"2017\"},{\"n\":\"2016\",\"v\":\"2016\"},{\"n\":\"2015\",\"v\":\"2015\"},{\"n\":\"2014\",\"v\":\"2014\"},{\"n\":\"2013\",\"v\":\"2013\"},{\"n\":\"2012\",\"v\":\"2012\"},{\"n\":\"2011\",\"v\":\"2011\"},{\"n\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"2006\",\"v\":\"2006\"},{\"n\":\"2005\",\"v\":\"2005\"},{\"n\":\"2004\",\"v\":\"2004\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}]}");
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ /**
+ * 爬虫headers
+ *
+ * @param url
+ * @return
+ */
+ protected HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("method", "GET");
+ headers.put("Host", siteHost);
+ headers.put("Upgrade-Insecure-Requests", "1");
+ headers.put("DNT", "1");
+ headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
+ headers.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
+ return headers;
+ }
+
+ /**
+ * 获取分类数据 + 首页最近更新视频列表数据
+ *
+ * @param filter 是否开启筛选 关联的是 软件设置中 首页数据源里的筛选开关
+ * @return
+ */
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ String url = siteUrl + '/';
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ Elements elements = doc.select("ul.nav-menu>li>a");
+ JSONArray classes = new JSONArray();
+ ArrayList allClass = new ArrayList<>();
+ for (Element ele : elements) {
+ String name = ele.text();
+ boolean show = !filter || (name.equals("電影") || name.equals("劇集") || name.equals("綜藝") || name.equals("動漫"));
+ if (allClass.contains(name))
+ show = false;
+ if (show) {
+ allClass.add(name);
+ Matcher mather = regexCategory.matcher(ele.attr("href"));
+ if (!mather.find())
+ continue;
+ // 把分类的id和名称取出来加到列表里
+ String id = mather.group(1).trim();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_id", id);
+ jsonObject.put("type_name", name);
+ classes.put(jsonObject);
+ }
+ }
+ JSONObject result = new JSONObject();
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ result.put("class", classes);
+ try {
+ // 取首页推荐视频列表
+ Elements list = doc.select("div.col-lg-wide-75 > ul.myui-vodlist li div.myui-vodlist__box");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst(".title").text();
+ String cover = vod.selectFirst(".myui-vodlist__thumb").attr("data-original");
+ String remark = vod.selectFirst("span.pic-text").text();
+
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".myui-vodlist__thumb").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ /**
+ * 获取分类信息数据
+ *
+ * @param tid 分类id
+ * @param pg 页数
+ * @param filter 同homeContent方法中的filter
+ * @param extend 筛选参数{k:v, k1:v1}
+ * @return
+ */
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ String url = siteUrl + "/show/";
+ if (extend != null && extend.size() > 0 && extend.containsKey("tid") && extend.get("tid").length() > 0) {
+ url += extend.get("tid");
+ } else {
+ url += tid;
+ }
+ if (extend != null && extend.size() > 0) {
+ for (Iterator it = extend.keySet().iterator(); it.hasNext(); ) {
+ String key = it.next();
+ String value = extend.get(key);
+ if (value.length() > 0) {
+ url += "/" + key + "/" + URLEncoder.encode(value);
+ }
+ }
+ }
+ url += "/page/" + pg + ".html";
+ String html = OkHttpUtil.string(url, getHeaders(url));
+ Document doc = Jsoup.parse(html);
+ JSONObject result = new JSONObject();
+ int pageCount = 0;
+ int page = -1;
+
+ // 取页码相关信息
+ Elements pageInfo = doc.select(".myui-page li a");
+ if (pageInfo.size() == 0) {
+ page = Integer.parseInt(pg);
+ pageCount = page;
+ } else {
+ for (int i = 0; i < pageInfo.size(); i++) {
+ Element a = pageInfo.get(i);
+ String name = a.text();
+ if (page == -1 && a.hasClass("btn-warm")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ page = Integer.parseInt(matcher.group(1).trim());
+ } else {
+ page = 0;
+ }
+ }
+ if (name.equals("尾页")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ pageCount = Integer.parseInt(matcher.group(1).trim());
+ } else {
+ pageCount = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ JSONArray videos = new JSONArray();
+ if (!html.contains("没有找到您想要的结果哦")) {
+ // 取当前分类页的视频列表
+ Elements list = doc.select("ul.myui-vodlist li div.myui-vodlist__box");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst(".title").text();
+ String cover = vod.selectFirst(".myui-vodlist__thumb").attr("data-original");
+ String remark = vod.selectFirst("span.pic-text").text();
+
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".myui-vodlist__thumb").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", 48);
+ result.put("total", pageCount <= 1 ? videos.length() : pageCount * 48);
+
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 视频详情信息
+ *
+ * @param ids 视频id
+ * @return
+ */
+ @Override
+ public String detailContent(List ids) {
+ try {
+ // 视频详情url
+ String url = siteUrl + "/vod/" + ids.get(0) + ".html";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+
+ // 取基本数据
+ String vid = doc.selectFirst("span.mac_hits").attr("data-id");
+
+ String cover = doc.selectFirst("a.myui-vodlist__thumb img").attr("data-original");
+ String title = doc.selectFirst("div.myui-content__detail h1.title").text();
+ String desc = Jsoup.parse(doc.selectFirst("meta[name=description]").attr("content")).text();
+ String category = "", area = "", year = "", remark = "", director = "", actor = "";
+ Elements span_text_muted = doc.select("div.myui-content__detail span.text-muted");
+ for (int i = 0; i < span_text_muted.size(); i++) {
+ Element text = span_text_muted.get(i);
+ String info = text.text();
+ if (info.equals("分类:")) {
+ category = text.nextElementSibling().text();
+ } else if (info.equals("年份:")) {
+ year = text.nextElementSibling().text();
+ } else if (info.equals("地区:")) {
+ area = text.nextElementSibling().text();
+ } else if (info.equals("更新:")) {
+ remark = text.nextElementSibling().text();
+ } else if (info.equals("导演:")) {
+ List directors = new ArrayList<>();
+ Elements aa = text.parent().select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ directors.add(aa.get(j).text());
+ }
+ director = TextUtils.join(",", directors);
+ } else if (info.equals("主演:")) {
+ List actors = new ArrayList<>();
+ Elements aa = text.parent().select("a");
+ for (int j = 0; j < aa.size(); j++) {
+ actors.add(aa.get(j).text());
+ }
+ actor = TextUtils.join(",", actors);
+ }
+ }
+
+ vodList.put("vod_id", vid);
+ vodList.put("vod_name", title);
+ vodList.put("vod_pic", cover);
+ vodList.put("type_name", category);
+ vodList.put("vod_year", year);
+ vodList.put("vod_area", area);
+ vodList.put("vod_remarks", remark);
+ vodList.put("vod_actor", actor);
+ vodList.put("vod_director", director);
+ vodList.put("vod_content", desc);
+
+ Map vod_play = new TreeMap<>(new Comparator() {
+ @Override
+ public int compare(String o1, String o2) {
+ try {
+ int sort1 = playerConfig.getJSONObject(o1).getInt("or");
+ int sort2 = playerConfig.getJSONObject(o2).getInt("or");
+
+ if (sort1 == sort2) {
+ return 1;
+ }
+ return sort1 - sort2 > 0 ? 1 : -1;
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ return 1;
+ }
+ });
+
+ // 取播放列表数据
+ Elements sources = doc.select("div.myui-panel__head>ul").get(0).select("li");
+ Elements sourceList = doc.select("div.tab-content>div.tab-pane");
+
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ String sourceName = source.text();
+ boolean found = false;
+ for (Iterator it = playerConfig.keys(); it.hasNext(); ) {
+ String flag = it.next();
+ if (playerConfig.getJSONObject(flag).getString("sh").equals(sourceName)) {
+ sourceName = flag;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+ String playList = "";
+ Elements playListA = sourceList.get(i).select("ul>li>a");
+ List vodItems = new ArrayList<>();
+
+ for (int j = 0; j < playListA.size(); j++) {
+ Element vod = playListA.get(j);
+ Matcher matcher = regexPlay.matcher(vod.attr("href"));
+ if (!matcher.find())
+ continue;
+ String playURL = matcher.group(1) + "-" + matcher.group(2) + "-" + matcher.group(3);
+ vodItems.add(vod.text() + "$" + playURL);
+ }
+ if (vodItems.size() > 0)
+ playList = TextUtils.join("#", vodItems);
+
+ if (playList.length() == 0)
+ continue;
+
+ vod_play.put(sourceName, playList);
+ }
+
+ if (vod_play.size() > 0) {
+ String vod_play_from = TextUtils.join("$$$", vod_play.keySet());
+ String vod_play_url = TextUtils.join("$$$", vod_play.values());
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+ }
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取视频播放信息
+ *
+ * @param flag 播放源
+ * @param id 视频id
+ * @param vipFlags 所有可能需要vip解析的源
+ * @return
+ */
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ //定义播放用的headers
+ JSONObject headers = new JSONObject();
+ //headers.put("Host", " cokemv.co");
+ headers.put("origin", " https://jumi.tv");
+ headers.put("User-Agent", " Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
+ headers.put("Accept", " */*");
+ headers.put("Accept-Language", " zh-CN,zh;q=0.9,en-US;q=0.3,en;q=0.7");
+ headers.put("Accept-Encoding", " gzip, deflate");
+ headers.put("referer", " https://jumi.tv/");
+
+
+ // 播放页 url
+ String url = siteUrl + "/play/" + id + ".html";
+ Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url)));
+ Elements allScript = doc.select("script");
+ JSONObject result = new JSONObject();
+ for (int i = 0; i < allScript.size(); i++) {
+ String scContent = allScript.get(i).html().trim();
+ if (scContent.startsWith("var player_")) { // 取直链
+ int start = scContent.indexOf('{');
+ int end = scContent.lastIndexOf('}') + 1;
+ String json = scContent.substring(start, end);
+ JSONObject player = new JSONObject(json);
+ if (playerConfig.has(player.getString("from"))) {
+ JSONObject pCfg = playerConfig.getJSONObject(player.getString("from"));
+ String videoUrl = player.getString("url");
+ String playUrl = pCfg.getString("pu");
+ result.put("parse", pCfg.getInt("sn"));
+ result.put("playUrl", playUrl);
+ result.put("url", videoUrl);
+ result.put("header", headers.toString());
+ }
+ break;
+ }
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ if (quick)
+ return "";
+ long currentTime = System.currentTimeMillis();
+ String url = siteUrl + "/index.php/ajax/suggest?mid=1&wd=" + URLEncoder.encode(key) + "&limit=10×tamp=" + currentTime;
+ JSONObject searchResult = new JSONObject(OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONArray videos = new JSONArray();
+ if (searchResult.getInt("total") > 0) {
+ JSONArray lists = new JSONArray(searchResult.getString("list"));
+ for (int i = 0; i < lists.length(); i++) {
+ JSONObject vod = lists.getJSONObject(i);
+ String id = vod.getString("id");
+ String title = vod.getString("name");
+ String cover = vod.getString("pic");
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", "");
+ videos.put(v);
+ }
+ }
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Kmys.java b/app/src/main/java/com/github/catvod/spider/Kmys.java
new file mode 100644
index 0000000..ed68e99
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Kmys.java
@@ -0,0 +1,567 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.util.Base64;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.Misc;
+import com.github.catvod.utils.okhttp.OKCallBack;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.net.URLEncoder;
+import java.security.KeyFactory;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.crypto.Cipher;
+
+import okhttp3.Call;
+import okhttp3.Headers;
+import okhttp3.Response;
+
+/**
+ * Author: @SDL
+ */
+public class Kmys extends Spider {
+ private String apiDomain = "";
+ private String staticDomain = "";
+
+ private String appId = "4"; // 飞瓜 1 酷猫 5 暗影 4
+
+ private String device = "1a7348ae45f8f6de4d798614fc07e7271657392501986";
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ SharedPreferences sharedPreferences = context.getSharedPreferences("sp_Kmys", Context.MODE_PRIVATE);
+ try {
+ device = sharedPreferences.getString("device", null);
+ } catch (Throwable th) {
+ } finally {
+ if (device == null) {
+ device = Misc.MD5(UUID.randomUUID().toString(), Misc.CharsetUTF8).toLowerCase();
+ sharedPreferences.edit().putString("device", device).commit();
+ }
+ }
+ }
+
+ private HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("versionNumber", "360");
+ headers.put("versionName", "3.6.0");
+ headers.put("device", device);
+ headers.put("ed", device);
+ headers.put("appId", appId);
+ headers.put("platformId", "7");
+ headers.put("User-Agent", "okhttp/3.14.7");
+ return headers;
+ }
+
+ private void checkDomain() {
+ if (staticDomain.isEmpty()) {
+ String url = "http://feigua2021.oss-cn-beijing.aliyuncs.com/static/config/video/" + appId + ".json";
+ HashMap headers = new HashMap<>();
+ headers.put("User-Agent", "okhttp/3.14.7");
+ headers.put("ed", device);
+ String json = OkHttpUtil.string(url, headers);
+ try {
+ JSONObject obj = new JSONObject(json);
+ apiDomain = obj.getString("apiDomain");
+ staticDomain = obj.getString("staticDomain");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ checkDomain();
+ String url = staticDomain + "/static/" + appId + "/config/lib-new.json";
+ String content = OkHttpUtil.string(url, getHeaders(url));
+ JSONObject jsonObject = new JSONObject(content).getJSONObject("data");
+
+ JSONArray years = jsonObject.getJSONArray("year");
+ JSONArray types = jsonObject.getJSONArray("types");
+
+ JSONArray classes = new JSONArray();
+ JSONObject filterConfig = new JSONObject();
+
+ for (int i = 0; i < types.length(); i++) {
+ JSONObject item = types.getJSONObject(i);
+ String typeId = item.getString("typeId").trim();
+ if (typeId.isEmpty())
+ continue;
+ String typeName = item.getString("typeName");
+ JSONObject newCls = new JSONObject();
+ newCls.put("type_id", typeId);
+ newCls.put("type_name", typeName);
+ classes.put(newCls);
+
+ JSONArray tags = item.getJSONArray("tags");
+ JSONArray extendsAll = new JSONArray();
+ // 类型
+ JSONObject newTypeExtend = new JSONObject();
+ newTypeExtend.put("key", "type");
+ newTypeExtend.put("name", "类型");
+ JSONArray newTypeExtendKV = new JSONArray();
+ JSONObject kv = new JSONObject();
+ kv.put("n", "全部");
+ kv.put("v", "-1");
+ newTypeExtendKV.put(kv);
+ for (int j = 0; j < tags.length(); j++) {
+ JSONObject child = tags.getJSONObject(j);
+ kv = new JSONObject();
+ kv.put("n", child.getString("typeName"));
+ kv.put("v", child.getString("typeId"));
+ newTypeExtendKV.put(kv);
+ }
+ newTypeExtend.put("value", newTypeExtendKV);
+ extendsAll.put(newTypeExtend);
+ // 排序
+ newTypeExtend = new JSONObject();
+ newTypeExtend.put("key", "sort");
+ newTypeExtend.put("name", "排序");
+ newTypeExtendKV = new JSONArray();
+ kv = new JSONObject();
+ kv.put("n", "最热");
+ kv.put("v", "2");
+ newTypeExtendKV.put(kv);
+ kv = new JSONObject();
+ kv.put("n", "最新");
+ kv.put("v", "1");
+ newTypeExtendKV.put(kv);
+ kv = new JSONObject();
+ kv.put("n", "好评");
+ kv.put("v", "3");
+ newTypeExtendKV.put(kv);
+ newTypeExtend.put("value", newTypeExtendKV);
+ extendsAll.put(newTypeExtend);
+ // 地区
+ JSONArray regions = item.getJSONArray("children");
+ newTypeExtend = new JSONObject();
+ newTypeExtend.put("key", "area");
+ newTypeExtend.put("name", "地区");
+ newTypeExtendKV = new JSONArray();
+ kv = new JSONObject();
+ kv.put("n", "全部");
+ kv.put("v", "-1");
+ newTypeExtendKV.put(kv);
+ for (int j = 0; j < regions.length(); j++) {
+ JSONObject child = regions.getJSONObject(j);
+ kv = new JSONObject();
+ kv.put("n", child.getString("typeName"));
+ kv.put("v", child.getString("typeId"));
+ newTypeExtendKV.put(kv);
+ }
+ newTypeExtend.put("value", newTypeExtendKV);
+ extendsAll.put(newTypeExtend);
+
+ // 年份
+ newTypeExtend = new JSONObject();
+ newTypeExtend.put("key", "year");
+ newTypeExtend.put("name", "年份");
+ newTypeExtendKV = new JSONArray();
+ kv = new JSONObject();
+ kv.put("n", "全部");
+ kv.put("v", "-1");
+ newTypeExtendKV.put(kv);
+ for (int j = 0; j < years.length(); j++) {
+ String year = years.getString(j).trim();
+ if (year.isEmpty())
+ continue;
+ kv = new JSONObject();
+ kv.put("n", year);
+ kv.put("v", year);
+ newTypeExtendKV.put(kv);
+ }
+ newTypeExtend.put("value", newTypeExtendKV);
+ extendsAll.put(newTypeExtend);
+ filterConfig.put(typeId, extendsAll);
+ }
+ JSONObject result = new JSONObject();
+ result.put("class", classes);
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ return result.toString();
+ } catch (Throwable th) {
+
+ }
+ return "";
+ }
+
+ @Override
+ public String homeVideoContent() {
+ try {
+ checkDomain();
+ String url = staticDomain + "/static/" + appId + "/index/cloumn/1.json";
+ String content = OkHttpUtil.string(url, getHeaders(url));
+ JSONObject jsonObject = new JSONObject(content).getJSONObject("data");
+ JSONArray list = jsonObject.getJSONArray("list");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.length(); i++) {
+ JSONArray videoList = list.getJSONObject(i).getJSONArray("videoList");
+ for (int j = 0; j < videoList.length(); j++) {
+ JSONObject vObj = videoList.getJSONObject(j);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", vObj.getString("id"));
+ v.put("vod_name", vObj.getString("vodName"));
+ v.put("vod_pic", fixUrl(vObj.getString("vodPicThumb")));
+ v.put("vod_remarks", vObj.getString("lastName"));
+ videos.put(v);
+ }
+ }
+ JSONObject result = new JSONObject();
+ result.put("list", videos);
+ return result.toString();
+ } catch (Throwable th) {
+
+ }
+ return "";
+ }
+
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ checkDomain();
+ JSONObject result = new JSONObject();
+
+ String url = apiDomain + "/videolibrary/v2/" + appId + "/" + tid;
+ extend = extend == null ? new HashMap<>() : extend;
+ if (!extend.containsKey("area")) {
+ extend.put("area", "-1");
+ }
+ if (!extend.containsKey("type")) {
+ extend.put("type", "-1");
+ }
+ if (!extend.containsKey("sort")) {
+ extend.put("sort", "2");
+ }
+ if (!extend.containsKey("year")) {
+ extend.put("year", "-1");
+ }
+ url += "/" + extend.get("area");
+ url += "/" + extend.get("type");
+ url += "/" + extend.get("sort");
+ url += "/-1";
+ url += "/" + extend.get("year");
+ url += "/-1/" + pg + ".json";
+
+ String content = OkHttpUtil.string(url, getHeaders(url));
+ JSONObject jsonObject = new JSONObject(content).getJSONObject("data");
+ JSONArray jsonArray = jsonObject.getJSONArray("list");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < jsonArray.length(); i++) {
+ JSONObject vObj = jsonArray.getJSONObject(i);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", vObj.getString("id"));
+ v.put("vod_name", vObj.getString("vodName"));
+ v.put("vod_pic", fixUrl(vObj.getString("vodPicThumb")));
+ v.put("vod_remarks", vObj.getString("lastName"));
+ videos.put(v);
+ }
+
+ int total = jsonObject.getInt("count");
+ int limit = jsonObject.getInt("pageSize");
+ int totalPg = total % limit == 0 ? (total / limit) : (total / limit + 1);
+ result.put("page", jsonObject.getInt("pageIndex"));
+ result.put("pagecount", totalPg);
+ result.put("limit", limit);
+ result.put("total", total);
+ result.put("list", videos);
+ return result.toString();
+ } catch (Throwable th) {
+
+ }
+ return "";
+ }
+
+ @Override
+ public String detailContent(List ids) {
+ try {
+ checkDomain();
+ JSONObject result = new JSONObject();
+ String url = staticDomain + "/static/video/detail/" + ids.get(0) + ".json";
+ String content = OkHttpUtil.string(url, getHeaders(url));
+ JSONObject jsonObject = new JSONObject(content).getJSONObject("data");
+ JSONObject vodList = new JSONObject();
+ vodList.put("vod_id", jsonObject.getString("id"));
+ vodList.put("vod_name", jsonObject.getString("vodName"));
+ vodList.put("vod_pic", fixUrl(jsonObject.getString("vodPic")));
+ vodList.put("type_name", jsonObject.getString("typeName"));
+ vodList.put("vod_year", jsonObject.getString("vodYear"));
+ vodList.put("vod_area", jsonObject.getString("vodArea"));
+ vodList.put("vod_remarks", "");
+ vodList.put("vod_actor", jsonObject.getString("vodActor"));
+ vodList.put("vod_director", "");
+ vodList.put("vod_content", jsonObject.getString("vodBlurb"));
+
+ String vodPlayUrl = jsonObject.getString("vodPlayUrl");
+ vodPlayUrl = rsa(vodPlayUrl.substring(0, 10) + vodPlayUrl.substring(16));
+
+ ArrayList playFrom = new ArrayList<>();
+ ArrayList playList = new ArrayList<>();
+
+ JSONArray playSource = new JSONArray(vodPlayUrl);
+ for (int i = 0; i < playSource.length(); i++) {
+ JSONObject item = playSource.getJSONObject(i);
+ String srcName = item.getString("name");
+ boolean userProxy = srcName.equals("高速线路");
+ ArrayList urls = new ArrayList<>();
+ JSONArray playUrls = item.getJSONArray("list");
+ for (int j = 0; j < playUrls.length(); j++) {
+ JSONObject urlObj = playUrls.getJSONObject(j);
+ if (userProxy)
+ urls.add(urlObj.getString("name") + "$" + Proxy.localProxyUrl() + "?do=kmys&type=m3u8&url=" + Base64.encodeToString(urlObj.getString("url").getBytes(Misc.CharsetUTF8), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP) + ".." + urlObj.getInt("isParse"));
+ else
+ urls.add(urlObj.getString("name") + "$" + urlObj.getString("url") + ".." + urlObj.getInt("isParse"));
+ }
+ if (urls.isEmpty())
+ continue;
+ playFrom.add(srcName);
+ playList.add(TextUtils.join("#", urls));
+ }
+
+ String vod_play_from = TextUtils.join("$$$", playFrom);
+ String vod_play_url = TextUtils.join("$$$", playList);
+ vodList.put("vod_play_from", vod_play_from);
+ vodList.put("vod_play_url", vod_play_url);
+
+ JSONArray list = new JSONArray();
+ list.put(vodList);
+ result.put("list", list);
+ return result.toString();
+ } catch (Throwable th) {
+
+ }
+ return "";
+ }
+
+ @Override
+ public String playerContent(String flag, String id, List vipFlags) {
+ try {
+ JSONObject result = new JSONObject();
+ String[] info = id.split("\\.\\.");
+ String url = info[0];
+ int isParse = Integer.parseInt(info[1]);
+ if (isParse == 2) {
+ result.put("parse", 0);
+ result.put("playUrl", "");
+ result.put("url", url);
+ } else {
+ result.put("parse", 0);
+ result.put("playUrl", "");
+ result.put("url", url);
+ }
+ return result.toString();
+ } catch (Throwable th) {
+
+ }
+ return "";
+ }
+
+ @Override
+ public String searchContent(String key, boolean quick) {
+ try {
+ checkDomain();
+ JSONObject result = new JSONObject();
+ String url = apiDomain + "/api/v2/index/search?pageIndex=1&wd=" + URLEncoder.encode(key) + "&limit=10&type=1";
+ String content = OkHttpUtil.string(url, getHeaders(url));
+ JSONArray videos = new JSONArray();
+ JSONObject jsonObject = new JSONObject(content).getJSONObject("data");
+ JSONArray jsonArray = jsonObject.getJSONArray("list");
+ for (int i = 0; i < jsonArray.length(); i++) {
+ JSONObject vObj = jsonArray.getJSONObject(i);
+ JSONObject v = new JSONObject();
+ String title = vObj.getString("vodName");
+ if (!title.contains(key))
+ continue;
+ v.put("vod_id", vObj.getString("id"));
+ v.put("vod_name", title);
+ v.put("vod_pic", fixUrl(vObj.getString("vodPicThumb")));
+ v.put("vod_remarks", vObj.getString("lastName"));
+ videos.put(v);
+ }
+ result.put("list", videos);
+ return result.toString();
+ } catch (Throwable th) {
+
+ }
+ return "";
+ }
+
+ protected String fixUrl(String src) {
+ try {
+ if (src.startsWith("//")) {
+ Uri parse = Uri.parse(staticDomain);
+ src = parse.getScheme() + ":" + src;
+ } else if (!src.contains("://")) {
+ Uri parse = Uri.parse(staticDomain);
+ if (!src.startsWith("/"))
+ src = "/" + src;
+ src = parse.getScheme() + "://" + parse.getHost() + src;
+ }
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return src;
+ }
+
+ String rsa(String in) {
+ try {
+ RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.decode("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3VLHgbkFN0ebMaR4e0D\n" +
+ "z6Z2mFexPBFKGqK0tuRhzu7XOrG92nKWfnublf2p1i22UN81whBLINjMttOuqW6\n" +
+ "fM9DCnAPTelud1zCXWYWIsv5Z19inJSG8vytJ7xg1dnfuRSRUkx11IE7bm0T/sM\n" +
+ "0sI4GgcktQJNSizyirHtuJjUUxxQabEhFkFeqQ5r+A69KjB5QkotCc4pG5lENyT\n" +
+ "ARHGSsfaiJthaiH0yJ/8tUlyMgJ9H6/jbQg0wlLcEUzdfe2KuCPrTRzIzx4Cjm1\n" +
+ "JogT6JV2byvXpzAMC3O48LDiekJdVztg2Cj7E0cGrOsGs+IK6F7TWsKD/cIELTF\n" +
+ "hLz6dExQIDAQAB", Base64.DEFAULT)));
+ Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
+ cipher.init(Cipher.DECRYPT_MODE, pubKey);
+ byte[] inData = Base64.decode(in, Base64.DEFAULT);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ if (inData.length <= 256) {
+ outputStream.write(cipher.doFinal(inData));
+ } else {
+ for (int i = 0; i < inData.length; i += 256) {
+ outputStream.write(cipher.doFinal(inData, i, 256));
+ }
+ }
+ outputStream.flush();
+ String result = new String(outputStream.toByteArray(), Misc.CharsetUTF8);
+ outputStream.close();
+ return result;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ private static HashMap kmysPlayerHeaders = null;
+ private static String signPlayerStr = "700a4cce35";
+ private static final Pattern tsRex = Pattern.compile("(\\S+.ts)|(#EXT-X-KEY:\\S+\")(\\S+)(\")");
+
+ static String subUrl(String url) {
+ if (url.startsWith("http://")) {
+ return url.substring(0, url.substring(7).indexOf(47) + 7);
+ }
+ String tmp = url.startsWith("https://") ? url.substring(0, url.substring(8).indexOf(47) + 8) : "";
+ return url.substring(tmp.length());
+ }
+
+ static Object[] getVodContent(String m3u8) {
+ Uri uri = Uri.parse(m3u8);
+ String time = String.valueOf(System.currentTimeMillis());
+ String key = Misc.MD5(subUrl(m3u8) + signPlayerStr + time, Misc.CharsetUTF8).toLowerCase();
+ String realUrl = m3u8 + "?key=" + key + "&v=360&i=5&p=7&ed=1a7348ae45f8f6de4d798614fc07e7271657392501986&time=" + time;
+ String m3u8Content = OkHttpUtil.string(realUrl, kmysPlayerHeaders);
+ String tsUrl = m3u8.substring(0, m3u8.indexOf(uri.getLastPathSegment()));
+ StringBuilder sb = new StringBuilder();
+ int start = 0;
+ Matcher matcher = tsRex.matcher(m3u8Content);
+ while (matcher.find()) {
+ sb.append(m3u8Content, start, matcher.start());
+ if (matcher.group().contains("EXT-X-KEY")) {
+ String keyRealUrl = Proxy.localProxyUrl() + "?do=kmys&type=key&url=" + Base64.encodeToString((tsUrl + matcher.group(3)).getBytes(Misc.CharsetUTF8), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP);
+ sb.append(matcher.group(2) + keyRealUrl + matcher.group(4));
+ } else {
+ String tsRealUrl = Proxy.localProxyUrl() + "?do=kmys&type=ts&url=" + Base64.encodeToString((tsUrl + matcher.group(1)).getBytes(Misc.CharsetUTF8), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP);
+ sb.append(tsRealUrl);
+ }
+ start = matcher.end();
+ }
+ sb.append(m3u8Content, start, m3u8Content.length());
+ String type = "application/octet-stream";
+ Object[] result = new Object[3];
+ result[0] = 200;
+ result[1] = type;
+ ByteArrayInputStream baos = new ByteArrayInputStream(sb.toString().getBytes(Misc.CharsetUTF8));
+ result[2] = baos;
+ return result;
+ }
+
+ static Object[] getKeyContent(String key) {
+ String time = String.valueOf(System.currentTimeMillis());
+ String md5 = Misc.MD5(subUrl(key) + signPlayerStr + time, Misc.CharsetUTF8).toLowerCase();
+ String realUrl = key + "?key=" + md5 + "&v=360&i=5&p=7&ed=1a7348ae45f8f6de4d798614fc07e7271657392501986&time=" + time;
+ String keyContent = OkHttpUtil.string(realUrl, kmysPlayerHeaders);
+ String type = "application/octet-stream";
+ Object[] result = new Object[3];
+ result[0] = 200;
+ result[1] = type;
+ ByteArrayInputStream baos = new ByteArrayInputStream(keyContent.getBytes(Misc.CharsetUTF8));
+ result[2] = baos;
+ return result;
+ }
+
+ static Object[] getTsContent(String ts) {
+ String time = String.valueOf(System.currentTimeMillis());
+ String key = Misc.MD5(subUrl(ts) + signPlayerStr + time, Misc.CharsetUTF8).toLowerCase();
+ String realUrl = ts + "?key=" + key + "&v=360&i=5&p=7&ed=1a7348ae45f8f6de4d798614fc07e7271657392501986&time=" + time;
+ OKCallBack.OKCallBackDefault callBack = new OKCallBack.OKCallBackDefault() {
+
+
+ @Override
+ public void onFailure(Call call, Exception e) {
+
+ }
+
+ @Override
+ public void onResponse(Response response) {
+ }
+ };
+ OkHttpUtil.get(OkHttpUtil.defaultClient(), realUrl, null, kmysPlayerHeaders, callBack);
+ if (callBack.getResult().code() == 200) {
+ Headers headers = callBack.getResult().headers();
+ String type = headers.get("Content-Type");
+ if (type == null) {
+ type = "application/octet-stream";
+ }
+ Object[] result = new Object[3];
+ result[0] = 200;
+ result[1] = type;
+ result[2] = callBack.getResult().body().byteStream();
+ return result;
+ }
+ return null;
+ }
+
+ public static Object[] vod(Map params) {
+ String type = params.get("type");
+ String url = params.get("url");
+ url = new String(Base64.decode(url, Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP), Misc.CharsetUTF8);
+ if (kmysPlayerHeaders == null) {
+ kmysPlayerHeaders = new HashMap<>();
+ kmysPlayerHeaders.put("User-Agent", "okhttp/3.14.7");
+ kmysPlayerHeaders.put("ed", "1a7348ae45f8f6de4d798614fc07e7271657392501986");
+ kmysPlayerHeaders.put("Connection", "close");
+ }
+ if (type.equals("m3u8")) {
+ return getVodContent(url);
+ } else if (type.equals("key")) {
+ return getKeyContent(url);
+ } else if (type.equals("ts")) {
+ return getTsContent(url);
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/catvod/spider/Kunyu77.java b/app/src/main/java/com/github/catvod/spider/Kunyu77.java
index ef6d1ff..8ff5f86 100644
--- a/app/src/main/java/com/github/catvod/spider/Kunyu77.java
+++ b/app/src/main/java/com/github/catvod/spider/Kunyu77.java
@@ -24,7 +24,7 @@ import java.util.Set;
* Author: @SDL
*/
public class Kunyu77 extends Spider {
- private static final String siteUrl = "http://api.kunyu77.com";
+ private static final String siteUrl = "https://clbky.kyky.vip";
private String uAgent = "Dalvik/2.1.0 (Linux; U; Android " + Build.VERSION.RELEASE + "; " + Build.MODEL + " Build/" + Build.ID + ")";
@@ -367,4 +367,4 @@ public class Kunyu77 extends Spider {
return src;
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/github/catvod/spider/Lgyy.java b/app/src/main/java/com/github/catvod/spider/Lgyy.java
new file mode 100644
index 0000000..de7dd02
--- /dev/null
+++ b/app/src/main/java/com/github/catvod/spider/Lgyy.java
@@ -0,0 +1,500 @@
+package com.github.catvod.spider;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Base64;
+
+import com.github.catvod.crawler.Spider;
+import com.github.catvod.crawler.SpiderDebug;
+import com.github.catvod.utils.okhttp.OKCallBack;
+import com.github.catvod.utils.okhttp.OkHttpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import okhttp3.Call;
+
+
+/**
+ * 蓝光影院
+ *
+ * Author: 匿名20220729
+ */
+public class Lgyy extends Spider {
+ private static final String siteUrl = "https://lgyy.tv";
+
+ /**
+ * 播放源配置
+ */
+ private JSONObject playerConfig;
+ /**
+ * 筛选配置
+ */
+ private JSONObject filterConfig;
+
+ private Pattern regexCategory = Pattern.compile("/vodtype/(\\d+).html");
+ private Pattern regexVid = Pattern.compile("/voddetail/(\\d+).html");
+ private Pattern regexPlay = Pattern.compile("/vodplay/(\\d+)-(\\d+)-(\\d+).html");
+ private Pattern regexPage = Pattern.compile("/vodshow/(\\S+).html");
+
+ @Override
+ public void init(Context context) {
+ super.init(context);
+ try {
+ playerConfig = new JSONObject("{\"duoduozy\":{\"show\":\"蓝光专线\",\"des\":\"\",\"ps\":\"0\",\"parse\":\"https://player.tjomet.com/lgyy/?url=\"},\"sohu\":{\"show\":\"搜狐\",\"des\":\"\",\"ps\":\"0\",\"parse\":\"https://player.tjomet.com/lgyy/?url=\"},\"qq\":{\"show\":\"腾讯\",\"des\":\"\",\"ps\":\"0\",\"parse\":\"https://player.tjomet.com/lgyy/?url=\"},\"bilibili\":{\"show\":\"哔哩\",\"des\":\"\",\"ps\":\"0\",\"parse\":\"https://player.tjomet.com/lgyy/?url=\"},\"youku\":{\"show\":\"优酷\",\"des\":\"\",\"ps\":\"0\",\"parse\":\"https://player.tjomet.com/lgyy/?url=\"},\"qiyi\":{\"show\":\"爱奇艺\",\"des\":\"\",\"ps\":\"0\",\"parse\":\"https://player.tjomet.com/lgyy/?url=\"},\"mgtv\":{\"show\":\"芒果\",\"des\":\"\",\"ps\":\"0\",\"parse\":\"https://player.tjomet.com/lgyy/?url=\"},\"xigua\":{\"show\":\"西瓜\",\"des\":\"\",\"ps\":\"0\",\"parse\":\"https://player.tjomet.com/lgyy/?url=\"},\"pptv\":{\"show\":\"PPTV\",\"des\":\"\",\"ps\":\"0\",\"parse\":\"https://player.tjomet.com/lgyy/?url=\"}}");
+ filterConfig = new JSONObject("{}");
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ }
+
+ /**
+ * 爬虫headers
+ *
+ * @param url
+ * @return
+ */
+ protected HashMap getHeaders(String url) {
+ HashMap headers = new HashMap<>();
+ headers.put("method", "GET");
+ if (!TextUtils.isEmpty(url)) {
+ headers.put("Referer", url);
+ }
+ headers.put("Accept-Encoding", "gzip, deflate, br");
+ headers.put("upgrade-insecure-requests", "1");
+ headers.put("DNT", "1");
+ headers.put("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36");
+ headers.put("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
+ headers.put("accept-language", "zh-CN,zh;q=0.9");
+ return headers;
+ }
+
+ /**
+ * 获取分类数据 + 首页最近更新视频列表数据
+ *
+ * @param filter 是否开启筛选 关联的是 软件设置中 首页数据源里的筛选开关
+ * @return
+ */
+ @Override
+ public String homeContent(boolean filter) {
+ try {
+ Document doc = Jsoup.parse(new URL(siteUrl).openStream(), "utf-8",OkHttpUtil.string(siteUrl, getHeaders(siteUrl)));
+ // 分类节点
+ Elements elements = doc.select("ul[class='navbar-items swiper-wrapper'] >li a");
+ JSONArray classes = new JSONArray();
+ for (Element ele : elements) {
+ String name = ele.text();
+ boolean show = true;
+ if (filter) {
+ show = name.equals("电影") ||
+ name.equals("电视剧") ||
+ name.equals("综艺") ||
+ name.equals("动漫") ||
+ name.equals("纪录片");
+ }
+ if (show) {
+ Matcher mather = regexCategory.matcher(ele.attr("href"));
+ if (!mather.find())
+ continue;
+ String id = mather.group(1).trim();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("type_id", id);
+ jsonObject.put("type_name", name);
+ classes.put(jsonObject);
+ }
+ }
+ JSONObject result = new JSONObject();
+ if (filter) {
+ result.put("filters", filterConfig);
+ }
+ result.put("class", classes);
+ try {
+ Elements list = doc.select("div[class='module-items module-poster-items-base'] >a");
+ JSONArray videos = new JSONArray();
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".module-poster-item").attr("href"));
+ if (!matcher.find())
+ continue;
+ String title = vod.selectFirst(".module-poster-item").attr("title");
+ String cover = vod.selectFirst("div.module-item-cover div.module-item-pic img").attr("data-original");
+ String remark = vod.selectFirst("div.module-item-cover div.module-item-note").text();
+ if (!TextUtils.isEmpty(cover) && !cover.startsWith("http")) {
+ cover = siteUrl + cover;
+ }
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ result.put("list", videos);
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+ /**
+ * 获取分类信息数据
+ *
+ * @param tid 分类id
+ * @param pg 页数
+ * @param filter 同homeContent方法中的filter
+ * @param extend 筛选参数{k:v, k1:v1}
+ * @return
+ */
+ @Override
+ public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
+ try {
+ String[] urlParams = new String[]{"", "", "", "", "", "", "", "", "", "", "", ""};
+ urlParams[0] = tid;
+ urlParams[8] = pg;
+ if (extend != null && extend.size() > 0) {
+ for (Iterator it = extend.keySet().iterator(); it.hasNext(); ) {
+ String key = it.next();
+ String value = extend.get(key);
+ if (value.trim().length() == 0)
+ continue;
+ urlParams[Integer.parseInt(key)] = URLEncoder.encode(value);
+ }
+ }
+ // 获取分类数据的url
+ String url = siteUrl + "/vodshow/" + TextUtils.join("-", urlParams) + "/";
+ String html = OkHttpUtil.string(url, getHeaders(url));
+ Document doc = Jsoup.parse(new URL(url).openStream(), "utf-8",OkHttpUtil.string(url, getHeaders(url)));
+
+ JSONObject result = new JSONObject();
+ int pageCount = 0;
+ int page = -1;
+
+ Elements pageInfo = doc.select("div[id='page'] a");
+ if (pageInfo.size() == 0) {
+ page = Integer.parseInt(pg);
+ pageCount = page;
+ } else {
+ for (int i = 0; i < pageInfo.size(); i++) {
+ Element li = pageInfo.get(i);
+ Element a = li.selectFirst("a");
+ if (a == null)
+ continue;
+ String name = a.text();
+ if (page == -1 && li.hasClass("page-current")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ page = Integer.parseInt(matcher.group(1).split("-")[8]);
+ } else {
+ page = 0;
+ }
+ }
+ if (name.equals("尾页")) {
+ Matcher matcher = regexPage.matcher(a.attr("href"));
+ if (matcher.find()) {
+ pageCount = Integer.parseInt(matcher.group(1).split("-")[8]);
+ } else {
+ pageCount = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ JSONArray videos = new JSONArray();
+ if (!html.contains("没有找到您想要的结果哦")) {
+ Elements list = doc.select("div[class='module-items module-poster-items-base'] >a");
+ for (int i = 0; i < list.size(); i++) {
+ Element vod = list.get(i);
+ String title = vod.selectFirst(".module-poster-item").attr("title");
+ String cover = vod.selectFirst("div.module-item-cover div.module-item-pic img").attr("data-original");
+ if (!TextUtils.isEmpty(cover) && !cover.startsWith("http")) {
+ cover = siteUrl + cover;
+ }
+ String remark = vod.selectFirst("div.module-item-cover div.module-item-note").text();
+ Matcher matcher = regexVid.matcher(vod.selectFirst(".module-poster-item").attr("href"));
+ if (!matcher.find())
+ continue;
+ String id = matcher.group(1);
+ JSONObject v = new JSONObject();
+ v.put("vod_id", id);
+ v.put("vod_name", title);
+ v.put("vod_pic", cover);
+ v.put("vod_remarks", remark);
+ videos.put(v);
+ }
+ }
+ result.put("page", page);
+ result.put("pagecount", pageCount);
+ result.put("limit", 48);
+ result.put("total", pageCount <= 1 ? videos.length() : pageCount * 48);
+
+ result.put("list", videos);
+ return result.toString();
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return "";
+ }
+
+
+ private static String Regex(Pattern pattern, String content) {
+ if (pattern == null) {
+ return content;
+ }
+ try {
+ Matcher matcher = pattern.matcher(content);
+ if (matcher.find()) {
+ return matcher.group(1).trim();
+ }
+ } catch (Exception e) {
+ SpiderDebug.log(e);
+ }
+ return content;
+ }
+ /**
+ * 视频详情信息
+ *
+ * @param ids 视频id
+ * @return
+ */
+ @Override
+ public String detailContent(List ids) {
+ try {
+ // 视频详情url
+ String url = siteUrl + "/voddetail/" + ids.get(0) + ".html";
+ Document doc = Jsoup.parse(new URL(url).openStream(), "utf-8",OkHttpUtil.string(url, getHeaders(url)));
+ JSONObject result = new JSONObject();
+ JSONObject vodList = new JSONObject();
+
+ // 取基本数据
+ String cover = doc.selectFirst("div.module-item-pic img").attr("data-original");
+ if (!TextUtils.isEmpty(cover) && !cover.startsWith("http")) {
+ cover = siteUrl + cover;
+ }
+ String title = doc.selectFirst("div.module-info-heading h1").text();
+ String category = "", area = "", year = "", remark = "", director = "", actor = "", desc = "";
+ Elements data = doc.select("div.module-info-items > div");
+ desc = doc.selectFirst("div.module-info-introduction-content p").text().trim();
+ category =doc.select("div.module-info-tag div").get(2).text().trim();
+ year=doc.select("div.module-info-tag div").get(0).text().trim();
+ area =doc.select("div.module-info-tag div").get(1).text().trim();
+ //year = Regex(Pattern.compile("上映:(\\S+)"), data.get(0).text());
+ actor = Regex(Pattern.compile("主演:(\\S+)"), data.nextAll().text());
+ director = Regex(Pattern.compile("导演:(\\S+)"), data.nextAll().text());
+ // remark=data.select("div.module-info-item-content").text().trim();
+
+ vodList.put("vod_id", ids.get(0));
+ vodList.put("vod_name", title);
+ vodList.put("vod_pic", cover);
+ vodList.put("type_name", category);
+ vodList.put("vod_year", year);
+ vodList.put("vod_area", area);
+ vodList.put("vod_remarks", remark);
+ vodList.put("vod_actor", actor);
+ vodList.put("vod_director", director);
+ vodList.put("vod_content", desc);
+
+ Map vod_play = new TreeMap<>(new Comparator() {
+ @Override
+ public int compare(String o1, String o2) {
+ try {
+ int sort1 = playerConfig.getJSONObject(o1).getInt("or");
+ int sort2 = playerConfig.getJSONObject(o2).getInt("or");
+
+ if (sort1 == sort2) {
+ return 1;
+ }
+ return sort1 - sort2 > 0 ? 1 : -1;
+ } catch (JSONException e) {
+ SpiderDebug.log(e);
+ }
+ return 1;
+ }
+ });
+
+ // 取播放列表数据
+ Elements sources = doc.select("div[id=y-playList] > div");
+ //Elements sourceList = doc.select("div.stui-vodlist__head > ul.stui-content__playlist");
+
+ for (int i = 0; i < sources.size(); i++) {
+ Element source = sources.get(i);
+ String sourceName = source.attr("data-dropdown-value");
+ boolean found = false;
+ for (Iterator