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 it = playerConfig.keys(); it.hasNext(); ) { + String flag = it.next(); + if (playerConfig.getJSONObject(flag).getString("show").equals(sourceName)) { + //sourceName = flag; + sourceName = playerConfig.getJSONObject(flag).getString("show"); + found = true; + break; + } + } + if (!found) + continue; + String playList = ""; + Elements playListA = doc.select("div.module-play-list div 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 + */ + + private final Pattern urlt = Pattern.compile("\"url\": *\"([^\"]*)\","); + private final Pattern token = Pattern.compile("\"token\": *\"([^\"]*)\""); + private final Pattern vkey = Pattern.compile("\"vkey\": *\"([^\"]*)\","); + private final Pattern urls = Pattern.compile("urls = *\'([^\']*)"); + @Override + public String playerContent(String flag, String id, List vipFlags) { + try { + JSONObject headers = new JSONObject(); + headers.put("Referer", "https://lgyy.tv"); + headers.put("User-Agent", " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"); + headers.put("Accept", " text/html,application/xhtml+xml,application/xml;q=0.9,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,en-GB;q=0.8,en-US;q=0.7,en;q=0.6"); + headers.put("Accept-Encoding", " gzip, deflate"); + String url = siteUrl + "/vodplay/" + id + ".html"; + Elements allScript = Jsoup.parse(new URL(url).openStream(), "utf-8",OkHttpUtil.string(url, getHeaders(url))).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_")) + { + JSONObject player = new JSONObject(scContent.substring(scContent.indexOf('{'), scContent.lastIndexOf('}') + 1)); + if (playerConfig.has(player.getString("from"))) + { + JSONObject pCfg = playerConfig.getJSONObject(player.getString("from")); + String jxurl = "https://player.tjomet.com/lgyy/dplayer.php?url=" + player.getString("url"); + Document doc = Jsoup.parse(new URL(jxurl).openStream(), "utf-8",OkHttpUtil.string(jxurl, getHeaders(jxurl))); + Elements script = doc.select("body>script[type=text/javascript]"); + for (int j = 0; j < script.size(); j++) + { + String Content = script.get(j).html().trim(); + Matcher matcher = urls.matcher(Content); + if (matcher.find()) { + String urls = matcher.group(1); + String zlurl = new String(Base64.decode(urls.substring(8).getBytes(), 0)); + result.put("url", zlurl.substring(8, zlurl.length() - 8)); + result.put("header", headers.toString()); + result.put("parse", 0); + result.put("playUrl", ""); + break; + } + + + } + } + 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 ""; + 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"); + if (!TextUtils.isEmpty(cover) && !cover.startsWith("http")) { + cover = siteUrl + cover; + } + 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/Lib.java b/app/src/main/java/com/github/catvod/spider/Lib.java index 9eb5235..9ebbe36 100644 --- a/app/src/main/java/com/github/catvod/spider/Lib.java +++ b/app/src/main/java/com/github/catvod/spider/Lib.java @@ -49,7 +49,7 @@ public class Lib extends Spider { public void init(Context context) { super.init(context); try { - playerConfig = new JSONObject("{\"LINE405\":{\"sh\":\"LINE405\",\"pu\":\"https://sh-data-s01.chinaeast2.cloudapp.chinacloudapi.cn/lb.php?url=\",\"sn\":1,\"or\":999},\"LINE406\":{\"sh\":\"LINE406\",\"pu\":\"https://sh-data-s01.chinaeast2.cloudapp.chinacloudapi.cn/zm.php?url=\",\"sn\":1,\"or\":999},\"LINE407\":{\"sh\":\"LINE407\",\"pu\":\"https://sh-data-s01.chinaeast2.cloudapp.chinacloudapi.cn/lb.php?url=\",\"sn\":1,\"or\":999},\"LINE408\":{\"sh\":\"LINE408\",\"pu\":\"\",\"sn\":0,\"or\":999},\"p300\":{\"sh\":\"LINE300\",\"pu\":\"\",\"sn\":0,\"or\":999},\"p301\":{\"sh\":\"LINE301\",\"pu\":\"\",\"sn\":0,\"or\":999},\"line402-日语\":{\"sh\":\"LINE402\",\"pu\":\"\",\"sn\":0,\"or\":999},\"LINE400\":{\"sh\":\"LINE400\",\"pu\":\"https://sh-data-s01.chinaeast2.cloudapp.chinacloudapi.cn/lb.php?url=\",\"sn\":1,\"or\":999},\"line401\":{\"sh\":\"LINE401\",\"pu\":\"\",\"sn\":0,\"or\":999}}"); + playerConfig = new JSONObject("{\"duoduozy\":{\"sh\":\"LINE100\",\"pu\":\"https://play.shtpin.com/xplay/?url=\",\"sn\":1,\"or\":999},\"LINE405\":{\"sh\":\"LINELIB\",\"pu\":\"https://sh-data-s01.chinaeast2.cloudapp.chinacloudapi.cn/lb.php?url=\",\"sn\":1,\"or\":999},\"LINE406\":{\"sh\":\"LINE406\",\"pu\":\"https://sh-data-s01.chinaeast2.cloudapp.chinacloudapi.cn/zm.php?url=\",\"sn\":1,\"or\":999},\"LINE407\":{\"sh\":\"LINE407\",\"pu\":\"https://sh-data-s01.chinaeast2.cloudapp.chinacloudapi.cn/lb.php?url=\",\"sn\":1,\"or\":999},\"LINE408\":{\"sh\":\"LINE408\",\"pu\":\"\",\"sn\":0,\"or\":999},\"p300\":{\"sh\":\"LINE300\",\"pu\":\"\",\"sn\":0,\"or\":999},\"p301\":{\"sh\":\"LINE301\",\"pu\":\"\",\"sn\":0,\"or\":999},\"line402-日语\":{\"sh\":\"LINE402\",\"pu\":\"\",\"sn\":0,\"or\":999},\"LINE400\":{\"sh\":\"LINE400\",\"pu\":\"https://sh-data-s01.chinaeast2.cloudapp.chinacloudapi.cn/lb.php?url=\",\"sn\":1,\"or\":999},\"line401\":{\"sh\":\"LINE401\",\"pu\":\"\",\"sn\":0,\"or\":999}}"); filterConfig = new JSONObject("{\"1\":[{\"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\":\"儿童\"}]},{\"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\":\"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\":\"4\",\"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\":\"2\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"2\":[{\"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\":\"4\",\"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\":\"11\",\"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\":\"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\":\"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\":\"2\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"15\":[{\"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\":\"其他\"}]},{\"key\":\"1\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韩国\",\"v\":\"韩国\"}]},{\"key\":\"11\",\"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\":\"2\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"16\":[{\"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\":\"其他\"}]},{\"key\":\"11\",\"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\":\"4\",\"name\":\"语言\",\"value\":[{\"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); @@ -247,6 +247,21 @@ public class Lib extends Spider { } return ""; } + + private static String doReplaceRegex(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; + } /** * 视频详情信息 @@ -438,46 +453,41 @@ public class Lib extends Spider { return ""; } - protected static HashMap sHeaders() { - HashMap headers = new HashMap<>(); - 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-encoding", "gzip, deflate, br"); - headers.put("Accept-language", "zh-SG,zh;q=0.9,en-GB;q=0.8,en;q=0.7,zh-CN;q=0.6"); - return headers; - } + // protected static HashMap sHeaders(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/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-encoding", "gzip, deflate, br"); + // headers.put("Accept-language", "zh-SG,zh;q=0.9,en-GB;q=0.8,en;q=0.7,zh-CN;q=0.6"); + // return headers; + // } @Override public String searchContent(String key, boolean quick) { try { - String url = "https://shitu.paodekuaiweixinqun.com/search?q=site%3Alibvio.me%2Fdetail+" + URLEncoder.encode(key); - Document docs = Jsoup.parse(OkHttpUtil.string(url, sHeaders())); + 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(); - JSONObject v = new JSONObject(); - Elements list = docs.select("div.NJo7tc div.yuRUbf"); - for (int i = 0; i < list.size(); i++) { - Element doc = list.get(i); - String sourceName = doc.select("div.yuRUbf a h3").text(); - if (sourceName.contains(key)) { - String list1 = doc.select("div.yuRUbf a").attr("href"); - Document link = Jsoup.parse(OkHttpUtil.string(list1, getHeaders(url))); - Matcher matcher = regexVid.matcher(list1); - Elements data = link.select("p.data"); - if (matcher.find()) { - - String group = matcher.group(1); - String cover = link.select("div.stui-content__thumb a img").attr("data-original"); - String title = link.select("div.stui-content__detail h1").text(); - Pattern rms = Pattern.compile("更新:(\\S+)"); - String remark = doReplaceRegex(rms, data.get(3).text()); - - v.put("vod_name", title); - v.put("vod_remarks", remark); - v.put("vod_id", group); - v.put("vod_pic", cover); - videos.put(v); + 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"); + if (!TextUtils.isEmpty(cover) && !cover.startsWith("http")) { + cover = siteUrl + cover; } + 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); @@ -487,18 +497,18 @@ public class Lib extends Spider { } 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; - } -} \ No newline at end of file +} + // 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; +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/Live1211.java b/app/src/main/java/com/github/catvod/spider/Live1211.java new file mode 100644 index 0000000..b8ef6e2 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Live1211.java @@ -0,0 +1,249 @@ +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.JSONObject; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +public class Live1211 extends Spider { + + private static final String host = "http://live.yj1211.work"; + + private static String platform = "douyu"; + + @Override + public void init(Context context) { + super.init(context); + } + + @Override + public void init(Context context, String extend) { + platform = extend; + super.init(context, extend); + } + + @Override + public String homeContent(boolean filter) { + JSONObject result = new JSONObject(); + try { + String resp = OkHttpUtil.string(host + "/api/live/getAreas?platform=" + platform, null); + JSONObject res = new JSONObject(resp); + JSONArray list = res.getJSONArray("data"); + JSONArray classes = new JSONArray(); + JSONObject filters = new JSONObject(); + for (int i = 0; i < list.length(); i++) { + JSONArray typeItems = list.getJSONArray(i); + JSONArray values = new JSONArray(); + for (int j = 0; j < typeItems.length(); j++) { + JSONObject typeItem = typeItems.optJSONObject(j); + if (j == 0) { + String typeName = typeItem.getString("typeName"); + String typeId = typeItem.getString("areaName"); + JSONObject newCls = new JSONObject(); + newCls.put("type_id", typeId); + newCls.put("type_name", typeName); + classes.put(newCls); + + JSONArray filterList = new JSONArray(); + filters.put(typeId, filterList); + + JSONObject filterItem = new JSONObject(); + filterList.put(filterItem); + + filterItem.put("key", "area"); + filterItem.put("name", "分类"); + filterItem.put("value", values); + + } + JSONObject kv = new JSONObject(); + kv.put("n", typeItem.optString("areaName")); + kv.put("v", typeItem.optString("areaName")); + values.put(kv); + } + } + result.put("class", classes); + result.put("filters", filters); + } catch (Exception e) { + SpiderDebug.log(e); + } + return result.toString(); + } + + /** + * 平台推荐 http://live.yj1211.work/api/live/getRecommendByPlatform?platform=douyu&page=1&size=20 + * + * @return + */ + @Override + public String homeVideoContent() { + JSONObject result = new JSONObject(); + try { + String url = host + "/api/live/getRecommendByPlatform?page=1&size=20&platform=" + platform; + JSONArray list = new JSONArray(); + JSONArray data = new JSONObject(OkHttpUtil.string(url, null)).getJSONArray("data"); + for (int i = 0; i < data.length(); i++) { + JSONObject vr = data.getJSONObject(i); + JSONObject vod = new JSONObject(); + vod.put("vod_id", vr.optString("roomId")); + vod.put("vod_name", vr.getString("ownerName")); + vod.put("vod_pic", vr.getString("roomPic")); + vod.put("vod_remarks", vr.getString("categoryName") + "|" + vr.getLong("online") / 10000 + "w"); + list.put(vod); + } + result.put("list", list); + } catch (Exception e) { + SpiderDebug.log(e); + } + return result.toString(); + } + + @Override + public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { + JSONObject result = new JSONObject(); + try { + String url = host + "/api/live/getRecommendByPlatformArea?platform=" + platform; + url = url + "&area="; + if (extend.containsKey("area")) { + url = url + extend.get("area"); + } else { + url = url + tid; + } + + url = url + "&page=" + pg + "&size=20"; + JSONArray data = new JSONObject(OkHttpUtil.string(url, null)).getJSONArray("data"); + JSONArray vods = new JSONArray(); + for (int i = 0; i < data.length(); i++) { + JSONObject item = data.getJSONObject(i); + JSONObject vod = new JSONObject(); + vod.put("vod_id", item.optString("roomId")); + vod.put("vod_name", item.getString("ownerName")); + vod.put("vod_pic", item.getString("roomPic")); + vod.put("vod_remarks", item.getString("categoryName") + "|" + item.getLong("online") / 10000 + "w"); + vods.put(vod); + } + int parseInt = Integer.parseInt(pg); + result.put("page", parseInt); + if (vods.length() == 20) { + parseInt++; + } + result.put("pagecount", parseInt); + result.put("limit", 20); + result.put("total", Integer.MAX_VALUE); + result.put("list", vods); + } catch (Exception e) { + SpiderDebug.log(e); + } + return result.toString(); + } + + @Override + public String detailContent(List ids) { + JSONObject result = new JSONObject(); + try { + String url = host + "/api/live/getRoomInfo?platform=" + platform + "&roomId=" + ids.get(0); + JSONObject data = new JSONObject(OkHttpUtil.string(url, null)).optJSONObject("data"); + JSONObject vod = new JSONObject(); + vod.put("vod_id", data.getString("roomId")); + vod.put("vod_name", data.getString("roomName")); + vod.put("vod_pic", data.getString("roomPic")); + vod.put("type_name", data.optString("categoryName")); + vod.put("vod_area", data.optString("ownerName")); + vod.put("vod_remarks", data.optLong("online") / 10000 + "w"); + List reUrls = new LinkedList<>(); + + if(platform.equals("huya")){ + String playurl ="https://mp.huya.com/cache.php?m=Live&do=profileRoom" + "&roomid=" + ids.get(0); + JSONObject flv = new JSONObject(OkHttpUtil.string(playurl, null)).getJSONObject("data").getJSONObject("stream").getJSONObject("flv"); + JSONArray playData =flv.optJSONArray("multiLine"); + JSONArray playData_Name =flv.optJSONArray("rateArray"); + if(playData.length()>0){ + for(int i=0;i vipFlags) { + JSONObject result = new JSONObject(); + try { + result.put("parse", "0"); + result.put("url", id); + } catch (Exception e) { + SpiderDebug.log(e); + } + return result.toString(); + } + + @Override + public boolean isVideoFormat(String url) { + return super.isVideoFormat(url); + } + + @Override + public boolean manualVideoCheck() { + return super.manualVideoCheck(); + } +} diff --git a/app/src/main/java/com/github/catvod/spider/LocalFile.java b/app/src/main/java/com/github/catvod/spider/LocalFile.java new file mode 100644 index 0000000..0fecaf2 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/LocalFile.java @@ -0,0 +1,144 @@ +package com.github.catvod.spider; + +import android.content.Context; +import android.os.Environment; + +import com.github.catvod.crawler.Spider; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import org.json.JSONArray; +import org.json.JSONObject; + +public class LocalFile extends Spider { + + public String categoryContent(String tid, String pg, boolean filter, HashMap hashMap) { + try { + + File file = new File(tid); + File[] list = file.listFiles(); + JSONArray jSONArray2 = new JSONArray(); + for (File f : list) { + String filename = f.getName(); + if(filename.indexOf('.') ==0){ + continue; + } + String pic = "https://img.tukuppt.com/png_preview/00/18/23/GBmBU6fHo7.jpg!/fw/260"; + if(!f.isDirectory()){ + pic = "https://img.tukuppt.com/png_preview/00/42/50/3ySGW7mvyY.jpg!/fw/260"; + } + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("vod_id", f.getAbsolutePath()); + jSONObject2.put("vod_name", f.getName()); + jSONObject2.put("vod_pic", pic); + // 当vod_tag为folder时会点击该item会把当前vod_id当成新的类型ID重新进 + jSONObject2.put("vod_tag",f.isDirectory() ? "folder" : "file" ); + jSONObject2.put("vod_remarks", fileTime(f.lastModified(), "yyyy/MM/dd aHH:mm:ss")); + jSONArray2.put(jSONObject2); + } + + 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 + { + JSONObject jSONObject; + String filename = ids.get(0); + File f = new File(filename); + JSONObject vod = new JSONObject(); + vod.put("vod_id", filename); + vod.put("vod_name", f.getName()); + vod.put("vod_pic", ""); + vod.put("type_name", ""); + vod.put("vod_play_from", "播放"); + vod.put("vod_play_url", f.getName()+"$"+filename); + JSONObject result = new JSONObject(); + JSONArray list = new JSONArray(); + list.put(vod); + result.put("list", list); + return result.toString(); + } + catch (Exception e){ + e.printStackTrace(); + } + return ""; + + } + + + String fileTime(long time, String fmt) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(time); + Date date = calendar.getTime(); + SimpleDateFormat sdf = new SimpleDateFormat(fmt); + return sdf.format(date); + } + + public String homeContent(boolean z) { + try { + JSONObject filterConfig = new JSONObject(); + JSONArray classes = new JSONArray(); + JSONObject newCls = new JSONObject(); + String root = Environment.getExternalStorageDirectory().getAbsolutePath(); + newCls.put("type_id", root); + newCls.put("type_name", "本地文件"); + // type_flag 是扩展字段,目前可取值0、1、2,该字段不存在时表示正常模式 + 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) { + LocalFile.super.init(context); + } + + 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/MGTV.java b/app/src/main/java/com/github/catvod/spider/MGTV.java new file mode 100644 index 0000000..8a5e85a --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/MGTV.java @@ -0,0 +1,314 @@ +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.net.URLEncoder; +import java.util.ArrayList; +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 rxhttp.wrapper.annotations.NonNull; + +public class MGTV extends Spider { + protected JSONObject a; + protected JSONObject q = new JSONObject(); + + 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) { + try { + String str3 = "https://pianku.api.mgtv.com/rider/list/msite/v2?platform=msite&channelId=" + str + "&pn=" + str2 + "&chargeInfo=&sort=c2"; + if (hashMap != null) { + for (String str4 : hashMap.keySet()) { + String trim = hashMap.get(str4).trim(); + if (trim.length() != 0) { + str3 = str3 + "&" + str4 + "=" + URLEncoder.encode(trim); + } + } + } + String content = OkHttpUtil.string(str3, getHeaders(str3)); + JSONObject jSONObject = new JSONObject(); + try { + JSONArray optJSONArray = new JSONObject(content).optJSONObject("data").optJSONArray("hitDocs"); + JSONArray jSONArray = new JSONArray(); + for (int i = 0; i < optJSONArray.length(); i++) { + JSONObject optJSONObject = optJSONArray.optJSONObject(i); + String optString = optJSONObject.optString("title"); + String q = q(str3, optJSONObject.optString("img")); + String optString2 = optJSONObject.optString("updateInfo"); + if (optString2.equals("")) { + optString2 = optJSONObject.optString("subtitle"); + } + String vodId = optJSONObject.optString("playPartId"); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("vod_id", vodId); + jSONObject2.put("vod_name", optString); + jSONObject2.put("vod_pic", q); + jSONObject2.put("vod_remarks", optString2); + jSONArray.put(jSONObject2); + } + jSONObject.put("list", jSONArray); + 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 vodId = list.get(0); + String infoUrl = "https://pcweb.api.mgtv.com/player/vinfo?video_id=" + vodId; + String infoJson = OkHttpUtil.string(infoUrl, getHeaders(infoUrl)); + JSONObject info = new JSONObject(infoJson).getJSONObject("data"); + String pic = info.getString("clip_imgurl2"); + + int pageSize = 30; + int page = 1; + String url = "https://pcweb.api.mgtv.com/episode/list?_support=10000000&version=5.5.35&video_id="+vodId+"&page="+page+"&size="+pageSize+"&allowedRC=1&_support=10000000"; + String json = OkHttpUtil.string(url, getHeaders(url)); + JSONObject jSONObject = new JSONObject(json).getJSONObject("data"); + JSONObject jSONObject2 = new JSONObject(); + JSONObject optJSONObject = jSONObject.optJSONObject("info"); + jSONObject2.put("vod_id", vodId); + jSONObject2.put("vod_name", optJSONObject.optString("title")); + jSONObject2.put("vod_pic", pic); + jSONObject2.put("vod_content", optJSONObject.optString("desc")); + JSONArray optJSONArray = jSONObject.optJSONArray("list"); + ArrayList arrayList = new ArrayList(); + + for (int i = 0; i < optJSONArray.length(); i++) { + JSONObject optJSONObject2 = optJSONArray.optJSONObject(i); + String viewName = optJSONObject2.optString("t1") + " " + optJSONObject2.optString("t2"); + arrayList.add(viewName + "$" + optJSONObject2.optString("url")); + } + + int totalPage = jSONObject.getInt("total_page"); + int count = jSONObject.getInt("count"); + int total = jSONObject.getInt("total"); + ArrayList blocks = new ArrayList(); + ArrayList blockList = new ArrayList(); + if (totalPage == 1) { + blocks.add("mgtv"); + } else if (totalPage > 1) { + blocks.add("1-" + pageSize); + } + blockList.add(join("#", arrayList)); + if (totalPage > page) { + for (int curPage = 2; curPage<=totalPage; curPage++) { + String listUrl = "https://pcweb.api.mgtv.com/episode/list?_support=10000000&version=5.5.35&video_id="+vodId+"&page="+curPage+"&size="+pageSize+"&allowedRC=1&_support=10000000"; + String resultJson = OkHttpUtil.string(listUrl, getHeaders(listUrl)); + JSONObject dataObj = new JSONObject(resultJson).getJSONObject("data"); + JSONArray dataList = dataObj.getJSONArray("list"); + int first = (curPage - 1) * pageSize + 1; + int last = 0; + if (totalPage == curPage) { + last = total; + } else { + last = curPage * pageSize; + } + blocks.add(first + "-" + last); + ArrayList curArrayList = new ArrayList(); + for (int i = 0; i < dataList.length(); i++) { + JSONObject item = dataList.optJSONObject(i); + String viewThisName = item.optString("t1") + " " + item.optString("t2"); + curArrayList.add(viewThisName + "$" + item.optString("url")); + } + blockList.add(join("#", curArrayList)); + } + } + + jSONObject2.put("vod_play_from", join("$$$", blocks)); + jSONObject2.put("vod_play_url", join("$$$", blockList)); + JSONObject result = new JSONObject(); + JSONArray jSONArray = new JSONArray(); + jSONArray.put(jSONObject2); + result.put("list", jSONArray); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } + + protected HashMap getHeaders(String str) { + HashMap hashMap = new HashMap<>(); + hashMap.put("referer", "https://so.mgtv.com"); + 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) { + try { + JSONArray optJSONArray = new JSONObject(OkHttpUtil.string("https://pianku.api.mgtv.com/rider/config/platformChannels/v1?platform=msite&abroad=0&_support=10000000", getHeaders("https://pianku.api.mgtv.com/rider/config/platformChannels/v1?platform=msite&abroad=0&_support=10000000"))).optJSONArray("data"); + JSONArray jSONArray = new JSONArray(); + for (int i = 0; i < optJSONArray.length(); i++) { + JSONObject optJSONObject = optJSONArray.optJSONObject(i); + JSONObject jSONObject = new JSONObject(); + jSONObject.put("type_name", optJSONObject.optString("channelName")); + jSONObject.put("type_id", optJSONObject.optString("channelId")); + jSONArray.put(jSONObject); + } + JSONObject jSONObject2 = new JSONObject(); + if (z) { + jSONObject2.put("filters", this.a); + } + jSONObject2.put("class", jSONArray); + try { + JSONArray optJSONArray2 = new JSONObject(OkHttpUtil.string("https://pianku.api.mgtv.com/rider/list/pcweb/v3?platform=pcweb&channelId=2&pn=1&chargeInfo=&sort=c2", getHeaders("https://pianku.api.mgtv.com/rider/list/pcweb/v3?platform=pcweb&channelId=2&pn=1&chargeInfo=&sort=c2"))).optJSONObject("data").optJSONArray("hitDocs"); + JSONArray jSONArray2 = new JSONArray(); + for (int i2 = 0; i2 < optJSONArray2.length(); i2++) { + JSONObject optJSONObject2 = optJSONArray2.optJSONObject(i2); + String optString = optJSONObject2.optString("title"); + String q = optJSONObject2.optString("imgUrlH"); + String optString2 = optJSONObject2.optString("updateInfo"); + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put("vod_id", optJSONObject2.optString("playPartId")); + jSONObject3.put("vod_name", optString); + jSONObject3.put("vod_pic", q); + jSONObject3.put("vod_remarks", optString2); + jSONArray2.put(jSONObject3); + } + jSONObject2.put("list", jSONArray2); + } catch (Exception e) { + SpiderDebug.log(e); + } + return jSONObject2.toString(4); + } catch (Exception e2) { + SpiderDebug.log(e2); + return ""; + } + } + + public String homeVideoContent() { + try { + JSONArray jSONArray = new JSONObject(OkHttpUtil.string("https://www.mgtv.com/api.php/app/index_video?token=", getHeaders("https://www.mgtv.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) { + MGTV.super.init(context); + try { + this.a = new JSONObject("{\"1\":[{\"name\":\"类型\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"4\",\"n\":\"王牌综艺\"},{\"v\":\"5\",\"n\":\"大咖秀场\"},{\"v\":\"6\",\"n\":\"搞笑\"},{\"v\":\"7\",\"n\":\"情感\"},{\"v\":\"8\",\"n\":\"音乐\"},{\"v\":\"9\",\"n\":\"生活\"},{\"v\":\"179\",\"n\":\"亲子\"},{\"v\":\"170\",\"n\":\"旅游\"},{\"v\":\"171\",\"n\":\"时尚\"},{\"v\":\"173\",\"n\":\"真人秀\"},{\"v\":\"174\",\"n\":\"竞技\"},{\"v\":\"172\",\"n\":\"访谈\"},{\"v\":\"180\",\"n\":\"脱口秀\"}],\"key\":\"kind\"},{\"name\":\"地区\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"内地\"},{\"v\":\"2\",\"n\":\"港台\"},{\"v\":\"3\",\"n\":\"其他\"}],\"key\":\"area\"},{\"name\":\"排序\",\"value\":[{\"v\":\"c1\",\"n\":\"最新\"},{\"v\":\"c2\",\"n\":\"最热\"},{\"v\":\"c4\",\"n\":\"知乎高分\"}],\"key\":\"sort\"}],\"2\":[{\"name\":\"类型\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"14\",\"n\":\"甜蜜互宠\"},{\"v\":\"15\",\"n\":\"虐恋情深\"},{\"v\":\"16\",\"n\":\"青涩校园\"},{\"v\":\"17\",\"n\":\"仙侠玄幻\"},{\"v\":\"19\",\"n\":\"都市职场\"},{\"v\":\"148\",\"n\":\"古装\"},{\"v\":\"20\",\"n\":\"快意江湖\"},{\"v\":\"147\",\"n\":\"偶像\"},{\"v\":\"21\",\"n\":\"悬疑推理\"},{\"v\":\"22\",\"n\":\"家长里短\"},{\"v\":\"23\",\"n\":\"芒果出品\"},{\"v\":\"24\",\"n\":\"轻松搞笑\"},{\"v\":\"25\",\"n\":\"铁血战争\"},{\"v\":\"26\",\"n\":\"其他\"}],\"key\":\"kind\"},{\"name\":\"地区\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"10\",\"n\":\"内地\"},{\"v\":\"11\",\"n\":\"日韩\"},{\"v\":\"12\",\"n\":\"港台\"}],\"key\":\"area\"},{\"name\":\"排序\",\"value\":[{\"v\":\"c2\",\"n\":\"最热\"},{\"v\":\"c1\",\"n\":\"最新\"},{\"v\":\"c4\",\"n\":\"知乎高分\"}],\"key\":\"sort\"},{\"name\":\"版本\",\"value\":[{\"v\":\"all\",\"n\":\"全部\"},{\"v\":\"2037\",\"n\":\"TV版\"},{\"v\":\"2038\",\"n\":\"特别版\"},{\"v\":\"2040\",\"n\":\"精华版\"},{\"v\":\"2036\",\"n\":\"未删减版\"}],\"key\":\"edition\"}],\"3\":[{\"name\":\"类型\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"34\",\"n\":\"院线大片\"},{\"v\":\"175\",\"n\":\"爱情\"},{\"v\":\"176\",\"n\":\"喜剧\"},{\"v\":\"177\",\"n\":\"动作\"},{\"v\":\"178\",\"n\":\"科幻\"},{\"v\":\"39\",\"n\":\"青春\"},{\"v\":\"43\",\"n\":\"恐怖悬疑\"},{\"v\":\"44\",\"n\":\"战争\"},{\"v\":\"45\",\"n\":\"警匪\"},{\"v\":\"46\",\"n\":\"历史\"},{\"v\":\"47\",\"n\":\"歌舞\"},{\"v\":\"48\",\"n\":\"动画\"},{\"v\":\"50\",\"n\":\"其他\"}],\"key\":\"kind\"},{\"name\":\"资费\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"b1\",\"n\":\"免费\"},{\"v\":\"b2\",\"n\":\"VIP\"},{\"v\":\"b3\",\"n\":\"VIP用券\"},{\"v\":\"b4\",\"n\":\"付费点播\"}],\"key\":\"chargeInfo\"},{\"name\":\"排序\",\"value\":[{\"v\":\"c2\",\"n\":\"最热\"},{\"v\":\"c1\",\"n\":\"最新\"},{\"v\":\"c4\",\"n\":\"知乎高分\"}],\"key\":\"sort\"}],\"106\":[{\"name\":\"类型\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"106\",\"n\":\"时事\"},{\"v\":\"107\",\"n\":\"社会\"},{\"v\":\"108\",\"n\":\"文娱\"},{\"v\":\"109\",\"n\":\"军事\"}],\"key\":\"kind\"},{\"name\":\"排序\",\"value\":[{\"v\":\"c1\",\"n\":\"最新\"},{\"v\":\"c2\",\"n\":\"最热\"}],\"key\":\"sort\"}],\"91\":[{\"name\":\"类型\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"119\",\"n\":\"吐槽\"},{\"v\":\"120\",\"n\":\"恶搞\"},{\"v\":\"121\",\"n\":\"爆笑\"},{\"v\":\"122\",\"n\":\"奇趣\"},{\"v\":\"123\",\"n\":\"饭制\"},{\"v\":\"124\",\"n\":\"其他\"}],\"key\":\"kind\"},{\"name\":\"排序\",\"value\":[{\"v\":\"c2\",\"n\":\"最热\"},{\"v\":\"c1\",\"n\":\"最新\"}],\"key\":\"sort\"}],\"50\":[{\"name\":\"类型\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"60\",\"n\":\"恋爱少女\"},{\"v\":\"86\",\"n\":\"热血\"},{\"v\":\"62\",\"n\":\"搞笑\"},{\"v\":\"63\",\"n\":\"青春\"},{\"v\":\"64\",\"n\":\"魔幻仙侠\"},{\"v\":\"65\",\"n\":\"激燃运动\"},{\"v\":\"66\",\"n\":\"特摄\"},{\"v\":\"67\",\"n\":\"推理\"},{\"v\":\"68\",\"n\":\"亲子幼教\"},{\"v\":\"69\",\"n\":\"芒果出品\"},{\"v\":\"70\",\"n\":\"动漫音乐\"},{\"v\":\"71\",\"n\":\"经典\"},{\"v\":\"72\",\"n\":\"其他\"}],\"key\":\"kind\"},{\"name\":\"地区\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"52\",\"n\":\"内地\"},{\"v\":\"53\",\"n\":\"欧美\"},{\"v\":\"54\",\"n\":\"日韩\"},{\"v\":\"55\",\"n\":\"其他\"}],\"key\":\"area\"},{\"name\":\"版本\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"165\",\"n\":\"剧场版\"},{\"v\":\"57\",\"n\":\"TV版\"},{\"v\":\"166\",\"n\":\"OVA版\"},{\"v\":\"167\",\"n\":\"真人版\"}],\"key\":\"edition\"},{\"name\":\"排序\",\"value\":[{\"v\":\"c2\",\"n\":\"最热\"},{\"v\":\"c1\",\"n\":\"最新\"}],\"key\":\"sort\"}],\"51\":[{\"name\":\"类型\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"97\",\"n\":\"美食\"},{\"v\":\"98\",\"n\":\"文化\"},{\"v\":\"99\",\"n\":\"社会\"},{\"v\":\"100\",\"n\":\"历史\"},{\"v\":\"101\",\"n\":\"军事\"},{\"v\":\"102\",\"n\":\"人物\"},{\"v\":\"103\",\"n\":\"探索\"},{\"v\":\"104\",\"n\":\"自然\"},{\"v\":\"105\",\"n\":\"其他\"}],\"key\":\"kind\"},{\"name\":\"排序\",\"value\":[{\"v\":\"c2\",\"n\":\"最热\"},{\"v\":\"c1\",\"n\":\"最新\"}],\"key\":\"sort\"}],\"20\":[{\"name\":\"类型\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"150\",\"n\":\"MV\"},{\"v\":\"151\",\"n\":\"影视原声\"},{\"v\":\"152\",\"n\":\"音乐节目\"},{\"v\":\"153\",\"n\":\"演唱会\"},{\"v\":\"154\",\"n\":\"颁奖礼\"},{\"v\":\"155\",\"n\":\"音乐现场\"},{\"v\":\"156\",\"n\":\"其他\"}],\"key\":\"kind\"},{\"name\":\"风格\",\"value\":[{\"v\":\"a1\",\"n\":\"全部\"},{\"v\":\"157\",\"n\":\"流行\"},{\"v\":\"158\",\"n\":\"Hip-hop\"},{\"v\":\"159\",\"n\":\"R&B\"},{\"v\":\"160\",\"n\":\"摇滚\"},{\"v\":\"161\",\"n\":\"民谣\"},{\"v\":\"162\",\"n\":\"爵士\"},{\"v\":\"163\",\"n\":\"古典\"},{\"v\":\"164\",\"n\":\"其他\"}],\"key\":\"musicStyle\"},{\"name\":\"排序\",\"value\":[{\"v\":\"c1\",\"n\":\"最新\"},{\"v\":\"c2\",\"n\":\"最热\"}],\"key\":\"sort\"}]}"); + } 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", "https://www.mgtv.com" + 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://mobileso.bz.mgtv.com/pc/search/v1?allowedRC=1&q=" + str + "&pn=1&pc=10&uid=&corr=1&_support=10000000"; + String json = OkHttpUtil.string(url, getHeaders(url)); + JSONObject data = new JSONObject(json).getJSONObject("data"); + JSONArray contents = data.getJSONArray("contents"); + JSONArray items = new JSONArray(); + for (int i = 0; i < contents.length(); i++) { + JSONObject jSONObject = contents.getJSONObject(i).getJSONObject("data"); + if (!jSONObject.has("sourceList")) { + continue; + } + JSONArray sourceList = jSONObject.getJSONArray("sourceList"); + String vodUrl = sourceList.getJSONObject(0).getString("url"); + String vodId = sourceList.getJSONObject(0).getString("vid"); + String pic = jSONObject.optString("pic"); + JSONObject item = new JSONObject(); + item.put("vod_id", vodId); + item.put("vod_name", jSONObject.optString("title")); + item.put("vod_pic", pic); + item.put("vod_remarks", jSONObject.optString("playTime")); + items.put(item); + } + JSONObject result = new JSONObject(); + result.put("list", items); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } +} diff --git a/app/src/main/java/com/github/catvod/spider/MixWeb.java b/app/src/main/java/com/github/catvod/spider/MixWeb.java new file mode 100644 index 0000000..a050d75 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/MixWeb.java @@ -0,0 +1,178 @@ +package com.github.catvod.parser; + +import android.util.Base64; +import com.github.catvod.crawler.SpiderDebug; +import com.github.catvod.utils.Misc; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.ByteArrayInputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; + +public class MixWeb { + + /* + "parses": [ + { + "name": "聚合", + "type": 3, + "url": "Demo" + }, + { + "name": "解析", + "type": 1, + "url": "https://192.168.10.88/jx.php?url=", + "ext": { + "flag": [ + "qq", + "iqiyi", + "qiyi", + "爱奇艺", + "腾讯", + "letv", + "sohu", + "tudou", + "pptv", + "mgtv", + "wasu", + "bilibili" + ] + } + }] + */ + + public static HashMap> flagWebJx = new HashMap<>(); + + static HashMap> configs = null; + + public static JSONObject parse(LinkedHashMap> jx, String nameMe, String flag, String url) { + try { + if (configs == null) { + configs = new HashMap<>(); + Iterator keys = jx.keySet().iterator(); + while (keys.hasNext()) { + String key = keys.next(); + HashMap parseBean = jx.get(key); + String type = parseBean.get("type"); + if (type.equals("0")) { + try { + //取出单个解析的flags列表 + JSONArray flags = new JSONObject(parseBean.get("ext")).getJSONArray("flag"); + for (int j = 0; j < flags.length(); j++) { + //获取单个flags + String flagKey = flags.getString(j); + //取出configs中对应flags的解析 + ArrayList flagJx = configs.get(flagKey); + //如果configs中没有这个flags,则插入一个空的值 + if (flagJx == null) { + flagJx = new ArrayList<>(); + configs.put(flagKey, flagJx); + } + //如果有就在flagJx中增加解析 + flagJx.add(key); + } + } catch (Throwable th) { + + } + } + } + } + // 通过上面的配置获得解析列表 + ArrayList webJx = new ArrayList<>(); + ArrayList flagJx = configs.get(flag); + //如果flagJx不为空 + if (flagJx != null && !flagJx.isEmpty()) { + for (int i = 0; i < flagJx.size(); i++) { + String key = flagJx.get(i); + HashMap parseBean = jx.get(key); + String type = parseBean.get("type"); + if (type.equals("0")) { + //将json解析放入webJx + webJx.add(parseBean.get("url")); + } + } + } else { + Iterator keys = jx.keySet().iterator(); + while (keys.hasNext()) { + String key = keys.next(); + HashMap parseBean = jx.get(key); + String type = parseBean.get("type"); + if (type.equals("0")) { + webJx.add(parseBean.get("url")); + } + } + } + if (!webJx.isEmpty()) { + flagWebJx.put(flag, webJx); + } + + // json解析没有得到结果 用webview解析 + if (!webJx.isEmpty()) { + JSONObject webResult = new JSONObject(); + webResult.put("url", "proxy://do=MixWeb&flag=" + flag + "&url=" + Base64.encodeToString(url.getBytes(), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP)); + webResult.put("parse", 1); + webResult.put("ua", Misc.UaWinChrome); + return webResult; + } + } catch (Throwable th) { + SpiderDebug.log(th); + } + return new JSONObject(); + } + + + public static Object[] loadHtml(String flag, String url) { + try { + url = new String(Base64.decode(url, Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP), "UTF-8"); + String html = "\n" + + "\n" + + "\n" + + "\n" + + "解析\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + ""; + + StringBuilder jxs = new StringBuilder(); + if (flagWebJx.containsKey(flag)) { + ArrayList jxUrls = flagWebJx.get(flag); + for (int i = 0; i < jxUrls.size(); i++) { + jxs.append("\""); + jxs.append(jxUrls.get(i)); + jxs.append("\""); + if (i < jxUrls.size() - 1) { + jxs.append(","); + } + } + } + html = html.replace("#url#", url).replace("#jxs#", jxs.toString()); + Object[] result = new Object[3]; + result[0] = 200; + result[1] = "text/html; charset=\"UTF-8\""; + ByteArrayInputStream baos = new ByteArrayInputStream(html.toString().getBytes("UTF-8")); + result[2] = baos; + return result; + } catch (Throwable th) { + th.printStackTrace(); + } + return null; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/N0ys.java b/app/src/main/java/com/github/catvod/spider/N0ys.java new file mode 100644 index 0000000..4e63721 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/N0ys.java @@ -0,0 +1,471 @@ +package com.github.catvod.spider; + +import android.content.Context; +import android.net.Uri; +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; + +/** + * 90影视 + *

+ * Author: 小黄瓜 + */ +public class N0ys extends Spider { + private static final String siteUrl = "http://1090ys8.com"; + private static final String siteHost = "1090ys8.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 Pattern regexCategory = Pattern.compile("/whole/(\\w+).html"); + private Pattern regexVid = Pattern.compile("/show/(\\w+).html"); + private Pattern regexPlay = Pattern.compile("/play/(\\w+)-(\\d+)-(\\d+).html"); + private Pattern regexPage = Pattern.compile("/whole/\\d+/page/(\\d+).html"); + + @Override + public void init(Context context) { + super.init(context); + try { + playerConfig = new JSONObject("{\"youbo\":{\"sh\":\"高速1\",\"sn\":\"0\",\"pu\":\"http://jx1090ys5.hongfanedu.top/x2.php?id=\",\"or\":999},\"wanpan\":{\"sh\":\"高速备用\",\"sn\":\"0\",\"pu\":\"\",\"or\":999},\"niuxyun\":{\"sh\":\"高速2\",\"sn\":\"1\",\"pu\":\"http://1090ys2.com/nxjx/jx.php?id=\",\"or\":999},\"bjm3u8\":{\"sh\":\"备用2\",\"sn\":\"0\",\"pu\":\"\",\"or\":999},\"dbm3u8\":{\"sh\":\"备用3\",\"sn\":\"0\",\"pu\":\"\",\"or\":999},\"nfmp4\":{\"sh\":\"高速3\",\"sn\":\"0\",\"pu\":\"\",\"or\":999},\"tkm3u8\":{\"sh\":\"备用1\",\"sn\":\"0\",\"pu\":\"\",\"or\":999},\"wjm3u8\":{\"sh\":\"备用4\",\"sn\":\"0\",\"pu\":\"\",\"or\":999}}"); + } 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.type-slide > li a"); + JSONArray classes = new JSONArray(); + for (Element ele : elements) { + String name = ele.text(); + 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(); + 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 { + // 获取分类数据的url + String url = siteUrl + "/whole/" + tid + "/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(".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)); + } else { + page = 0; + } + } + 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("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", 30); + result.put("total", pageCount <= 1 ? videos.length() : pageCount * 30); + + 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 + "/show/" + 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("a.stui-vodlist__thumb img").attr("data-original"); + String title = doc.selectFirst("a.stui-vodlist__thumb").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.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.nextSibling().outerHtml().trim(); + } 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("导演:")) { + director = text.nextSibling().outerHtml().trim(); + } else if (info.equals("主演:")) { + actor = text.nextSibling().outerHtml().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.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 = "http://1090ys8.com/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"); + String from = player.getString("from"); + if (from.equals("youbo")) { + // 感谢猫大神的直连解密代码 + HashMap hds = getHeaders(url); + hds.put("Host", "jx1090ys5.hongfanedu.top"); + hds.put("Referer", url); + String content1 = OkHttpUtil.string(playUrl + videoUrl, hds); + Document doc1 = Jsoup.parse(content1); + String url2 = doc1.selectFirst("iframe#WANG").attr("src"); + String url2host = Uri.parse(url2).getHost(); + hds.put("Host", url2host); + hds.put("Referer", "http://jx1090ys5.hongfanedu.top/"); + 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 = "http://" + url2host + "/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", "{\"Referer\":\" " + url2 + "\"}"); + } 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) { + try { + 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/Nekk.java b/app/src/main/java/com/github/catvod/spider/Nekk.java new file mode 100644 index 0000000..1c21002 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Nekk.java @@ -0,0 +1,489 @@ +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.io.UnsupportedEncodingException; +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 okhttp3.Call; +import okhttp3.Headers; +import okhttp3.Response; + + +public class Nekk extends Spider { + + private static final String siteUrl = "https://www.9ela.com"; + private static final String siteHost = "www.9ela.com"; + + protected JSONObject playerConfig; + protected JSONObject filterConfig; + + protected Pattern regexCategory = Pattern.compile("/vodshow/(\\S+).html"); + protected Pattern regexVid = Pattern.compile("/voddetail/(\\d+).html"); + protected Pattern regexPlay = Pattern.compile("/vodplay/(\\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("{\"9ekk\":{\"sh\":\"手机线路\",\"sn\":0,\"pu\":\"\",\"or\":999},\"ttee\":{\"sh\":\"9亿超清\",\"sn\":0,\"pu\":\"\",\"or\":999},\"9999ku\":{\"sh\":\"手机线路2\",\"sn\":0,\"pu\":\"\",\"or\":999},\"gsyun\":{\"sh\":\"九亿超清\",\"sn\":0,\"pu\":\"\",\"or\":999},\"kkyun\":{\"sh\":\"HD超清线路\",\"sn\":0,\"pu\":\"\",\"or\":999},\"ty01\":{\"sh\":\"超清线路\",\"sn\":0,\"pu\":\"\",\"or\":999},\"ppayun\":{\"sh\":\"九亿线路\",\"sn\":0,\"pu\":\"https://wy.mlkioiy.cn/api/GetDownUrlWy/d91ea50eb7eb4932b92aa8bb3c61560d/\",\"or\":999},\"8kdm\":{\"sh\":\"九亿动漫\",\"sn\":0,\"pu\":\"\",\"or\":999},\"jsyun\":{\"sh\":\"九亿备用\",\"sn\":0,\"pu\":\"\",\"or\":999},\"9evip\":{\"sh\":\"九亿解析-弃用\",\"sn\":0,\"pu\":\"\",\"or\":999},\"189pan\":{\"sh\":\"九亿超清11\",\"sn\":0,\"pu\":\"http://1987s.com/api/dp.php?url=\",\"or\":999},\"VIP\":{\"sh\":\"VIP线路\",\"sn\":0,\"pu\":\"\",\"or\":999},\"qq\":{\"sh\":\"九亿解析\",\"sn\":1,\"pu\":\"\",\"or\":999},\"mgtv\":{\"sh\":\"九亿解析\",\"sn\":1,\"pu\":\"\",\"or\":999},\"bjm3u8\":{\"sh\":\"线路三\",\"sn\":0,\"pu\":\"\",\"or\":999},\"dbm3u8\":{\"sh\":\"线路四\",\"sn\":0,\"pu\":\"\",\"or\":999},\"ckm3u8\":{\"sh\":\"线路二\",\"sn\":0,\"pu\":\"\",\"or\":999},\"mahua\":{\"sh\":\"线路四\",\"sn\":0,\"pu\":\"\",\"or\":999},\"123kum3u8\":{\"sh\":\"123kum3u8\",\"sn\":1,\"pu\":\"https://jx.123ku.com/123kudpbfq/?url=\",\"or\":999},\"pqc\":{\"sh\":\"测试\",\"sn\":1,\"pu\":\"https://jx.qiuzeqi.top/jx1/dp/index.php?url=\",\"or\":999},\"test\":{\"sh\":\"test\",\"sn\":1,\"pu\":\"https//1987s.com/api/dp.php?url=\",\"or\":999}}"); + filterConfig = new JSONObject("{\"dianying\":[{\"key\":\"tid\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语配音电影\",\"v\":\"gypy\"},{\"n\":\"最近热播电影\",\"v\":\"zuijinrebodianying\"},{\"n\":\"动作片\",\"v\":\"dongzuopian\"},{\"n\":\"喜剧片\",\"v\":\"xijupian\"},{\"n\":\"爱情片\",\"v\":\"aiqingpian\"},{\"n\":\"科幻片\",\"v\":\"kehuanpian\"},{\"n\":\"恐怖片\",\"v\":\"kongbupian\"},{\"n\":\"剧情片\",\"v\":\"juqingpian\"},{\"n\":\"战争片\",\"v\":\"zhanzhengpian\"}]},{\"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\":\"其他\"},{\"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\"}]}],\"lianxuju\":[{\"key\":\"tid\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"最近热播电视剧\",\"v\":\"zuijinrebodianshiju\"},{\"n\":\"国语配音剧集\",\"v\":\"guoyupeiyinhanju\"},{\"n\":\"热播美剧\",\"v\":\"rebomeiju\"},{\"n\":\"电视剧\",\"v\":\"guochanju\"},{\"n\":\"港台剧\",\"v\":\"gangtaiju\"},{\"n\":\"日韩剧\",\"v\":\"rihanju\"},{\"n\":\"欧美剧\",\"v\":\"oumeiju\"}]},{\"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\":\"其他\"}]},{\"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\":\"其他\"}]},{\"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\"}]}],\"zongyi\":[{\"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\"}]}],\"dongman\":[{\"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 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 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; + } + + + @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-list > 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; + 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 = fixCover(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 ""; + } + + @Override + public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { + try { + String url = siteUrl + "/vodshow/"; + 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 = fixCover(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 ""; + } + + @Override + public String detailContent(List ids) { + try { + String url = siteUrl + "/voddetail/" + 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 = fixCover(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 ""; + } + + @Override + public String playerContent(String flag, String id, List vipFlags) { + try { + String url = siteUrl + "/vodplay/" + 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"); + if (player.has("encrypt")) { + int encrypt = player.getInt("encrypt"); + if (encrypt == 1) { + videoUrl = URLDecoder.decode(videoUrl); + } else if (encrypt == 2) { + videoUrl = new String(Base64.decode(videoUrl, Base64.DEFAULT)); + videoUrl = URLDecoder.decode(videoUrl); + } + } + String playUrl = pCfg.getString("pu"); + result.put("parse", pCfg.getInt("sn")); + result.put("playUrl", playUrl); + result.put("url", videoUrl); + if (flag.equals("9ekk")) { + JSONObject headers = new JSONObject(); + headers.put("User-Agent", " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36"); + headers.put("Accept", " */*"); + headers.put("Connection", " keep-alive"); + result.put("header", headers.toString()); + } else { + result.put("header", ""); + } + } + 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 = fixCover(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 fixCover(String cover) { + try { + return "proxy://do=nekk&pic=" + Base64.encodeToString(cover.getBytes("UTF-8"), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return cover; + } + + private static HashMap nekkPicHeader = null; + + public static Object[] loadPic(String pic) { + try { + pic = new String(Base64.decode(pic, Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP), "UTF-8"); + + if (nekkPicHeader == null) { + nekkPicHeader = new HashMap<>(); + nekkPicHeader.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36"); + nekkPicHeader.put("referer", siteUrl + "/"); + } + OKCallBack.OKCallBackDefault callBack = new OKCallBack.OKCallBackDefault() { + @Override + protected void onFailure(Call call, Exception e) { + + } + + @Override + protected void onResponse(Response response) { + + } + }; + OkHttpUtil.get(OkHttpUtil.defaultClient(), pic, null, nekkPicHeader, 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; + System.out.println(pic); + System.out.println(type); + result[2] = callBack.getResult().body().byteStream(); + return result; + } + } catch (Throwable th) { + th.printStackTrace(); + } + return null; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/NewXPath.java b/app/src/main/java/com/github/catvod/spider/NewXPath.java new file mode 100644 index 0000000..5165724 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/NewXPath.java @@ -0,0 +1,474 @@ +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 com.github.catvod.xpath.XPathRule; + +import org.json.JSONArray; +import org.json.JSONObject; +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 NewXPath extends Spider { + + + @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(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(e); + } + } + } catch (Exception e) { + SpiderDebug.log(e); + } + result.put("class", classes); + if (filter && rule.getFilter() != null) { + result.put("filters", rule.getFilter()); + } + return result.toString(); + } catch ( + Exception e) { + SpiderDebug.log(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(e); + } + return ""; + } + + protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) { + return rule.getCateUrl().replace("{cateId}", tid).replace("{catePg}", pg); + } + + @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(e); + } + } + JSONObject v = new JSONObject(); + v.put("vod_id", name + "$$$" + pic + "$$$" + 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(e); + } + return ""; + } + + protected void detailContentExt(String content, JSONObject vod) { + + } + + @Override + public String detailContent(List ids) { + try { + fetchRule(); + String[] idInfo = ids.get(0).split("\\$\\$\\$"); + System.out.println(ids.get(0)); + String webUrl = rule.getDetailUrl().replace("{vid}", idInfo[2]); + + String webContent = fetch(webUrl); + JXDocument doc = JXDocument.create(webContent); + JXNode vodNode = doc.selNOne(rule.getDetailNode()); + + String cover = idInfo[1], title = idInfo[0], desc = "", category = "", area = "", year = "", remark = "", director = "", actor = ""; + + + 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", idInfo[2]); + 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<>(); + 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); + 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(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(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", name + "$$$" + pic + "$$$" + 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(e); + } + } + JSONObject v = new JSONObject(); + v.put("vod_id", name + "$$$" + pic + "$$$" + 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(e); + } + return ""; + } + + @Override + public boolean manualVideoCheck() { + return false; + } + + private String[] videoFormatList = new String[]{".m3u8", ".mp4", ".mpeg", ".flv", ".mp3", ".m4a"}; + + + @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(webUrl); + return OkHttpUtil.string(webUrl, getHeaders(webUrl)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/Nfx.java b/app/src/main/java/com/github/catvod/spider/Nfx.java new file mode 100644 index 0000000..ed70d51 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Nfx.java @@ -0,0 +1,449 @@ +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 Nfx extends Spider { + + private static final String siteUrl = "https://nfxhd.com/"; + private static final String siteHost = "nfxhd.com"; + + protected JSONObject playerConfig; + + protected Pattern regexCategory = Pattern.compile("/vodtype/(\\w+)/"); + protected Pattern regexVid = Pattern.compile("/voddetail/(\\w+)/"); + protected Pattern regexPlay = Pattern.compile("/vodplay/(\\w+)-(\\d+)-(\\d+)/"); + protected Pattern regexPage = Pattern.compile("/vodshow/(\\S+)/"); + + @Override + public void init(Context context) { + super.init(context); + try { + playerConfig = new JSONObject("{\"adaplay\":{\"sh\":\"菜逼播放器\",\"sn\":\"1\",\"pu\":\"https://nfxhd.com/dp.php/?url=\",\"or\":999},\"xigua\":{\"sh\":\"手动点播放才能播放的播放器\",\"sn\":\"1\",\"pu\":\"https://nfxhd.com/dp.php/?url=\",\"or\":999},\"danmuku\":{\"sh\":\"海王播放器\",\"sn\":\"1\",\"pu\":\"\",\"or\":999},\"dplayer\":{\"sh\":\"冥王星播放器\",\"sn\":\"0\",\"pu\":\"\",\"or\":999},\"bdxm3u8\":{\"sh\":\"北斗星m3u8\",\"sn\":\"1\",\"pu\":\"https://player.bdxzym3u8.com/dplayer/?url=\",\"or\":999},\"bdxyun\":{\"sh\":\"北斗星云播放\",\"sn\":\"1\",\"pu\":\"\",\"or\":999},\"gangtiexia\":{\"sh\":\"土星播放器\",\"sn\":\"1\",\"pu\":\"https://wy.bigmao.top/api/ShowVideoWy/3bb24322f78b47dfb8723c13d46d45ee/\",\"or\":999},\"tt10\":{\"sh\":\"木星播放器\",\"sn\":\"1\",\"pu\":\"https://wy.bigmao.top/api/ShowVideoMu/3bb24322f78b47dfb8723c13d46d45ee/\",\"or\":999},\"docker\":{\"sh\":\"彗星播放器\",\"sn\":\"1\",\"pu\":\"https://wy.bigmao.top/api/ShowVideoDoc/3bb24322f78b47dfb8723c13d46d45ee/\",\"or\":999},\"qq\":{\"sh\":\"腾讯视频\",\"sn\":\"1\",\"pu\":\"\",\"or\":999},\"youku\":{\"sh\":\"优酷\",\"sn\":\"1\",\"pu\":\"\",\"or\":999},\"qiyi\":{\"sh\":\"爱奇艺\",\"sn\":\"1\",\"pu\":\"\",\"or\":999},\"mgtv\":{\"sh\":\"仅限APP播放\",\"sn\":\"1\",\"pu\":\"\",\"or\":999},\"m3u8\":{\"sh\":\"m3u8\",\"sn\":\"1\",\"pu\":\"\",\"or\":999},\"mx771\":{\"sh\":\"站长采集的播放器\",\"sn\":\"0\",\"pu\":\"\",\"or\":999},\"ppayun2\":{\"sh\":\"白鸟座播放器\",\"sn\":\"1\",\"pu\":\"https://wy.bigmao.top/api/ShowVideoMu/3bb24322f78b47dfb8723c13d46d45ee/\",\"or\":999},\"sohu\":{\"sh\":\"搜狐\",\"sn\":\"1\",\"pu\":\"\",\"or\":999},\"iframe\":{\"sh\":\"iframe外链数据\",\"sn\":\"0\",\"pu\":\"\",\"or\":999}}"); + } 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(); + result.put("class", classes); + try { + // 取首页推荐视频列表 + Elements list = doc.select("ul.myui-vodlist>li>div"); + 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 { + // 获取分类数据的url + String url = siteUrl + "/vodtype/" + tid + "-" + pg + "/"; + 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("div.myui-panel_bd>ul>li>div"); + 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 + "/voddetail/" + ids.get(0) + "/"; + 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 = doc.selectFirst("div.col-pd>span.sketch").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()); + } + } 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").get(1).select("h3"); + Elements sourceList = doc.select("ul.myui-content__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("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 { + //定义播放用的headers + JSONObject headers = new JSONObject(); + //headers.put("Host", " cokemv.co"); + headers.put("origin", " https://nfxhd.com"); + 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 + "/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"); + 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/Proxy.java b/app/src/main/java/com/github/catvod/spider/Proxy.java index fd3a0bd..93f073b 100644 --- a/app/src/main/java/com/github/catvod/spider/Proxy.java +++ b/app/src/main/java/com/github/catvod/spider/Proxy.java @@ -6,6 +6,8 @@ import com.github.catvod.crawler.Spider; import com.github.catvod.crawler.SpiderDebug; import com.github.catvod.live.TxtSubscribe; import com.github.catvod.utils.okhttp.OkHttpUtil; +import com.github.catvod.parser.MixDemo; +import com.github.catvod.parser.MixWeb; import java.io.ByteArrayInputStream; import java.util.Map; @@ -55,8 +57,19 @@ public class Proxy extends Spider { return result; } else if (what.equals("push")) { return PushAgent.vod(params); + } else if (what.equals("kmys")) { + return Kmys.vod(params); + } else if (what.equals("ali")) { + return PushAgent.vod(params); } else if (what.equals("czspp")) { return Czsapp.loadsub(params.get("url")); + } else if (what.equals("XYQBiu")) { + return XYQBiu.loadPic(params); + } else if (what.equals("MixDemo")) { + return MixDemo.loadHtml(params.get("flag"), params.get("url")); + } + else if (what.equals("MixWeb")) { + return MixWeb.loadHtml(params.get("flag"), params.get("url")); } } catch (Throwable th) { @@ -65,4 +78,4 @@ public class Proxy extends Spider { return null; } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/github/catvod/spider/PushAgent.java b/app/src/main/java/com/github/catvod/spider/PushAgent.java index 1e34978..b1f08f6 100644 --- a/app/src/main/java/com/github/catvod/spider/PushAgent.java +++ b/app/src/main/java/com/github/catvod/spider/PushAgent.java @@ -1,656 +1,660 @@ -package com.github.catvod.spider; - -import android.content.Context; -import android.net.UrlQuerySanitizer; -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.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.ByteArrayInputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.locks.ReentrantLock; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import okhttp3.Call; -import okhttp3.OkHttpClient; -import okhttp3.Response; -import okhttp3.ResponseBody; - -public class PushAgent extends Spider { - - private static String j = ""; - private static long StopRefresh; - private static final Map l = new HashMap(); - private static final Map q = new HashMap(); - private static final Map> dizz = new HashMap(); - private static final ReentrantLock ReentrantLock = new ReentrantLock(); - private static final long n = 0; - private static final String SiteUrl = "https://api.aliyundrive.com"; - private static final Pattern AliPLink = Pattern.compile("(https://www.aliyundrive.com/s/[^\"]+)"); - public static Pattern Folder = Pattern.compile("www.aliyundrive.com/s/([^/]+)(/folder/([^/]+))?"); - public static String Token; - - @Override - public void init(Context context, String extend) { - super.init(context, extend); - if (extend.startsWith("http")) { - Token = OkHttpUtil.string(extend, null); - } else { - Token = extend; - } - } - - protected static long Time() { - return (System.currentTimeMillis() / 1000) + n; - } - - public static Object[] ProxyMedia(Map map) { - try { - String ShareId = map.get("share_id"); - String FileId = map.get("file_id"); - String MediaId = map.get("media_id"); - String Token = getShareTk(ShareId, ""); - ReentrantLock.lock(); - String str4 = dizz.get(FileId).get(MediaId); - UrlQuerySanitizer urlQuerySanitizer = new UrlQuerySanitizer(str4); - Long l2 = new Long(urlQuerySanitizer.getValue("x-oss-expires")); - long longValue = l2.longValue(); - if (longValue - Time() <= 60) { - VideoDetail(ShareId, Token, FileId); - Map> map3 = dizz; - str4 = map3.get(FileId).get(MediaId); - } - ReentrantLock.unlock(); - new HashMap(); - OKCallBack.OKCallBackDefault abVar = new OKCallBack.OKCallBackDefault() { - public void onResponse(Response response) { - } - - @Override - protected void onFailure(Call call, Exception exc) { - } - }; - OkHttpClient YM = OkHttpUtil.defaultClient(); - HashMap t = Headers(); - OkHttpUtil.get(YM, str4, null, t, abVar); - ResponseBody body = abVar.getResult().body(); - return new Object[]{200, "video/MP2T", body.byteStream()}; - } catch (Exception e) { - SpiderDebug.log(e); - return null; - } - } - - public static Object[] vod(Map map) { - String str = map.get("type"); - if (str.equals("m3u8")) { - return getFile(map); - } - if (str.equals("media")) { - return ProxyMedia(map); - } - return null; - } - - - public static Object[] getFile(Map map) { - try { - String ShareId = map.get("share_id"); - String ShareTK = getShareTk(ShareId, ""); - return new Object[]{200, "application/octet-stream", new ByteArrayInputStream(VideoDetail(ShareId, ShareTK, map.get("file_id")).getBytes())}; - } catch (Exception e) { - SpiderDebug.log(e); - return null; - } - } - - private static String Post(String str, String str2, Map map) { - OKCallBack.OKCallBackString acVar = new OKCallBack.OKCallBackString() { - - public void onResponse(String r) { - } - - @Override - protected void onFailure(Call call, Exception exc) { - } - }; - OkHttpClient YM = OkHttpUtil.defaultClient(); - OkHttpUtil.postJson(YM, str, str2, map, acVar); - return acVar.getResult(); - } - - private static synchronized String getShareTk(String str, String str2) { - - try { - long b = Time(); - Map map = l; - String str3 = map.get(str); - Long l2 = q.get(str); - if (!TextUtils.isEmpty(str3)) { - if (l2 - b > 600) { - return str3; - } - } - JSONObject jSONObject = new JSONObject(); - jSONObject.put("share_id", str); - jSONObject.put("share_pwd", str2); - String jSONObject2 = jSONObject.toString(); - JSONObject jSONObject3 = new JSONObject(Post("https://api.aliyundrive.com/v2/share_link/get_share_token", jSONObject2, Headers())); - String string = jSONObject3.getString("share_token"); - Long valueOf = Long.valueOf(b + jSONObject3.getLong("expires_in")); - Map map2 = q; - map2.put(str, valueOf); - Map map3 = l; - map3.put(str, string); - return string; - } catch (Exception e) { - SpiderDebug.log(e); - return ""; - } - - } - - - private static HashMap Headers() { - HashMap headers = new HashMap<>(); - headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36"); - headers.put("Referer", "https://www.aliyundrive.com/"); - return headers; - } - - private static HashMap sHeaders() { - HashMap headers = new HashMap<>(); - headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36"); - return headers; - } - - - private static void refreshTk() { - long b = Time(); - String str = j; - if (str.isEmpty() || StopRefresh - b <= 600) { - try { - JSONObject jSONObject = new JSONObject(); - jSONObject.put("refresh_token", Token); - String jSONObject2 = jSONObject.toString(); - HashMap t = Headers(); - JSONObject jSONObject3 = new JSONObject(Post("https://api.aliyundrive.com/token/refresh", jSONObject2, t)); - StringBuilder sb = new StringBuilder(); - String string = jSONObject3.getString("token_type"); - sb.append(string); - sb.append(" "); - String string2 = jSONObject3.getString("access_token"); - sb.append(string2); - j = sb.toString(); - long j2 = jSONObject3.getLong("expires_in"); - StopRefresh = b + j2; - } catch (Exception e) { - SpiderDebug.log(e); - } - } - } - - - private static String VideoDetail(String shareid, String token, String fileid) { - int i; - try { - String url = SiteUrl + "/v2/file/get_share_link_video_preview_play_info"; - JSONObject Data = new JSONObject(); - Data.put("share_id", shareid); - Data.put("category", "live_transcoding"); - Data.put("file_id", fileid); - Data.put("template_id", ""); - HashMap headers = Headers(); - headers.put("x-share-token", token); - String str5 = j; - headers.put("authorization", str5); - String jSONObject2 = Data.toString(); - JSONObject jSONObject3 = new JSONObject(Post(url, jSONObject2, headers)); - ArrayList arrayList = new ArrayList(); - arrayList.add("FHD"); - arrayList.add("HD"); - arrayList.add("SD"); - JSONObject jSONObject4 = jSONObject3.getJSONObject("video_preview_play_info"); - JSONArray jSONArray = jSONObject4.getJSONArray("live_transcoding_task_list"); - Iterator it = arrayList.iterator(); - String objectUrl = ""; - while (true) { - boolean hasNext = it.hasNext(); - i = 0; - if (!hasNext) { - break; - } - String str7 = (String) it.next(); - if (!objectUrl.isEmpty()) { - break; - } - while (true) { - if (i < jSONArray.length()) { - JSONObject jSONObject5 = jSONArray.getJSONObject(i); - String string = jSONObject5.getString("template_id"); - if (string.equals(str7)) { - objectUrl = jSONObject5.getString("url"); - break; - } - i++; - } - } - } - if (TextUtils.isEmpty(objectUrl)) { - JSONObject jSONObject6 = jSONArray.getJSONObject(0); - objectUrl = jSONObject6.getString("url"); - } - HashMap hashMap = new HashMap(); - HashMap header = Headers(); - OkHttpUtil.stringNoRedirect(objectUrl, header, hashMap); - String d = OkHttpUtil.getRedirectLocation(hashMap); - String i2 = OkHttpUtil.string(d, Headers()); - String substring = d.substring(0, d.lastIndexOf("/")) + "/"; - ArrayList arrayList2 = new ArrayList(); - HashMap hashMap2 = new HashMap(); - String[] split = i2.split("\n"); - int length = split.length; - int i3 = 0; - while (i < length) { - String str8 = split[i]; - if (str8.contains("x-oss-expires")) { - i3++; - String sb6 = substring + str8; - String sb8 = "" + i3; - hashMap2.put(sb8, sb6); - str8 = Proxy.localProxyUrl() + "?do=push&type=media&share_id=" + shareid + "&file_id=" + fileid + "&media_id=" + i3; - } - arrayList2.add(str8); - i++; - } - dizz.put(fileid, hashMap2); - return TextUtils.join("\n", arrayList2); - } catch (Exception e) { - SpiderDebug.log(e); - return ""; - } - } - - public void listFiles(Map map, String str, String str2, String str3) { - String str4; - try { - String str5 = "https://api.aliyundrive.com/adrive/v3/file/list"; - HashMap Y2 = Headers(); - Y2.put("x-share-token", str2); - JSONObject jSONObject = new JSONObject(); - jSONObject.put("image_thumbnail_process", "image/resize,w_160/format,jpeg"); - jSONObject.put("image_url_process", "image/resize,w_1920/format,jpeg"); - jSONObject.put("limit", 200); - jSONObject.put("order_by", "updated_at"); - jSONObject.put("order_direction", "DESC"); - jSONObject.put("parent_file_id", str3); - jSONObject.put("share_id", str); - jSONObject.put("video_thumbnail_process", "video/snapshot,t_1000,f_jpg,ar_auto,w_300"); - String str6 = ""; - ArrayList arrayList = new ArrayList(); - for (int i = 1; i <= 50 && (i < 2 || !TextUtils.isEmpty(str6)); i++) { - jSONObject.put("marker", str6); - JSONObject jSONObject2 = new JSONObject(Post(str5, jSONObject.toString(), Y2)); - JSONArray jSONArray = jSONObject2.getJSONArray("items"); - int i2 = 0; - while (i2 < jSONArray.length()) { - JSONObject jSONObject3 = jSONArray.getJSONObject(i2); - if (jSONObject3.getString("type").equals("folder")) { - arrayList.add(jSONObject3.getString("file_id")); - str4 = str5; - } else { - str4 = str5; - if (jSONObject3.getString("mime_type").contains("video")) { - String replace = jSONObject3.getString("name").replace("#", "_").replace("$", "_"); - if (replace.length() > 20) { - replace = replace.substring(0, 10) + "..." + replace.substring(replace.length() - 10); - } - String fileIds = jSONObject3.getString("file_id"); - map.put(replace, str + "+" + str2 + "+" + fileIds); - } - } - i2++; - str5 = str4; - } - str6 = jSONObject2.getString("next_marker"); - } - for (String str7 : arrayList) { - try { - listFiles(map, str, str2, str7); - } catch (Exception e) { - SpiderDebug.log(e); - return; - } - } - } catch (Exception e) { - SpiderDebug.log(e); - } - } - - public String getAliContent(List list) { - String str; - try { - String url = list.get(0).trim(); - Pattern pattern = Folder; - Matcher matcher = pattern.matcher(url); - if (!matcher.find()) { - return ""; - } - String group = matcher.group(1); - if (matcher.groupCount() == 3) { - str = matcher.group(3); - } else { - str = ""; - } - String AnonymousUrl = SiteUrl + "/adrive/v3/share_link/get_share_by_anonymous"; - JSONObject Data = new JSONObject(); - Data.put("share_id", group); - HashMap headers = Headers(); - JSONObject jSONObject3 = new JSONObject(Post(AnonymousUrl, Data.toString(), headers)); - JSONArray jSONArray = jSONObject3.getJSONArray("file_infos"); - if (jSONArray.length() == 0) { - return ""; - } - JSONObject jSONObject4 = null; - boolean isEmpty = TextUtils.isEmpty(str); - if (!isEmpty) { - int i = 0; - while (true) { - if (i >= jSONArray.length()) { - break; - } - JSONObject jSONObject5 = jSONArray.getJSONObject(i); - String string = jSONObject5.getString("file_id"); - String string2 = jSONObject5.getString("file_id"); - if (string.equals(string2)) { - jSONObject4 = jSONObject5; - break; - } - i++; - } - if (jSONObject4 == null) { - return ""; - } - } else { - jSONObject4 = jSONArray.getJSONObject(0); - str = jSONObject4.getString("file_id"); - } - JSONObject jSONObject6 = new JSONObject(); - jSONObject6.put("vod_id", url); - String string3 = jSONObject3.getString("share_name"); - jSONObject6.put("vod_name", string3); - jSONObject6.put("vod_pic", jSONObject3.getString("avatar")); - jSONObject6.put("vod_content", url); - jSONObject6.put("vod_play_from", "AliYun"); - ArrayList arrayList = new ArrayList(); - String string4 = jSONObject4.getString("type"); - if (!string4.equals("folder")) { - String string5 = jSONObject4.getString("type"); - if (string5.equals("file")) { - String string6 = jSONObject4.getString("category"); - if (string6.equals("video")) { - str = "root"; - } - } - return ""; - } - - String s = getShareTk(group, ""); - Map hashMap = new HashMap<>(); - listFiles(hashMap, group, s, str); - ArrayList arrayList2 = new ArrayList(hashMap.keySet()); - Collections.sort(arrayList2); - Iterator it = arrayList2.iterator(); - while (true) { - if (!it.hasNext()) { - break; - } - String str3 = (String) it.next(); - String sb4 = str3 + "$" + hashMap.get(str3); - arrayList.add(sb4); - } - ArrayList arrayList3 = new ArrayList(); - for (int i2 = 0; i2 < 4; i2++) { - String join = TextUtils.join("#", arrayList); - arrayList3.add(join); - } - String join2 = TextUtils.join("$$$", arrayList3); - jSONObject6.put("vod_play_url", join2); - JSONObject result = new JSONObject(); - JSONArray jSONArray2 = new JSONArray(); - jSONArray2.put(jSONObject6); - result.put("list", jSONArray2); - return result.toString(); - } catch (Exception e) { - SpiderDebug.log(e); - return ""; - } - } - - @Override - public String detailContent(List list) { - try { - String url = list.get(0); - Pattern pattern = Folder; - Pattern pattern2 = AliPLink; - Matcher matcher2 = pattern2.matcher(url); - Matcher matcher = pattern.matcher(url); - if (Misc.isVip(url) && !url.contains("qq.com") && !url.contains("mgtv.com")) { - Document doc = Jsoup.parse(OkHttpUtil.string(url, null)); - String VodName = doc.select("head > title").text(); - JSONObject result = new JSONObject(); - JSONArray lists = new JSONArray(); - JSONObject vodAtom = new JSONObject(); - vodAtom.put("vod_id", url); - vodAtom.put("vod_name", VodName); - vodAtom.put("vod_pic", "https://img.zcool.cn/community/0123545c74c5aea801213f261297df.png"); - vodAtom.put("type_name", "官源"); - vodAtom.put("vod_year", ""); - vodAtom.put("vod_area", ""); - vodAtom.put("vod_remarks", ""); - vodAtom.put("vod_actor", ""); - vodAtom.put("vod_director", ""); - vodAtom.put("vod_content", ""); - vodAtom.put("vod_play_from", "jx"); - vodAtom.put("vod_play_url", "立即播放$" + url); - lists.put(vodAtom); - result.put("list", lists); - return result.toString(); - } else if (Misc.isVip(url) && url.contains("qq.com")) { - List vodItems = new ArrayList<>(); - JSONObject result = new JSONObject(); - JSONArray lists = new JSONArray(); - JSONObject vodAtom = new JSONObject(); - Document doc = Jsoup.parse(OkHttpUtil.string(url, sHeaders())); - String VodName = doc.select("head > title").text(); - Elements playListA = doc.select("div.episode-list-rect__item"); - if (!playListA.isEmpty()) { - for (int j = 0; j < playListA.size(); j++) { - Element vod = playListA.get(j); - String a = vod.select("div").attr("data-vid"); - String b = vod.select("div").attr("data-cid"); - String id = "https://v.qq.com/x/cover/" + b + "/" + a; - String name = vod.select("div span").text(); - vodItems.add(name + "$" + id); - } - String playList = TextUtils.join("#", vodItems); - vodAtom.put("vod_play_url", playList); - } else { - vodAtom.put("vod_play_url", "立即播放$" + url); - } - vodAtom.put("vod_id", url); - vodAtom.put("vod_name", VodName); - vodAtom.put("vod_pic", "https://img2.baidu.com/it/u=2655029475,2190949369&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=593"); - vodAtom.put("type_name", "腾讯TV"); - vodAtom.put("vod_year", ""); - vodAtom.put("vod_area", ""); - vodAtom.put("vod_remarks", ""); - vodAtom.put("vod_actor", ""); - vodAtom.put("vod_director", ""); - vodAtom.put("vod_content", url); - vodAtom.put("vod_play_from", "jx"); - lists.put(vodAtom); - result.put("list", lists); - return result.toString(); - } else if (Misc.isVip(url) && url.contains("mgtv.com")) { - List vodItems = new ArrayList<>(); - JSONObject result = new JSONObject(); - JSONArray lists = new JSONArray(); - JSONObject vodAtom = new JSONObject(); - Pattern mgtv = Pattern.compile("https://\\S+mgtv.com/b/(\\d+)/(\\d+).html.*"); - Matcher mgtv1 = mgtv.matcher(url); - String VodNames = ""; - if (mgtv1.find()) { - String Ep = "https://pcweb.api.mgtv.com/episode/list?video_id=" + mgtv1.group(2); - JSONObject Data = new JSONObject(OkHttpUtil.string(Ep, Headers())); - VodNames = Data.getJSONObject("data").getJSONObject("info").getString("title"); - JSONArray a = new JSONArray(Data.getJSONObject("data").getString("list")); - if (a.length() > 0) { - for (int i = 0; i < a.length(); i++) { - JSONObject jObj = a.getJSONObject(i); - if (jObj.getString("isIntact").equals("1")) { - String VodName = jObj.getString("t4"); - String id = jObj.getString("video_id"); - String VodId = "https://www.mgtv.com/b/" + mgtv1.group(1) + "/" + id + ".html"; - vodItems.add(VodName + "$" + VodId); - } - } - String playList = TextUtils.join("#", vodItems); - vodAtom.put("vod_play_url", playList); - } else { - vodAtom.put("vod_play_url", "立即播放$" + url); - } - } - vodAtom.put("vod_id", url); - vodAtom.put("vod_name", VodNames); - vodAtom.put("vod_pic", "https://img2.baidu.com/it/u=2562822927,704100654&fm=253&fmt=auto&app=138&f=JPEG?w=600&h=380"); - vodAtom.put("type_name", "芒果TV"); - vodAtom.put("vod_year", ""); - vodAtom.put("vod_area", ""); - vodAtom.put("vod_remarks", ""); - vodAtom.put("vod_actor", ""); - vodAtom.put("vod_director", ""); - vodAtom.put("vod_content", url); - vodAtom.put("vod_play_from", "jx"); - lists.put(vodAtom); - result.put("list", lists); - return result.toString(); - } else if (Misc.isVideoFormat(url)) { - JSONObject result = new JSONObject(); - JSONArray lists = new JSONArray(); - JSONObject vodAtom = new JSONObject(); - vodAtom.put("vod_id", url); - vodAtom.put("vod_name", url); - vodAtom.put("vod_pic", "https://img.zcool.cn/community/0123545c74c5aea801213f261297df.png"); - vodAtom.put("type_name", "直连"); - vodAtom.put("vod_play_from", "player"); - vodAtom.put("vod_play_url", "立即播放$" + url); - lists.put(vodAtom); - result.put("list", lists); - return result.toString(); - } else if (url.startsWith("magnet")) { - String VodName = url; - if (url.length() > 100) { - VodName = url.substring(0, 30) + "..." + url.substring(url.length() - 10); - } - JSONObject result = new JSONObject(); - JSONArray lists = new JSONArray(); - JSONObject vodAtom = new JSONObject(); - vodAtom.put("vod_id", url); - vodAtom.put("vod_name", VodName); - vodAtom.put("vod_pic", "https://img2.baidu.com/it/u=1609185522,4130752057&fm=253&f=JPEG"); - vodAtom.put("type_name", "磁力"); - vodAtom.put("vod_play_from", "磁力测试"); - vodAtom.put("vod_play_url", "立即播放$" + url); - lists.put(vodAtom); - result.put("list", lists); - return result.toString(); - } else if (url.startsWith("http") && (matcher2.find())) { - return getAliContent(list); - } else if (url.startsWith("http") && (!matcher.find()) && (!matcher2.find())) { - Document doc = Jsoup.parse(OkHttpUtil.string(url, null)); - String VodName = doc.select("head > title").text(); - JSONObject result = new JSONObject(); - JSONArray lists = new JSONArray(); - JSONObject vodAtom = new JSONObject(); - vodAtom.put("vod_id", url); - vodAtom.put("vod_name", VodName); - vodAtom.put("vod_pic", "https://pic.rmb.bdstatic.com/bjh/1d0b02d0f57f0a42201f92caba5107ed.jpeg"); - vodAtom.put("type_name", "嗅探"); - vodAtom.put("vod_content", url); - vodAtom.put("vod_play_from", "嗅探"); - vodAtom.put("vod_play_url", "立即播放嗅探$" + url); - lists.put(vodAtom); - result.put("list", lists); - return result.toString(); - } - } catch (Throwable throwable) { - - } - return ""; - } - - - @Override - public String playerContent(String flag, String id, List vipFlags) { - try { - switch (flag) { - case "jx": { - JSONObject result = new JSONObject(); - result.put("parse", 1); - result.put("jx", "1"); - result.put("url", id); - return result.toString(); - } - case "player": { - JSONObject result = new JSONObject(); - result.put("parse", 0); - result.put("playUrl", ""); - result.put("url", id); - return result.toString(); - } - case "嗅探": { - JSONObject result = new JSONObject(); - result.put("parse", 1); - result.put("playUrl", ""); - result.put("url", id); - return result.toString(); - } - case "AliYun": - refreshTk(); - String[] split = id.split("\\+"); - String str3 = split[0]; - String str5 = split[2]; - String url = Proxy.localProxyUrl() + "?do=push&type=m3u8&share_id=" + str3 + "&file_id=" + str5; - JSONObject jSONObject = new JSONObject(); - jSONObject.put("parse", "0"); - jSONObject.put("playUrl", ""); - jSONObject.put("url", url); - jSONObject.put("header", ""); - return jSONObject.toString(); - } - } catch (Exception e) { - e.printStackTrace(); - SpiderDebug.log(e); - } - return ""; - } - -} \ No newline at end of file +package com.github.catvod.spider; + +import android.content.Context; +import android.net.UrlQuerySanitizer; +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.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.io.ByteArrayInputStream; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.ReentrantLock; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import okhttp3.Call; +import okhttp3.Response; + + +/** + * Author: @SDL + */ +public class PushAgent extends Spider { + private static long timeToken = 0; + + private static String accessToken = ""; + private static String refreshToken = ""; + + private static Map shareToken = new HashMap<>(); + private static Map shareExpires = new HashMap<>(); + private static final Map> videosMap = new HashMap<>(); + private static final ReentrantLock rLock = new ReentrantLock(); + public static Pattern regexAli = Pattern.compile("(https://www.aliyundrive.com/s/[^\"]+)"); + //TANGSAN + public static Pattern Folder = Pattern.compile("www.aliyundrive.com/s/([^/]+)(/folder/([^/]+))?"); + + public static Pattern regexAliFolder = Pattern.compile("www.aliyundrive.com/s/([^/]+)(/folder/([^/]+))?"); + + @Override + public void init(Context context, String extend) { + super.init(context, extend); + if (extend.startsWith("http")) { + refreshToken = OkHttpUtil.string(extend, null); + } else { + refreshToken = extend; + } + } + +// @Override +// public void init(Context context) { +// super.init(context); +//// refreshToken = OkHttpUtil.string("https://gitea.com/qiaoji/jar/raw/branch/main/token.txt", null); +//// if(refreshToken.length()!=32){ +//// refreshToken = "ad3c78559a494bde814f1a6c8c40db51"; +//// } +// refreshToken = "ad3c78559a494bde814f1a6c8c40db51"; +// } + + private static HashMap getHeaders() { + HashMap headers = new HashMap<>(); + headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36"); + headers.put("Referer", "https://www.aliyundrive.com/"); + return headers; + } + + private static HashMap getHeaders2() { + HashMap headers = new HashMap<>(); + headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36"); + return headers; + } + + private static String postJson(String url, String jsonStr, Map headerMap) { + OKCallBack.OKCallBackString callback = new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception e) { + + } + + @Override + public void onResponse(String response) { + + } + }; + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), url, jsonStr, headerMap, callback); + return callback.getResult(); + } + + protected static long getTimeSys() { + return (System.currentTimeMillis() / 1000); + } + + private static void getRefreshTk() { + long timeSys = getTimeSys(); + if (accessToken.isEmpty() || timeToken - timeSys <= 600) { + try { + JSONObject json = new JSONObject(); + json.put("refresh_token", refreshToken); + JSONObject response = new JSONObject(postJson("https://api.aliyundrive.com/token/refresh", json.toString(), getHeaders())); + accessToken = response.getString("token_type") + " " + response.getString("access_token"); + timeToken = response.getLong("expires_in") + timeSys; + } catch (JSONException e) { + SpiderDebug.log(e); + } + } + } + + private static synchronized String getShareTk(String shareId, String sharePwd) { + synchronized (PushAgent.class) { + try { + long timeSys = getTimeSys(); + String token = shareToken.get(shareId); + Long expires = shareExpires.get(shareId); + if (!TextUtils.isEmpty(token) && expires - timeSys > 600) { + return token; + } + JSONObject json = new JSONObject(); + json.put("share_id", shareId); + json.put("share_pwd", sharePwd); + JSONObject response = new JSONObject(postJson("https://api.aliyundrive.com/v2/share_link/get_share_token", json.toString(), getHeaders())); + String string = response.getString("share_token"); + shareExpires.put(shareId, timeSys + response.getLong("expires_in")); + shareToken.put(shareId, string); + return string; + } catch (JSONException e) { + SpiderDebug.log(e); + return ""; + } + } + } + + public static Object[] loadsub(String url) { + try { + return new Object[]{200, "application/octet-stream", new ByteArrayInputStream(OkHttpUtil.string(url, getHeaders()).getBytes())}; + } catch (Exception e2) { + e2.printStackTrace(); + SpiderDebug.log(e2); + return null; + } + } + + public static Object[] File(Map params) { + try { + String shareId = params.get("share_id"); + return new Object[]{200, "application/octet-stream", new ByteArrayInputStream(getVideoUrl(shareId, getShareTk(shareId, ""), params.get("file_id")).getBytes())}; + } catch (Exception e2) { + SpiderDebug.log(e2); + return null; + } + } + + public static Object[] ProxyMedia(Map params) { + try { + String shareId = params.get("share_id"); + String fileId = params.get("file_id"); + String mediaId = params.get("media_id"); + String shareToken = getShareTk(shareId, ""); + ReentrantLock reentrantLock = rLock; + reentrantLock.lock(); + String url = videosMap.get(fileId).get(mediaId); + if (new Long(new UrlQuerySanitizer(url).getValue("x-oss-expires")) - getTimeSys() <= 60) { + getVideoUrl(shareId, shareToken, fileId); + url = videosMap.get(fileId).get(mediaId); + } + reentrantLock.unlock(); + + OKCallBack.OKCallBackDefault callback = new OKCallBack.OKCallBackDefault() { + @Override + public void onFailure(Call call, Exception e) { + + } + + @Override + public void onResponse(Response response) { + + } + }; + OkHttpUtil.get(OkHttpUtil.defaultClient(), url, null, getHeaders(),callback); + return new Object[]{200, "video/MP2T", callback.getResult().body().byteStream()}; + } catch (Exception e2) { + SpiderDebug.log(e2); + return null; + } + } + + + public static Object[] vod(Map map) { + String type = map.get("type"); + if (type.equals("m3u8")) { + return File(map); + } + if (type.equals("media")) { + return ProxyMedia(map); + } + return null; + } + + private static String getVideoUrl(String shareId, String shareToken, String fileId) { + try { + getRefreshTk(); + JSONObject json = new JSONObject(); + json.put("share_id", shareId); + json.put("category", "live_transcoding"); + json.put("file_id", fileId); + json.put("template_id", ""); + HashMap Headers = getHeaders(); + Headers.put("x-share-token", shareToken); + Headers.put("authorization", accessToken); + JSONObject jSONObject3 = new JSONObject(postJson("https://api.aliyundrive.com/v2/file/get_share_link_video_preview_play_info", json.toString(), Headers)); + JSONArray playList = jSONObject3.getJSONObject("video_preview_play_info").getJSONArray("live_transcoding_task_list"); + String videoUrl = ""; + String[] orders = new String[]{"FHD", "HD", "SD"}; + for (String or : orders) { + for (int i = 0; i < playList.length(); i++) { + JSONObject obj = playList.getJSONObject(i); + if (obj.optString("template_id").equals(or)) { + videoUrl = obj.getString("url"); + break; + } + } + if (!videoUrl.isEmpty()) + break; + } + if (videoUrl.isEmpty() && playList.length() > 0) { + videoUrl = playList.getJSONObject(0).getString("url"); + } + Map> respHeaderMap = new HashMap<>(); + OkHttpUtil.stringNoRedirect(videoUrl, getHeaders(), respHeaderMap); + String url = OkHttpUtil.getRedirectLocation(respHeaderMap); + String medias = OkHttpUtil.string(url, getHeaders()); + String site = url.substring(0, url.lastIndexOf("/")) + "/"; + ArrayList lists = new ArrayList<>(); + Map video = new HashMap<>(); + String[] split = medias.split("\n"); + int j = 0; + for (int i = 0; i < split.length; i++) { + String vod = split[i]; + if (vod.contains("x-oss-expires")) { + j++; + video.put("" + j, site + vod); + vod = Proxy.localProxyUrl() + "?do=ali&type=media&share_id=" + shareId + "&file_id=" + fileId + "&media_id=" + j; + } + lists.add(vod); + } + videosMap.put(fileId, video); +// Map o = new HashMap<>(); +// o.put("share_id",shareId); +// o.put("file_id",fileId); +// o.put("media_id",""+(--j)); +// ProxyMedia(o); + return TextUtils.join("\n", lists); + } catch (Exception e2) { + SpiderDebug.log(e2); + return ""; + } + } + + private static String getOriginalVideoUrl(String shareId, String shareToken, String fileId, String category) { + try { + getRefreshTk(); + HashMap json = getHeaders(); + json.put("x-share-token", shareToken); + json.put("authorization", accessToken); + if (category.equals("video")) { + JSONObject jSONObject = new JSONObject(); + jSONObject.put("share_id", shareId); + jSONObject.put("category", "live_transcoding"); + jSONObject.put("file_id", fileId); + jSONObject.put("template_id", ""); + JSONObject jSONObject2 = new JSONObject(postJson("https://api.aliyundrive.com/v2/file/get_share_link_video_preview_play_info", jSONObject.toString(), json)); + shareId = jSONObject2.getString("share_id"); + fileId = jSONObject2.getString("file_id"); + } + JSONObject jSONObject3 = new JSONObject(); + if (category.equals("video")) { + jSONObject3.put("expire_sec", 600); + jSONObject3.put("file_id", fileId); + jSONObject3.put("share_id", shareId); + } + if (category.equals("audio")) { + jSONObject3.put("share_id", shareId); + jSONObject3.put("get_audio_play_info", true); + jSONObject3.put("file_id", fileId); + } + return new JSONObject(postJson("https://api.aliyundrive.com/v2/file/get_share_link_download_url", jSONObject3.toString(), json)).getString("download_url"); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } + + + public void listFiles(Map map, String shareId, String shareToken, String fileId) { + try { + String url = "https://api.aliyundrive.com/adrive/v3/file/list"; + HashMap headers = getHeaders(); + headers.put("x-share-token", shareToken); + JSONObject json = new JSONObject(); + json.put("image_thumbnail_process", "image/resize,w_160/format,jpeg"); + json.put("image_url_process", "image/resize,w_1920/format,jpeg"); + json.put("limit", 200); + json.put("order_by", "updated_at"); + json.put("order_direction", "DESC"); + json.put("parent_file_id", fileId); + json.put("share_id", shareId); + json.put("video_thumbnail_process", "video/snapshot,t_1000,f_jpg,ar_auto,w_300"); + String marker = ""; + ArrayList arrayList = new ArrayList<>(); + for(int i=1;i<=50;i++) { + if (i >1 && marker.isEmpty()) + break; + json.put("marker", marker); + JSONObject data = new JSONObject(postJson(url, json.toString(), headers)); + JSONArray items = data.getJSONArray("items"); + + for (int j = 0; j < items.length(); j++) { + JSONObject item = items.getJSONObject(j); + if (item.getString("type").equals("folder")) { + arrayList.add(item.getString("file_id")); + } else { + //vnd.rn-realmedia-vbr 为rmvb格式 + if (item.getString("mime_type").contains("video")||item.getString("mime_type").contains("vnd.rn-realmedia-vbr")) { + String replace = item.getString("name").replace("#", "_").replace("$", "_"); + map.put(replace, shareId + "+" + shareToken + "+" + item.getString("file_id")+"+"+item.getString("category")); + } + } + } + marker = data.getString("next_marker"); + } + + for (String item : arrayList) { + try { + listFiles(map, shareId, shareToken, item); + } catch (Exception e) { + SpiderDebug.log(e); + return; + } + } + } catch (Exception e) { + SpiderDebug.log(e); + } + } + + + @Override + public String detailContent(List ids) { + try { + String url = ids.get(0); + if (Misc.isVip(url) && !url.contains("qq.com") && !url.contains("mgtv.com")) { + JSONObject result = new JSONObject(); + JSONArray list = new JSONArray(); + JSONObject vodAtom = new JSONObject(); + vodAtom.put("vod_id", url); + vodAtom.put("vod_name", url); + vodAtom.put("vod_pic", "https://pic.rmb.bdstatic.com/bjh/1d0b02d0f57f0a42201f92caba5107ed.jpeg"); + vodAtom.put("type_name", "官源"); + vodAtom.put("vod_year", ""); + vodAtom.put("vod_area", ""); + vodAtom.put("vod_remarks", ""); + vodAtom.put("vod_actor", ""); + vodAtom.put("vod_director", ""); + vodAtom.put("vod_content", ""); + vodAtom.put("vod_play_from", "jx"); + vodAtom.put("vod_play_url", "立即播放$" + url); + list.put(vodAtom); + result.put("list", list); + return result.toString(); + } else if (Misc.isVip(url) && url.contains("qq.com")) { + List vodItems = new ArrayList<>(); + JSONObject result = new JSONObject(); + JSONArray lists = new JSONArray(); + JSONObject vodAtom = new JSONObject(); + Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders2())); + String VodName = doc.select("head > title").text(); + Elements playListA = doc.select("div.episode-list-rect__item"); + if (!playListA.isEmpty()) { + for (int j = 0; j < playListA.size(); j++) { + Element vod = playListA.get(j); + String a = vod.select("div").attr("data-vid"); + String b = vod.select("div").attr("data-cid"); + String id = "https://v.qq.com/x/cover/" + b + "/" + a; + String name = vod.select("div span").text(); + vodItems.add(name + "$" + id); + } + String playList = TextUtils.join("#", vodItems); + vodAtom.put("vod_play_url", playList); + } else { + vodAtom.put("vod_play_url", "立即播放$" + url); + } + vodAtom.put("vod_id", url); + vodAtom.put("vod_name", VodName); + vodAtom.put("vod_pic", "https://img2.baidu.com/it/u=2655029475,2190949369&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=593"); + vodAtom.put("type_name", "腾讯视频"); + vodAtom.put("vod_year", ""); + vodAtom.put("vod_area", ""); + vodAtom.put("vod_remarks", ""); + vodAtom.put("vod_actor", ""); + vodAtom.put("vod_director", ""); + vodAtom.put("vod_content", url); + vodAtom.put("vod_play_from", "jx"); + lists.put(vodAtom); + result.put("list", lists); + return result.toString(); + } else if (Misc.isVip(url) && url.contains("mgtv.com")) { + List vodItems = new ArrayList<>(); + JSONObject result = new JSONObject(); + JSONArray lists = new JSONArray(); + JSONObject vodAtom = new JSONObject(); + Pattern mgtv = Pattern.compile("https://\\S+mgtv.com/b/(\\d+)/(\\d+).html.*"); + Matcher mgtv1 = mgtv.matcher(url); + String VodNames = ""; + if (mgtv1.find()) { + String Ep = "https://pcweb.api.mgtv.com/episode/list?video_id=" + mgtv1.group(2); + JSONObject Data = new JSONObject(OkHttpUtil.string(Ep, getHeaders2())); + VodNames = Data.getJSONObject("data").getJSONObject("info").getString("title"); + JSONArray a = new JSONArray(Data.getJSONObject("data").getString("list")); + if (a.length() > 0) { + for (int i = 0; i < a.length(); i++) { + JSONObject jObj = a.getJSONObject(i); + if (jObj.getString("isIntact").equals("1")) { + String VodName = jObj.getString("t4"); + String id = jObj.getString("video_id"); + String VodId = "https://www.mgtv.com/b/" + mgtv1.group(1) + "/" + id + ".html"; + vodItems.add(VodName + "$" + VodId); + } + } + String playList = TextUtils.join("#", vodItems); + vodAtom.put("vod_play_url", playList); + } else { + vodAtom.put("vod_play_url", "立即播放$" + url); + } + } + vodAtom.put("vod_id", url); + vodAtom.put("vod_name", VodNames); + vodAtom.put("vod_pic", "https://img2.baidu.com/it/u=2562822927,704100654&fm=253&fmt=auto&app=138&f=JPEG?w=600&h=380"); + vodAtom.put("type_name", "芒果视频"); + vodAtom.put("vod_year", ""); + vodAtom.put("vod_area", ""); + vodAtom.put("vod_remarks", ""); + vodAtom.put("vod_actor", ""); + vodAtom.put("vod_director", ""); + vodAtom.put("vod_content", url); + vodAtom.put("vod_play_from", "jx"); + lists.put(vodAtom); + result.put("list", lists); + return result.toString(); + } else if (Misc.isVideoFormat(url)) { + JSONObject result = new JSONObject(); + JSONArray list = new JSONArray(); + JSONObject vodAtom = new JSONObject(); + vodAtom.put("vod_id", url); + vodAtom.put("vod_name", url); + vodAtom.put("vod_pic", "https://pic.rmb.bdstatic.com/bjh/1d0b02d0f57f0a42201f92caba5107ed.jpeg"); + vodAtom.put("type_name", "直连"); + vodAtom.put("vod_play_from", "player"); + vodAtom.put("vod_play_url", "立即播放$" + url); + list.put(vodAtom); + result.put("list", list); + return result.toString(); + } else if (url.startsWith("magnet:")) { + String name = ""; + Matcher matcher = Pattern.compile("(^|&)dn=([^&]*)(&|$)").matcher(URLDecoder.decode(url)); + if (matcher.find()) { + name = matcher.group(2); + } + JSONObject result = new JSONObject(); + JSONArray list = new JSONArray(); + JSONObject vodAtom = new JSONObject(); + vodAtom.put("vod_id", url); + vodAtom.put("vod_name", !name.equals("") ? name : url); + vodAtom.put("vod_pic", "https://pic.rmb.bdstatic.com/bjh/1d0b02d0f57f0a42201f92caba5107ed.jpeg"); + vodAtom.put("type_name", "磁力链接"); + vodAtom.put("vod_content", url); + vodAtom.put("vod_play_from", "magnet"); + vodAtom.put("vod_play_url", "立即播放$" + url); + list.put(vodAtom); + result.put("list", list); + return result.toString(); + } else if (regexAli.matcher(url).find()) { + Matcher matcher = regexAliFolder.matcher(url); + if (!matcher.find()) { + return ""; + } + String shareId = matcher.group(1); + String fileId = matcher.groupCount() == 3 ? matcher.group(3) : ""; + JSONObject json = new JSONObject(); + json.put("share_id", shareId); + JSONObject shareLinkJson = new JSONObject(postJson("https://api.aliyundrive.com/adrive/v3/share_link/get_share_by_anonymous", json.toString(), getHeaders())); + JSONArray fileInfoLists = shareLinkJson.getJSONArray("file_infos"); + if (fileInfoLists.length() == 0) { + return ""; + } + JSONObject fileInfo = null; + if (!TextUtils.isEmpty(fileId)) { + for (int i = 0; i < fileInfoLists.length(); i++) { + JSONObject item = fileInfoLists.getJSONObject(i); + if (item.getString("file_id").equals(item.getString("file_id"))) { + fileInfo = item; + break; + } + } + } else { + fileInfo = fileInfoLists.getJSONObject(0); + fileId = fileInfo.getString("file_id"); + } + JSONObject vodAtom = new JSONObject(); + vodAtom.put("vod_id", url); + vodAtom.put("vod_name", shareLinkJson.getString("share_name")); + vodAtom.put("vod_pic", shareLinkJson.getString("avatar")); + vodAtom.put("vod_content", url); + vodAtom.put("type_name", "阿里云盘"); + ArrayList vodItems = new ArrayList<>(); + if (!fileInfo.getString("type").equals("folder")) { + if (!fileInfo.getString("type").equals("file") || !fileInfo.getString("category").equals("video")) { + return ""; + } + fileId = "root"; + } + String shareTk = getShareTk(shareId, ""); + Map hashMap = new HashMap<>(); + listFiles(hashMap, shareId, shareTk, fileId); + ArrayList arrayList2 = new ArrayList<>(hashMap.keySet()); + Collections.sort(arrayList2); + for (String item : arrayList2) { + vodItems.add(item + "$" + hashMap.get(item)); + } + if(vodItems.size()>0){ + ArrayList playLists = new ArrayList<>(); + playLists.add(TextUtils.join("#", vodItems)); + playLists.add(TextUtils.join("#", vodItems)); + vodAtom.put("vod_play_url", TextUtils.join("$$$", playLists)); + vodAtom.put("vod_play_from", "AliYun$$$AliYun原画"); + } + JSONObject result = new JSONObject(); + JSONArray list = new JSONArray(); + list.put(vodAtom); + result.put("list", list); +// Map o = new HashMap<>(); +// o.put("share_id",shareId); +// o.put("file_id",hashMap.get(arrayList2.get(0)).split("\\+")[2]); +// getRefreshTk(); +// File(o); + return result.toString(); + + } else if (url.startsWith("http://") || url.startsWith("https://")) { + JSONObject result = new JSONObject(); + JSONArray list = new JSONArray(); + JSONObject vodAtom = new JSONObject(); + vodAtom.put("vod_id", url); + vodAtom.put("vod_name", url); + vodAtom.put("vod_pic", "https://pic.rmb.bdstatic.com/bjh/1d0b02d0f57f0a42201f92caba5107ed.jpeg"); + vodAtom.put("type_name", "网页"); + vodAtom.put("vod_play_from", "parse"); + vodAtom.put("vod_play_url", "立即播放$" + url); + list.put(vodAtom); + result.put("list", list); + return result.toString(); + } + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + return ""; + } + + @Override + public String playerContent(String flag, String id, List vipFlags) { + try { + if (flag.equals("jx")) { + JSONObject result = new JSONObject(); + result.put("parse", 1); + result.put("jx", "1"); + result.put("url", id); + return result.toString(); + } else if (flag.equals("parse")) { + JSONObject result = new JSONObject(); + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", id); + return result.toString(); + } else if (flag.equals("player") || flag.equals("magnet")) { + JSONObject result = new JSONObject(); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", id); + return result.toString(); + }else if (flag.equals("AliYun")) { + String[] split = id.split("\\+"); + String videoUrl = Proxy.localProxyUrl() + "?do=ali&type=m3u8&share_id=" + split[0] + "&file_id=" + split[2]; + JSONObject result = new JSONObject(); + result.put("parse", "0"); + result.put("playUrl", ""); + result.put("url", videoUrl); + result.put("header", ""); + return result.toString(); + }else if (flag.equals("AliYun原画")) { + String[] split = id.split("\\+"); + String url = getOriginalVideoUrl(split[0], split[1], split[2], split[3]); + Map> headerMap = new HashMap<>(); + OkHttpUtil.stringNoRedirect(url, getHeaders(), headerMap); + String videoUrl = OkHttpUtil.getRedirectLocation(headerMap); + JSONObject result = new JSONObject(); + result.put("parse", "0"); + result.put("playUrl", ""); + result.put("url", videoUrl); + result.put("header", new JSONObject(getHeaders()).toString()); + return result.toString(); + + } + } catch (Throwable throwable) { + + } + return ""; + } + + /** + * 搜索 + * + * @param key + * @param quick 是否播放页的快捷搜索 + * @return + */ + @Override + public String searchContent(String key, boolean quick) { + try { + String trim = key.trim(); + if (!regexAli.matcher(trim).find()) { + return ""; + } + JSONArray videos = new JSONArray(); + JSONObject v = new JSONObject(); + v.put("vod_id", trim); + v.put("vod_name", trim); + videos.put(v); + JSONObject result = new JSONObject(); + result.put("list", videos); + return result.toString(); + } catch (Exception e2) { + SpiderDebug.log(e2); + return ""; + } + } +} diff --git a/app/src/main/java/com/github/catvod/spider/QQ.java b/app/src/main/java/com/github/catvod/spider/QQ.java new file mode 100644 index 0000000..1c38906 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/QQ.java @@ -0,0 +1,331 @@ +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.net.URLEncoder; +import java.util.ArrayList; +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 org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import rxhttp.wrapper.annotations.NonNull; + +public class QQ extends Spider { + protected JSONObject dn; + protected JSONObject q = new JSONObject(); + + 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) { + String str3; + try { + String str4 = "https://v.qq.com/x/bu/pagesheet/list?_all=1&append=1&channel=" + str + "&listpage=1&offset=" + ((Integer.parseInt(str2) - 1) * 21) + "&pagesize=21&sort=18"; + if (hashMap != null) { + for (String str5 : hashMap.keySet()) { + String trim = hashMap.get(str5).trim(); + if (trim.length() != 0) { + str4 = str4 + "&" + str5 + "=" + URLEncoder.encode(trim); + } + } + } + String content = OkHttpUtil.string(str4, getHeaders(str4)); + JSONObject jSONObject = new JSONObject(); + try { + Elements listItems = Jsoup.parse(content).select(".list_item"); + JSONArray jSONArray = new JSONArray(); + for (int i = 0; i < listItems.size(); i++) { + Element item = listItems.get(i); + String Pd = item.select("a").attr("title"); + String q = q(str4, item.select("img").attr("src")); + if (item.select(".figure_caption") == null) { + str3 = ""; + } else { + str3 = item.select(".figure_caption").text(); + } + String Pd2 = item.select("a").attr("data-float"); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("vod_id", Pd2); + jSONObject2.put("vod_name", Pd); + jSONObject2.put("vod_pic", q); + jSONObject2.put("vod_remarks", str3); + jSONArray.put(jSONObject2); + } + 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) { + JSONArray jSONArray; + CharSequence charSequence; + JSONArray jSONArray2; + CharSequence charSequence2; + CharSequence charSequence3 = ","; + try { + String str = "https://node.video.qq.com/x/api/float_vinfo2?cid=" + list.get(0); + JSONObject jSONObject = new JSONObject(OkHttpUtil.string(str, getHeaders(str))); + JSONObject optJSONObject = jSONObject.optJSONObject("c"); + if (optJSONObject == null) { + return ""; + } + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("vod_id", list.get(0)); + jSONObject2.put("vod_name", optJSONObject.optString("title")); + jSONObject2.put("vod_pic", q(str, optJSONObject.optString("pic"))); + jSONObject2.put("type_name", jSONObject.optJSONArray("typ").opt(0)); + jSONObject2.put("vod_year", optJSONObject.optString("year")); + jSONObject.optJSONObject("people"); + JSONArray optJSONArray = jSONObject.optJSONArray("nam").optJSONArray(0); + ArrayList arrayList = new ArrayList(); + if (optJSONArray != null) { + for (int i = 0; i < optJSONArray.length(); i++) { + arrayList.add(optJSONArray.opt(i)); + } + } + jSONObject2.put("vod_actor", join(charSequence3, arrayList)); + jSONObject2.put("vod_content", optJSONObject.optString("description")); + JSONArray jSONArray3 = optJSONObject.getJSONArray("video_ids"); + ArrayList arrayList2 = new ArrayList(); + ArrayList arrayList3 = new ArrayList(); + int i2 = 1; + while (i2 <= jSONArray3.length()) { + arrayList2.add(jSONArray3.optString(i2 - 1)); + if (!(i2 % 30 == 0 || i2 == jSONArray3.length())) { + charSequence = charSequence3; + jSONArray = jSONArray3; + i2++; + charSequence3 = charSequence; + jSONArray3 = jSONArray; + } + String str2 = "https://union.video.qq.com/fcgi-bin/data?otype=json&tid=682&appid=20001238&appkey=6c03bbe9658448a4&union_platform=1&idlist=" + join(charSequence3, arrayList2); + String h = OkHttpUtil.string(str2, getHeaders(str2)); + JSONArray jSONArray4 = new JSONObject(h.substring(13, h.length() - 1)).getJSONArray("results"); + int i3 = 0; + while (i3 < jSONArray4.length()) { + JSONObject jSONObject3 = jSONArray4.getJSONObject(i3).getJSONObject("fields"); + if (!jSONObject3.optString("title").contains("预告")) { + StringBuilder sb = new StringBuilder(); + String optString = jSONObject3.optString("title"); + charSequence2 = charSequence3; + StringBuilder sb2 = new StringBuilder(); + jSONArray2 = jSONArray3; + sb2.append(optJSONObject.optString("title")); + sb2.append("_"); + sb.append(optString.replace(sb2.toString(), "")); + sb.append("$https://v.qq.com/x/cover/"); + sb.append(list.get(0)); + sb.append("/"); + sb.append(jSONObject3.optString("vid")); + sb.append(".html"); + arrayList3.add(sb.toString()); + } else { + charSequence2 = charSequence3; + jSONArray2 = jSONArray3; + } + i3++; + charSequence3 = charSequence2; + jSONArray3 = jSONArray2; + } + charSequence = charSequence3; + jSONArray = jSONArray3; + arrayList2.clear(); + i2++; + charSequence3 = charSequence; + jSONArray3 = jSONArray; + } + jSONObject2.put("vod_play_from", "qq"); + jSONObject2.put("vod_play_url", join("#", arrayList3)); + JSONObject jSONObject4 = new JSONObject(); + JSONArray jSONArray5 = new JSONArray(); + jSONArray5.put(jSONObject2); + jSONObject4.put("list", jSONArray5); + return jSONObject4.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) { + try { + Document doc = Jsoup.parse(OkHttpUtil.string("https://v.qq.com/channel/tv?listpage=1&channel=tv&sort=18&_all=1", getHeaders("https://v.qq.com/channel/tv?listpage=1&channel=tv&sort=18&_all=1"))); + JSONArray jSONArray = new JSONArray(); + Iterator it = doc.select(".nav_cell").iterator(); + while (it.hasNext()) { + Element next = it.next(); + JSONObject jSONObject = new JSONObject(); + String Pd = next.select("a").attr("href"); + if (!Pd.contains("/art") && !Pd.contains("feeds_hotspot") && !Pd.contains("wwe") && !Pd.contains("choice") && !Pd.contains("sports_new") && !Pd.contains("games") && !Pd.contains("lols11") && !Pd.contains("ent") && !Pd.contains("news") && !Pd.contains("fashion") && !Pd.contains("tech") && !Pd.contains("auto") && !Pd.contains("house") && !Pd.contains("finance") && !Pd.contains("astro") && !Pd.contains("nba") && !Pd.contains("fun") && !Pd.contains("baby") && !Pd.contains("music") && !Pd.contains("life") && !Pd.contains("travel") && Pd.contains("/channel/")) { + jSONObject.put("type_name", next.select("a").text()); + jSONObject.put("type_id", Pd.split("/channel/")[1]); + jSONArray.put(jSONObject); + } + } + String h = OkHttpUtil.string("https://v.qq.com/x/bu/pagesheet/list?_all=1&append=1&channel=choice", getHeaders("https://v.qq.com/x/bu/pagesheet/list?_all=1&append=1&channel=choice")); + JSONObject jSONObject2 = new JSONObject(); + if (z) { + jSONObject2.put("filters", this.dn); + } + jSONObject2.put("class", jSONArray); + try { + Elements listItem = Jsoup.parse(h).select(".list_item"); + JSONArray jSONArray2 = new JSONArray(); + for (int i = 0; i < listItem.size(); i++) { + Element item = listItem.get(i); + String title = item.select("a").attr("title"); + String pic = q("https://v.qq.com/x/bu/pagesheet/list?_all=1&append=1&channel=choice", item.select("img").attr("src")); + String remark = item.select(".figure_caption").text(); + String id = item.select("a").attr("data-float"); + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put("vod_id", id); + jSONObject3.put("vod_name", title); + jSONObject3.put("vod_pic", pic); + jSONObject3.put("vod_remarks", remark); + jSONArray2.put(jSONObject3); + } + jSONObject2.put("list", jSONArray2); + } catch (Exception e) { + SpiderDebug.log(e); + } + return jSONObject2.toString(4); + } catch (Exception e2) { + SpiderDebug.log(e2); + return ""; + } + } + + public String homeVideoContent() { + try { + JSONArray jSONArray = new JSONObject(OkHttpUtil.string("https://v.qq.com/api.php/app/index_video?token=", getHeaders("https://v.qq.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) { + QQ.super.init(context); + try { + this.dn = new JSONObject("{\"tv\":[{\"name\":\"排序\",\"value\":[{\"v\":\"19\",\"n\":\"最新\"},{\"v\":\"18\",\"n\":\"最热\"},{\"v\":\"16\",\"n\":\"好评\"},{\"v\":\"21\",\"n\":\"口碑好剧\"},{\"v\":\"54\",\"n\":\"高分好评\"},{\"v\":\"22\",\"n\":\"知乎高分\"}],\"key\":\"sort\"},{\"name\":\"类型\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"偶像爱情\"},{\"v\":\"2\",\"n\":\"古装历史\"},{\"v\":\"3\",\"n\":\"玄幻史诗\"},{\"v\":\"4\",\"n\":\"都市生活\"},{\"v\":\"14\",\"n\":\"当代主旋律\"},{\"v\":\"5\",\"n\":\"罪案谍战\"},{\"v\":\"6\",\"n\":\"历险科幻\"},{\"v\":\"7\",\"n\":\"军旅抗战\"},{\"v\":\"8\",\"n\":\"喜剧\"},{\"v\":\"9\",\"n\":\"武侠江湖\"},{\"v\":\"10\",\"n\":\"青春校园\"},{\"v\":\"11\",\"n\":\"时代传奇\"},{\"v\":\"12\",\"n\":\"体育电竞\"},{\"v\":\"13\",\"n\":\"真人动漫\"},{\"v\":\"15\",\"n\":\"短剧\"},{\"v\":\"44\",\"n\":\"独播\"}],\"key\":\"feature\"},{\"name\":\"地区\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"814\",\"n\":\"内地\"},{\"v\":\"815\",\"n\":\"美国\"},{\"v\":\"816\",\"n\":\"英国\"},{\"v\":\"818\",\"n\":\"韩国\"},{\"v\":\"9\",\"n\":\"泰国\"},{\"v\":\"10\",\"n\":\"日本\"},{\"v\":\"14\",\"n\":\"中国香港\"},{\"v\":\"817\",\"n\":\"中国台湾\"},{\"v\":\"819\",\"n\":\"其他\"}],\"key\":\"iarea\"},{\"name\":\"年份\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"2022\",\"n\":\"2022\"},{\"v\":\"2021\",\"n\":\"2021\"},{\"v\":\"2020\",\"n\":\"2020\"},{\"v\":\"4061\",\"n\":\"2019\"},{\"v\":\"4060\",\"n\":\"2018\"},{\"v\":\"2017\",\"n\":\"2017\"},{\"v\":\"859\",\"n\":\"2016\"},{\"v\":\"860\",\"n\":\"2015\"},{\"v\":\"861\",\"n\":\"2014\"},{\"v\":\"862\",\"n\":\"2013\"},{\"v\":\"863\",\"n\":\"2012\"},{\"v\":\"864\",\"n\":\"2011\"},{\"v\":\"865\",\"n\":\"2010\"},{\"v\":\"866\",\"n\":\"其他\"}],\"key\":\"year\"},{\"name\":\"资费\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"867\",\"n\":\"免费\"},{\"v\":\"6\",\"n\":\"会员\"}],\"key\":\"pay\"}],\"education\":[{\"name\":\"排序\",\"value\":[{\"v\":\"19\",\"n\":\"按更新\"},{\"v\":\"40\",\"n\":\"最热\"}],\"key\":\"sort\"},{\"name\":\"学段\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"2\",\"n\":\"小学\"},{\"v\":\"3\",\"n\":\"初中\"},{\"v\":\"4\",\"n\":\"高中\"},{\"v\":\"5\",\"n\":\"大学\"},{\"v\":\"6\",\"n\":\"研究生\"},{\"v\":\"7\",\"n\":\"成人\"}],\"key\":\"section\"},{\"name\":\"学级\",\"value\":[{\"v\":\"1\",\"n\":\"全部\"},{\"v\":\"5\",\"n\":\"一年级\"},{\"v\":\"6\",\"n\":\"二年级\"},{\"v\":\"7\",\"n\":\"三年级\"},{\"v\":\"8\",\"n\":\"四年级\"},{\"v\":\"9\",\"n\":\"五年级\"},{\"v\":\"10\",\"n\":\"六年级\"},{\"v\":\"11\",\"n\":\"初一\"},{\"v\":\"12\",\"n\":\"初二\"},{\"v\":\"13\",\"n\":\"初三\"},{\"v\":\"14\",\"n\":\"高一\"},{\"v\":\"15\",\"n\":\"高二\"},{\"v\":\"16\",\"n\":\"高三\"},{\"v\":\"20\",\"n\":\"大四\"}],\"key\":\"grade\"},{\"name\":\"学科\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"41\",\"n\":\"语文\"},{\"v\":\"42\",\"n\":\"数学\"},{\"v\":\"43\",\"n\":\"英语\"},{\"v\":\"44\",\"n\":\"物理\"},{\"v\":\"45\",\"n\":\"化学\"},{\"v\":\"46\",\"n\":\"生物\"},{\"v\":\"47\",\"n\":\"政治\"},{\"v\":\"50\",\"n\":\"其它\"}],\"key\":\"subject\"}],\"movie\":[{\"name\":\"排序\",\"value\":[{\"v\":\"18\",\"n\":\"最近热播\"},{\"v\":\"19\",\"n\":\"最新上架\"},{\"v\":\"21\",\"n\":\"高分好评\"},{\"v\":\"22\",\"n\":\"知乎高分\"}],\"key\":\"sort\"},{\"name\":\"类型\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"100018\",\"n\":\"剧情\"},{\"v\":\"100004\",\"n\":\"喜剧\"},{\"v\":\"100061\",\"n\":\"动作\"},{\"v\":\"100005\",\"n\":\"爱情\"},{\"v\":\"100010\",\"n\":\"惊悚\"},{\"v\":\"4\",\"n\":\"犯罪\"},{\"v\":\"100009\",\"n\":\"悬疑\"},{\"v\":\"100006\",\"n\":\"战争\"},{\"v\":\"100012\",\"n\":\"科幻\"},{\"v\":\"100015\",\"n\":\"动画\"},{\"v\":\"100007\",\"n\":\"恐怖\"},{\"v\":\"100017\",\"n\":\"家庭\"},{\"v\":\"100022\",\"n\":\"传记\"},{\"v\":\"100003\",\"n\":\"冒险\"},{\"v\":\"100016\",\"n\":\"奇幻\"},{\"v\":\"100011\",\"n\":\"武侠\"},{\"v\":\"100021\",\"n\":\"历史\"},{\"v\":\"2\",\"n\":\"运动\"},{\"v\":\"100014\",\"n\":\"歌舞\"},{\"v\":\"100013\",\"n\":\"音乐\"},{\"v\":\"100020\",\"n\":\"纪录\"},{\"v\":\"100019\",\"n\":\"伦理\"},{\"v\":\"3\",\"n\":\"西部\"}],\"key\":\"itype\"},{\"name\":\"地区\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"100024\",\"n\":\"内地\"},{\"v\":\"100025\",\"n\":\"中国香港\"},{\"v\":\"100029\",\"n\":\"美国\"},{\"v\":\"100032\",\"n\":\"欧洲\"},{\"v\":\"100026\",\"n\":\"中国台湾\"},{\"v\":\"100027\",\"n\":\"日本\"},{\"v\":\"100028\",\"n\":\"韩国\"},{\"v\":\"100030\",\"n\":\"印度\"},{\"v\":\"100031\",\"n\":\"泰国\"},{\"v\":\"15\",\"n\":\"英国\"},{\"v\":\"16\",\"n\":\"法国\"},{\"v\":\"17\",\"n\":\"德国\"},{\"v\":\"18\",\"n\":\"加拿大\"},{\"v\":\"19\",\"n\":\"西班牙\"},{\"v\":\"20\",\"n\":\"意大利\"},{\"v\":\"21\",\"n\":\"澳大利亚\"},{\"v\":\"22\",\"n\":\"北欧\"},{\"v\":\"23\",\"n\":\"拉丁美洲\"},{\"v\":\"100033\",\"n\":\"其它\"}],\"key\":\"iarea\"},{\"name\":\"特色\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"院线\"},{\"v\":\"2\",\"n\":\"自制电影\"},{\"v\":\"5\",\"n\":\"独播\"},{\"v\":\"8\",\"n\":\"原声\"},{\"v\":\"9\",\"n\":\"粤语\"},{\"v\":\"3\",\"n\":\"蓝光\"},{\"v\":\"6\",\"n\":\"奥斯卡\"}],\"key\":\"characteristic\"},{\"name\":\"年份\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"2022\",\"n\":\"2022\"},{\"v\":\"2022\",\"n\":\"2022\"},{\"v\":\"2021\",\"n\":\"2021\"},{\"v\":\"2020\",\"n\":\"2020\"},{\"v\":\"20\",\"n\":\"2019\"},{\"v\":\"2018\",\"n\":\"2018\"},{\"v\":\"2017\",\"n\":\"2017\"},{\"v\":\"2016\",\"n\":\"2016\"},{\"v\":\"100063\",\"n\":\"2015\"},{\"v\":\"100034\",\"n\":\"2014\"},{\"v\":\"100035\",\"n\":\"2013-2011\"},{\"v\":\"100036\",\"n\":\"2010-2006\"},{\"v\":\"100037\",\"n\":\"2005-2000\"},{\"v\":\"100038\",\"n\":\"90年代\"},{\"v\":\"100039\",\"n\":\"80年代\"},{\"v\":\"100040\",\"n\":\"其它\"}],\"key\":\"year\"},{\"name\":\"资费\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"免费\"},{\"v\":\"2\",\"n\":\"包月\"},{\"v\":\"3\",\"n\":\"用券\"},{\"v\":\"4\",\"n\":\"付费\"}],\"key\":\"charge\"}],\"variety\":[{\"name\":\"排序\",\"value\":[{\"v\":\"4\",\"n\":\"最热\"},{\"v\":\"5\",\"n\":\"最新\"}],\"key\":\"sort\"},{\"name\":\"独家\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"腾讯自制\"},{\"v\":\"2\",\"n\":\"独播\"}],\"key\":\"exclusive\"},{\"name\":\"地区\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"国内\"},{\"v\":\"2\",\"n\":\"海外\"}],\"key\":\"iarea\"},{\"name\":\"类型\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"10\",\"n\":\"游戏\"},{\"v\":\"11\",\"n\":\"音乐\"},{\"v\":\"24\",\"n\":\"养成\"},{\"v\":\"12\",\"n\":\"情感\"},{\"v\":\"14\",\"n\":\"喜剧\"},{\"v\":\"2\",\"n\":\"脱口秀\"},{\"v\":\"16\",\"n\":\"表演\"},{\"v\":\"25\",\"n\":\"体验\"},{\"v\":\"17\",\"n\":\"亲子\"},{\"v\":\"26\",\"n\":\"文化\"},{\"v\":\"19\",\"n\":\"美食\"},{\"v\":\"20\",\"n\":\"职场\"},{\"v\":\"21\",\"n\":\"体育\"},{\"v\":\"15\",\"n\":\"潮流文化\"},{\"v\":\"3\",\"n\":\"访谈\"},{\"v\":\"22\",\"n\":\"生活服务\"},{\"v\":\"23\",\"n\":\"萌宠\"},{\"v\":\"7\",\"n\":\"资讯\"},{\"v\":\"6\",\"n\":\"晚会\"}],\"key\":\"itype\"},{\"name\":\"年份\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"2022\",\"n\":\"2022\"},{\"v\":\"2021\",\"n\":\"2021\"},{\"v\":\"50\",\"n\":\"2020\"},{\"v\":\"7\",\"n\":\"2019\"},{\"v\":\"1\",\"n\":\"2018\"},{\"v\":\"2\",\"n\":\"2017\"},{\"v\":\"3\",\"n\":\"2016\"},{\"v\":\"4\",\"n\":\"2015\"},{\"v\":\"5\",\"n\":\"2014\"},{\"v\":\"6\",\"n\":\"2013\"},{\"v\":\"2012\",\"n\":\"2012\"},{\"v\":\"2011\",\"n\":\"2011\"},{\"v\":\"2010\",\"n\":\"2010\"},{\"v\":\"99\",\"n\":\"更早\"}],\"key\":\"iyear\"},{\"name\":\"付费\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"会员\"}],\"key\":\"ipay\"}],\"cartoon\":[{\"name\":\"排序\",\"value\":[{\"v\":\"40\",\"n\":\"最热\"},{\"v\":\"23\",\"n\":\"最新\"},{\"v\":\"20\",\"n\":\"好评\"},{\"v\":\"22\",\"n\":\"知乎高分\"}],\"key\":\"sort\"},{\"name\":\"类型\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"2\",\"n\":\"冒险\"},{\"v\":\"5\",\"n\":\"战斗\"},{\"v\":\"1\",\"n\":\"搞笑\"},{\"v\":\"3\",\"n\":\"经典\"},{\"v\":\"4\",\"n\":\"科幻\"},{\"v\":\"9\",\"n\":\"玄幻\"},{\"v\":\"6\",\"n\":\"魔幻\"},{\"v\":\"13\",\"n\":\"武侠\"},{\"v\":\"7\",\"n\":\"恋爱\"},{\"v\":\"14\",\"n\":\"推理\"},{\"v\":\"11\",\"n\":\"腾讯出品\"},{\"v\":\"15\",\"n\":\"日常\"},{\"v\":\"16\",\"n\":\"校园\"},{\"v\":\"17\",\"n\":\"悬疑\"},{\"v\":\"18\",\"n\":\"真人\"},{\"v\":\"19\",\"n\":\"历史\"},{\"v\":\"20\",\"n\":\"竞技\"},{\"v\":\"12\",\"n\":\"其他\"}],\"key\":\"itype\"},{\"name\":\"地区\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"内地\"},{\"v\":\"2\",\"n\":\"日本\"},{\"v\":\"3\",\"n\":\"欧美\"},{\"v\":\"4\",\"n\":\"其他\"}],\"key\":\"iarea\"},{\"name\":\"时间\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"2022\",\"n\":\"2022\"},{\"v\":\"2021\",\"n\":\"2021\"},{\"v\":\"50\",\"n\":\"2020\"},{\"v\":\"11\",\"n\":\"2019\"},{\"v\":\"2018\",\"n\":\"2018\"},{\"v\":\"2017\",\"n\":\"2017\"},{\"v\":\"1\",\"n\":\"2016\"},{\"v\":\"2\",\"n\":\"2015\"},{\"v\":\"3\",\"n\":\"2014\"},{\"v\":\"4\",\"n\":\"2013\"},{\"v\":\"5\",\"n\":\"2012\"},{\"v\":\"6\",\"n\":\"2011\"},{\"v\":\"7\",\"n\":\"00年代\"},{\"v\":\"8\",\"n\":\"90年代\"},{\"v\":\"9\",\"n\":\"80年代\"},{\"v\":\"10\",\"n\":\"更早\"}],\"key\":\"iyear\"},{\"name\":\"资费\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"免费\"},{\"v\":\"2\",\"n\":\"会员\"}],\"key\":\"ipay\"},{\"name\":\"状态\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"46\",\"n\":\"预告片\"},{\"v\":\"44\",\"n\":\"连载\"},{\"v\":\"45\",\"n\":\"完结\"}],\"key\":\"anime_status\"},{\"name\":\"分类\",\"value\":[{\"v\":\"1\",\"n\":\"全部\"},{\"v\":\"2\",\"n\":\"3D动画\"},{\"v\":\"3\",\"n\":\"2D动画\"},{\"v\":\"4\",\"n\":\"特摄\"},{\"v\":\"5\",\"n\":\"其他\"}],\"key\":\"item\"}],\"doco\":[{\"name\":\"排序\",\"value\":[{\"v\":\"19\",\"n\":\"最新\"},{\"v\":\"18\",\"n\":\"最热\"},{\"v\":\"20\",\"n\":\"好评\"},{\"v\":\"22\",\"n\":\"知乎高分\"}],\"key\":\"sort\"},{\"name\":\"出品机构\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"BBC\"},{\"v\":\"4\",\"n\":\"国家地理\"},{\"v\":\"3175\",\"n\":\"HBO\"},{\"v\":\"2\",\"n\":\"NHK\"},{\"v\":\"7\",\"n\":\"历史频道\"},{\"v\":\"3530\",\"n\":\"ITV\"},{\"v\":\"3174\",\"n\":\"探索频道\"},{\"v\":\"3176\",\"n\":\"ZDF\"},{\"v\":\"3172\",\"n\":\"ARTE\"},{\"v\":\"15\",\"n\":\"腾讯自制\"},{\"v\":\"6\",\"n\":\"合作机构\"},{\"v\":\"5\",\"n\":\"其他\"}],\"key\":\"itrailer\"},{\"name\":\"类型\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"4\",\"n\":\"自然\"},{\"v\":\"9\",\"n\":\"美食\"},{\"v\":\"3\",\"n\":\"社会\"},{\"v\":\"5\",\"n\":\"人文\"},{\"v\":\"1\",\"n\":\"历史\"},{\"v\":\"2\",\"n\":\"军事\"},{\"v\":\"7\",\"n\":\"科技\"},{\"v\":\"13\",\"n\":\"财经\"},{\"v\":\"15\",\"n\":\"探险\"},{\"v\":\"6\",\"n\":\"罪案\"},{\"v\":\"11\",\"n\":\"竞技\"},{\"v\":\"10\",\"n\":\"旅游\"}],\"key\":\"itype\"},{\"name\":\"资费\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"免费\"},{\"v\":\"2\",\"n\":\"会员\"}],\"key\":\"pay\"}],\"child\":[{\"name\":\"排序\",\"value\":[{\"v\":\"19\",\"n\":\"最新\"},{\"v\":\"18\",\"n\":\"最热\"},{\"v\":\"20\",\"n\":\"好评\"}],\"key\":\"sort\"},{\"name\":\"地区\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"欧美\"},{\"v\":\"2\",\"n\":\"日韩\"},{\"v\":\"3\",\"n\":\"国内\"}],\"key\":\"iarea\"},{\"name\":\"年龄\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"0-3岁\"},{\"v\":\"2\",\"n\":\"4-6岁\"},{\"v\":\"3\",\"n\":\"7-9岁\"},{\"v\":\"4\",\"n\":\"10岁以上\"}],\"key\":\"iyear\"},{\"name\":\"性别\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"男孩\"},{\"v\":\"2\",\"n\":\"女孩\"}],\"key\":\"gender\"},{\"name\":\"类型\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"儿歌\"},{\"v\":\"2\",\"n\":\"益智\"},{\"v\":\"3\",\"n\":\"手工·绘画\"},{\"v\":\"4\",\"n\":\"玩具\"},{\"v\":\"5\",\"n\":\"英语\"},{\"v\":\"7\",\"n\":\"早教\"},{\"v\":\"6\",\"n\":\"数学\"},{\"v\":\"8\",\"n\":\"国学\"},{\"v\":\"9\",\"n\":\"合家欢\"},{\"v\":\"10\",\"n\":\"冒险\"},{\"v\":\"11\",\"n\":\"交通工具\"},{\"v\":\"12\",\"n\":\"魔幻·科幻\"},{\"v\":\"13\",\"n\":\"动物\"},{\"v\":\"14\",\"n\":\"真人特摄\"},{\"v\":\"15\",\"n\":\"探索\"},{\"v\":\"16\",\"n\":\"其他\"}],\"key\":\"itype\"},{\"name\":\"资费\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"1\",\"n\":\"免费\"},{\"v\":\"2\",\"n\":\"会员\"}],\"key\":\"ipay\"}],\"knowledge\":[{\"name\":\"排序\",\"value\":[{\"v\":\"41\",\"n\":\"最热\"},{\"v\":\"10\",\"n\":\"最新\"}],\"key\":\"sort\"},{\"name\":\"分类\",\"value\":[{\"v\":\"-1\",\"n\":\"全部\"},{\"v\":\"2\",\"n\":\"文化历史\"},{\"v\":\"3\",\"n\":\"亲子育儿\"},{\"v\":\"4\",\"n\":\"职场\"},{\"v\":\"5\",\"n\":\"商业理财\"},{\"v\":\"7\",\"n\":\"生活\"},{\"v\":\"9\",\"n\":\"情感心理\"},{\"v\":\"8\",\"n\":\"运动健身\"},{\"v\":\"6\",\"n\":\"艺术兴趣\"},{\"v\":\"12\",\"n\":\"游戏\"},{\"v\":\"14\",\"n\":\"科学科普\"},{\"v\":\"15\",\"n\":\"健康\"},{\"v\":\"16\",\"n\":\"IT/互联网\"}],\"key\":\"pay_level_one\"}]}"); + } 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 str2 = "http://node.video.qq.com/x/api/msearch?keyWord=" + str; + JSONArray jSONArray = new JSONObject(OkHttpUtil.string(str2, getHeaders(str2))).getJSONArray("uiData"); + JSONArray jSONArray2 = new JSONArray(); + for (int i = 0; i < jSONArray.length(); i++) { + JSONObject jSONObject = jSONArray.getJSONObject(i).getJSONArray("data").getJSONObject(0); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("vod_id", jSONObject.optString("id")); + jSONObject2.put("vod_name", jSONObject.optString("title")); + jSONObject2.put("vod_pic", jSONObject.optString("posterPic")); + jSONObject2.put("vod_remarks", jSONObject.optString("publishDate")); + jSONArray2.put(jSONObject2); + } + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put("list", jSONArray2); + return jSONObject3.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } +} diff --git a/app/src/main/java/com/github/catvod/spider/QXBiubiu.java b/app/src/main/java/com/github/catvod/spider/QXBiubiu.java new file mode 100644 index 0000000..1a4f58a --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/QXBiubiu.java @@ -0,0 +1,505 @@ +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.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 java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import okhttp3.Call; + +public class QXBiubiu extends Spider { + + @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(); + String[] fenleis = getRuleVal("fenlei", "").split("#"); + for (String fenlei : fenleis) { + String[] info = fenlei.split("\\$"); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("type_name", info[0]); + jsonObject.put("type_id", info[1]); + classes.put(jsonObject); + } + result.put("class", classes); + return result.toString(); + } catch ( + Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + protected HashMap getHeaders(String url) { + HashMap headers = new HashMap<>(); + String ua = getRuleVal("ua", Misc.UaWinChrome).trim(); + if (ua.isEmpty()) + ua = Misc.UaWinChrome; + headers.put("User-Agent", ua); + return headers; + } + + @Override + public String homeVideoContent() { + try { + fetchRule(); + if (getRuleVal("shouye").equals("1")) { + JSONArray videos = new JSONArray(); + String[] fenleis = getRuleVal("fenlei", "").split("#"); + for (String fenlei : fenleis) { + String[] info = fenlei.split("\\$"); + JSONObject data = category(info[1], "1", false, new HashMap<>()); + if (data != null) { + JSONArray vids = data.optJSONArray("list"); + if (vids != null) { + for (int i = 0; i < vids.length() && i < 5; i++) { + videos.put(vids.getJSONObject(i)); + } + } + } + if (videos.length() >= 30) + break; + } + JSONObject result = new JSONObject(); + result.put("list", videos); + return result.toString(); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + private JSONObject category(String tid, String pg, boolean filter, HashMap extend) { + try { + fetchRule(); + if (tid.equals("空")) + tid = ""; + String qishiye = rule.optString("qishiye", "nil"); + if (qishiye.equals("空")) + pg = ""; + else if (!qishiye.equals("nil")) { + pg = String.valueOf(Integer.parseInt(pg) - 1 + Integer.parseInt(qishiye)); + } + String webUrl = getRuleVal("url") + tid + pg + getRuleVal("houzhui"); + String html = fetch(webUrl); + html = removeUnicode(html); + String parseContent = html; + boolean shifouercijiequ = getRuleVal("shifouercijiequ").equals("1"); + if (shifouercijiequ) { + String jiequqian = getRuleVal("jiequqian"); + String jiequhou = getRuleVal("jiequhou"); + parseContent = subContent(html, jiequqian, jiequhou).get(0); + } + String jiequshuzuqian = getRuleVal("jiequshuzuqian"); + String jiequshuzuhou = getRuleVal("jiequshuzuhou"); + JSONArray videos = new JSONArray(); + ArrayList jiequContents = subContent(parseContent, jiequshuzuqian, jiequshuzuhou); + for (int i = 0; i < jiequContents.size(); i++) { + //try { + String jiequContent = jiequContents.get(i); + String title = removeHtml(subContent(jiequContent, getRuleVal("biaotiqian"), getRuleVal("biaotihou")).get(0)); + String pic = ""; + String tupianqian = getRuleVal("tupianqian").toLowerCase(); + if (tupianqian.startsWith("http://") || tupianqian.startsWith("https://")) { + pic = getRuleVal("tupianqian"); + } else { + pic = subContent(jiequContent, getRuleVal("tupianqian"), getRuleVal("tupianhou")).get(0); + } + pic = Misc.fixUrl(webUrl, pic); + String link = subContent(jiequContent, getRuleVal("lianjieqian"), getRuleVal("lianjiehou")).get(0); + link = getRuleVal("ljqianzhui").isEmpty() ? (link + getRuleVal("ljhouzhui")) : ("x:" + getRuleVal("ljqianzhui")) + link + getRuleVal("ljhouzhui"); + String remark = ""; + if (!getRuleVal("fubiaotiqian").isEmpty() && !getRuleVal("fubiaotihou").isEmpty()) { + try { + remark = subContent(jiequContent, getRuleVal("fubiaotiqian"), getRuleVal("fubiaotihou")).get(0).replaceAll("[\\s\\S]+", "").replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", ""); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + JSONObject v = new JSONObject(); + v.put("vod_id", title + "$$$" + pic + "$$$" + link); + v.put("vod_name", title); + v.put("vod_pic", pic); + v.put("vod_remarks", remark); + videos.put(v); + //} catch (Throwable th) { + //th.printStackTrace(); + //break; + //} + } + 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; + } catch (Exception e) { + SpiderDebug.log(e); + } + return null; + } + + private static String removeUnicode(String str) { + Pattern pattern = Pattern.compile("(\\\\u(\\w{4}))"); + Matcher matcher = pattern.matcher(str); + while (matcher.find()) { + String full = matcher.group(1); + String ucode = matcher.group(2); + char c = (char) Integer.parseInt(ucode, 16); + str = str.replace(full, c + ""); + } + return str; + } + + String removeHtml(String text) { + return Jsoup.parse(text).text(); + } + + @Override + public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { + JSONObject obj = category(tid, pg, filter, extend); + return obj != null ? obj.toString() : ""; + } + + @Override + public String detailContent(List ids) { + try { + fetchRule(); + String[] idInfo = ids.get(0).split("\\$\\$\\$"); + String webUrl = idInfo[2].startsWith("x:") ? idInfo[2] : getRuleVal("url") + idInfo[2]; + String html = fetch(webUrl.startsWith("x:") ? webUrl.substring(2) : webUrl); + String parseContent = html; + boolean bfshifouercijiequ = getRuleVal("bfshifouercijiequ").equals("1"); + if (bfshifouercijiequ) { + String jiequqian = getRuleVal("bfjiequqian"); + String jiequhou = getRuleVal("bfjiequhou"); + parseContent = subContent(html, jiequqian, jiequhou).get(0); + } + + ArrayList playList = new ArrayList<>(); + boolean playDirect = getRuleVal("直接播放").equals("1"); + if (!playDirect) { + String jiequshuzuqian = getRuleVal("bfjiequshuzuqian"); + String jiequshuzuhou = getRuleVal("bfjiequshuzuhou"); + boolean bfyshifouercijiequ = getRuleVal("bfyshifouercijiequ").equals("1"); + ArrayList jiequContents = subContent(parseContent, jiequshuzuqian, jiequshuzuhou); + for (int i = 0; i < jiequContents.size(); i++) { + try { + String jiequContent = jiequContents.get(i); + String parseJqContent = bfyshifouercijiequ ? subContent(jiequContent, getRuleVal("bfyjiequqian"), getRuleVal("bfyjiequhou")).get(0) : jiequContent; + ArrayList lastParseContents = subContent(parseJqContent, getRuleVal("bfyjiequshuzuqian"), getRuleVal("bfyjiequshuzuhou")); + List vodItems = new ArrayList<>(); + for (int j = 0; j < lastParseContents.size(); j++) { + String title = subContent(lastParseContents.get(j), getRuleVal("bfbiaotiqian"), getRuleVal("bfbiaotihou")).get(0); + String link = subContent(lastParseContents.get(j), getRuleVal("bflianjieqian"), getRuleVal("bflianjiehou")).get(0); + String bfqianzhui = getRuleVal("bfqianzhui"); + if (!bfqianzhui.isEmpty()) { + link = bfqianzhui + link; + } + vodItems.add(title + "$" + link); + } + playList.add(TextUtils.join("#", vodItems)); + } catch (Throwable th) { + th.printStackTrace(); + } + } + } else { + playList.add(idInfo[0] + "$" + idInfo[2]); + } + String cover = idInfo[1], title = idInfo[0], desc = "", category = "", area = "", year = "", remark = "", director = "", actor = ""; + + if (!getRuleVal("leixinqian").isEmpty() && !getRuleVal("leixinhou").isEmpty()) { + try { + category = subContent(html, getRuleVal("leixinqian"), getRuleVal("leixinhou")).get(0).replaceAll("\\s+", "").replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", ""); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + if (!getRuleVal("niandaiqian").isEmpty() && !getRuleVal("niandaihou").isEmpty()) { + try { + year = subContent(html, getRuleVal("niandaiqian"), getRuleVal("niandaihou")).get(0).replaceAll("\\s+", "").replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", ""); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + if (!getRuleVal("zhuangtaiqian").isEmpty() && !getRuleVal("zhuangtaihou").isEmpty()) { + try { + remark = subContent(html, getRuleVal("zhuangtaiqian"), getRuleVal("zhuangtaihou")).get(0); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + if (!getRuleVal("zhuyanqian").isEmpty() && !getRuleVal("zhuyanhou").isEmpty()) { + try { + actor = subContent(html, getRuleVal("zhuyanqian"), getRuleVal("zhuyanhou")).get(0).replaceAll("\\s+", ""); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + if (!getRuleVal("daoyanqian").isEmpty() && !getRuleVal("daoyanhou").isEmpty()) { + try { + director = subContent(html, getRuleVal("daoyanqian"), getRuleVal("daoyanhou")).get(0).replaceAll("\\s+", ""); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + if (!getRuleVal("juqingqian").isEmpty() && !getRuleVal("juqinghou").isEmpty()) { + try { + desc = subContent(html, getRuleVal("juqingqian"), getRuleVal("juqinghou")).get(0); + } 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<>(); + String xlparseContent = html; + if(getRuleVal("xlbiaotiqian").isEmpty() && getRuleVal("xlbiaotihou").isEmpty()){ + + for (int i = 0; i < playList.size(); i++) { + playFrom.add("播放列表" + (i + 1)); + } + }else{ + + boolean xlshifouercijiequ = getRuleVal("xlshifouercijiequ").equals("1"); + if (xlshifouercijiequ) { + String xljiequqian = getRuleVal("xljiequqian"); + String xljiequhou = getRuleVal("xljiequhou"); + xlparseContent = subContent(html, xljiequqian, xljiequhou).get(0); + } + + String xljiequshuzuqian = getRuleVal("xljiequshuzuqian"); + String xljiequshuzuhou = getRuleVal("xljiequshuzuhou"); + ArrayList xljiequContents = subContent(xlparseContent, xljiequshuzuqian, xljiequshuzuhou); + for (int i = 0; i < playList.size(); i++) { + try { + String xltitle = subContent(xljiequContents.get(i), getRuleVal("xlbiaotiqian"), getRuleVal("xlbiaotihou")).get(0).replaceAll("\\s+", "").replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", ""); + playFrom.add(xltitle); + } catch (Throwable th) { + th.printStackTrace(); + break; + } + } + + } + + 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); + + JSONObject result = new JSONObject(); + JSONArray list = new JSONArray(); + list.put(vod); + 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 { + fetchRule(); + String webUrl = id.startsWith("x:") ? id.substring(2) : getRuleVal("url") + id; + JSONObject result = new JSONObject(); + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", webUrl); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public String searchContent(String key, boolean quick) { + try { + fetchRule(); + boolean ssmoshiJson = getRuleVal("ssmoshi").equals("0"); + String webUrlTmp = getRuleVal("url") + getRuleVal("sousuoqian") + key + getRuleVal("sousuohou"); + String webUrl = webUrlTmp.split(";")[0]; + String webContent = webUrlTmp.contains(";post") ? fetchPost(webUrl) : fetch(webUrl); + JSONObject result = new JSONObject(); + JSONArray videos = new JSONArray(); + if (ssmoshiJson) { + JSONObject data = new JSONObject(webContent); + JSONArray vodArray = data.getJSONArray("list"); + for (int j = 0; j < vodArray.length(); j++) { + JSONObject vod = vodArray.getJSONObject(j); + String name = vod.optString(getRuleVal("jsname")).trim(); + String id = vod.optString(getRuleVal("jsid")).trim(); + String pic = vod.optString(getRuleVal("jspic")).trim(); + pic = Misc.fixUrl(webUrl, pic); + String link = getRuleVal("sousuohouzhui") + id; + link = getRuleVal("ssljqianzhui").isEmpty() ? (link + getRuleVal("ssljhouzhui")) : ("x:" + getRuleVal("ssljqianzhui")) + link + getRuleVal("ssljhouzhui"); + JSONObject v = new JSONObject(); + v.put("vod_id", name + "$$$" + pic + "$$$" + link); + v.put("vod_name", name); + v.put("vod_pic", pic); + v.put("vod_remarks", ""); + videos.put(v); + } + } else { + String parseContent = webContent; + boolean shifouercijiequ = getRuleVal("sousuoshifouercijiequ").equals("1"); + if (shifouercijiequ) { + String jiequqian = getRuleVal("ssjiequqian"); + String jiequhou = getRuleVal("ssjiequhou"); + parseContent = subContent(webContent, jiequqian, jiequhou).get(0); + } + String jiequshuzuqian = getRuleVal("ssjiequshuzuqian"); + String jiequshuzuhou = getRuleVal("ssjiequshuzuhou"); + ArrayList jiequContents = subContent(parseContent, jiequshuzuqian, jiequshuzuhou); + for (int i = 0; i < jiequContents.size(); i++) { + try { + String jiequContent = jiequContents.get(i); + String title = subContent(jiequContent, getRuleVal("ssbiaotiqian"), getRuleVal("ssbiaotihou")).get(0); + String pic = subContent(jiequContent, getRuleVal("sstupianqian"), getRuleVal("sstupianhou")).get(0); + pic = Misc.fixUrl(webUrl, pic); + String link = subContent(jiequContent, getRuleVal("sslianjieqian"), getRuleVal("sslianjiehou")).get(0); + link = getRuleVal("ssljqianzhui").isEmpty() ? (link + getRuleVal("ssljhouzhui")) : ("x:" + getRuleVal("ssljqianzhui")) + link + getRuleVal("ssljhouzhui"); + JSONObject v = new JSONObject(); + v.put("vod_id", title + "$$$" + pic + "$$$" + link); + v.put("vod_name", title); + v.put("vod_pic", pic); + v.put("vod_remarks", ""); + videos.put(v); + } catch (Throwable th) { + th.printStackTrace(); + break; + } + } + } + result.put("list", videos); + return result.toString(); + } catch ( + Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + protected String ext = null; + protected JSONObject rule = null; + + protected void fetchRule() { + if (rule == null) { + if (ext != null) { + try { + if (ext.startsWith("http")) { + String json = OkHttpUtil.string(ext, null); + rule = new JSONObject(json); + } else { + rule = new JSONObject(ext); + } + } catch (JSONException e) { + } + } + } + } + + protected String fetch(String webUrl) { + SpiderDebug.log(webUrl); + return OkHttpUtil.string(webUrl, getHeaders(webUrl)).replaceAll("\r|\n", ""); + } + + protected String fetchPost(String webUrl) { + SpiderDebug.log(webUrl); + OKCallBack.OKCallBackString callBack = new OKCallBack.OKCallBackString() { + @Override + protected void onFailure(Call call, Exception e) { + + } + + @Override + protected void onResponse(String response) { + } + }; + OkHttpUtil.post(OkHttpUtil.defaultClient(), webUrl, callBack); + return callBack.getResult().replaceAll("\r|\n", ""); + } + + private String getRuleVal(String key, String defaultVal) { + String v = rule.optString(key); + if (v.isEmpty() || v.equals("空")) + return defaultVal; + return v; + } + + private String getRuleVal(String key) { + return getRuleVal(key, ""); + } + + private ArrayList subContent(String content, String startFlag, String endFlag) { + ArrayList result = new ArrayList<>(); + if (startFlag.isEmpty() && endFlag.isEmpty()) { + result.add(content); + return result; + } + try { + Pattern pattern = Pattern.compile(escapeExprSpecialWord(startFlag) + "(.*?)" + escapeExprSpecialWord(endFlag)); + Matcher matcher = pattern.matcher(content); + while (matcher.find()) { + result.add(matcher.group(1)); + } + } catch (Throwable th) { + th.printStackTrace(); + } + return result; + } + + String escapeExprSpecialWord(String regexStr) { + if (!regexStr.isEmpty()) { + String[] fbsArr = {"\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|"}; + for (String key : fbsArr) { + if (regexStr.contains(key)) { + regexStr = regexStr.replace(key, "\\" + key); + } + } + } + return regexStr; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/SP293.java b/app/src/main/java/com/github/catvod/spider/SP293.java new file mode 100644 index 0000000..136805a --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/SP293.java @@ -0,0 +1,339 @@ +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.spider.merge.RSA; +import com.github.catvod.utils.okhttp.OkHttpUtil; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.json.JSONArray; +import org.json.JSONObject; + +public class SP293 extends Spider { + public static String l = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL4cSBLgAtKxA3brZ73KA6/uagCFNBqh3+GVWZGyKlrChUrrqcBHmV/fZcH/oVIwZHCxv0rnOesTE7WZhzgbbUEsBDK8W8+paIwQI3Pvpp3JzEvduOfS/4G4EPYpKiGE3+vK9q7h+9xVv6FS8uzKAe6uS98qDgHad46cMJVkYR0DAgMBAAECgYAZMBAQiCN3nMJTwC63g4tnhNQAi6Vynd3Wun3qgst/yOP2IDEWa6YTgLqvsFnEVOsJz1MD7ozK63UiC1xR/7hCvqTziaV7g0lCB9Gk9ZMRIpS8pPtfnDSMjeYzMCQWvdRMOf8BkFp7SISCtlQRm9VKKRKMZ27zH3BvIvTed4tYoQJBAOw7Gda7L2CXBdKfpRK6KgUVkki/d9qEcm1kS9TFAxrQcEWdijF7l9w8LnaBPC0uaRKmEB4/uiOMXXN89Vo6CnECQQDOBR57KgMAAKDzFIRDyegl1Y6xTpEIi0/YlTlPyZmYpG2vS6czG+OQfJoT/w/vBw7mMGTR3IiQwF2qqYACUNCzAkEA60suwGgvl3i1jwX+iLmu8uN6kkVL3vZ/dyAoO+SD5ChrO5vgMstVBkNXUCgHRUVt2OpZMZfuEkxUJJz5UQZwsQJAUCLFnHrW9+VGtcbBO+0Jk83h1y4MVBp8UG6bAGIWkL1EvO7cdpDej5EoDack94DzVq50SP1TUZrB1GRiGoR86QJAfy9NP2vDtk8MyjIUWjpYTTUhjMk/6WurIBtwEzE56QLFLshm1KwEFh25qrdI4vXChQQKXAgu17b+I7qfYh2IMA=="; + public static String qb = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDWHmmu0aFU2m1ZnQb09+/QQRnuy3GmcwnTnFwPLR/CsfbsxiNQLULpdwhC1h1U/3yEyc2kZ549+X3iYFed3tHa0NLntcSw6w6IcEAgiaeHasRlzh98IgEai9XChbhLAy7a/s4HnhFXJCsg5/FqrjZ/FuEOhbCN3gWcc6Aly+OZhwIDAQAB"; + public static String zC = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMNlbdQeVJIW9baQ7qAUYL6gbMfKcfxuwTlt+eh8hf9oC2lcztpjwm1s/MWqHk7/yFpps/vup6p+1inh5gzlKov9Ay5hHa3feYtKsb07jgKyfUJUhAqRIrqAQz+XL96dtDyaGXd2mT2Vo7OLcN6NeDcGR8c5tVG34o3LEDEd9s8dAgMBAAECgYEAvxaGnhc7ZdOGYRDEDVFge4ywVYMqjlBSLzPaXv7InMrHvjbBJNrC3fjkCvsfwOpsqd8N4ae32QlJsJP3Q00qmR9I8beLjUe50zOSk1ExSdKTAHV8iHFlxxQhfP0y9T7pTYuDFMRC8Qcc2J7d6OUVF3Au/GBM6P8yFrKeDx2hXQECQQDjM4V75SmQ+dtPjajzBZt9OctVwAfEVePUX84dioMOS1W7KxaHYYpZMPMC9SkAsCYuGhw2bXIiCRQM+6PDm9aRAkEA3CncsOQTLRgpGOo/Lr5UXybq8EVB5s1ItTd+dCqAH8i220kw5OXH3siMwLJBdv8zUVrAwqocaNRzgjYY1WytzQJBAKAjAEKDEvkMIne/8QTZPu7UfWzDHLZVk29s12oa5qR8lMCHbimdplWXGrFK+stxXHfCD4CNQ5SZsXg1JQgKHwECQFprxvvPcCDBH3/gFPr5qGU78pmjmCFWhloG5KSJH/3tzUvaj34y8ReKfmRV0ZUx0r3C7BAHFYvoVVhRJ3ngHLECQQCC5iTBfTdd51Lb5kwxffk/iw+BRAsZ5SAzUlmwRyB0cvX/9yvton8PPK590yYQqkc6BMmNePzRypVlYNXzhYfe"; + public static String zcC = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAM6T6V5lfKE5miEMR88NalNn6CvzQC+PR8bH0ipUege8D/tFgjh22J3Yh1Ibgl1zsoifz3eF8/IKWZ6Hui7iUeOvbZteCuz7IBLFvnbPsNCP7SbLGPYRasVp3zqwt2NV72aZ/bI9pLczK2+b0R+KJXZ5V6fmVFx/QWWAo+NmkerVAgMBAAECgYA0yBQjm1iptRcNhJ7AZ5QYNX9b424t+LUFND8ds7HuUf3fXNY16R/VzOJed0rq58nhILwYtPAskrptSA6pNghn56dike27vANR6mTaYv+0o1FS/+lGQ1UohSAnzVw30L/tJzrobvvU4joXYjb95typAOiIvcOh8WAuwQRU7I5MAQJBAPh/Ji6mKbllYHAn+sHdE0cGm8QISZz+7dvZQQ8L7MzJG1eUYZXCXQ9Fiqrk3kLNwq6IW+eruBsH4HJa9LNyjwECQQDU0Lvy/EnnQNITryXQ20gxR+x4e9Nak+4GJbL6JFf9kqCUhei2ni8t/RO7wp+jrKUy2kdzGlRL+cv5dgxzv+/VAkBQua2DtgMT8TT0+mfhlpnultz/P9n6IG7Q3rDd3Hfexu4U82UIK43jqimz/omdlg5KeI2yovw5+8MUIywfJ3YBAkBanIVp8AGHdRH9T5XKV5NlaDpHEnHrHxE5jNOnrdHJJaU5l8p99twfuKGuUC+ogNnVzRqe55b8wl8W2Cx1HEQBAkAzWKejO1OWmdf+VwgUwShiRMvlNvzO7iPoyE6B4DrLM5dAMk8BN4Cyk1T/4pDfcj9FCydDk3fCmtPA0DWngU6A"; + private String n8 = ""; + private Map> ug = new HashMap(); + private String v = ""; + private String in = ""; + private String I4 = ""; + + private String l(String str) { + return RSA.l(str, qb); + } + + private HashMap n8() { + HashMap hashMap = new HashMap<>(); + hashMap.put("User-Agent", "Dalvik/2.1.0 (Linux; U; Android 10; PBEM00 Build/QKQ1.190918.001)"); + return hashMap; + } + + private String qb(String str, String str2) { + return RSA.qb(str, str2); + } + + private String zC() { + return String.valueOf(System.currentTimeMillis() / 1000); + } + + public String categoryContent(String str, String str2, boolean z, HashMap hashMap) { + JSONObject jSONObject = new JSONObject(); + try { + String str3 = this.n8 + "api.php/Videolast/video?class="; + if (hashMap.containsKey("class")) { + str3 = str3 + hashMap.get("class"); + } + String str4 = str3 + "&area="; + if (hashMap.containsKey("area")) { + str4 = str4 + hashMap.get("area"); + } + String str5 = str4 + "&year="; + if (hashMap.containsKey("year")) { + str5 = str5 + hashMap.get("year"); + } + JSONArray jSONArray = new JSONObject(qb(OkHttpUtil.string(str5 + "&tid=" + str + "&pg=" + str2 + "&limit=20&csrf=" + URLEncoder.encode(l(zC())), n8()), l)).getJSONArray("data"); + JSONArray jSONArray2 = new JSONArray(); + for (int i = 0; i < jSONArray.length(); i++) { + JSONObject jSONObject2 = jSONArray.getJSONObject(i); + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put("vod_id", jSONObject2.getString("vod_id")); + jSONObject3.put("vod_name", jSONObject2.getString("vod_name")); + jSONObject3.put("vod_pic", jSONObject2.getString("vod_pic")); + jSONObject3.put("vod_remarks", jSONObject2.getString("vod_remarks")); + jSONArray2.put(jSONObject3); + } + int parseInt = Integer.parseInt(str2); + jSONObject.put("page", parseInt); + if (jSONArray2.length() == 12) { + parseInt++; + } + jSONObject.put("pagecount", parseInt); + jSONObject.put("limit", 12); + jSONObject.put("total", Integer.MAX_VALUE); + jSONObject.put("list", jSONArray2); + } catch (Exception e) { + SpiderDebug.log(e); + } + return jSONObject.toString(); + } + + public String detailContent(List list) { + JSONObject jSONObject = new JSONObject(); + try { + JSONObject jSONObject2 = new JSONObject(); + String zC2 = zC(); + String l2 = l(zC2); + jSONObject2.put("time", zC2); + String str = new String(RSA.l(l2, qb)); + JSONObject aa = new JSONObject(OkHttpUtil.string(this.n8 + "api.php/Videolast/videoDetail?id=" + list.get(0) + "&ck=" + URLEncoder.encode(str) + "&csrf=" + URLEncoder.encode(l2), n8())); + //String ba = aa.optJSONObject("data").toString(); + JSONObject optJSONObject = new JSONObject(qb(aa.optString("data"), l)).optJSONObject("data").optJSONObject("vod_info"); + //JSONObject optJSONObjects = new JSONObject(qb(OkHttpUtil.string(this.n8 + "api.php/Videolast/videoDetail?id=" + list.get(0) + "&ck=" + URLEncoder.encode(str) + "&csrf=" + URLEncoder.encode(l2), n8()), l)).optJSONObject("data").optJSONObject("vod_info"); + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put("vod_id", optJSONObject.getString("vod_id")); + jSONObject3.put("vod_name", optJSONObject.getString("vod_name")); + jSONObject3.put("vod_pic", optJSONObject.getString("vod_pic")); + jSONObject3.put("type_name", optJSONObject.optString("vod_class")); + jSONObject3.put("vod_year", optJSONObject.optString("vod_year")); + jSONObject3.put("vod_area", optJSONObject.optString("vod_area")); + jSONObject3.put("vod_remarks", optJSONObject.optString("vod_remarks")); + jSONObject3.put("vod_actor", optJSONObject.optString("vod_actor")); + jSONObject3.put("vod_content", optJSONObject.optString("vod_content").trim()); + JSONArray jSONArray = aa.getJSONArray("video_list"); + LinkedHashMap linkedHashMap = new LinkedHashMap(); + for (int i = 0; i < jSONArray.length(); i++) { + JSONObject jSONObject4 = jSONArray.getJSONObject(i); + String string = jSONObject4.getString("code"); + linkedHashMap.put(string, jSONObject4.optString("url")); + JSONArray optJSONArray = jSONObject4.optJSONArray("parse_api"); + this.I4 = jSONObject4.optString("user_agent"); + if (!this.ug.containsKey(string)) { + HashSet hashSet = new HashSet(); + for (int i2 = 0; i2 < optJSONArray.length(); i2++) { + hashSet.add(optJSONArray.optString(i2)); + } + this.ug.put(string, hashSet); + SpiderDebug.log(this.ug.toString()); + } else { + Set set = this.ug.get(string); + for (int i3 = 0; i3 < optJSONArray.length(); i3++) { + set.add(optJSONArray.optString(i3)); + } + } + } + String join = TextUtils.join("$$$", linkedHashMap.keySet()); + String join2 = TextUtils.join("$$$", linkedHashMap.values()); + jSONObject3.put("vod_play_from", join); + jSONObject3.put("vod_play_url", join2); + JSONArray jSONArray2 = new JSONArray(); + jSONArray2.put(jSONObject3); + jSONObject.put("list", jSONArray2); + } catch (Exception unused) { + } + return jSONObject.toString(); + } + + public String homeContent(boolean z) { + String str = "type_id"; + String str2 = "type_name"; + JSONObject jSONObject = new JSONObject(); + try { + JSONArray jSONArray = new JSONObject(qb(OkHttpUtil.string(this.n8 + "api.php/Videolast/nav?csrf=" + URLEncoder.encode(l(zC())), (Map) null), l)).getJSONArray("data"); + JSONArray jSONArray2 = new JSONArray(); + for (int i = 0; i < jSONArray.length(); i++) { + JSONObject jSONObject2 = jSONArray.getJSONObject(i); + String string = jSONObject2.getString(str2); + String string2 = jSONObject2.getString(str); + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put(str, string2); + jSONObject3.put(str2, string); + JSONObject optJSONObject = jSONObject2.optJSONObject("type_extend"); + if (!z || optJSONObject == null) { + str = str; + str2 = str2; + jSONArray = jSONArray; + } else { + JSONArray jSONArray3 = new JSONArray(); + LinkedHashMap linkedHashMap = new LinkedHashMap(); + linkedHashMap.put("class", "剧情"); + linkedHashMap.put("area", "地区"); + linkedHashMap.put("lang", "语言"); + linkedHashMap.put("year", "年份"); + Iterator it = linkedHashMap.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = (Map.Entry) it.next(); + String string3 = optJSONObject.getString((String) entry.getKey()); + if (!TextUtils.isEmpty(string3)) { + JSONObject jSONObject4 = new JSONObject(); + jSONObject4.put("key", entry.getKey()); + jSONObject4.put("name", entry.getValue()); + jSONArray3.put(jSONObject4); + String[] split = string3.split(","); + JSONArray jSONArray4 = new JSONArray(); + JSONObject jSONObject5 = new JSONObject(); + jSONObject5.put("n", "全部"); + jSONObject5.put("v", ""); + jSONArray4.put(jSONObject5); + int length = split.length; + int i2 = 0; + while (i2 < length) { + String str3 = split[i2]; + JSONObject jSONObject6 = new JSONObject(); + jSONObject6.put("n", str3); + jSONObject6.put("v", str3); + jSONArray4.put(jSONObject6); + i2++; + jSONArray = jSONArray; + split = split; + } + jSONObject4.put("value", jSONArray4); + it = it; + str = str; + str2 = str2; + jSONArray = jSONArray; + } + } + str = str; + str2 = str2; + jSONArray = jSONArray; + if (!jSONObject.has("filters")) { + jSONObject.put("filters", new JSONObject()); + } + jSONObject.getJSONObject("filters").put(string2, jSONArray3); + } + jSONArray2.put(jSONObject3); + } + jSONObject.put("class", jSONArray2); + } catch (Exception e) { + SpiderDebug.log(e); + } + return jSONObject.toString(); + } + + public String homeVideoContent() { + JSONObject jSONObject = new JSONObject(); + try { + JSONArray jSONArray = new JSONArray(); + JSONArray jSONArray2 = new JSONObject(qb(OkHttpUtil.string(this.n8 + "api.php/Videolast/indexVideo?csrf=" + URLEncoder.encode(l(zC())), n8()), l)).getJSONArray("data"); + for (int i = 0; i < jSONArray2.length(); i++) { + JSONArray jSONArray3 = jSONArray2.getJSONObject(i).getJSONArray("vlist"); + for (int i2 = 0; i2 < jSONArray3.length(); i2++) { + JSONObject jSONObject2 = jSONArray3.getJSONObject(i2); + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put("vod_id", jSONObject2.getString("vod_id")); + jSONObject3.put("vod_name", jSONObject2.getString("vod_name")); + jSONObject3.put("vod_pic", jSONObject2.getString("vod_pic")); + jSONObject3.put("vod_remarks", jSONObject2.getString("vod_remarks")); + jSONArray.put(jSONObject3); + } + } + jSONObject.put("list", jSONArray); + } catch (Exception e) { + SpiderDebug.log(e); + } + return jSONObject.toString(); + } + + public void init(Context context) { + SP293.super.init(context); + } + + public boolean isVideoFormat(String str) { + return SP293.super.isVideoFormat(str); + } + + public boolean manualVideoCheck() { + return SP293.super.manualVideoCheck(); + } + + public String playerContent(String str, String str2, List list) { + JSONObject jSONObject = new JSONObject(); + try { + jSONObject.put("parse", "0"); + jSONObject.put("playUrl", ""); + SpiderDebug.log(new JSONObject(this.ug).toString()); + if (this.ug.containsKey(str)) { + Iterator it = this.ug.get(str).iterator(); + while (true) { + if (!it.hasNext()) { + break; + } + HashMap hashMap = new HashMap(); + hashMap.put("User-Agent", "hahaha"); + //hashMap.put("Host", "123.56.222.84:2025"); + JSONObject jSONObject2 = new JSONObject(OkHttpUtil.string(it.next() + str2 + "&appId=1000&version=1.3.3&device_id=b08b45ee1124f23b", hashMap)); + String optString = jSONObject2.optString("data"); + + Integer valueOf = Integer.valueOf(jSONObject2.optInt("encryption")); + if (Integer.valueOf(jSONObject2.optInt("code")).intValue() == 1 || (!optString.equals("") && valueOf.intValue() >= 0)) { + if (valueOf.intValue() == 1) { + JSONObject jSONObject3 = new JSONObject(qb(jSONObject2.optString("data"), zcC)); + String optString2 = jSONObject3.optString("url"); + String optString3 = jSONObject3.optString("header"); + if (!TextUtils.isEmpty(optString2)) { + jSONObject.put("url", optString2); + if (!TextUtils.isEmpty(optString3) && optString2.contains("weiyun")) { + jSONObject.put("header", optString3); + } + } + } else if (valueOf.intValue() == 0) { + String optString4 = new JSONObject(optString).optString("url"); + if (!TextUtils.isEmpty(optString4)) { + jSONObject.put("url", optString4); + break; + } + } else { + continue; + } + } + } + } + } catch (Exception e) { + SpiderDebug.log(e); + } + return jSONObject.toString(); + } + + public String searchContent(String str, boolean z) { + JSONObject jSONObject = new JSONObject(); + try { + JSONArray optJSONArray = new JSONObject(qb(OkHttpUtil.string(this.n8 + "api.php/Videolast/search?pg=1&text=" + URLEncoder.encode(str) + "&pg=1&csrf=" + URLEncoder.encode(l(zC())), n8()), l)).optJSONArray("data"); + JSONArray jSONArray = new JSONArray(); + for (int i = 0; i < optJSONArray.length(); i++) { + JSONObject jSONObject2 = optJSONArray.getJSONObject(i); + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put("vod_id", jSONObject2.getString("vod_id")); + jSONObject3.put("vod_name", jSONObject2.getString("vod_name")); + jSONObject3.put("vod_pic", jSONObject2.getString("vod_pic")); + jSONObject3.put("vod_remarks", jSONObject2.getString("vod_remarks")); + jSONArray.put(jSONObject3); + } + jSONObject.put("list", jSONArray); + } catch (Exception e) { + SpiderDebug.log(e); + } + return jSONObject.toString(); + } + + public void init(Context context, String str) { + try { + this.n8 = new JSONObject(qb(OkHttpUtil.string("https://alogin.oss-cn-beijing.aliyuncs.com/iphones.json", n8()), zC)).optJSONObject("data").optString("url"); + JSONObject jSONObject = new JSONObject(OkHttpUtil.string("https://agit.ai/fangzimo/TVBox/raw/branch/main/293.txt", (Map) null)); + this.in = jSONObject.optString("appId"); + this.v = jSONObject.optString("version"); + + } catch (Exception e) { + SpiderDebug.log(e); + } + } +} diff --git a/app/src/main/java/com/github/catvod/spider/Tangrenjie.java b/app/src/main/java/com/github/catvod/spider/Tangrenjie.java new file mode 100644 index 0000000..eb24503 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Tangrenjie.java @@ -0,0 +1,538 @@ +package com.github.catvod.spider; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Base64; +import android.widget.Switch; + +import java.net.URLDecoder; + +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; + +public class Tangrenjie extends Spider { + private static final String siteUrl = "https://www.tangrenjie.tv"; + private static final String siteHost = "tangrenjie.tv"; + /** + * 播放源配置 + */ + private JSONObject playerConfig; + /** + * 筛选配置 + */ + private JSONObject filterConfig; + private Pattern regexCategory = Pattern.compile("/vod/type/id/(\\d+).html"); + private Pattern regexVid = Pattern.compile("/vod/detail/id/(\\d+).html"); + private Pattern regexPlay = Pattern.compile("/vod/play/id/(\\d+)/sid/(\\d+)/nid/(\\d+).html"); + private Pattern regexPage = Pattern.compile("\\S+/page/(\\d+)\\S+"); + + @Override + public void init(Context context) { + super.init(context); + try { + playerConfig = new JSONObject("{\"if101\":{\"show\":\"蓝光一\",\"des\":\"\",\"ps\":\"0\",\"parse\":\"\",\"or\":999}}"); + filterConfig = new JSONObject("{\"1\":[{\"key\":\"cateId\",\"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\"}]},{\"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\":\"其他\"}]},{\"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\":\"2008\",\"v\":\"2008\"},{\"n\":\"2000\",\"v\":\"2000\"},{\"n\":\"1997\",\"v\":\"1997\"},{\"n\":\"1980\",\"v\":\"1980\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"2\":[{\"key\":\"cateId\",\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国产剧\",\"v\":\"13\"},{\"n\":\"港台剧\",\"v\":\"14\"},{\"n\":\"日韩剧\",\"v\":\"15\"},{\"n\":\"欧美剧\",\"v\":\"16\"},{\"n\":\"海外剧\",\"v\":\"27\"}]},{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"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\":\"2008\",\"v\":\"2008\"},{\"n\":\"2000\",\"v\":\"2000\"},{\"n\":\"1997\",\"v\":\"1997\"},{\"n\":\"1980\",\"v\":\"1980\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"4\":[{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"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\":\"2008\",\"v\":\"2008\"},{\"n\":\"2000\",\"v\":\"2000\"},{\"n\":\"1997\",\"v\":\"1997\"},{\"n\":\"1980\",\"v\":\"1980\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"3\":[{\"key\":\"cateId\",\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"纪录片\",\"v\":\"28\"}]},{\"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\":\"其他\"}]},{\"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\":\"2008\",\"v\":\"2008\"},{\"n\":\"2000\",\"v\":\"2000\"},{\"n\":\"1997\",\"v\":\"1997\"},{\"n\":\"1980\",\"v\":\"1980\"}]},{\"key\":\"by\",\"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("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.top_nav li a"); + JSONArray classes = new JSONArray(); + for (Element ele : elements) { + Elements b = ele.select("b"); + String name = b.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("div.cbox1").get(1); + Elements list = homeList.select("ul.vodlist li.vodlist_item"); + JSONArray videos = new JSONArray(); + for (int i = 0; i < list.size(); i++) { + Element vod = list.get(i); + String title = vod.selectFirst("a.vodlist_thumb").attr("title"); + String cover = siteUrl + vod.selectFirst("a.vodlist_thumb").attr("data-original"); + String remark = vod.select("span.pic_text b").text(); + + Matcher matcher = regexVid.matcher(vod.selectFirst("a.vodlist_thumb").attr("href")); + if (!matcher.find()) + continue; + String id = "1="+ 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 + "/vod/show/id/"; + 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("ul.page"); + 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("li a"); + if (a == null) + continue; + String span = pageInfo.select("li.active a").text(); + String wy = doc.select("ul.page li a").last().attr("href"); + if (page == -1) { + page = Integer.parseInt(span); + } else { + page = 0; + } + Matcher matcher = regexPage.matcher(wy); + 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.vodlist li.vodlist_item"); + for (int i = 0; i < list.size(); i++) { + Element vod = list.get(i); + String title = vod.selectFirst("a.vodlist_thumb").attr("title"); + String cover = siteUrl + vod.selectFirst("a.vodlist_thumb").attr("data-original"); + String remark = vod.select("span.pic_text b").text(); + Matcher matcher = regexVid.matcher(vod.selectFirst("a.vodlist_thumb").attr("href")); + if (!matcher.find()) + continue; + String id = tid + "=" + 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", 20); + result.put("total", pageCount <= 1 ? videos.length() : pageCount * 20); + 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[] idd = ids.get(0).split("="); + String tid =idd[0]; + String detail = idd[1]; + String url = siteUrl + "/vod/detail/id/" + detail + ".html"; + String htmltemp = OkHttpUtil.string(url, getHeaders(url)); + String htmlsrc =""; + if(tid.equals("1")){ + htmlsrc = htmltemp.substring(0,25000); + }else{ + htmlsrc = htmltemp; + } + Document doc = Jsoup.parse(htmlsrc); + JSONObject result = new JSONObject(); + JSONObject vodList = new JSONObject(); + // 取基本数据 + String vid = doc.selectFirst("div.content_thumb a").attr("href"); + String cover = siteUrl + doc.selectFirst("div.content_thumb a").attr("data-original"); + String title = doc.selectFirst("div.content_thumb a").attr("title"); + String desc = doc.selectFirst("div.content > section > font").text(); + String category = "", area = "", year = "", director = "", actor = "", remark = ""; + remark = doc.select("span.data_style b").text(); + Elements span_text_muted = doc.select("li.data span"); + for (int i = 0; i < span_text_muted.size() - 2; i++) { + Element text = span_text_muted.get(i); + String info = text.text(); + if (info.contains("类型")) { + try { + String cate = text.parent().text(); + category =cate.substring(3); + } catch (Exception e) { + category = ""; + } + } else if (info.contains("年份")) { + try { + year = text.parent().select("a").get(0).text(); + } catch (Exception e) { + year = ""; + } + } else if (info.contains("地区")) { + try { + area = text.parent().select("a").get(0).text(); + } catch (Exception e) { + area = ""; + } + } + } + List actors = new ArrayList<>(); + Elements aa = doc.select("li.data").get(0).select("a"); + for (int j = 0; j < aa.size(); j++) { + actors.add(aa.get(j).text()); + } + actor = TextUtils.join(",", actors); + List directors = new ArrayList<>(); + Elements bb = doc.select("li.data").get(1).select("a"); + for (int j = 0; j < bb.size(); j++) { + directors.add(bb.get(j).text()); + } + director = TextUtils.join(",", directors); + 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.play_source_tab a"); + Elements sourceList = doc.select("div.playlist_full"); + for (int i = 0; i < sources.size(); i++) { + Element source = sources.get(i); + String sourceName = source.attr("alt"); + sourceName = sourceName.replaceAll("[^\u4E00-\u9FA5]", ""); + 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) + 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) + "/sid/" + matcher.group(2) + "/nid/" + matcher.group(3); + vodItems.add( vod.text() + "$" + playURL + "="+ tid); + } + 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[] idd = id.split("="); + String tid =idd[1]; + String detail = idd[0]; + String url = siteUrl + "/vod/play/id/" + detail + ".html"; + String htmltemp = OkHttpUtil.string(url, getHeaders(url)); + String htmlsrc =""; + if(tid.equals("1")){ + htmlsrc = htmltemp.substring(0,25000); + }else{ + htmlsrc = htmltemp; + } + Document doc = Jsoup.parse(htmlsrc); + Elements allScript = doc.select("script"); + JSONObject result = new JSONObject(); + 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); + String urlsrc = player.getString("url"); + String urlb64 = new String(Base64.decode(urlsrc.getBytes(), Base64.DEFAULT)); + String urldec = URLDecoder.decode(urlb64,"UTF-8"); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", urldec); + result.put("header", ""); + break; + } + + } + //无直链则嗅探 + String uu = result.getString("url"); + if (!(uu.length() >0)){ + result.put("parse", 1); + result.put("url", url); + } + + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public String searchContent(String key, boolean quick) { + try { + String url = siteUrl + "/vod/search.html?wd=" + URLEncoder.encode(key) + "&submit="; + String html = OkHttpUtil.string(url, getHeaders(url)); + Document doc = Jsoup.parse(html); + JSONObject result = new JSONObject(); + JSONArray videos = new JSONArray(); + if (!html.contains("没有找到您想要的结果哦")) { + Elements list = doc.select("li.searchlist_item"); + for (int i = 0; i < list.size(); i++) { + Element vod = list.get(i); + String classes = vod.selectFirst("h4.vodlist_title > a >span").text(); + String tid=""; + switch (classes) { + case "电影": + tid = "1"; + break; + case "电视剧": + tid = "2"; + break; + case "综艺": + tid = "3"; + break; + case "动漫": + tid = "4"; + break; + } + String title = vod.selectFirst("a.vodlist_thumb").attr("title"); + String cover = siteUrl + vod.selectFirst("a.vodlist_thumb").attr("data-original"); + String remark = vod.select("span.pic_text").text(); + Matcher matcher = regexVid.matcher(vod.selectFirst("a.vodlist_thumb").attr("href")); + if (!matcher.find()) + continue; + String id = tid + "=" + 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 ""; + } + + 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; + } + + @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; + } + +} diff --git a/app/src/main/java/com/github/catvod/spider/Upyunso.java b/app/src/main/java/com/github/catvod/spider/Upyunso.java new file mode 100644 index 0000000..1229f0b --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Upyunso.java @@ -0,0 +1,118 @@ +package com.github.catvod.spider; + +import android.content.Context; +import android.util.Base64; + +import com.github.catvod.crawler.Spider; +import com.github.catvod.utils.okhttp.OkHttpUtil; + +import java.net.URLEncoder; +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 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; + + +public class Upyunso extends Spider { + private PushAgent pushAgent; + private static String siteUrl = "https://www.upyunso.com/"; + private static String apiUrl = "https://api.upyunso.com/"; + private static Pattern aliyun = Pattern.compile("(https:\\/\\/www.aliyundrive.com\\/s\\/[^\\\"]+)"); + + @Override + public void init(Context context, String extend) { + super.init(context, extend); + pushAgent = new PushAgent(); + pushAgent.init(context, extend); + } + + @Override + public String detailContent(List list) { + try { + Pattern pattern = aliyun; + if (pattern.matcher(list.get(0)).find()) { + return pushAgent.detailContent(list); + } + String jqurl=(apiUrl+list.get(0)).replace(".html",""); + String jxUrl=new String(Base64.decode(OkHttpUtil.string(jqurl, sHeaders()), Base64.DEFAULT)); + String realUrl= new JSONObject(jxUrl).getJSONObject("result").getString("res_url"); + Matcher matcher = pattern.matcher(realUrl); + if (!matcher.find()) { + return ""; + } + list.set(0, matcher.group(1).replaceAll("\\\\", "")); + return pushAgent.detailContent(list); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + @Override + public String playerContent(String str, String str2, List list) { + return pushAgent.playerContent(str, str2, list); + } + +// protected static HashMap Headers() { +// 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("origin", "https://www.upyunso.com"); +// return headers; +// } + + protected static HashMap sHeaders() { + 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"); + return headers; + } + + + @Override + public String searchContent(String key, boolean quick) { + try { + JSONObject result = new JSONObject(); + JSONArray videos = new JSONArray(); + String cover = "https://inews.gtimg.com/newsapp_bt/0/13263837859/1000"; + + String searchurl = apiUrl + "search?keyword=" + URLEncoder.encode(key) + "&page=1&s_type=2"; + String content = new String(Base64.decode(OkHttpUtil.string(searchurl, sHeaders()), Base64.DEFAULT)); + JSONArray playList = new JSONObject(content).getJSONObject("result").getJSONArray("items"); + + + for (int i = 0; i < playList.length(); i++) { + JSONArray source = playList.getJSONObject(i).getJSONArray("content"); + for (int j = 0; j < source.length(); j++) { + JSONObject vid = source.getJSONObject(j); + String sourceName = vid.getString("title"); + String sourceUrl = vid.getString("size"); + if (sourceUrl.contains("download.html")) { + JSONObject v = new JSONObject(); + v.put("vod_name", sourceName); + v.put("vod_id", sourceUrl); + v.put("vod_pic", cover); + videos.put(v); + } else + continue; + + } + + } + result.put("list", videos); + return result.toString(); + + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/Wmkk.java b/app/src/main/java/com/github/catvod/spider/Wmkk.java new file mode 100644 index 0000000..1c50c1f --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Wmkk.java @@ -0,0 +1,509 @@ +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.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; + + +/** + * 蓝光影院 + *

+ * Author: 匿名20220729 + */ +public class Wmkk extends Spider { + private static final String siteUrl = "https://www.wanmeikk.film"; + + /** + * 播放源配置 + */ + private JSONObject playerConfig; + /** + * 筛选配置 + */ + private JSONObject filterConfig; + + private Pattern regexCategory = Pattern.compile("/category/(\\d+).html"); //分类 + private Pattern regexVid = Pattern.compile("/project/(\\d+).html"); //详情页 + private Pattern regexPlay = Pattern.compile("/play/(\\d+)-(\\d+)-(\\d+).html"); //播放页 + private Pattern regexPage = Pattern.compile("/category/(\\S+).html"); //筛选页 + + @Override + public void init(Context context) { + super.init(context); + try { + playerConfig = new JSONObject("{\"wanmeikk\":{\"show\":\"一路向北\",\"pu\":\"https://www.wanmeikk.film/dplayer.php?url=\",\"sn\":0,\"or\":999},\"fantasy\":{\"show\":\"七里香\",\"pu\":\"https://www.wanmeikk.film/dplayer.php?url=\",\"sn\":0,\"or\":999},\"1080P\":{\"show\":\"告白气球\",\"pu\":\"https://www.wanmeikk.film/dplayer.php?url=\",\"sn\":0,\"or\":999},\"wanmei\":{\"show\":\"兰亭序\",\"pu\":\"https://www.wanmeikk.film/dplayer.php?url=\",\"sn\":0,\"or\":999},\"fuckplayer\":{\"show\":\"晴天\",\"pu\":\"https://www.wanmeikk.film/dplayer.php?url=\",\"sn\":0,\"or\":999}}"); + //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.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("动漫") || + 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-vodlist__box"); + Element homeList = doc.select("ul.stui-vodlist").get(0); + Elements list = homeList.select("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("a").attr("href")); + if (!matcher.find()) + continue; + String title = vod.selectFirst("a").attr("title"); + String cover = vod.selectFirst("a ").attr("data-original"); + String remark = vod.selectFirst("a span.pic-text").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[1] = 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 + "/category/"+tid+"-"+pg+".html"; + 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("ul.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("-")[1]); + } else { + page = 0; + } + } + if (name.equals("尾页")) { + Matcher matcher = regexPage.matcher(a.attr("href")); + if (matcher.find()) { + pageCount = Integer.parseInt(matcher.group(1).split("-")[1]); + } else { + pageCount = 0; + } + break; + } + } + } + + JSONArray videos = new JSONArray(); + if (!html.contains("没有找到您想要的结果哦")) { + Elements list = doc.select("div.stui-vodlist__box "); + 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"); + if (!TextUtils.isEmpty(cover) && !cover.startsWith("http")) { + cover = siteUrl + cover; + } + String remark = vod.selectFirst("a span.pic-text").text(); + Matcher matcher = regexVid.matcher(vod.selectFirst("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", 58); + result.put("total", pageCount <= 1 ? videos.length() : pageCount * 58); + + 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 + "/project/" + 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("a.picture img").attr("data-original"); + if (!TextUtils.isEmpty(cover) && !cover.startsWith("http")) { + cover = siteUrl + cover; + } + String title = doc.selectFirst("div.stui-content__detail h1.title").text(); + String category = "", area = "", year = "", remark = "", director = "", actor = "", desc = ""; + Elements data = doc.select("p.data"); + desc = doc.selectFirst("span.detail-content").text().trim(); + category =doc.select("a").get(0).text().trim(); + year=doc.select("a").get(0).text().trim(); + area =doc.select("a").get(0).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.stui-pannel__head.bottom-line>h3"); + //System.out.println("sources:" + sources); + Elements sourceList = doc.select("ul.stui-content__playlist"); + + for (int i = 0; i < sources.size(); i++) { + Element source = sources.get(i); + // String sourceName = source.attr("h3"); + // String sourceName = sources.select("h3").text().trim(); + 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; + sourceName = playerConfig.getJSONObject(flag).getString("show"); + found = true; + break; + } + } + if (!found) + continue; + String playList = ""; + Elements playListA = sourceList.get(i).select("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 + */ + + private final Pattern urlt = Pattern.compile("\"url\": *\"([^\"]*)\","); + private final Pattern token = Pattern.compile("\"token\": *\"([^\"]*)\""); + private final Pattern vkey = Pattern.compile("\"vkey\": *\"([^\"]*)\","); + private final Pattern urls = Pattern.compile("urls = *\'([^\']*)\';"); + @Override + public String playerContent(String flag, String id, List vipFlags) { + try { + JSONObject headers = new JSONObject(); + // headers.put("Referer", "https://www.wanmeikk.film"); + headers.put("User-Agent", " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"); + // headers.put("Accept", " text/html,application/xhtml+xml,application/xml;q=0.9,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,en-GB;q=0.8,en-US;q=0.7,en;q=0.6"); + // headers.put("Accept-Encoding", " gzip, deflate"); + String url = siteUrl + "/play/" + id + ".html"; + Elements allScript = Jsoup.parse(new URL(url).openStream(), "utf-8",OkHttpUtil.string(url, getHeaders(url))).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_")) + { + JSONObject player = new JSONObject(scContent.substring(scContent.indexOf('{'), scContent.lastIndexOf('}') + 1)); + if (playerConfig.has(player.getString("from"))) + { + JSONObject pCfg = playerConfig.getJSONObject(player.getString("from")); + String jxurl = "https://www.wanmeikk.film/dplayer.php?url=" + player.getString("url"); + Document doc = Jsoup.parse(new URL(jxurl).openStream(), "utf-8", OkHttpUtil.string(jxurl, getHeaders(jxurl))); + Elements script = doc.select("body > script[type=text/javascript]"); + for (int j = 0; j < script.size(); j++) + { + String Content = script.get(j).html().trim(); + Matcher matcher = urls.matcher(Content); + if (matcher.find()) { + String urls = matcher.group(1); + // String zlurl = new String(Base64.decode(urls.substring(8).getBytes(), 0)); + result.put("url", urls); + result.put("header", headers.toString()); + result.put("parse", 0); + result.put("playUrl", ""); + break; + } + + + } + + } + 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 ""; + 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"); + if (!TextUtils.isEmpty(cover) && !cover.startsWith("http")) { + cover = siteUrl + cover; + } + 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/XBiu.java b/app/src/main/java/com/github/catvod/spider/XBiu.java new file mode 100644 index 0000000..11032ee --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/XBiu.java @@ -0,0 +1,1935 @@ +package com.github.catvod.spider; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Base64; +import android.util.Pair; + +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.net.URL; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import okhttp3.Call; + +public class XBiu extends Spider { + + protected String ext = null; + public JSONObject rule = null; + // 默认的视频类型 + private ArrayList videoFormatList = new ArrayList<>(Arrays.asList(".m3u8", ".mp4", ".mpeg", ".flv", ".mkv")); + + + protected final int base64Flag = Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP; + // 一定是正确的分类名称,用来帮助定位分类列表,猜cateManual + protected final ArrayList cateManuals = new ArrayList<>(Arrays.asList("电影", "剧集", "电视剧", "连续剧", "综艺", "动漫")); + // 无效的分类名,彡来过滤cateManual + protected final ArrayList invalidCateNames = new ArrayList<>(Arrays.asList("更多","下载", "首页", "资讯", "留言", "导航", "专题", "短视频", "热榜", "排行", "追剧","更新","APP", "直播", "label", "Netflix")); + // 详情页 影片信息相关字段,猜详情页信息时用 + protected final ArrayList detailItemNames = new ArrayList<>(Arrays.asList("导演", "主演", "演员", "地区", "类型", "年份", "年代")); + protected final ArrayList detailItemKeys = new ArrayList<>(Arrays.asList("vod_director", "vod_actor", "vod_actor", "vod_area", "type_name", "vod_year", "vod_year")); + protected String splitFlag = ""; // 分段标志,猜cateManual时用 + + // html标签查找时用到的辅助类 + protected class HtmlMatchInfo { + public String group0; // 正则表达式匹配到的字符串 + /** + * 一般用来放href中的内容 + */ + public String group1; // + public String group2; // + public String diff; // 两个匹配结果比较group1得到的不同部分 + public int startPos; // 正则匹配到的起始位置 + public int endPos; // 正则匹配到的结束位置 + public ArrayList uploads; // 祖先结节的索引 + public int matchedUpNodePos = -1; // 与其他HtmlMatchInfo最匹配的祖先节点位置 + public int diffStartIndex; // 不同那部分数据的开始位置 + public int diffEndIndex; // 不同那部分数据的结束位置 + + public void init(Matcher m) { + this.group0 = m.group(0); + if (m.groupCount() > 0) + this.group1 = m.group(1); + if (m.groupCount() > 1) + this.group2 = m.group(2); + this.startPos = m.start(0); + this.endPos = m.end(0); + } + + // 通过比较两个group1的不同部分,不同部分的内容以splitFlag中的字符为开始或结束位置 + public boolean findDiffStr(HtmlMatchInfo rhs, String splitFlag) { + int len = Math.min(group1.length(), rhs.group1.length()); + // 找不同字符的开始位置 + for (int i =0; i < len; ++i){ + char a = group1.charAt(i); + char b = rhs.group1.charAt(i); + if(a== b && splitFlag.indexOf (a) != -1) { + diffStartIndex = i+1; + rhs.diffStartIndex = i+1; + } + if(a != b) break; + } + + // 找不同字符的结束位置 + diffEndIndex = group1.length(); + rhs.diffEndIndex = rhs.group1.length(); + for (int i =1; i < len; ++i){ + char a = group1.charAt(group1.length()-i); + char b = rhs.group1.charAt(rhs.group1.length()-i); + if(a== b && splitFlag.indexOf (a) != -1) { + diffEndIndex = group1.length()-i; + rhs.diffEndIndex = rhs.group1.length()-i; + } + if(a != b) break; + } + if(this.diff == null || this.diff.isEmpty() && diffStartIndex < diffEndIndex) { + diff = group1.substring(diffStartIndex, diffEndIndex); + }else{ + if( diffEndIndex < diffStartIndex || !diff.equals(group1.substring(diffStartIndex, diffEndIndex))){ + return false; + } + } + if(rhs.diffStartIndex < rhs.diffEndIndex) { + rhs.diff = rhs.group1.substring(rhs.diffStartIndex, rhs.diffEndIndex); + } + return true; + } + + // 判断 rhs 与当前对象是有相同的祖先节点 + boolean hasSameUpNode(HtmlMatchInfo rhs) { + if (rhs.uploads.size() != this.uploads.size()) return false; + for (int i = 0; i < uploads.size(); ++i) { + if (uploads.get(i).intValue() != rhs.uploads.get(i).intValue()) continue; + if (matchedUpNodePos == -1 || uploads.get(i).intValue() == matchedUpNodePos) { + matchedUpNodePos = uploads.get(i).intValue(); + rhs.matchedUpNodePos = uploads.get(i).intValue(); + return true; + } + return false; + } + return false; + } + } + + public void init(Context context, String extend) { + super.init(context, extend); + this.ext = extend; + } + + // 初始化抓虫规则 + protected void fetchRule() { + if (rule == null) { + if (ext != null) { + try { + + if (ext.startsWith("http")) { + if(ext.indexOf("{cateId}") != -1 || ext.indexOf("{catePg}") !=-1){ + rule = new JSONObject(); + rule.put("homeUrl", ext); + }else{ + String json = OkHttpUtil.string(ext, null); + rule = new JSONObject(json); + } + + } else { + rule = new JSONObject(ext); + } + + if (!rule.has("list")) { + rule.put("list", new JSONObject()); + } + JSONObject list = rule.getJSONObject("list"); + // 初始化homeUrl,list.url + String homeUrl= rule.getString("homeUrl"); + if(homeUrl.indexOf("{cateId}") != -1){ + URL r = new URL(homeUrl); + String path = r.getPath(); + // 更新解析出来的homeUrl + rule.put("homeUrl", homeUrl.substring(0, homeUrl.indexOf(path))); + if(!list.has("url")){ + list.put("url", homeUrl); + } + } + // 初始化截断标志 + String listUrl = list.getString("url"); + if(listUrl.indexOf("/") !=-1) splitFlag+='/'; + if(listUrl.indexOf(".") !=-1) splitFlag+='.'; + if(listUrl.indexOf("-") !=-1) splitFlag+='-'; + + if (!rule.has("detail")) { + rule.put("detail", new JSONObject()); + } + + if (!rule.has("playlist")) { + rule.put("playlist", new JSONObject()); + } + + // 如果没有search,则生成一个默认的search规则,大部分网站的search规则都一样 + // 省掉一个search json + if (!rule.has("search")) { + String url = addHttpPrefix("index.php/ajax/suggest?mid=1&wd=阿凡达"); + try { + // 尝试访问这个json接口,如果返回了正确的json格式,就认为支持json搜索 + JSONObject result = new JSONObject( OkHttpUtil.string(url, getHeaders(url))); + JSONObject search = new JSONObject(); + search.put("vod_id", "id"); + search.put("vod_name", "name"); + search.put("vod_pic", "pic"); + search.put("url", addHttpPrefix("index.php/ajax/suggest?mid=1&wd={wd}")); + rule.put("search", search); + } + catch (Exception e){ + + } + } + + // 部分网站的播放页上直接就有 播放地址,基本上就是一样的格式,可以尝试在playerContent中直接拿直链 + if (!rule.has("play")) { + JSONObject play = new JSONObject(); + JSONArray region = new JSONArray(); + region.put("var player_aaaa="); + region.put(0); + + JSONArray vod_url = new JSONArray(); + vod_url.put("\"url\":\""); + vod_url.put("\""); + play.put("region", region); + play.put("vod_url", vod_url); + rule.put("play", play); + } + + // play字段中可以填写播放连接的关键字用来帮助识别嗅探结果, + // 一般奇葩的网站会用到 + if (rule.has("play")) { // 自定义嗅探关键字 + JSONObject play = rule.getJSONObject("play"); + JSONArray keywords = play.optJSONArray("keywords"); + if (keywords != null) { + videoFormatList.clear(); + for (int i = 0; i < keywords.length(); ++i) { + videoFormatList.add(keywords.getString(i)); + } + } + } + + // 猜cateManaul + JSONObject cateManual = rule.optJSONObject("cateManual"); + String body = ""; + if (cateManual == null) { + // 重建 cateManaul规则 + body = this.fetchUrl(rule.getString("homeUrl"), rule.optJSONObject("header")); + if(body.length() > 32*1024) { body = body.substring(0, 32 * 1024); } + cateManual = this.guess_rule_cateManual(body); + if(cateManual != null){ + rule.put("cateManual", cateManual); + } + } + + // 猜list.vod_id + if (!list.has("vod_id")) { + if(body.isEmpty()){ + body = this.fetchUrl(rule.getString("homeUrl"), rule.optJSONObject("header")); + if(body.length() > 32*1024) { body = body.substring(0, 32 * 1024); } + } + JSONArray listvodid = this.guess_rule_vod_id(body); + list.put("vod_id", listvodid); + } + + // 如果没有json搜索接口,那么尝试在主页上找search 的接口 url + if (!rule.has("search")) { + if(body.isEmpty()){ + body = this.fetchUrl(rule.getString("homeUrl"), rule.optJSONObject("header")); + if(body.length() > 32*1024) { body = body.substring(0, 32 * 1024); } + } + String url = this.guess_rule_search_url(body); + if(!url.isEmpty()){ + JSONObject search = new JSONObject(); + search.put("url", url); + rule.put("search", search); + } + } + + SpiderDebug.log(String.format("默认rule: %s", rule.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + + public String addHttpPrefix(String url) { + try { + if (url.isEmpty()) return ""; + if (url.startsWith("http")) return url; + String result = rule.getString("homeUrl"); + if (result.endsWith("/")) { + result = result.substring(0, result.length() - 1); + } + if (url.startsWith("/")) { + result += url; + } else { + result += "/" + url; + } + return result; + } catch (JSONException e) { + e.printStackTrace(); + } + return url; + } + + protected HashMap getHeaders(String url) { + HashMap headers = new HashMap<>(); + try { + if (rule.has("header")) { + JSONObject header = rule.getJSONObject("header"); + Iterator iter = header.keys(); + while (iter.hasNext()) { + String key = iter.next(); + headers.put(key, header.getString(key)); + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + if (!headers.containsKey("User-Agent")) { + headers.put("User-Agent", Misc.UaWinChrome); + } + return headers; + } + + public static class HtmlNodeHlper{ + // 非正常配对的html标签,进行html层级查找时要用到 + protected static ArrayList notPairedTag = new ArrayList<>(Arrays.asList("img", "br", "meta", "!--")); // 为注释 + // 判断当前html标签是否为正常的标签 + public static boolean isPairedHtmlTag(String str, int startPos) { + String tmp = str.substring(startPos, Math.min(str.length(), startPos + 10)); + for (String p : notPairedTag) { + if (tmp.indexOf(p) != -1) { // 找到了 + // 找 > 如果匹配了 /> 则认为是配对的 + for (int i = startPos + 1; i < str.length(); ++i) { + String sm = str.substring(i); + if (str.charAt(i) == '>') { + if (str.charAt(i - 1) == '/') { + return true; + } else { + return false; + } + } + } + return false; + } + } + return true; + } + + // 查找当前标签的html代码 pos必须是标签的开始位置 < + public static String nodeString(String str, int pos) { + if (pos < 0 || pos >= str.length() || str.charAt(pos) != '<') return str; + int isRightNode = 0; + for (int i = pos; i < str.length() - 1; ++i) { +// String sm = str.substring(i, i + 400); + switch (str.charAt(i)) { + // 遇到 / 那么这个位置有可能是xml的结束标识,这种情况下再遇到<则不是当前节点的上级节点 + case '/': { + if (str.charAt(i + 1) == '>') { // "/>" 认为是标签的结束位置 + isRightNode--; + } else if (str.charAt(i - 1) == '<') { // "': { + if (isRightNode == 0) { + return str.substring(pos, i + 1); + } + break; + } + case '<': { + if (str.charAt(i + 1) != '/' && isPairedHtmlTag(str, i)) { // 不是 " findUpNodes(String str, int pos, int lookback) { + ArrayList nodes = new ArrayList<>(); + ArrayList urls = new ArrayList<>(); + if (pos == -1) return nodes; + int isUpNode = 0; + for (int i = pos; i >= 0; --i) { + switch (str.charAt(i)) { + // 遇到 / 那么这个位置有可能是xml的结束标识,这种情况下再遇到<则不是当前节点的上级节点 + case '/': { + if (str.charAt(i + 1) == '>') { + isUpNode++; +// SpiderDebug.log(String.format("not xml %s", str.substring(i, i + 20))); + } else if (str.charAt(i - 1) == '<') { + isUpNode++; + --i; +// SpiderDebug.log(String.format("not xml %s", str.substring(i, i + 20))); + } + break; + } + case '<': { + if (isUpNode == 0) { +// SpiderDebug.log(String.format("find up node %d %s", i, str.substring(i, i + 30))); + urls.add(String.format("%5d", i)); + nodes.add(i); + } else if (isPairedHtmlTag(str, i)) { + isUpNode--; + if (isUpNode < 0) isUpNode = 0; +// SpiderDebug.log(String.format("%s", str.substring(i, i + 30))); + } + + break; + } + default: + break; + } + if (nodes.size() >= lookback) { + break; + } + } + return nodes; + } + // 获取当前节点的所有子节点 + public static ArrayList getChildNodes(String str) { + ArrayList arr = new ArrayList<>(); + int pos = 0; + if (pos < 0 || pos >= str.length() || str.charAt(pos) != '<') return arr; + ++pos; + while (pos > -1 && pos < str.length()) { + pos = str.indexOf('<', pos); + String p = nodeString(str, pos); + if (p.isEmpty()) { + break; + } + arr.add(p); + pos += p.length(); + } + return arr; + } + + // 移除字符串的html标签 + public static String trimHtmlString(String str, String r) { + String ret = str.replace("\r\n", "") + .replace("\n", "") + .replaceAll("<.+?>", r) + // .replace(" ", "") + .replaceAll("\\s+", " ") + .replace(" ", "") + .replace(" ", "") + .trim(); + return ret; + } + + public static String trimHtmlString(String str) { + return trimHtmlString(str, ""); + } + + } + + public static class Utils{ + // 查找列表块的起始位置,取最靠近共同祖先节点的位置 + public static int findBlockPos(ArrayList a, ArrayList b) { + int len = a.size() > b.size() ? b.size() : a.size(); + if(len ==1 ) return b.get(0); + for (int i = 0; i < len; ++i) { + if (a.get(i).intValue() == b.get(i).intValue()) { + return b.get(i - 1); + } + } + return b.get(len - 1); + } + + // 查找两个字符串之间的子串 + // keys 字段说明 + // 0 prefix 1 suffix 2 找到子串后左边index的偏移量 3 找到子串后右边index的偏移量 + public static String findSubString(String str, int startPos, JSONArray keys, String defaultVal) { + try { + if (keys == null) return defaultVal; + String prefix = keys.getString(0); + String suffix = keys.getString(1); + int offsetl = 0; // 左边的偏移量 + int offsetr = 0; // 右边的偏移量 + if (keys.length() > 2) { + offsetl = keys.getInt(2); + } + if (keys.length() > 3) { + offsetr = keys.getInt(3); + } + int a = str.indexOf(prefix, startPos) + prefix.length(); + if (a < prefix.length()) return defaultVal; + int b = str.indexOf(suffix, a); + if (b < a) return defaultVal; + return HtmlNodeHlper.trimHtmlString(str.substring(a + offsetl, b + offsetr)); + } catch (JSONException e) { + e.printStackTrace(); + } + return defaultVal; + } + + public static String findSubString(String str, int startPos, JSONArray keys) { + return findSubString(str, startPos, keys, ""); + } + + // 获取回看层数 + public static int getLookbackCount(JSONArray keys) { + try { + if (keys != null && keys.length() > 4) return keys.getInt(4); + } catch (Exception e) { + //e.printStackTrace(); + } + return 0; + } + + // 遍历JSONObect中的JSONArray查找回看的层数可用的规则 + public static JSONArray getLookbackArray(JSONObject obj) { + try { + Iterator iter = obj.keys(); + while (iter.hasNext()) { + String key = (String) iter.next(); + Object val = obj.get(key); + if (val.getClass().getSimpleName().equals("JSONArray")) { + int c = getLookbackCount((JSONArray) val); + if (c > 0) return (JSONArray) val; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + // 统计子串个数 + public static int getSubStringCount(String str, String sub){ + int pos =0; + int count =0; + while (pos < str.length()){ + pos = str.indexOf(sub, pos); + if(pos == -1) break; + pos += sub.length(); + ++count; + } + return count; + } + + // 获取指定区间的字符串 + public static String getRegion(String str, JSONObject obj) { + try { + if (obj == null) return str; + JSONArray region = obj.optJSONArray("region"); + if (region == null) return str; + String prefix = region.getString(0); + int a = str.indexOf(prefix); + if (a == -1) return str; + int b = str.length(); + if (region.length() > 1) { + b = str.indexOf(region.getString(1), a + prefix.length()); + if (b == -1) b = str.length(); + } + return str.substring(a, b); + } catch (JSONException e) { + e.printStackTrace(); + } + return str; + } + + } + + // 猜测分类列表的html区间代码 + protected String guessCateManualHtmlString(String body) { + String regx = String.format(" list = new ArrayList<>(); + int mcount = 0; + while (m.find() ) { + ++mcount; + if(mcount >30 && !list.isEmpty()){ + break; + } + HtmlMatchInfo cate = new HtmlMatchInfo(); + cate.init(m); + cate.group2 = HtmlNodeHlper.trimHtmlString(HtmlNodeHlper.nodeString(body, cate.startPos)); + if (cate.group2.isEmpty()) continue; + boolean bOk = false; + for (String v : cateManuals){ + if(cate.group2.indexOf(v) !=-1) { + bOk = true; + break; + } + } + if(!bOk) continue; + cate.uploads = HtmlNodeHlper.findUpNodes(body, cate.startPos, 3); + if (!list.isEmpty()) { + boolean b = list.get(0).hasSameUpNode(cate); + if (!b) { // 当前找到的info和list中的匹配 + if (list.size() > 1) { // 如果list中的数据大于1 则认为找到了类型列表 + return HtmlNodeHlper.nodeString(body, list.get(0).matchedUpNodePos); + } + list.clear(); + } + } + list.add(cate); + } + if (list.size() > 1) { // 如果list中的数据大于1 则认为找到了类型列表 + return HtmlNodeHlper.nodeString(body, list.get(0).matchedUpNodePos); + } else { + return ""; + } + } + + // 从html代码中猜测分类名和分类ID cateManual规则 + protected JSONObject guess_rule_cateManual(String body) { + try { + String str = this.guessCateManualHtmlString(body); + if (str.isEmpty()) return new JSONObject(); + + String regx = String.format("](\\s*?\\S+?\\s*?)(\"|<)", TextUtils.join("|", cateManuals)); + Pattern pattern = Pattern.compile(regx, Pattern.CASE_INSENSITIVE); + Matcher m = pattern.matcher(str); + ArrayList list = new ArrayList<>(); + while (m.find()) { + // HtmlMatchInfo 字段映射 + // HtmlMatchInfo.group1 -> href + // HtmlMatchInfo.group2 -> name + // HtmlMatchInfo.diff -> id 分类ID + HtmlMatchInfo cate = new HtmlMatchInfo(); + cate.init(m); + if (cate.group1.length() < 5) continue; + cate.group2 = HtmlNodeHlper.trimHtmlString(HtmlNodeHlper.nodeString(str, cate.startPos)); + if(cate.group2.isEmpty()) continue; + // 判断是否为正常的分类名 + boolean validCateName = true; + for (int j = 0; j < invalidCateNames.size(); ++j) { + if (cate.group2.indexOf(invalidCateNames.get(j)) != -1) { + SpiderDebug.log(String.format("排除无效分类:%s --> %s", cate.group1, cate.group2)); + validCateName = false; + break; + } + } + if(!validCateName) continue; + + if (!list.isEmpty()) { + if (!list.get(0).findDiffStr(cate, splitFlag)) { + SpiderDebug.log(String.format("排除可能无效的分类 %s <--> %s", cate.group1, cate.group2)); + continue; + } + } + list.add(cate); + } + + ArrayList baseInfoIndexs = new ArrayList<>(); + // 找到最可能是正确的导航item + for (int i =0; i < list.size(); ++i){ + list.get(i).diff = null; + for (String v : cateManuals){ + if(list.get(i).group2.indexOf(v) !=-1) { + baseInfoIndexs.add(i); + break; + } + } + } + + // 以找到的导航item为基准重建分类ID + int baseInfoIndex=0; + for (int i =1; i < baseInfoIndexs.size(); ++i){ + baseInfoIndex=baseInfoIndexs.get(0).intValue(); + list.get(baseInfoIndex).findDiffStr(list.get(baseInfoIndexs.get(i).intValue()), splitFlag); + } + + JSONObject cateManual = new JSONObject(); + for (int i = 0; i < list.size(); ++i) { + if(list.get(i).diff == null || list.get(i).diff.isEmpty()) { + if(!list.get(baseInfoIndex).findDiffStr(list.get(i), splitFlag)){ + SpiderDebug.log(String.format("排除可能无效的分类 : %s", list.get(i).group0)); + continue; + } + } + + boolean validCateName = true; + String name = list.get(i).group2; + String id = list.get(i).diff; + if (id == null || id.isEmpty()) continue; + if (name == null || name.isEmpty()) continue; + for (int k =0; k arr = HtmlNodeHlper.findUpNodes(body,m.start(0), i); + String r = HtmlNodeHlper.nodeString(body, arr.get(arr.size()-1)); + String regex2 = "action=\"(.+?)\""; + Pattern pattern2 = Pattern.compile(regex2, Pattern.CASE_INSENSITIVE); + Matcher m2 = pattern2.matcher(r); + if(m2.find()){ + String url = m2.group(1); + char ch = url.indexOf('?') ==-1 ? '?' : '&'; + url = addHttpPrefix(url + ch + wd + "={wd}"); + return url; + } + + } + } + return ""; + } + // 猜测列表数据的 vod_id 规则 + public JSONArray guess_rule_vod_id(String body) { + try { + String regx = " founds = new HashMap<>(); + ArrayList list = new ArrayList<>(); + while (m.find()) { + HtmlMatchInfo cate = new HtmlMatchInfo(); + cate.init(m); + cate.uploads = HtmlNodeHlper.findUpNodes(body, cate.startPos, 4); +// String ms = this.findNodeString(body, cate.uploads.get(cate.uploads.size()-1)); + if (!list.isEmpty()) { + + if(cate.group1.equals( list.get(list.size()-1).group1)) continue; + boolean b = list.get(list.size()-1).hasSameUpNode(cate); + if (!b) { // 当前找到的info和list中的匹配 + if (list.size() > 1) { + HtmlMatchInfo info = list.get(0); + info.findDiffStr(list.get(1), splitFlag); + int id = 0; + boolean isNumberID = false; + try { id = Integer.valueOf(info.diff).intValue(); isNumberID = true; }catch (Exception e){} + + if(id > 100 ){ // cateID一般都是小于100的 + String url = (info.group1.replace(list.get(0).diff, "{vid}")); + JSONArray arr = new JSONArray(); + String prefix = url.substring(0, url.indexOf("{vid}")); + String suffix = url.substring(prefix.length() + "{vid}".length()); + int lookback = info.uploads.indexOf(info.matchedUpNodePos) - 1; + if (lookback < 1) lookback = 1; + arr.put(prefix); + arr.put(suffix); + arr.put(0); + arr.put(0); + arr.put(lookback); + arr.put(list.size()); + + if (!founds.containsKey(url)) { + founds.put(url, arr); + } else { + int nlen = founds.get(url).getInt(5) + list.size(); + arr.put(5, nlen); + founds.put(url, arr); + if(nlen >= 30){ + list.clear(); + break; + } + } + } + + } + list.clear(); + } + } + list.add(cate); + if(list.size()>30){ + break; + } + } + + + if (list.size() > 5 || (list.size()>1 && founds.isEmpty())) { // 如果list中的数据大于1 则认为找到了类型列表 + HtmlMatchInfo info = list.get(0); + info.findDiffStr(list.get(1), splitFlag); + int id = 0; + boolean isNumberID = false; + try { id = Integer.valueOf(info.diff).intValue(); isNumberID = true; }catch (Exception e){} + + if(id > 100 ){ // cateID一般都是小于100的 + + String url = (info.group1.replace(list.get(0).diff, "{vid}")); + JSONArray arr = new JSONArray(); + String prefix = url.substring(0, url.indexOf("{vid}")); + String suffix = url.substring(prefix.length() + "{vid}".length()); + int lookback = info.uploads.indexOf(info.matchedUpNodePos) - 1; + if (lookback < 1) lookback = 1; + arr.put(prefix); + arr.put(suffix); + arr.put(0); + arr.put(0); + arr.put(lookback); + arr.put(list.size()); + + if (!founds.containsKey(url)) { + founds.put(url, arr); + } else { + int nlen = founds.get(url).getInt(5) + list.size(); + arr.put(5, nlen); + founds.put(url, arr); + } + } + } + + + JSONArray c = null; + for (String key : founds.keySet()) { + JSONArray v = founds.get(key); + if(c == null || c.getInt(5) < v.getInt(5)) c = v; + } + return c; + + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + // 猜播放列表 + public JSONArray guess_rule_vod_play_url(String str, String vid) { + String regex = "href=\"(/.+?)\""; + Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); + Matcher m = pattern.matcher(str); + HtmlMatchInfo info = new HtmlMatchInfo(); + ArrayList vec = new ArrayList<>(); + boolean p0__ = false; + while (m.find()){ + String sb = m.group(1); + // 太长的url认为是错误的播放地址 + if(sb.length() > 100) continue; + if(sb.indexOf(vid) == -1) continue; + // 如果当前url的长度比上一个url的长度短也认为是无效的播放地址(带上了vod_id一般短一点的可能是详情页的地址) + // 一般来讲 999-1-1.html 这种格式是播放页的地址,不排除这种地址 + boolean is__html = (sb.indexOf(vid+"-") != -1); + if(!is__html && vec.size() > 0 && vec.get(vec.size()-1).length() > sb.length()) continue; + if(is__html && !p0__ ){ // 找到了准确度最高的播放连接格式,如果检查到列表头不是这种格式的话,清空列表从头开始 + vec.clear(); + } + // 如果列表里面装了标准的连接格式,不标准的就不要了 + if(p0__ && !is__html) continue; + + info.init(m); + if(vec.isEmpty()) p0__ = is__html; + vec.add(m.group(1)); + if(vec.size() > 10 && vec.get(vec.size()-2).length() == sb.length()) { + break; + } + } + if(info.group0 != null){ + for (int i =1;i < 4; ++i){ + ArrayList nodes = HtmlNodeHlper.findUpNodes(str, info.startPos, i); + int startPos = nodes.get(nodes.size()-1).intValue(); + //String smd = str.substring(startPos, startPos+10); + String smd = HtmlNodeHlper.nodeString(str, startPos); + + if(smd.indexOf(" map = new HashMap(); + + for (int i = 0; i < words.length; ++i) { + words[i] =words[i].trim(); + if (!words[i].isEmpty() && words[i].indexOf("更新") ==-1) { + + int c = 1; + if (map.containsKey(words[i])) { + c = 1 + map.get(words[i]).intValue(); + ;//[words[i]] + } + map.put(words[i], Integer.valueOf(c)); + } + } + String s = ""; + int c = 0; + for (String key : map.keySet()) { + int v = map.get(key).intValue(); + if (v > c) { + c = v; + s = key; + } + } + val = s; + } + return val.replace("在线", "") + .replace("立即", "") + .replace("观看", "") + .replace("点播", "") + .replace("影片", "") + .replace("信息", "") + .replace("播放", "") + .trim(); + //return val; + } catch (Exception e) { + + } + return ""; + } + + public String guess_value_vod_remarks(String nd, int startPos, String vod_name) { + try { + String all = HtmlNodeHlper.trimHtmlString(nd, "!!!!"); + String[] words = all.split("!!!!"); + String val = ""; + for (int i = 0; i < words.length; ++i) { + String wd = words[i].trim(); + if (!wd.isEmpty() && wd.indexOf(vod_name) == -1) { + String dot = (!val.isEmpty()) ? "," : "";// val += ","; + String tmp = val + dot + wd; + if (tmp.length() > 20) { + break; + } + val = tmp; + } + } + return val; + } catch (Exception e) { + + } + return ""; + + } + + public String guess_value_vod_pic(String nd, int startPos) { + try { + JSONArray vec = new JSONArray(); + vec.put("data-original=\""); + vec.put("\""); + String val = Utils.findSubString(nd, startPos, vec); + if (val.isEmpty()) { + vec.put(0, "data-src=\""); + val = Utils.findSubString(nd, startPos, vec); + } + if (val.isEmpty()) { + vec.put(0, "src=\""); + val = Utils.findSubString(nd, startPos, vec); + } + if (val.isEmpty()) { + vec.put(0, "data-bg=\""); + val = Utils.findSubString(nd, startPos, vec); + } + if (val.isEmpty()) { + //TODO: 直接在nd中找个.jpg .png 之类的当图片 + } + return addHttpPrefix(val); + } catch (Exception e) { + + } + return ""; + } + + @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 boolean manualVideoCheck() { + return true; + } + + + @Override + public String homeContent(boolean z) { + try { + fetchRule(); + + JSONObject result = new JSONObject(); + JSONArray classes = new JSONArray(); + JSONObject cateManual = rule.optJSONObject("cateManual"); + + Iterator keys = cateManual.keys(); + while (keys.hasNext()) { + String key = keys.next(); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("type_name", key); + jsonObject.put("type_id", cateManual.getString(key)); + classes.put(jsonObject); + } + + result.put("class", classes); + if (z && rule.has("filter")) { + result.put("filters", rule.getJSONObject("filter")); + } + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + // from xpath 加入过滤条件 + protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) { + try { + JSONObject list = this.rule.getJSONObject("list"); + String cateUrl = list.optString(pg, ""); + if(cateUrl.isEmpty()) + cateUrl = list.getString("url"); + if (filter && 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) { + cateUrl = cateUrl.replace("{" + key + "}", URLEncoder.encode(value)); + } + } + } + cateUrl = cateUrl.replace("{cateId}", tid).replace("{catePg}", pg); + Matcher m = Pattern.compile("\\{(.*?)\\}").matcher(cateUrl); + while (m.find()) { + String n = m.group(0).replace("{", "").replace("}", ""); + cateUrl = cateUrl.replace(m.group(0), "").replace("/" + n + "/", ""); + } + return cateUrl; + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } + + @Override + public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { + try { + JSONObject list = this.rule.getJSONObject("list"); + String url = categoryUrl(tid, pg, filter, extend); + String body = fetchUrl(url, list.optJSONObject("header")); + String str = Utils.getRegion(body, list); + JSONArray videos = new JSONArray(); + JSONArray lookback = Utils.getLookbackArray(list); + Set set = new HashSet(); + int pos = 0; + ArrayList urlnodes = null; + int lookup = -1; + while (lookback != null) { + pos = str.indexOf(lookback.getString(0), pos); + if (pos == -1) break; + + ArrayList arr = null; + int blockPos = 0; + String nd =""; + do { + arr = HtmlNodeHlper.findUpNodes(str, pos - 1, lookback.getInt(4)); + if (urlnodes == null) { + urlnodes = arr; + blockPos = arr.get(arr.size() - 1); + } else { + blockPos = Utils.findBlockPos(urlnodes, arr); + } + nd = HtmlNodeHlper.nodeString(str, blockPos); + + // 检查是否回看层数过多,如果回看导数过多会导致加载不出来数据或一页只加载一条数据,需要进行修正 + if(lookup < 0){ + int count = Utils.getSubStringCount(nd, lookback.getString(0)); + if(count > 3 && lookback.getInt(4)>1){ + lookback.put(4, lookback.getInt(4)-1); + urlnodes = null; + blockPos=0; + nd=""; + SpiderDebug.log(String.format("找到过多的url匹配项(%d),降低匹配层级为%d", count, lookback.getInt(4))); + }else if(lookup == -1){ + String pic = guess_value_vod_pic(nd,0); //尝试找一下图片,如果没找到的话增加一级 + String vName = guess_value_vod_name(nd,0); + if(pic.isEmpty()||vName.isEmpty()){ + lookback.put(4, lookback.getInt(4)+1); + urlnodes = null; + blockPos=0; + nd=""; + lookup = -2; // 只退一次 + SpiderDebug.log(String.format("当前层级未找到(%s),增加匹配层级为%d", pic.isEmpty()? "图片": "标题", lookback.getInt(4))); + }else{ + lookup = lookback.getInt(4); + } + }else{ + lookup = lookback.getInt(4); + } + } + }while (lookup < 0 ); + + + pos += nd.length(); + blockPos = 0; + String vod_id = Utils.findSubString(nd, blockPos, list.getJSONArray("vod_id")); + if (!set.contains(vod_id)) { // 排除重复数据 + set.add(vod_id); + JSONObject v = new JSONObject(); + v.put("vod_id", vod_id); + v.put("vod_name", Utils.findSubString(nd, blockPos, list.optJSONArray("vod_name"))); + v.put("vod_pic", addHttpPrefix(Utils.findSubString(nd, blockPos, list.optJSONArray("vod_pic")))); + v.put("vod_remarks", Utils.findSubString(nd, blockPos, list.optJSONArray("vod_remarks"))); + + if (v.getString("vod_name").isEmpty()) { + v.put("vod_name", guess_value_vod_name(nd, 0)); + } + + if (v.getString("vod_pic").isEmpty()) { + v.put("vod_pic", guess_value_vod_pic(nd, 0)); + } + + // 随便整点remark + if (v.getString("vod_remarks").isEmpty()) { + String vod_name = v.getString("vod_name"); + v.put("vod_remarks", guess_value_vod_remarks(nd, 0, vod_name)); + } + v.put("vod_id", Base64.encodeToString(v.toString().getBytes(Misc.CharsetUTF8), base64Flag)); + videos.put(v); + } +// pos += vod_id.length(); + } + + 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) { + e.printStackTrace(); + return ""; + } + } + + // 生成播放的名称 + public ArrayList makeVodPlayFrom(int sz) { + ArrayList vec = new ArrayList(); + for (int i = 1; i <= sz; ++i) { + vec.add("播放列表" + i); + } + return vec; + } + + // 查找播放列表名 + public ArrayList findVodPlayFrom(String str, int sz) { + try { + ArrayList urlnodes = null; + JSONObject playlist = this.rule.getJSONObject("playlist"); + if (!playlist.has("vod_play_from")) { + return makeVodPlayFrom(sz); + } + ArrayList> vod_play_from = new ArrayList>(); + JSONArray rule_vod_play_from = playlist.getJSONArray("vod_play_from"); + for (int i = 0; i < rule_vod_play_from.length(); ++i) { + String s = rule_vod_play_from.get(i).getClass().getSimpleName(); + String key = ""; + String alias = ""; + if (s.equals("String")) { + key = alias = rule_vod_play_from.getString(i); + } else if (s.equals("JSONArray")) { + JSONArray item = rule_vod_play_from.getJSONArray(i); + key = alias = item.getString(0); + if (item.length() > 1) { + alias = item.getString(1); + } + } else { + return makeVodPlayFrom(sz); + } + + int pos = str.indexOf(key); + if (pos == -1) continue; + vod_play_from.add(new Pair<>(pos, alias)); + } + // 找到的名称与实际需要的数量不匹配,返回默认的名称 + if (vod_play_from.size() != sz) { + return makeVodPlayFrom(sz); + } + // 排序 + Collections.sort(vod_play_from, new Comparator>() { + @Override + public int compare(Pair a, Pair b) { + return a.first.intValue() - b.first.intValue(); + } + }); + + ArrayList vec = new ArrayList(); + for (int i = 0; i < vod_play_from.size(); ++i) { + vec.add(vod_play_from.get(i).second); + } + return vec; + } catch (Exception e) { + e.printStackTrace(); + } + return makeVodPlayFrom(sz); + } + + // 查找播放列表 + public ArrayList findVodPlayUrl(String str) { + ArrayList tmp_vod_play_url = new ArrayList(); + ArrayList vod_play_url = new ArrayList(); + try { + int pos = 0; + ArrayList urlnodes = null; + JSONObject playlist = this.rule.getJSONObject("playlist"); + int sort = playlist.optInt("sort", 0); // 如果这个值是0。表示要倒序播放列表 + HashMap map = new HashMap(); + Set rmset = new HashSet(); +// String tmp = ""; + ArrayList tmp = new ArrayList(); + JSONArray lookback = Utils.getLookbackArray(playlist); + while (lookback != null) { + JSONArray rule_vod_play_url = playlist.getJSONArray("vod_play_url"); + pos = str.indexOf(rule_vod_play_url.getString(0), pos); + if (pos == -1) break; + ArrayList arr = HtmlNodeHlper.findUpNodes(str, pos - 1, lookback.getInt(4)); + + int blockPos = 0; + if (urlnodes == null || arr.size() != urlnodes.size() || arr.get(arr.size() - 1).intValue() != urlnodes.get(urlnodes.size() - 1).intValue()) { + urlnodes = arr; + blockPos = arr.get(Math.max(0, arr.size() - 2)); + // 如果上级节点不同,说明当前播放列表已经结束,可以 + if (!tmp.isEmpty()) { + SpiderDebug.log("change play list "); + if (sort != 0) { + Collections.reverse(tmp); + } + tmp_vod_play_url.add(TextUtils.join("#", tmp)); + tmp = new ArrayList(); + } + } else { + blockPos = Utils.findBlockPos(urlnodes, arr); + } +// String bs = str.substring(blockPos, blockPos + 1000); +// String b = this.findNodeString(str, blockPos); + // 处理play_url 为空的情况 + String play_url = addHttpPrefix(Utils.findSubString(str, blockPos, playlist.getJSONArray("vod_play_url"))); + + if (map.containsKey(play_url)) { // 如果以经找过当前播放的url,那么认为之前找到的都是垃圾数据,清空之间的成果 + SpiderDebug.log("发现重复播放连接,清空已解析到的播放列表"); + rmset.add(map.get(play_url)); // 添加移除标志 + } + map.put(play_url, tmp_vod_play_url.size()); + String play_url_title = Utils.findSubString(str, blockPos, playlist.optJSONArray("vod_play_url_title")); + if (play_url_title.isEmpty()) { + play_url_title = HtmlNodeHlper.trimHtmlString(HtmlNodeHlper.nodeString(str, blockPos)); + int dd = 3; + } + tmp.add(play_url_title + "$" + play_url); +// SpiderDebug.log(String.format("%s$%s", play_url_title, play_url)); + pos += play_url.length(); + } + + if (!tmp.isEmpty()) { + if (sort != 0) { + Collections.reverse(tmp); + } + tmp_vod_play_url.add(TextUtils.join("#", tmp)); + } + + for (int i = 0; i < tmp_vod_play_url.size(); ++i) { + if (!rmset.contains(i)) { + vod_play_url.add(tmp_vod_play_url.get(i)); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return vod_play_url; + } + + // 猜测详情数据的html区间 + protected String guessDetailContentRegion(String body) { + String regx = String.format(">\\s*?(%s)|(%s)", TextUtils.join("|", detailItemNames), TextUtils.join(":|", detailItemNames)); + Pattern pattern = Pattern.compile(regx, Pattern.CASE_INSENSITIVE); + Matcher m = pattern.matcher(body); + ArrayList list = new ArrayList<>(); + while (m.find()) { + HtmlMatchInfo cate = new HtmlMatchInfo(); + cate.init(m); + cate.uploads = HtmlNodeHlper.findUpNodes(body, cate.startPos, 5); + if (!list.isEmpty()) { + boolean b = list.get(0).hasSameUpNode(cate); + if (!b) { // 当前找到的info和list中的匹配 + if (list.size() > 1) { + boolean found = false; + for (int i = 0; i < list.size(); ++i) { + if (list.get(i).group0.indexOf("导演") != -1) { + found = true; + } + } + if (found) { + return HtmlNodeHlper.nodeString(body, list.get(0).matchedUpNodePos); + } else { + list.clear(); + } + } + list.clear(); + } + } + list.add(cate); + } + if (list.size() > 1) { // 如果list中的数据大于1 则认为找到了类型列表 + return HtmlNodeHlper.nodeString(body, list.get(0).matchedUpNodePos); + } else { + return ""; + } + } + + @Override + public String detailContent(List ids) { + try { + fetchRule(); + JSONObject vinfo = new JSONObject(new String(Base64.decode(ids.get(0), base64Flag), "UTF-8")); + + JSONObject detail = rule.optJSONObject("detail"); + if (detail == null) return ""; + // 如果不存在url,则使用list中的vod_id来生成url + if (!detail.has("url")) { + JSONObject list = rule.getJSONObject("list"); + JSONArray tmp = list.getJSONArray("vod_id"); + String u = addHttpPrefix(tmp.getString(0) + "{vid}" + tmp.getString(1)); + detail.put("url", u); + } + String url = detail.getString("url").replace("{vid}", vinfo.getString("vod_id")); + String body = fetchUrl(url, detail.optJSONObject("header")); + String str = Utils.getRegion(body, detail); + int startPos = 0; + + String nodeString = ""; + // 圈定 详情数据的范围 + JSONArray lookback = Utils.getLookbackArray(detail); + if (lookback != null) { + int pos = str.indexOf(lookback.getString(0), 0); + if (pos != -1) { + ArrayList arr = HtmlNodeHlper.findUpNodes(str, pos - 1, lookback.getInt(4)); + if (arr.size() > 0) { + startPos = arr.get(arr.size() - 1); + nodeString = HtmlNodeHlper.nodeString(str, startPos); // 精确详情数据的范围 + } + } + } + // 没有指定详情数据范围则猜一个出来 + if (nodeString.isEmpty()) { + nodeString = this.guessDetailContentRegion(body); + } + + if (nodeString.length() != str.length()) { + str = nodeString; + startPos = 0; + } + /////////////////////////////////////////////////////////////////////////////////////// + + JSONObject vod = new JSONObject(); + vod.put("vod_id", ids.get(0)); + vod.put("vod_name", Utils.findSubString(str, startPos, detail.optJSONArray("vod_name"))); + vod.put("vod_pic", addHttpPrefix(Utils.findSubString(str, startPos, detail.optJSONArray("vod_pic")))); + vod.put("type_name", Utils.findSubString(str, startPos, detail.optJSONArray("type_name"))); + vod.put("vod_year", Utils.findSubString(str, startPos, detail.optJSONArray("vod_year"))); + vod.put("vod_area", Utils.findSubString(str, startPos, detail.optJSONArray("vod_area"))); + vod.put("vod_remarks", Utils.findSubString(str, startPos, detail.optJSONArray("vod_remarks"))); + vod.put("vod_actor", Utils.findSubString(str, startPos, detail.optJSONArray("vod_actor"))); + vod.put("vod_director", Utils.findSubString(str, startPos, detail.optJSONArray("vod_director"))); + vod.put("vod_content", Utils.findSubString(str, startPos, detail.optJSONArray("vod_content"))); + + + //////////////////////////////////////////////////////////////////////////////////////// + if (vod.getString("vod_name").isEmpty()) { + vod.put("vod_name", vinfo.optString("vod_name", "")); + } + // 从页面中猜个视频名称出来 + if (vod.getString("vod_name").isEmpty()) { + vod.put("vod_name", guess_value_vod_name(str, startPos)); + } + + //////////////////////////////////////////////////////////////////////////////////////// + if (vod.getString("vod_pic").isEmpty()) { + vod.put("vod_pic", vinfo.optString("vod_pic", "")); + } + if (vod.getString("vod_pic").isEmpty()) { + vod.put("vod_pic", guess_value_vod_pic(str, startPos)); + } + + //////////////////////////////////////////////////////////////////////////////////////// + if (lookback != null && lookback.length() > 1) { + JSONArray key = new JSONArray(); + String name = lookback.getString(0); + String skey = lookback.getString(0); + + ArrayList detailItems = new ArrayList<>(Arrays.asList("导演", "演员", "类型", "年份")); + for (String p : detailItems) { + if (name.indexOf(p) != -1) { + skey = p; + break; + } + } + key.put(name); + key.put(lookback.getString(1)); + if (vod.getString("vod_director").isEmpty()) { + key.put(0, name.replace(skey, "导演")); + vod.put("vod_director", Utils.findSubString(str, startPos, key)); + } + if (vod.getString("vod_actor").isEmpty()) { + key.put(0, name.replace(skey, "主演")); + vod.put("vod_actor", Utils.findSubString(str, startPos, key)); + } + + if (vod.getString("vod_content").isEmpty()) { + String all = HtmlNodeHlper.trimHtmlString(str, "!!!!"); + String[] words = all.split("!!!!"); + String v = ""; + for (int i = 0; i < words.length; ++i) { + if (words[i].length() > v.length()) { + v = words[i]; + } + } + vod.put("vod_content", HtmlNodeHlper.trimHtmlString(v)); + } + + } else { // 猜一下详情数据 + if (vod.getString("vod_director").isEmpty()) { + ArrayList arr = HtmlNodeHlper.getChildNodes(nodeString); + String content = ""; + String f = TextUtils.join("|", detailItemNames); + String regex = String.format("%s",f); + Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); + for (int i = 0; i < arr.size(); ++i) { + String p = HtmlNodeHlper.trimHtmlString(arr.get(i), " ").replace(":", ""); + if (p.length() > content.length()) { content = p; } + String[] all = p.split(regex); + // split出来的可能存在空字符串,去除掉 + ArrayList items = new ArrayList<>(); + for(String c: all){ + if(c.isEmpty()) continue; + items.add(c); + } + Matcher m = pattern.matcher(p); + int index = 0; + while (m.find() && index < items.size()){ + String s = m.group(0); + for (int j = 0; j < detailItemNames.size(); ++j) { + String name = detailItemNames.get(j); + String key = detailItemKeys.get(j); + if (s.indexOf(name) != -1) { + if (vod.getString(key).isEmpty()) { + vod.put(key, items.get(index).trim()); + } + break; + } + } + ++index; + } + } + + if (vod.getString("vod_content").isEmpty()) { + vod.put("vod_content", content); + } + } + } + + + playlistContent(ids, vod, body);// 获取播放列表 + + + JSONObject result = new JSONObject(); + JSONArray list = new JSONArray(); + list.put(vod); + result.put("list", list); + return result.toString(); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + + } + + // 播放页 str 为 detailContent 函数中http返回值 + protected void playlistContent(List ids, JSONObject vod, String body) { + try { + fetchRule(); + JSONObject vinfo = new JSONObject(new String(Base64.decode(ids.get(0), base64Flag), "UTF-8")); + + JSONObject playlist = rule.optJSONObject("playlist"); + if (playlist == null) return; + if (playlist.has("url")) { + String detailUrl = rule.getJSONObject("detail").optString("url"); + String playListUrl = playlist.getString("url"); + if(!detailUrl.equals(playListUrl)){ + String url = playlist.getString("url").replace("{vid}", vinfo.getString("vod_id")); + body = fetchUrl(url, playlist.optJSONObject("header")); + } + } + String str = Utils.getRegion(body, playlist); + + ArrayList vod_play_url = null; + if (!playlist.has("vod_play_url")) { + // 猜vod_play_url的查找规则 + JSONArray vod_play_url_rule = this.guess_rule_vod_play_url(str, vinfo.getString("vod_id")); + if(vod_play_url_rule != null){ + playlist.put("vod_play_url", vod_play_url_rule); + } + } + vod_play_url = this.findVodPlayUrl(str); + ArrayList vod_play_from = this.findVodPlayFrom(str, vod_play_url.size()); + + // 如果有说明播放源的名称,那么对播放源进行排序 + String f1 = TextUtils.join("$$$", vod_play_from); + String f2 = TextUtils.join("$$$", makeVodPlayFrom(vod_play_url.size())); + + if (!f1.equals(f2)) { + ArrayList urls = new ArrayList<>(); + ArrayList froms = new ArrayList<>(); + + JSONArray rule_vod_play_from = playlist.getJSONArray("vod_play_from"); + for (int i = 0; i < rule_vod_play_from.length(); ++i) { + String s = rule_vod_play_from.get(i).getClass().getSimpleName(); + String alias = ""; + if (s.equals("String")) { + alias = rule_vod_play_from.getString(i); + } else if (s.equals("JSONArray")) { + JSONArray item = rule_vod_play_from.getJSONArray(i); + alias = item.getString(0); + if (item.length() > 1) { + alias = item.getString(1); + } + } + + for (int j = 0; j < vod_play_from.size(); ++j) { + if (vod_play_from.get(j).equals(alias)) { + urls.add(vod_play_url.get(j)); + froms.add(vod_play_from.get(j)); + } + } + + } + vod_play_url = urls; + vod_play_from = froms; + } + vod.put("vod_play_url", TextUtils.join("$$$", vod_play_url)); + vod.put("vod_play_from", TextUtils.join("$$$", vod_play_from)); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + // 尝试从播放页中找播放url + protected String parsePlayUrl(String str, String str2, List list) { + try { + JSONObject play = rule.optJSONObject("play"); + if (play == null) { + return ""; + } + String tmp = fetchUrl(str2, play.optJSONObject("header")); + String body = Utils.getRegion(tmp, play); + int startPos = 0; + JSONArray lookback = Utils.getLookbackArray(play); + if (lookback != null) { + int pos = body.indexOf(lookback.getString(0), 0); + if (pos != -1) { + ArrayList arr = HtmlNodeHlper.findUpNodes(body, pos - 1, lookback.getInt(4)); + if (arr.size() > 0) { + startPos = arr.get(arr.size() - 1); + } else { + startPos = pos; + } + } + } + + String vod_url = Utils.findSubString(body, startPos, play.optJSONArray("vod_url")); + vod_url = vod_url.replace("\\/", "/"); + if (vod_url.isEmpty() || !isVideoFormat(vod_url)) return ""; + JSONObject result = new JSONObject(); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", vod_url); + return result.toString(); + + } catch (Exception e) { + e.printStackTrace(); + } + + return ""; + } + + @Override + public String playerContent(String str, String str2, List list) { + try { + fetchRule(); + // 先判断是否可以拿到直链 + String ret = parsePlayUrl(str, str2, list); + if (!ret.isEmpty()) return ret; + // 直接将网页地址返回回去进行嗅探 + JSONObject result = new JSONObject(); + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", str2); + return result.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } + + protected Object parseJsonSearchResult(Object obj) { + try { + if (obj == null) return null; + JSONObject search = rule.optJSONObject("search"); + if (search == null) return null; + String key_vod_id = search.getString("vod_id"); + String key_vod_name = search.getString("vod_name"); + String type = obj.getClass().getSimpleName(); + if (type.equals("JSONObject")) { + JSONObject object = (JSONObject) obj; + if (object.has(key_vod_id) && object.has(key_vod_name)) return object; + for (Iterator iter = object.keys(); iter.hasNext(); ) { + String k = iter.next(); + Object r = parseJsonSearchResult(object.get(k)); + if (r != null) { + return r; + } + } + } else if (type.equals("JSONArray")) { + JSONArray array = (JSONArray) obj; + for (int i = 0; i < array.length(); ++i) { + if (parseJsonSearchResult(array.get(i)) != null) { + return array; + } + } + } + + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + protected String parseSearchResult(String body) { + try { + JSONObject obj = new JSONObject(body); + Object info = parseJsonSearchResult(obj); + if (info == null) return ""; + JSONArray arr = new JSONArray(); + if (info.getClass().getSimpleName().equals("JSONObject")) { + arr.put(info); + } else { + arr = (JSONArray) info; + } + JSONObject search = rule.optJSONObject("search"); + JSONArray videos = new JSONArray(); + for (int i = 0; i < arr.length(); ++i) { + JSONObject v = new JSONObject(); + JSONObject o = arr.getJSONObject(i); + if (search.has("vod_id") && o.has(search.getString("vod_id"))) { + v.put("vod_id", o.get(search.getString("vod_id")).toString()); + } else { + continue; + } + if (search.has("vod_name") && o.has(search.getString("vod_name"))) { + v.put("vod_name", o.get(search.getString("vod_name")).toString()); + } else { + v.put("vod_name", "未知"); + } + + if (search.has("vod_pic") && o.has(search.getString("vod_pic"))) { + v.put("vod_pic", o.get(search.getString("vod_pic")).toString()); + } else { + v.put("vod_pic", ""); + } + + if (search.has("vod_remarks") && o.has(search.getString("vod_remarks"))) { + v.put("vod_remarks", o.get(search.getString("vod_remarks")).toString()); + } else { + v.put("vod_remarks", ""); + } + v.put("vod_id", Base64.encodeToString(v.toString().getBytes(Misc.CharsetUTF8), base64Flag)); + videos.put(v); + } + JSONObject result = new JSONObject(); + result.put("list", videos); + return result.toString(); + + } catch (Exception e) { +// e.printStackTrace(); + } + return ""; + } + + // post 搜索,只做了简单的支持 + protected String postSearch(String wd, boolean z) { + try { + JSONObject search = rule.optJSONObject("search"); + if (search == null) return ""; + String url = search.getString("url"); + JSONObject params = search.getJSONObject("post"); // 查询参数 + HashMap reqpayload = new HashMap<>(); + Iterator iter = params.keys(); + while (iter.hasNext()) { + String key = iter.next(); + String value = params.getString(key).replace("{wd}", wd); + reqpayload.put(key, value); + } + final String[] retval = {""}; + HashMap header = getHeaders(url); + header.put("content-type", "application/x-www-form-urlencoded"); + OkHttpUtil.post(OkHttpUtil.defaultClient(), url, reqpayload, header, new OKCallBack.OKCallBackString() { + @Override + protected void onFailure(Call call, Exception e) { + + } + + @Override + protected void onResponse(String response) { + retval[0] = response; + } + }); + return retval[0]; + } catch (Exception e) { + + } + return ""; + } + + @Override + public String searchContent(String wd, boolean z) { + try { + fetchRule(); + JSONObject search = rule.optJSONObject("search"); + if (search == null) return ""; + String str = ""; + if (search.has("post")) { + str = postSearch(wd, z); + } else { + String url = search.getString("url").replace("{wd}", wd); + str = fetchUrl(url, search.optJSONObject("header")); + } + str = Utils.getRegion(str, search); + // 先当JSON解析试试 + String r = parseSearchResult(str); + if (r != null && !r.isEmpty()) { + return r; + } + + if (!search.has("vod_id")) { + JSONObject list = rule.getJSONObject("list"); + search.put("vod_id", list.getJSONArray("vod_id")); + } + + JSONArray videos = new JSONArray(); + Set set = new HashSet(); + int pos = 0; + ArrayList urlnodes = null; + + JSONArray lookback = Utils.getLookbackArray(search); + + int lookup = -1; + while (lookback != null) { + pos = str.indexOf(lookback.getString(0), pos); + if (pos == -1) break; + + ArrayList arr = null; + int blockPos = 0; + String nd =""; + do { + arr = HtmlNodeHlper.findUpNodes(str, pos - 1, lookback.getInt(4)); + if (urlnodes == null) { + urlnodes = arr; + blockPos = arr.get(arr.size() - 1); + } else { + blockPos = Utils.findBlockPos(urlnodes, arr); + } + nd = HtmlNodeHlper.nodeString(str, blockPos); + // 检查是否回看层数过多,如果回看导数过多会导致加载不出来数据或一页只加载一条数据,需要进行修正 + if(lookup < 0){ + int count = Utils.getSubStringCount(nd, lookback.getString(0)); + if(count > 3 && lookback.getInt(4)>1){ + lookback.put(4, lookback.getInt(4)-1); + urlnodes = null; + blockPos=0; + nd=""; + SpiderDebug.log(String.format("找到过多的url匹配项(%d),降低匹配层级为%d", count, lookback.get(4))); + } + else if(lookup == -1){ + String pic = guess_value_vod_pic(nd,0); //尝试找一下图片,如果没找到的话增加一级 + String vName = guess_value_vod_name(nd,0); + if(pic.isEmpty()||vName.isEmpty()){ + lookback.put(4, lookback.getInt(4)+1); + urlnodes = null; + blockPos=0; + nd=""; + lookup = -2; // 只退一次 + SpiderDebug.log(String.format("当前层级未找到(%s),增加匹配层级为%d", pic.isEmpty()? "图片": "标题", lookback.getInt(4))); + }else{ + lookup = lookback.getInt(4); + } + }else{ + lookup = lookback.getInt(4); + } + } + }while (lookup < 0); + + pos += nd.length(); + blockPos = 0; + String vod_id = Utils.findSubString(nd, blockPos, search.getJSONArray("vod_id")); + if (!set.contains(vod_id)) { + set.add(vod_id); + JSONObject v = new JSONObject(); + v.put("vod_id", vod_id); + v.put("vod_name", Utils.findSubString(nd, blockPos, search.optJSONArray("vod_name"))); + v.put("vod_pic", addHttpPrefix(Utils.findSubString(nd, blockPos, search.optJSONArray("vod_pic")))); + v.put("vod_remarks", Utils.findSubString(nd, blockPos, search.optJSONArray("vod_remarks"))); + + if (v.getString("vod_name").isEmpty()) { + v.put("vod_name", guess_value_vod_name(nd, 0)); + } + + if (v.getString("vod_pic").isEmpty()) { + v.put("vod_pic", guess_value_vod_pic(nd, 0)); + } + // 随便整点remark + if (v.getString("vod_remarks").isEmpty()) { + String vod_name = v.getString("vod_name"); + v.put("vod_remarks", guess_value_vod_remarks(nd, 0, vod_name)); + } + v.put("vod_id", Base64.encodeToString(v.toString().getBytes(Misc.CharsetUTF8), base64Flag)); + videos.put(v); + } + } + + JSONObject result = new JSONObject(); + result.put("list", videos); + return result.toString(); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + protected String fetchUrl(String url, JSONObject h) { + String html = OkHttpUtil.string(url, getHeaders(url)); + html = this.jumpbtwaf(url, html, h); + return html.replaceAll("", "").replace("\r\n","").replace("\n",""); // 移除注释 + } + + protected String jumpbtwaf(String webUrl, String html, JSONObject h) { + + try { + // 没有配置btwaf不执行下面的代码 + if (!rule.optBoolean("btwaf", false)) { + return html; + } + + if (html.contains("检测中") && html.contains("跳转中") && html.contains("btwaf")) { + JSONArray keys = new JSONArray(); + keys.put("btwaf="); + keys.put("\""); + String btwaf = Utils.findSubString(html, 0, keys); + String bturl = webUrl + "?btwaf=" + btwaf; + + Map> cookies = new HashMap<>(); + OkHttpUtil.string(bturl, getHeaders(webUrl), cookies); + for (Map.Entry> entry : cookies.entrySet()) { + if (entry.getKey().equals("set-cookie") || entry.getKey().equals("Set-Cookie")) { + String btcookie = TextUtils.join(";", entry.getValue()); + if (!rule.has("header")) { + rule.put("header", new JSONObject()); + } + rule.getJSONObject("header").put("cookie", btcookie); + break; + } + } + html = fetchUrl(webUrl, h); + } + if (!html.contains("检测中") && !html.contains("btwaf")) { + return html; + } + + } catch (Exception e) { + e.printStackTrace(); + } + return html; + } + +} diff --git a/app/src/main/java/com/github/catvod/spider/XBiubiu.java b/app/src/main/java/com/github/catvod/spider/XBiubiu.java index 623a671..e805629 100644 --- a/app/src/main/java/com/github/catvod/spider/XBiubiu.java +++ b/app/src/main/java/com/github/catvod/spider/XBiubiu.java @@ -12,6 +12,7 @@ import com.github.catvod.utils.okhttp.OkHttpUtil; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.jsoup.Jsoup; import java.util.ArrayList; import java.util.HashMap; @@ -58,7 +59,7 @@ public class XBiubiu extends Spider { protected HashMap getHeaders(String url) { HashMap headers = new HashMap<>(); - String ua = getRuleVal("UserW", Misc.UaWinChrome).trim(); + String ua = getRuleVal("ua", Misc.UaWinChrome).trim(); if (ua.isEmpty()) ua = Misc.UaWinChrome; headers.put("User-Agent", ua); @@ -99,8 +100,17 @@ public class XBiubiu extends Spider { private JSONObject category(String tid, String pg, boolean filter, HashMap extend) { try { fetchRule(); + if (tid.equals("空")) + tid = ""; + String qishiye = rule.optString("qishiye", "nil"); + if (qishiye.equals("空")) + pg = ""; + else if (!qishiye.equals("nil")) { + pg = String.valueOf(Integer.parseInt(pg) - 1 + Integer.parseInt(qishiye)); + } String webUrl = getRuleVal("url") + tid + pg + getRuleVal("houzhui"); String html = fetch(webUrl); + html = removeUnicode(html); String parseContent = html; boolean shifouercijiequ = getRuleVal("shifouercijiequ").equals("1"); if (shifouercijiequ) { @@ -113,32 +123,30 @@ public class XBiubiu extends Spider { JSONArray videos = new JSONArray(); ArrayList jiequContents = subContent(parseContent, jiequshuzuqian, jiequshuzuhou); for (int i = 0; i < jiequContents.size(); i++) { - //try { - String jiequContent = jiequContents.get(i); - String title = subContent(jiequContent, getRuleVal("biaotiqian"), getRuleVal("biaotihou")).get(0); - String pic = subContent(jiequContent, getRuleVal("tupianqian"), getRuleVal("tupianhou")).get(0); - pic = Misc.fixUrl(webUrl, pic); - String link = subContent(jiequContent, getRuleVal("lianjieqian"), getRuleVal("lianjiehou")).get(0); - //String remarks = subContent(jiequContent, getRuleVal("gengxinqian"), getRuleVal("gengxinhou")).get(0); - //String remarks = subContent(jiequContent, getRuleVal("gengxinqian"), getRuleVal("gengxinhou")).get(0).replaceAll("\\s+", "").replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", ""); - String mark = ""; - if (!getRuleVal("gengxinqian").isEmpty() && !getRuleVal("gengxinhou").isEmpty()) { - try { - mark = subContent(jiequContent, getRuleVal("gengxinqian"), getRuleVal("gengxinhou")).get(0).replaceAll("\\s+", "").replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", ""); - } catch (Exception e) { - SpiderDebug.log(e); + try { + String jiequContent = jiequContents.get(i); + String title = removeHtml(subContent(jiequContent, getRuleVal("biaotiqian"), getRuleVal("biaotihou")).get(0)); + String pic = ""; + String tupianqian = getRuleVal("tupianqian").toLowerCase(); + if (tupianqian.startsWith("http://") || tupianqian.startsWith("https://")) { + pic = getRuleVal("tupianqian"); + } else { + pic = subContent(jiequContent, getRuleVal("tupianqian"), getRuleVal("tupianhou")).get(0); } + pic = Misc.fixUrl(webUrl, pic); + String link = subContent(jiequContent, getRuleVal("lianjieqian"), getRuleVal("lianjiehou")).get(0); + link = getRuleVal("ljqianzhui").isEmpty() ? (link + getRuleVal("ljhouzhui")) : ("x:" + getRuleVal("ljqianzhui")) + link + getRuleVal("ljhouzhui"); + String remark = !getRuleVal("fubiaotiqian").isEmpty() && !getRuleVal("fubiaotihou").isEmpty() ? + removeHtml(subContent(jiequContent, getRuleVal("fubiaotiqian"), getRuleVal("fubiaotihou")).get(0)) : ""; + JSONObject v = new JSONObject(); + v.put("vod_id", title + "$$$" + pic + "$$$" + link); + v.put("vod_name", title); + v.put("vod_pic", pic); + v.put("vod_remarks", remark); + videos.put(v); + } catch (Throwable th) { + th.printStackTrace(); } - JSONObject v = new JSONObject(); - v.put("vod_id", title + "$$$" + pic + "$$$" + link); - v.put("vod_name", title); - v.put("vod_pic", pic); - v.put("vod_remarks", mark); - videos.put(v); - //} catch (Throwable th) { - //th.printStackTrace(); - //break; - //} } JSONObject result = new JSONObject(); result.put("page", pg); @@ -153,6 +161,22 @@ public class XBiubiu extends Spider { return null; } + private static String removeUnicode(String str) { + Pattern pattern = Pattern.compile("(\\\\u(\\w{4}))"); + Matcher matcher = pattern.matcher(str); + while (matcher.find()) { + String full = matcher.group(1); + String ucode = matcher.group(2); + char c = (char) Integer.parseInt(ucode, 16); + str = str.replace(full, c + ""); + } + return str; + } + + String removeHtml(String text) { + return Jsoup.parse(text).text(); + } + @Override public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { JSONObject obj = category(tid, pg, filter, extend); @@ -164,8 +188,8 @@ public class XBiubiu extends Spider { try { fetchRule(); String[] idInfo = ids.get(0).split("\\$\\$\\$"); - String webUrl = getRuleVal("url") + idInfo[2]; - String html = fetch(webUrl); + String webUrl = idInfo[2].startsWith("x:") ? idInfo[2] : getRuleVal("url") + idInfo[2]; + String html = fetch(webUrl.startsWith("x:") ? webUrl.substring(2) : webUrl); String parseContent = html; boolean bfshifouercijiequ = getRuleVal("bfshifouercijiequ").equals("1"); if (bfshifouercijiequ) { @@ -175,36 +199,38 @@ public class XBiubiu extends Spider { } ArrayList playList = new ArrayList<>(); - - String jiequshuzuqian = getRuleVal("bfjiequshuzuqian"); - String jiequshuzuhou = getRuleVal("bfjiequshuzuhou"); - boolean bfyshifouercijiequ = getRuleVal("bfyshifouercijiequ").equals("1"); - ArrayList jiequContents = subContent(parseContent, jiequshuzuqian, jiequshuzuhou); - for (int i = 0; i < jiequContents.size(); i++) { - try { - String jiequContent = jiequContents.get(i); - String parseJqContent = bfyshifouercijiequ ? subContent(jiequContent, getRuleVal("bfyjiequqian"), getRuleVal("bfyjiequhou")).get(0) : jiequContent; - ArrayList lastParseContents = subContent(parseJqContent, getRuleVal("bfyjiequshuzuqian"), getRuleVal("bfyjiequshuzuhou")); - List vodItems = new ArrayList<>(); - for (int j = 0; j < lastParseContents.size(); j++) { - String title = subContent(lastParseContents.get(j), getRuleVal("bfbiaotiqian"), getRuleVal("bfbiaotihou")).get(0); - String link = subContent(lastParseContents.get(j), getRuleVal("bflianjieqian"), getRuleVal("bflianjiehou")).get(0); - vodItems.add(title + "$" + link); - } - playList.add(TextUtils.join("#", vodItems)); - } catch (Throwable th) { - th.printStackTrace(); - break; + boolean playDirect = getRuleVal("直接播放").equals("1"); + if (!playDirect) { + String jiequshuzuqian = getRuleVal("bfjiequshuzuqian"); + String jiequshuzuhou = getRuleVal("bfjiequshuzuhou"); + boolean bfyshifouercijiequ = getRuleVal("bfyshifouercijiequ").equals("1"); + ArrayList jiequContents = subContent(parseContent, jiequshuzuqian, jiequshuzuhou); + for (int i = 0; i < jiequContents.size(); i++) { + try { + String jiequContent = jiequContents.get(i); + String parseJqContent = bfyshifouercijiequ ? subContent(jiequContent, getRuleVal("bfyjiequqian"), getRuleVal("bfyjiequhou")).get(0) : jiequContent; + ArrayList lastParseContents = subContent(parseJqContent, getRuleVal("bfyjiequshuzuqian"), getRuleVal("bfyjiequshuzuhou")); + List vodItems = new ArrayList<>(); + for (int j = 0; j < lastParseContents.size(); j++) { + String title = subContent(lastParseContents.get(j), getRuleVal("bfbiaotiqian"), getRuleVal("bfbiaotihou")).get(0); + String link = subContent(lastParseContents.get(j), getRuleVal("bflianjieqian"), getRuleVal("bflianjiehou")).get(0); + String bfqianzhui = getRuleVal("bfqianzhui"); + if (!bfqianzhui.isEmpty()) { + link = bfqianzhui + link; + } + vodItems.add(title + "$" + link); + } + playList.add(TextUtils.join("#", vodItems)); + } catch (Throwable th) { + th.printStackTrace(); + } } - } - String cover = idInfo[1], title = idInfo[0], area = ""; - String director = ""; - String actor = ""; - String desc = ""; - String remark = ""; - String year = ""; - String category = ""; + } else { + playList.add(idInfo[0] + "$" + idInfo[2]); + } + + String cover = idInfo[1], title = idInfo[0], desc = "", category = "", area = "", year = "", remark = "", director = "", actor = ""; if (!getRuleVal("leixinqian").isEmpty() && !getRuleVal("leixinhou").isEmpty()) { try { @@ -247,7 +273,7 @@ public class XBiubiu extends Spider { } catch (Exception e) { SpiderDebug.log(e); } - } + } JSONObject vod = new JSONObject(); vod.put("vod_id", ids.get(0)); vod.put("vod_name", title); @@ -259,13 +285,36 @@ public class XBiubiu extends Spider { vod.put("vod_actor", actor); vod.put("vod_director", director); vod.put("vod_content", desc); - - ArrayList playFrom = new ArrayList<>(); - + ArrayList playFrom = new ArrayList<>(); + String xlparseContent = html; + if(getRuleVal("xlbiaotiqian").isEmpty() && getRuleVal("xlbiaotihou").isEmpty()){ + for (int i = 0; i < playList.size(); i++) { playFrom.add("播放列表" + (i + 1)); } - + }else{ + + boolean xlshifouercijiequ = getRuleVal("xlshifouercijiequ").equals("1"); + if (xlshifouercijiequ) { + String xljiequqian = getRuleVal("xljiequqian"); + String xljiequhou = getRuleVal("xljiequhou"); + xlparseContent = subContent(html, xljiequqian, xljiequhou).get(0); + } + + String xljiequshuzuqian = getRuleVal("xljiequshuzuqian"); + String xljiequshuzuhou = getRuleVal("xljiequshuzuhou"); + ArrayList xljiequContents = subContent(xlparseContent, xljiequshuzuqian, xljiequshuzuhou); + for (int i = 0; i < playList.size(); i++) { + try { + String xltitle = subContent(xljiequContents.get(i), getRuleVal("xlbiaotiqian"), getRuleVal("xlbiaotihou")).get(0); + playFrom.add(xltitle); + } catch (Throwable th) { + th.printStackTrace(); + break; + } + } + + } String vod_play_from = TextUtils.join("$$$", playFrom); String vod_play_url = TextUtils.join("$$$", playList); vod.put("vod_play_from", vod_play_from); @@ -282,12 +331,11 @@ public class XBiubiu extends Spider { return ""; } - @Override public String playerContent(String flag, String id, List vipFlags) { try { fetchRule(); - String webUrl = getRuleVal("url") + id; + String webUrl = id.startsWith("x:") ? id.substring(2) : getRuleVal("url") + id; JSONObject result = new JSONObject(); result.put("parse", 1); result.put("playUrl", ""); @@ -318,8 +366,10 @@ public class XBiubiu extends Spider { String id = vod.optString(getRuleVal("jsid")).trim(); String pic = vod.optString(getRuleVal("jspic")).trim(); pic = Misc.fixUrl(webUrl, pic); + String link = getRuleVal("sousuohouzhui") + id; + link = getRuleVal("ssljqianzhui").isEmpty() ? (link + getRuleVal("ssljhouzhui")) : ("x:" + getRuleVal("ssljqianzhui")) + link + getRuleVal("ssljhouzhui"); JSONObject v = new JSONObject(); - v.put("vod_id", name + "$$$" + pic + "$$$" + getRuleVal("sousuohouzhui") + id); + v.put("vod_id", name + "$$$" + pic + "$$$" + link); v.put("vod_name", name); v.put("vod_pic", pic); v.put("vod_remarks", ""); @@ -343,11 +393,20 @@ public class XBiubiu extends Spider { String pic = subContent(jiequContent, getRuleVal("sstupianqian"), getRuleVal("sstupianhou")).get(0); pic = Misc.fixUrl(webUrl, pic); String link = subContent(jiequContent, getRuleVal("sslianjieqian"), getRuleVal("sslianjiehou")).get(0); + link = getRuleVal("ssljqianzhui").isEmpty() ? (link + getRuleVal("ssljhouzhui")) : ("x:" + getRuleVal("ssljqianzhui")) + link + getRuleVal("ssljhouzhui"); + String remark = ""; + if (!getRuleVal("ssfubiaotiqian").isEmpty() && !getRuleVal("ssfubiaotihou").isEmpty()) { + try { + remark = subContent(jiequContent, getRuleVal("ssfubiaotiqian"), getRuleVal("ssfubiaotihou")).get(0).replaceAll("\\s+", "").replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", ""); + } catch (Exception e) { + SpiderDebug.log(e); + } + } JSONObject v = new JSONObject(); v.put("vod_id", title + "$$$" + pic + "$$$" + link); v.put("vod_name", title); v.put("vod_pic", pic); - v.put("vod_remarks", ""); + v.put("vod_remarks", remark); videos.put(v); } catch (Throwable th) { th.printStackTrace(); @@ -417,8 +476,12 @@ public class XBiubiu extends Spider { private ArrayList subContent(String content, String startFlag, String endFlag) { ArrayList result = new ArrayList<>(); + if (startFlag.isEmpty() && endFlag.isEmpty()) { + result.add(content); + return result; + } try { - Pattern pattern = Pattern.compile(startFlag + "(.*?)" + endFlag); + Pattern pattern = Pattern.compile(escapeExprSpecialWord(startFlag) + "(.*?)" + escapeExprSpecialWord(endFlag)); Matcher matcher = pattern.matcher(content); while (matcher.find()) { result.add(matcher.group(1)); @@ -428,4 +491,38 @@ public class XBiubiu extends Spider { } return result; } -} \ No newline at end of file + + String escapeExprSpecialWord(String regexStr) { + if (!regexStr.isEmpty()) { + String[] fbsArr = {"\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|"}; + for (String key : fbsArr) { + if (regexStr.contains(key)) { + regexStr = regexStr.replace(key, "\\" + key); + } + } + } + return regexStr; + } + + //修复软件不支持的格式无法嗅探的问题 + @Override + public boolean manualVideoCheck() { + return true; + } + + private String[] videoFormatList = new String[]{".m3u8", ".mp4", ".mpeg", ".flv", ".m4a",".mp3",".wma",".wmv"}; + + @Override + public boolean isVideoFormat(String url) { + url = url.toLowerCase(); + if (url.contains("=http") || url.contains("=https%3a%2f") || url.contains("=http%3a%2f")) { + return false; + } + for (String format : videoFormatList) { + if (url.contains(format)) { + return true; + } + } + return false; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/XPathBde4.java b/app/src/main/java/com/github/catvod/spider/XPathBde4.java new file mode 100644 index 0000000..799cd8d --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/XPathBde4.java @@ -0,0 +1,135 @@ +package com.github.catvod.spider; + +import android.util.Base64; + +import com.github.catvod.crawler.SpiderDebug; +import com.github.catvod.utils.okhttp.OKCallBack; +import com.github.catvod.utils.okhttp.OkHttpUtil; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import okhttp3.Call; +import okhttp3.Response; + +/** + * 需配合猫大的解密接口使用,没有接口不用尝试。 + */ + +public class XPathBde4 extends XPath { + + String tk = ""; + + @Override + protected void loadRuleExt(String json) { + try { + JSONObject jsonObj = new JSONObject(json); + tk = jsonObj.optString("decodeTk").trim(); + } catch (JSONException e) { + SpiderDebug.log(e); + } + } + + @Override + protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) { + String url = rule.getCateUrl().replace("{catePg}", pg); + String s = "all"; + if (extend != null) { + if (extend.containsKey("s")) { + s = extend.get("s"); + } + } + url = url.replace("{cateId}", s); + url += "?"; + if (extend != null && extend.size() > 0) { + for (Iterator it = extend.keySet().iterator(); it.hasNext(); ) { + String key = it.next(); + if (key.equals("s")) + continue; + String value = extend.get(key); + if (value.length() > 0) { + url += (key + "=" + URLEncoder.encode(value) + "&"); + } + } + } + if (!tid.equals("*")) { + url += ("type=" + tid); + } + return url; + } + + @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(webUrl); + String content = OkHttpUtil.string(webUrl, getHeaders(webUrl)); + String startFlag = "var m3u8 = \""; + int start = content.indexOf(startFlag); + start = start + startFlag.length(); + int end = content.indexOf("\";", start); + String m3u8 = content.substring(start, end).replace("\\", "").replace("https", "http"); + SpiderDebug.log(m3u8); + HashMap headers = getHeaders(m3u8); + + OKCallBack m3u8Callback = new OKCallBack() { + @Override + public String onParseResponse(Call call, Response response) { + try { + return new String(Base64.encode(response.body().bytes(), Base64.DEFAULT)); + } catch (IOException e) { + return ""; + } + } + + @Override + public void onFailure(Call call, Exception e) { + setResult(""); + SpiderDebug.log(e); + } + + @Override + public void onResponse(String response) { + } + }; + OkHttpUtil.get(OkHttpUtil.defaultClient(), m3u8, null, headers, m3u8Callback); + String m3u8Data = m3u8Callback.getResult(); + if (m3u8Data != null && !m3u8Data.isEmpty()) { + JSONObject result = new JSONObject(); + JSONObject json = new JSONObject(); + json.put("data", m3u8Data); + json.put("t", tk); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), "https://cat.idontcare.top/ssr/bde4", json.toString(), new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception e) { + } + + @Override + public void onResponse(String response) { + try { + result.put("url", response); + } catch (JSONException e) { + } + } + }); + result.put("parse", 0); + result.put("playUrl", ""); + if (!rule.getPlayUa().isEmpty()) { + result.put("ua", rule.getPlayUa()); + } + return result.toString(); + + } + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/XPathEgg.java b/app/src/main/java/com/github/catvod/spider/XPathEgg.java new file mode 100644 index 0000000..4a8ec16 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/XPathEgg.java @@ -0,0 +1,113 @@ +package com.github.catvod.spider; + +import com.github.catvod.crawler.SpiderDebug; +import com.github.catvod.utils.okhttp.OKCallBack; +import com.github.catvod.utils.okhttp.OkHttpUtil; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.List; + +import okhttp3.Call; + +public class XPathEgg extends XPath { + + String tk = ""; + + @Override + protected void loadRuleExt(String json) { + try { + JSONObject jsonObj = new JSONObject(json); + tk = jsonObj.optString("decodeTk").trim(); + } catch (JSONException e) { + SpiderDebug.log(e); + } + } + + @Override + protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) { + if (Integer.parseInt(pg) <= 1) { + return rule.getCateUrl().replace("{cateId}", tid); + } + return (rule.getCateUrl() + "index_{catePg}.html").replace("{cateId}", tid).replace("{catePg}", pg); + } + + @Override + protected void detailContentExt(String content, JSONObject vod) { + try { + String startFlag = "infoid="; + int start = content.indexOf(startFlag); + start = start + startFlag.length(); + int end = content.indexOf(";", start); + String infoid = content.substring(start, end); + + startFlag = "link5='"; + start = content.indexOf(startFlag); + start = start + startFlag.length(); + end = content.indexOf("';", start); + String link5 = content.substring(start, end); + + JSONObject json = new JSONObject(); + json.put("infoid", infoid); + json.put("link5", link5); + json.put("t", tk); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), "https://cat.idontcare.top/ssr/dandan", json.toString(), new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception e) { + } + + @Override + public void onResponse(String response) { + try { + JSONObject obj = new JSONObject(response); + vod.put("vod_play_from", obj.getString("vod_play_from")); + vod.put("vod_play_url", obj.getString("vod_play_url")); + } catch (JSONException e) { + } + } + }); + } catch (Exception e) { + + } + } + + @Override + public String playerContent(String flag, String id, List vipFlags) { + try { + fetchRule(); + HashMap json = new HashMap<>(); + json.put("url", id); + HashMap headers = new HashMap<>(); + headers.put("accept", "*/*"); + headers.put("x-requested-with", "XMLHttpRequest"); + headers.put("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"); + headers.put("origin", "https://www.dandanzan.cc"); + headers.put("accept-language", "zh-CN,zh;q=0.9"); + JSONObject result = new JSONObject(); + OkHttpUtil.post(OkHttpUtil.defaultClient(), rule.getPlayUrl(), json, headers, new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception e) { + } + + @Override + public void onResponse(String response) { + try { + result.put("url", response); + } catch (JSONException e) { + } + } + }); + result.put("parse", 0); + result.put("playUrl", ""); + if (!rule.getPlayUa().isEmpty()) { + result.put("ua", rule.getPlayUa()); + } + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/XPathMacTvgook.java b/app/src/main/java/com/github/catvod/spider/XPathMacTvgook.java new file mode 100644 index 0000000..479cef6 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/XPathMacTvgook.java @@ -0,0 +1,37 @@ +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 com.github.catvod.xpath.XPathRule; + +import org.json.JSONArray; +import org.json.JSONObject; +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 XPathMacTvgook extends XPathMac { + + @Override + public boolean manualVideoCheck() { + return rule.getHomeUrl().contains("tvgook.com"); + + } + + @Override + public boolean isVideoFormat(String url) { + return Misc.isVideoFormat(url)||(url.contains("/ppvod/")&&!url.contains("skipl=1")); + } + + +} diff --git a/app/src/main/java/com/github/catvod/spider/XYQBiu.java b/app/src/main/java/com/github/catvod/spider/XYQBiu.java new file mode 100644 index 0000000..05d4893 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/XYQBiu.java @@ -0,0 +1,1020 @@ +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.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 org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.select.Elements; + +import java.net.URLEncoder; +import java.net.URLDecoder; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import okhttp3.Call; +import okhttp3.Headers; +import okhttp3.Response; + +public class XYQBiu extends Spider { + +// private String btcookie = ""; + + @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(); + + String[] fenleis = getRuleVal("class_name", "").split("&"); + String[] fenleisval = getRuleVal("class_value", "").split("&"); + for (int i = 0; i < fenleis.length; i++) { + JSONObject fenjson = new JSONObject(); + fenjson.put("type_id", fenleisval[i].replaceAll("&&", "&")); + fenjson.put("type_name", fenleis[i]); + classes.put(fenjson); + } + result.put("class", classes); + String getclan = getRuleVal("filterdata", ""); + InetAddress addr = InetAddress.getLocalHost(); + String locadd = "http://" + addr.getHostAddress() + ":9978/file/"; + String filepath = null; + JSONObject filterdata = null; + if (getclan.startsWith("clan://") || getclan.startsWith("http")) { + if (getclan.startsWith("clan://")) { + if (getclan.startsWith("clan://localhost/")) { + filepath = getclan.replace("clan://localhost/", locadd); + } else { + filepath = getclan.replace("clan://", locadd); + } + } else { + filepath = getclan; + } + try { + String filtejson = OkHttpUtil.string(filepath, null); + filterdata = new JSONObject(filtejson); + } catch ( + Exception e) { + SpiderDebug.log(e); + } + } else { + filterdata = rule.optJSONObject("filterdata"); + } + if (filter && filterdata != null) { + result.put("filters", filterdata); + } + return result.toString(); + } catch ( + Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + protected HashMap getHeaders(String url) { + HashMap headers = new HashMap<>(); + String ua = getRuleVal("UserAgent", "okhttp/3.12.11").trim(); + if (ua.isEmpty()) { + ua = "okhttp/3.12.11"; + } else if (ua.equals("PC_UA")) { + ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36"; + } else if (ua.equals("MOBILE_UA")) { + ua = "Mozilla/5.0 (Linux; Android 11; Mi 10 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.152 Mobile Safari/537.36"; + } + headers.put("User-Agent", ua); + + if (!getRuleVal("Referer").isEmpty()) { + String webref = getRuleVal("Referer").trim(); + if (webref.startsWith("http")) { + headers.put("Referer", webref); + } + } + return headers; + } + + @Override + public String homeVideoContent() { + try { + fetchRule(); + if (getRuleVal("homeContent").equals("1")) { + JSONArray videos = new JSONArray(); + String[] fenleis = getRuleVal("class_value", "").split("&"); + for (String fenlei : fenleis) { + JSONObject data = category(fenlei.replaceAll("&&", "&"), "1", false, new HashMap<>()); + if (data != null) { + JSONArray vids = data.optJSONArray("list"); + if (vids != null) { + for (int i = 0; i < vids.length() && i < 5; i++) { + videos.put(vids.getJSONObject(i)); + } + } + } + if (videos.length() >= 20) + break; + } + JSONObject result = new JSONObject(); + result.put("list", videos); + return result.toString(); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + private JSONObject category(String tid, String pg, boolean filter, HashMap extend) { + try { + fetchRule(); + String fistpg = String.valueOf(Integer.parseInt(getRuleVal("firstpage", "1"))); + ////页码 + if (fistpg.equals("0")) { + pg = String.valueOf(Integer.parseInt(pg) - 1 * 1); + } else { + pg = String.valueOf(Integer.parseInt(pg) - 1 + Integer.parseInt(getRuleVal("firstpage", "1"))); + } + //web链接 + String webUrl = getRuleVal("class_url"); + if (webUrl.contains("firstPage=")) { + if (pg.equals("1")) { + webUrl = webUrl.split("\\[firstPage=")[1].split("\\]")[0]; + } else { + webUrl = webUrl.split("\\[firstPage=")[0]; + } + } + //筛选开始 + if (filter && 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) { + webUrl = webUrl.replace("{" + key + "}", URLEncoder.encode(value)); + } + } + } + webUrl = webUrl.replaceAll("\\{cateId\\}", tid).replaceAll("\\{catePg\\}", pg); + Matcher m = Pattern.compile("\\{(.*?)\\}").matcher(webUrl); + while (m.find()) { + String n = m.group(0).replace("{", "").replace("}", ""); + webUrl = webUrl.replace(m.group(0), "").replace("/" + n + "/", ""); + } + //筛选结束 + String html = null; +// String btwatUrl = ""; + //取网页 + if (webUrl.contains(";post")) { + OKCallBack.OKCallBackString callBack = new OKCallBack.OKCallBackString() { + + public void onResponse(String response) { + } + + @Override + protected void onFailure(Call call, Exception exc) { + } + }; + String posturl = webUrl.split("\\?")[0].replaceAll("??", "?").trim(); + String postbody = webUrl.split("\\?")[1].split(";")[0].replaceAll("??", "?").trim(); + if (!postbody.isEmpty() && postbody != null) { + if (postbody.startsWith("{") && postbody.endsWith("}")) { + JSONObject jsbody = new JSONObject(postbody); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), posturl, jsbody.toString(), getHeaders(posturl), callBack); + } else { + LinkedHashMap params = new LinkedHashMap(); + String[] userbody = postbody.split("&"); + for (String userbd : userbody) { + int loca = userbd.indexOf("="); + params.put(userbd.substring(0, loca), userbd.substring(loca + 1)); + } + OkHttpUtil.post(OkHttpUtil.defaultClient(), posturl, params, getHeaders(posturl), callBack); + } + } else { + OkHttpUtil.post(OkHttpUtil.defaultClient(), posturl, null, getHeaders(posturl), callBack); + } + html = convertUnicodeToCh(callBack.getResult().replaceAll("\r|\n", "")); +// btwatUrl = posturl; + } else { + html = convertUnicodeToCh(fetch(webUrl)); +// btwatUrl = webUrl; + } + +// html = jumpbtwaf(btwatUrl,html);//5秒盾 + String parseContent = html; + String mark = ""; + String pic = ""; + boolean fenleiJson = getRuleVal("cat_mode").equals("0"); + boolean picneetproxy = getRuleVal("PicNeedProxy").equals("1"); + + JSONArray videos = new JSONArray(); + JSONObject result = new JSONObject(); + if (fenleiJson) { + JSONObject data = new JSONObject(parseContent); + JSONArray vodArray = null; + String[] keylen = getRuleVal("catjsonlist", "data").split("\\."); + if (keylen.length == 1) { + vodArray = data.getJSONArray(keylen[0]); + } else if (keylen.length == 2) { + vodArray = data.getJSONObject(keylen[0]).getJSONArray(keylen[1]); + } else if (keylen.length == 3) { + vodArray = data.getJSONObject(keylen[0]).getJSONObject(keylen[1]).getJSONArray(keylen[2]); + } + //JSONArray vodArray = data.getJSONArray(getRuleVal("catjsonlist","list")); + for (int j = 0; j < vodArray.length(); j++) { + try { + JSONObject vod = vodArray.getJSONObject(j); + String name = vod.optString(getRuleVal("catjsonname")).trim(); + String id = vod.optString(getRuleVal("catjsonid")).trim(); + id = getRuleVal("cat_prefix", "") + id + getRuleVal("cat_suffix", ""); + if (!getRuleVal("catjsonpic").isEmpty()) { + try { + pic = vod.optString(getRuleVal("catjsonpic")).trim(); + pic = Misc.fixUrl(webUrl, pic); + if (picneetproxy) { + pic = fixCover(pic, webUrl); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + } + try { + mark = vod.optString(getRuleVal("catjsonstitle")).trim(); + } catch (Exception e) { + SpiderDebug.log(e); + } + JSONObject v = new JSONObject(); + v.put("vod_id", name + "$$$" + pic + "$$$" + id); + v.put("vod_name", name); + v.put("vod_pic", pic); + v.put("vod_remarks", mark); + videos.put(v); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + } else { + boolean shifouercijiequ = getRuleVal("cat_YN_twice").equals("1"); + if (shifouercijiequ) { + String jiequqian = getRuleVal("cat_twice_pre"); + String jiequhou = getRuleVal("cat_twice_suf"); + parseContent = subContent(html, jiequqian, jiequhou).get(0); + } + String jiequshuzuqian = getRuleVal("cat_arr_pre"); + String jiequshuzuhou = getRuleVal("cat_arr_suf"); + + ArrayList jiequContents = subContent(parseContent, jiequshuzuqian, jiequshuzuhou); + for (int i = 0; i < jiequContents.size(); i++) { + try { + String jiequContent = jiequContents.get(i); + String title = subContent(jiequContent, getRuleVal("cat_title").split("&&")[0], getRuleVal("cat_title").split("&&")[1]).get(0).replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", ""); + if (!getRuleVal("cat_pic").isEmpty()) { + try { + pic = subContent(jiequContent, getRuleVal("cat_pic").split("&&")[0], getRuleVal("cat_pic").split("&&")[1]).get(0); + pic = Misc.fixUrl(webUrl, pic); + if (picneetproxy) { + pic = fixCover(pic, webUrl); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + } + String link = subContent(jiequContent, getRuleVal("cat_url").split("&&")[0], getRuleVal("cat_url").split("&&")[1]).get(0); + link = getRuleVal("cat_prefix", "") + link + getRuleVal("cat_suffix", ""); + if (!getRuleVal("cat_subtitle").isEmpty()) { + try { + mark = subContent(jiequContent, getRuleVal("cat_subtitle").split("&&")[0], getRuleVal("cat_subtitle").split("&&")[1]).get(0).replaceAll("\\s+", "").replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", ""); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + JSONObject v = new JSONObject(); + v.put("vod_id", title + "$$$" + pic + "$$$" + link); + v.put("vod_name", title); + v.put("vod_pic", pic); + v.put("vod_remarks", mark); + videos.put(v); + } catch (Throwable th) { + th.printStackTrace(); + break; + } + } + } + + 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; + } catch (Exception e) { + SpiderDebug.log(e); + } + return null; + } + + @Override + public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { + JSONObject obj = category(tid, pg, filter, extend); + return obj != null ? obj.toString() : ""; + } + + @Override + public String detailContent(List ids) { + try { + fetchRule(); + String[] idInfo = ids.get(0).split("\\$\\$\\$"); + String webUrl = idInfo[2]; + + String cover = idInfo[1], vodtitle = idInfo[0], area = ""; + String desc = ""; + String director = ""; + String actor = ""; + String remark = ""; + String year = ""; + String category = ""; + + ArrayList playList = new ArrayList<>(); + ArrayList playFrom = new ArrayList<>(); + boolean isMagnet = false; + boolean zhijiebofang = getRuleVal("force_play").equals("1"); + boolean picneetproxy = getRuleVal("PicNeedProxy").equals("1"); + try { + if (picneetproxy) { + cover = fixCover(cover, webUrl); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + if (zhijiebofang) { + //直接播放 + playFrom.add(idInfo[0]); + playList.add(idInfo[0] + "$" + idInfo[2]); + if (idInfo[2].startsWith("magnet")) { + isMagnet = true; + } + } else { + //非直接播放 + String html = fetch(webUrl).trim(); +// html = jumpbtwaf(webUrl,html);//5秒盾 + html = convertUnicodeToCh(html); + String parseContent = html; + boolean bfshifouercijiequ = getRuleVal("list_YN_twice").equals("1"); + if (bfshifouercijiequ) { + String jiequqian = getRuleVal("list_twice_pre"); + String jiequhou = getRuleVal("list_twice_suf"); + parseContent = subContent(html, jiequqian, jiequhou).get(0); + } + + String jiequshuzuqian = getRuleVal("list_arr_pre"); + String jiequshuzuhou = getRuleVal("list_arr_suf"); + boolean bfyshifouercijiequ = getRuleVal("epi_YN_twice").equals("1"); + ArrayList jiequContents = subContent(parseContent, jiequshuzuqian, jiequshuzuhou); + for (int i = 0; i < jiequContents.size(); i++) { + try { + String jiequContent = jiequContents.get(i); + String parseJqContent = bfyshifouercijiequ ? subContent(jiequContent, getRuleVal("epi_twice_pre"), getRuleVal("epi_twice_suf")).get(0) : jiequContent; + ArrayList lastParseContents = subContent(parseJqContent, getRuleVal("epi_arr_pre"), getRuleVal("epi_arr_suf")); + List vodItems = new ArrayList<>(); + for (int j = 0; j < lastParseContents.size(); j++) { + String title = subContent(lastParseContents.get(j), getRuleVal("epi_title").split("&&")[0], getRuleVal("epi_title").split("&&")[1]).get(0); + String link = subContent(lastParseContents.get(j), getRuleVal("epi_url").split("&&")[0], getRuleVal("epi_url").split("&&")[1]).get(0); + link = getRuleVal("epiurl_prefix", "") + link + getRuleVal("epiurl_suffix", ""); + vodItems.add(title + "$" + link); + if (link.startsWith("magnet")) { + isMagnet = true; + break; + } + } + playList.add(TextUtils.join("#", vodItems)); + if (isMagnet) { + break; + } + } catch (Throwable th) { + th.printStackTrace(); + break; + } + } + + //线路代码 + String xlparseContent = html; + //没有线路规则代码时 + if (!getRuleVal("tab_title").isEmpty() && !getRuleVal("tab_arr_pre").isEmpty()) { + //代码取线路名 + boolean xlshifouercijiequ = getRuleVal("tab_YN_twice").equals("1"); + if (xlshifouercijiequ) { + String xljiequqian = getRuleVal("tab_twice_pre"); + String xljiequhou = getRuleVal("tab_twice_suf"); + xlparseContent = subContent(html, xljiequqian, xljiequhou).get(0); + } + + String xljiequshuzuqian = getRuleVal("tab_arr_pre"); + String xljiequshuzuhou = getRuleVal("tab_arr_suf"); + ArrayList xljiequContents = subContent(xlparseContent, xljiequshuzuqian, xljiequshuzuhou); + for (int i = 0; i < playList.size(); i++) { + try { + String xltitle = subContent(xljiequContents.get(i), getRuleVal("tab_title").split("&&")[0], getRuleVal("tab_title").split("&&")[1]).get(0).replaceAll("\\s+", "").replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", ""); + playFrom.add(xltitle); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + } else { + for (int i = 0; i < playList.size(); i++) { + playFrom.add("播放列表" + (i + 1)); + } + } + + if (!getRuleVal("proj_actor").isEmpty()) { + try { + actor = subContent(html, getRuleVal("proj_actor").split("&&")[0], getRuleVal("proj_actor").split("&&")[1]).get(0).replaceAll("\\s+", ""); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + if (!getRuleVal("proj_plot").isEmpty()) { + try { + desc = subContent(html, getRuleVal("proj_plot").split("&&")[0], getRuleVal("proj_plot").split("&&")[1]).get(0); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + } + //非直接播放结束 + JSONObject vod = new JSONObject(); + vod.put("vod_id", ids.get(0)); + vod.put("vod_name", vodtitle); + 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); + + 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); + + JSONObject result = new JSONObject(); + JSONArray list = new JSONArray(); + list.put(vod); + 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 { + fetchRule(); + String webUrl = id; + //WebView嗅探请求头 + JSONObject webheaders = new JSONObject(); + String webua = getRuleVal("UserAgent", "okhttp/3.12.11").trim(); + if (webua.isEmpty()) { + webua = "okhttp/3.12.11"; + } else if (webua.equals("PC_UA")) { + webua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36"; + } else if (webua.equals("MOBILE_UA")) { + webua = "Mozilla/5.0 (Linux; Android 11; Mi 10 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.152 Mobile Safari/537.36"; + } + webheaders.put("User-Agent", webua); + + if (!getRuleVal("Referer").isEmpty()) { + String webref = getRuleVal("Referer").trim(); + if (webref.startsWith("http")) { + webheaders.put("Referer", webref); + } else if (webref.equals("WebView")) { + webheaders.put("Referer", webUrl); + } + } + //嗅探请求头结束 + + JSONObject result = new JSONObject(); + boolean enforceplay = (getRuleVal("force_play").equals("1") || getRuleVal("force_play").equals("2")); + //强制视频链接 + if (enforceplay) { + webUrl = getRuleVal("play_prefix", "") + webUrl + getRuleVal("play_suffix", ""); + //请求头代码 + if (!getRuleVal("play_header").isEmpty()) { + JSONObject uaresult = rule.optJSONObject("play_header"); + if (uaresult != null) { + result.put("header", uaresult.toString()); + } else { + String[] usera = getRuleVal("play_header").split("#"); + JSONObject strua = new JSONObject(); + for (String user : usera) { + String[] head = user.split("\\$"); + strua.put(head[0], " " + head[1]); + } + result.put("header", strua.toString()); + } + } else { + result.put("header", webheaders.toString()); + } + //视频格式识别 + if (webUrl.contains("#isVideo=true#") || Misc.isVideoFormat(webUrl)) { + if (webUrl.contains("#isVideo=true#")) { + webUrl = webUrl.replaceAll("#isVideo=true#", ""); + } + result.put("parse", 0); + result.put("playUrl", ""); + } else if (Misc.isVip(webUrl)) { + result.put("parse", 1); + result.put("jx", "1"); + result.put("url", webUrl); + return result.toString(); + } else { + //不是视频就转嗅探 + result.put("parse", 1); + result.put("playUrl", ""); + } + result.put("url", webUrl); + return result.toString(); + } + //直接播放代码结束 + + //普通链接开始 + //分析mac链接解析 + boolean enMacPlayer = getRuleVal("Anal_MacPlayer").equals("1"); + String videoUrl = null; + String fromflag = null; + + if (enMacPlayer && enforceplay == false) { + try { + Document doc = Jsoup.parse(fetch(webUrl)); + Elements allScript = doc.select("script"); + 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); + String videoUrlTmp = player.getString("url"); + + fromflag = player.getString("from"); + if (player.has("encrypt")) { + int encrypt = player.getInt("encrypt"); + if (encrypt == 1) { + videoUrlTmp = URLDecoder.decode(videoUrlTmp); + } else if (encrypt == 2) { + videoUrlTmp = new String(Base64.decode(videoUrlTmp, Base64.DEFAULT)); + videoUrlTmp = URLDecoder.decode(videoUrlTmp); + } + } + videoUrl = videoUrlTmp; + break; + } + } + } catch (Exception e) { + SpiderDebug.log(e); + } + } + + + //视频不为null时进行处理解析 + if (videoUrl != null) { + 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); + } + } else if (fromflag.matches("duoduozy|ddzy")) { + + result.put("header", webheaders.toString()); + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", webUrl); + return result.toString(); + } else if (Misc.isVideoFormat(videoUrl)) { + try { + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", videoUrl); + result.put("header", ""); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + } + //视频不为null代码结束 + + result.put("header", webheaders.toString()); + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", webUrl); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public boolean manualVideoCheck() { + fetchRule(); + if (getRuleVal("ManualSniffer").equals("1")) { + return true; + } else { + return false; + } + } + + //private String[] videoFormatList = getRuleVal("videoformat",".m3u8#.mp4#.flv").split("#"); + + @Override + public boolean isVideoFormat(String url) { + fetchRule(); + String[] videoFormatList = getRuleVal("VideoFormat", ".m3u8#.mp4#.flv#.mp3#.m4a").split("#"); + String[] videoFilterList = getRuleVal("VideoFilter", "=http#.html").split("#"); + 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)) { + for (String videoFilter : videoFilterList) { + if (url.contains(videoFilter)) { + return false; + } + } + return true; + } + } + return false; + } + + @Override + public String searchContent(String key, boolean quick) { + try { + fetchRule(); + String webUrlTmp = getRuleVal("search_url").replaceAll("\\{wd\\}", key); + String webUrl = webUrlTmp.split(";")[0]; + String webContent = null; + + if (webUrlTmp.contains(";post")) { + OKCallBack.OKCallBackString callBack = new OKCallBack.OKCallBackString() { + + public void onResponse(String response) { + } + + @Override + protected void onFailure(Call call, Exception exc) { + } + }; + + String postbody = getRuleVal("sea_PtBody").replaceAll("\\{wd\\}", key).trim(); + if (!postbody.isEmpty() && postbody != null) { + if (postbody.startsWith("{") && postbody.endsWith("}")) { + JSONObject jsbody = new JSONObject(postbody); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), webUrl, jsbody.toString(), getHeaders(webUrl), callBack); + } else { + LinkedHashMap params = new LinkedHashMap(); + //params.put(postbody, key); + String[] userbody = postbody.split("&"); + for (String userbd : userbody) { + int loca = userbd.indexOf("="); + //int end = userbd.lastIndexOf('=') + 1; + //String[] bdhead = userbd.split("="); + params.put(userbd.substring(0, loca), userbd.substring(loca + 1)); + } + OkHttpUtil.post(OkHttpUtil.defaultClient(), webUrl, params, getHeaders(webUrl), callBack); + } + } else { + OkHttpUtil.post(OkHttpUtil.defaultClient(), webUrl, null, getHeaders(webUrl), callBack); + } + webContent = convertUnicodeToCh(callBack.getResult().replaceAll("\r|\n", "")); + } else { + webContent = convertUnicodeToCh(fetch(webUrl)); + } + + String mark = ""; + String pic = ""; + boolean ssmoshiJson = getRuleVal("search_mode").equals("0"); + boolean picneetproxy = getRuleVal("PicNeedProxy").equals("1"); + + JSONObject result = new JSONObject(); + JSONArray videos = new JSONArray(); + if (ssmoshiJson) { + JSONObject data = new JSONObject(webContent); + JSONArray vodArray = null; + String[] keylen = getRuleVal("jsonlist", "list").split("\\."); + if (keylen.length == 1) { + vodArray = data.getJSONArray(keylen[0]); + } else if (keylen.length == 2) { + vodArray = data.getJSONObject(keylen[0]).getJSONArray(keylen[1]); + } else if (keylen.length == 3) { + vodArray = data.getJSONObject(keylen[0]).getJSONObject(keylen[1]).getJSONArray(keylen[2]); + } + //JSONArray vodArray = data.getJSONArray(getRuleVal("jsonlist","list")); + for (int j = 0; j < vodArray.length(); j++) { + try { + JSONObject vod = vodArray.getJSONObject(j); + String name = vod.optString(getRuleVal("jsonname")).trim(); + String id = vod.optString(getRuleVal("jsonid")).trim(); + id = getRuleVal("cat_prefix", "") + id + getRuleVal("cat_suffix", ""); + if (!getRuleVal("jsonpic").isEmpty()) { + try { + pic = vod.optString(getRuleVal("jsonpic")).trim(); + pic = Misc.fixUrl(webUrl, pic); + if (picneetproxy) { + pic = fixCover(pic, webUrl); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + } + try { + mark = vod.optString(getRuleVal("jsonstitle")).trim(); + } catch (Exception e) { + SpiderDebug.log(e); + } + JSONObject v = new JSONObject(); + v.put("vod_id", name + "$$$" + pic + "$$$" + id); + v.put("vod_name", name); + v.put("vod_pic", pic); + v.put("vod_remarks", mark); + videos.put(v); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + } else { + String parseContent = webContent; + boolean shifouercijiequ = getRuleVal("sea_YN_twice").equals("1"); + if (shifouercijiequ) { + String jiequqian = getRuleVal("sea_twice_pre"); + String jiequhou = getRuleVal("sea_twice_suf"); + parseContent = subContent(webContent, jiequqian, jiequhou).get(0); + } + String jiequshuzuqian = getRuleVal("sea_arr_pre"); + String jiequshuzuhou = getRuleVal("sea_arr_suf"); + ArrayList jiequContents = subContent(parseContent, jiequshuzuqian, jiequshuzuhou); + for (int i = 0; i < jiequContents.size(); i++) { + try { + String jiequContent = jiequContents.get(i); + String title = subContent(jiequContent, getRuleVal("sea_title").split("&&")[0], getRuleVal("sea_title").split("&&")[1]).get(0).replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", ""); + if (!getRuleVal("sea_pic").isEmpty()) { + try { + pic = subContent(jiequContent, getRuleVal("sea_pic").split("&&")[0], getRuleVal("sea_pic").split("&&")[1]).get(0); + pic = Misc.fixUrl(webUrl, pic); + if (picneetproxy) { + pic = fixCover(pic, webUrl); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + } + String link = subContent(jiequContent, getRuleVal("sea_url").split("&&")[0], getRuleVal("sea_url").split("&&")[1]).get(0); + link = getRuleVal("search_prefix") + link + getRuleVal("search_suffix"); + try { + mark = subContent(jiequContent, getRuleVal("sea_subtitle").split("&&")[0], getRuleVal("sea_subtitle").split("&&")[1]).get(0).replaceAll("\\s+", "").replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", ""); + } catch (Exception e) { + SpiderDebug.log(e); + } + JSONObject v = new JSONObject(); + v.put("vod_id", title + "$$$" + pic + "$$$" + link); + v.put("vod_name", title); + v.put("vod_pic", pic); + v.put("vod_remarks", mark); + videos.put(v); + } catch (Throwable th) { + th.printStackTrace(); + break; + } + } + } + result.put("list", videos); + return result.toString(); + } catch ( + Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + protected String ext = null; + protected JSONObject rule = null; + + protected void fetchRule() { + if (rule == null) { + if (ext != null) { + try { + if (ext.startsWith("http")) { + String json = OkHttpUtil.string(ext, null); + rule = new JSONObject(json); + } else { + rule = new JSONObject(ext); + } + } catch (JSONException e) { + } + } + } + } + +// protected String fetch(String webUrl) { +// SpiderDebug.log(webUrl); +// return OkHttpUtil.string(webUrl, getHeaders(webUrl)).replaceAll("\r|\n", ""); + +// } + + + private static String convertUnicodeToCh(String str) { + Pattern pattern = Pattern.compile("(\\\\u(\\w{4}))"); + Matcher matcher = pattern.matcher(str); + + // 迭代,将str中的所有unicode转换为正常字符 + while (matcher.find()) { + String unicodeFull = matcher.group(1); // 匹配出的每个字的unicode,比如\u67e5 + String unicodeNum = matcher.group(2); // 匹配出每个字的数字,比如\u67e5,会匹配出67e5 + + // 将匹配出的数字按照16进制转换为10进制,转换为char类型,就是对应的正常字符了 + char singleChar = (char) Integer.parseInt(unicodeNum, 16); + + // 替换原始字符串中的unicode码 + str = str.replace(unicodeFull, singleChar + ""); + } + return str; + } + + private String getRuleVal(String key, String defaultVal) { + String v = rule.optString(key); + if (v.isEmpty() || v.equals("空") || v.equals("&&")) + return defaultVal; + return v; + } + + private String getRuleVal(String key) { + return getRuleVal(key, ""); + } + + private ArrayList subContent(String content, String startFlag, String endFlag) { + ArrayList result = new ArrayList<>(); + if (startFlag.isEmpty() && endFlag.isEmpty()) { + result.add(content); + return result; + } + try { + Pattern pattern = Pattern.compile(escapeExprSpecialWord(startFlag) + "(.*?)" + escapeExprSpecialWord(endFlag)); + Matcher matcher = pattern.matcher(content); + while (matcher.find()) { + result.add(matcher.group(1).trim()); + } + } catch (Throwable th) { + th.printStackTrace(); + } + if (result.isEmpty()) result.add(""); + return result; + } + + public static String escapeExprSpecialWord(String keyword) { + if (!keyword.isEmpty()) { + String[] fbsArr = {"\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|"}; + for (String key : fbsArr) { + if (keyword.contains(key)) { + keyword = keyword.replace(key, "\\" + key); + } + } + } + return keyword; + } + + protected String fixCover(String cover, String site) { + try { + return "proxy://do=XYQBiu&site=" + site + "&pic=" + cover; + } catch (Exception e) { + SpiderDebug.log(e); + } + return cover; + } + + private static HashMap XYQPicHeader = null; + + public static Object[] loadPic(Map prmap) { + try { + //pic = new String(Base64.decode(pic, Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP), "UTF-8"); + String site = prmap.get("site"); + String pic = prmap.get("pic"); + + if (XYQPicHeader == null) { + XYQPicHeader = new HashMap<>(); + XYQPicHeader.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36"); + XYQPicHeader.put("referer", site); + } + OKCallBack.OKCallBackDefault callBack = new OKCallBack.OKCallBackDefault() { + @Override + protected void onFailure(Call call, Exception e) { + + } + + @Override + protected void onResponse(Response response) { + + } + }; + OkHttpUtil.get(OkHttpUtil.defaultClient(), pic, null, XYQPicHeader, 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; + System.out.println(pic); + System.out.println(type); + result[2] = callBack.getResult().body().byteStream(); + return result; + } + } catch (Throwable th) { + th.printStackTrace(); + } + return null; + } + + + protected String fetch(String webUrl) { + String html = OkHttpUtil.string(webUrl, getHeaders(webUrl)); + html = this.jumpbtwaf(webUrl, html); + return html.replaceAll("", "").replace("\r\n","").replace("\n",""); // 移除注释 + } + + protected String jumpbtwaf(String webUrl, String html) { + + try { + // 没有配置btwaf不执行下面的代码 + if (!rule.optBoolean("btwaf", false)) { + return html; + } + + for (int i = 0; i < 3; i++) { + if (html.contains("检测中") && html.contains("跳转中") && html.contains("btwaf")) { + String btwaf = subContent(html, "btwaf=", "\"").get(0); + String bturl = webUrl + "?btwaf=" + btwaf; + + Map> cookies = new HashMap<>(); + OkHttpUtil.string(bturl, getHeaders(webUrl), cookies); + for (Map.Entry> entry : cookies.entrySet()) { + if (entry.getKey().equals("set-cookie") || entry.getKey().equals("Set-Cookie")) { + String btcookie = TextUtils.join(";", entry.getValue()); + if (!rule.has("header")) { + rule.put("header", new JSONObject()); + } + rule.getJSONObject("header").put("cookie", btcookie); + break; + } + } + html = fetch(webUrl); + } + if (!html.contains("检测中") && !html.contains("btwaf")) { + return html; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return html; + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/Xifanys.java b/app/src/main/java/com/github/catvod/spider/Xifanys.java new file mode 100644 index 0000000..a8ccb65 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Xifanys.java @@ -0,0 +1,479 @@ +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 Xifanys extends Spider { + + private static final String siteUrl = "https://www.xifanys.com/"; + private static final String siteHost = "xifanys.com"; + + protected JSONObject playerConfig; + protected JSONObject filterConfig; + + protected Pattern regexCategory = Pattern.compile("/yingpiantype/(\\S+).html"); + protected Pattern regexVid = Pattern.compile("/yingpiandetail/(\\S+).html"); + protected Pattern regexPlay = Pattern.compile("/yingpianplay/(\\S+)-(\\d+)-(\\d+).html"); + protected Pattern regexPage = Pattern.compile("/yingpianshow/(\\S+).html"); + + @Override + public void init(Context context) { + super.init(context); + try { + playerConfig = new JSONObject("{\"tkm3u8\":{\"sh\":\"R播\",\"pu\":\",\"sn\":0,\"or\":999},\"if101\":{\"sh\":\"Y播\",\"pu\":\"\",\"sn\":0,\"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"); + if (!TextUtils.isEmpty(url)) { + headers.put("Referer", url); + } + //headers.put("sec-ch-ua-platform","Windows"); + headers.put("Accept-Encoding", "gzip, deflate, br"); + headers.put("Upgrade-Insecure-Requests", "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(OkHttpUtil.string(siteUrl, getHeaders(siteUrl))); + // 分类节点 + Element cateList = doc.select("ul.nav-menu-items").get(0); + Elements elements = cateList.select("li > a"); + + JSONArray classes = new JSONArray(); + for (Element ele : elements) { + //分类名 + String name = ele.attr("title"); + 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); + //System.out.println(id+":"+name); + classes.put(jsonObject); + } + } + JSONObject result = new JSONObject(); + if (filter) { + result.put("filters", filterConfig); + } + result.put("class", classes); + try { + // 取首页推荐视频列表 + Element homeList = doc.select("div.module-items").get(0); + 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(".module-item-titlebox a").text(); + String cover = vod.selectFirst(".module-item-pic > img").attr("data-src"); + String remark = vod.selectFirst(".module-item-text").text(); + Matcher matcher = regexVid.matcher(vod.selectFirst(".module-item-titlebox 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 { + 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 + "/yingpianshow/" + 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("div.module-footer > div > 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); + //Element a = li.selectFirst("a"); + if (a == null) + continue; + String name = a.text(); + if (page == -1 && a.hasClass("display")) { + 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.module-items > div.module-item"); + for (int i = 0; i < list.size(); i++) { + Element vod = list.get(i); + String title = vod.selectFirst(".module-item-titlebox a").text(); + String cover = vod.selectFirst(".module-item-pic > img").attr("data-src"); + String remark = vod.selectFirst(".module-item-text").text(); + Matcher matcher = regexVid.matcher(vod.selectFirst(".module-item-titlebox 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", 72); + result.put("total", pageCount <= 1 ? videos.length() : pageCount * 72); + + 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 + "/yingpiandetail/" + ids.get(0) + ".html"; + //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.video-cover .module-item-pic > img").attr("data-src"); + String title = doc.selectFirst("div.video-cover .module-item-pic > a").attr("alt"); + 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.video-info-main span.video-info-itemtitle"); + 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("div.module-tab-content").get(0).select("div > span"); + //System.out.println(sources.size()); + Elements sourceList = doc.select("div.module-player-list"); + //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(".scroll-content > 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 + "/yingpianplay/" + 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/Xmau.java b/app/src/main/java/com/github/catvod/spider/Xmau.java new file mode 100644 index 0000000..7c5a047 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Xmau.java @@ -0,0 +1,263 @@ +package com.github.catvod.spider; + +import com.github.catvod.crawler.Spider; +import com.github.catvod.crawler.SpiderDebug; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.text.TextUtils; +import android.util.Base64; + + +import com.github.catvod.utils.Misc; +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.nio.charset.StandardCharsets; +import java.security.spec.AlgorithmParameterSpec; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.Calendar; +import java.net.URLDecoder; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +public class Xmau extends Spider { + @Override + public void init(Context context) {super.init(context);} + + + @Override + public String homeContent(boolean filter) { + try { + JSONObject cateobj = new JSONObject(); + JSONArray classes = new JSONArray(); + JSONObject result = new JSONObject(); + JSONArray videos = new JSONArray(); + JSONObject v = new JSONObject(); + cateobj.put("type_name", "test111"); + cateobj.put("type_id", "1"); + classes.put(cateobj); + result.put("class", classes); + v.put("vod_id", "testid222"); + v.put("vod_name", "testname333"); + v.put("vod_pic","https://pic.rmb.bdstatic.com/bjh/1d0b02d0f57f0a42201f92caba5107ed.jpeg"); + v.put("vod_remarks", "testmark444"); + videos.put(v); + result.put("list", videos); + return result.toString(); + } catch ( + Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public String detailContent(List ids) { + try { + + JSONObject result = new JSONObject(); + JSONObject vodList = new JSONObject(); + vodList.put("vod_id", "id"); + vodList.put("vod_name", "Xmau解密练习,写固定播放连结,有需要请自行补齐"); + vodList.put("vod_pic", "https://pic.rmb.bdstatic.com/bjh/1d0b02d0f57f0a42201f92caba5107ed.jpeg"); + vodList.put("vod_year", "year9999"); + vodList.put("type_name", "type7777"); + vodList.put("vod_area","are0000a" ); + vodList.put("vod_actor", "actor0987"); + vodList.put("vod_content", "content1234567890"); + String playList = ""; + List vodItems = new ArrayList<>(); + String pl1 = "playname1$playlink1"; + String pl2 = "playname2$playlink2"; + vodItems.add(pl1); + vodItems.add(pl2); + if (vodItems.size() > 0) + playList = TextUtils.join("#", vodItems); + if (playList.length() == 0) + playList = "nothing here"; + Map vod_play = new TreeMap<>(); + vod_play.put("test", 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 { + long currentTime = System.currentTimeMillis()/ 1000; + String apikey=getapikey(); + String deturl ="http://eg.xmau.cn/lvdou_api.php/v1.vod/detail?vod_id=8055&rel_limit=10&apikey="+apikey+"&keytime="+currentTime; + String detsrc = OkHttpUtil.string(deturl, getHeaders(deturl)); + JSONObject detsrcobj = new JSONObject(detsrc); + JSONObject detsrcobjdata= detsrcobj.getJSONObject("data"); + String requrlsrc = detsrcobjdata.getString("vod_play_url"); + String requrl = requrlsrc.substring(3); + currentTime = System.currentTimeMillis()/ 1000; + apikey=getapikey(); + String reqapiurl="https://h5.freejson.xyz/?url="+requrl+"&apikey="+apikey+"&keytime="+currentTime; + String reqapirsp = OkHttpUtil.string(reqapiurl, getHeaders(reqapiurl)); + Document doc = Jsoup.parse(reqapirsp); + Elements allScript = doc.select("script"); + String iv=""; + String enyurl=""; + for (int i = 0; i < allScript.size(); i++) { + String scContent = allScript.get(i).toString(); + if (scContent.contains("var le_token")) { + System.out.println("fpplog scContent:"+scContent); + int start = scContent.indexOf('"'); + int end = scContent.lastIndexOf('"') + 1; + iv = scContent.substring(start+1, end-1); + } + if (scContent.contains("var config")) { + int start = scContent.indexOf("var config ="); + int end = scContent.lastIndexOf('}') + 1; + String j1 = scContent.substring(start, end); + start = j1.indexOf('('); + end = j1.lastIndexOf(')') ; + enyurl = j1.substring(start+2, end-1); + break; + } + } + String enyurlb64dec=toHex(Base64.decode(enyurl.getBytes(), Base64.DEFAULT)); + String key = "A42EAC0C2B408472"; + String videolink=decrypt(enyurlb64dec,key,iv); + JSONObject result = new JSONObject(); + result.put("url", videolink); + result.put("header", new JSONObject(getHeaders(videolink)).toString()); + result.put("parse", 0); + result.put("playUrl", ""); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + + + private HashMap getHeaders(String url) { + HashMap headers = new HashMap<>(); + headers.put("User-Agent","User-Agent:okhttp/4.1.0"); + return headers; + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + protected String getapikey() { + try { + Calendar cal=Calendar.getInstance(); + int y=cal.get(Calendar.YEAR); + int h=cal.get(Calendar.HOUR_OF_DAY); + int m=cal.get(Calendar.MINUTE); + String apikeyori=y+":"+(h<10?("0"+h):h)+":"+y+":"+(m<10?("0"+m):m)+":lvdoutv-1.0.0"; + String apikey=Misc.MD5(apikeyori,StandardCharsets.UTF_8); + return apikey; + } catch (Exception exception) { + SpiderDebug.log(exception); + } + return null; + } + 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(); + } + + + private static final char[] DIGITS + = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + private static final String toHex(byte[] data) { + final StringBuffer sb = new StringBuffer(data.length * 2); + for (int i = 0; i < data.length; i++) { + sb.append(DIGITS[(data[i] >>> 4) & 0x0F]); + sb.append(DIGITS[data[i] & 0x0F]); + } + return sb.toString(); + } + + + + +} diff --git a/app/src/main/java/com/github/catvod/spider/Yiso.java b/app/src/main/java/com/github/catvod/spider/Yiso.java new file mode 100644 index 0000000..1dd6d8d --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Yiso.java @@ -0,0 +1,85 @@ +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.regex.Pattern; + +public class Yiso extends Spider { + private static final Pattern aliyun = Pattern.compile("(https://www.aliyundrive.com/s/[^\"]+)"); + private PushAgent pushAgent; + + public String detailContent(List list) { + try { + return pushAgent.detailContent(list); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public void init(Context context) { + super.init(context); + pushAgent = new PushAgent(); + pushAgent.init(context); + } + + public String playerContent(String str, String str2, List list) { + return pushAgent.playerContent(str, str2, list); + } + + protected static HashMap sHeaders() { + HashMap headers = new HashMap<>(); + headers.put("User-Agent", "Mozilla/5.0 (Linux; Android 12; V2049A Build/SP1A.210812.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/103.0.5060.129 Mobile Safari/537.36"); + headers.put("Referer", "https://yiso.fun/"); + return headers; + } + + private Pattern regexVid = Pattern.compile("(\\S+)"); + + public String searchContent(String key, boolean quick) { + try { + HashMap hashMap = new HashMap(); + HashMap LT = sHeaders(); + String url = "https://yiso.fun/api/search?name=" + URLEncoder.encode(key) + "&from=ali"; + + String content = OkHttpUtil.string(url, LT); + JSONObject data = new JSONObject(content); + JSONArray list = data.getJSONObject("data").getJSONArray("list"); + + JSONObject result = new JSONObject(); + JSONArray videos = new JSONArray(); + + for (int i = 0; i < list.length(); i++) { + JSONObject jSONObject = list.getJSONObject(i); + String sourceName = jSONObject.getJSONArray("fileInfos").getJSONObject(0).getString("fileName"); + String remark = jSONObject.getString("gmtCreate"); + String id = jSONObject.getString("url"); + + JSONObject v = new JSONObject(); + String cover = "https://inews.gtimg.com/newsapp_bt/0/13263837859/1000"; + v.put("vod_name", sourceName); + v.put("vod_remarks", remark); + 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/Yj1211.java b/app/src/main/java/com/github/catvod/spider/Yj1211.java new file mode 100644 index 0000000..e049124 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Yj1211.java @@ -0,0 +1,398 @@ +package com.github.catvod.spider; + + +import android.content.Context; +import android.text.TextUtils; + +import java.net.URLEncoder; +import java.util.Iterator; + + +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.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +public class Yj1211 extends Spider { + + @Override + public void init(Context context) { + super.init(context); + } + + + @Override + public String homeContent(boolean filter) { + try { + + String srcurl = "http://live.yj1211.work/api/live/getRecommend?page=1&size=20"; + String srcOrignstr =""; + for(int i=0 ; i<3 ; i++){ + srcOrignstr = OkHttpUtil.string(srcurl, getHeaders()); + if(srcOrignstr.length()>0){ + break; + }else{ + Thread.sleep(1000); + } + } + + JSONObject srcori = new JSONObject(srcOrignstr); + JSONArray srcoria = srcori.getJSONArray("data"); + + + JSONObject result = new JSONObject(); + JSONArray classes = new JSONArray(); + String catestr ="{\"推荐\":\"?\",\"斗鱼\":\"ByPlatform?platform=douyu&\",\"哔哩哔哩\":\"ByPlatform?platform=bilibili&\",\"虎牙\":\"ByPlatform?platform=huya&\",\"网易CC\":\"ByPlatform?platform=cc&\"}"; + 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); + + JSONObject filterConfig = new JSONObject(); + String geta ="http://live.yj1211.work/api/live/getAllAreas"; + String aaid = ""; + for(int i=0 ; i<3 ; i++){ + aaid = OkHttpUtil.string(geta, getHeaders()); + if(aaid.length()>0){ + break; + }else{ + Thread.sleep(1000); + } + } + + JSONObject aido = new JSONObject(aaid); + JSONArray aidoa = aido.getJSONArray("data"); + JSONArray extendsAll = new JSONArray(); + for (int j=0 ; j< 13;j++){ + JSONObject newTypeExtend = new JSONObject(); + String typeName = aidoa.getJSONArray(j).getJSONObject(0).getString("typeName"); + newTypeExtend.put("key", "typeName" + j); + newTypeExtend.put("name", typeName); + JSONArray newTypeExtendKV = new JSONArray(); + int fg = Math.min(aidoa.getJSONArray(j).length(), 20); + JSONObject kv = new JSONObject(); + kv.put("n", "全部"); + kv.put("v", typeName + "=" + "all"); + newTypeExtendKV.put(kv); + for (int k=0 ; k< fg ; k++){ + kv = new JSONObject(); + String areaName = aidoa.getJSONArray(j).getJSONObject(k).getString("areaName"); + kv.put("n", areaName); + kv.put("v", typeName + "=" + areaName); + newTypeExtendKV.put(kv); + } + newTypeExtend.put("value", newTypeExtendKV); + extendsAll.put(newTypeExtend); + } + for (int i = 0 ; i < 5 ; i++){ + String typeId = classes.getJSONObject(i).getString("type_id"); + filterConfig.put(typeId, extendsAll); + } + + JSONArray videos = new JSONArray(); + int ch = Math.min(srcoria.length(), 10); + for (int i = 0; i < ch; i++) { + JSONObject srchome = new JSONObject(); + String platForm = srcoria.getJSONObject(i).getString("platForm"); + String rd = srcoria.getJSONObject(i).getString("roomId"); + String id = platForm + "&" + rd; + String name = srcoria.getJSONObject(i).getString("ownerName"); + String pic = srcoria.getJSONObject(i).getString("ownerHeadPic"); + String mark = srcoria.getJSONObject(i).getString("categoryName"); + srchome.put("vod_id", id); + srchome.put("vod_name", name); + srchome.put("vod_pic",pic); + srchome.put("vod_remarks", mark); + videos.put(srchome); + } + if (filter) { + result.put("filters", filterConfig); + } + 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 catt=""; + switch (tid) { + case "?": + catt = "all"; + break; + case "ByPlatform?platform=douyu&": + catt = "douyu"; + break; + case "ByPlatform?platform=bilibili&": + catt = "bilibili"; + break; + case "ByPlatform?platform=huya&": + catt = "huya"; + break; + case "ByPlatform?platform=cc&": + catt = "cc"; + break; + } + + + + + + + extend = extend == null ? new HashMap<>() : extend; + String srcurl=""; + String[] cate= new String[13]; + int pp = 0; + for(int i = 0; i < 13; i++){ + cate[i] = extend.containsKey("typeName"+i) ? extend.get("typeName"+i) : ("typeName"+i + "=" + "all"); + String[] info = cate[i].split("="); + String area = info[1]; + if( !area.contains("all") ){ + pp= pp + 1; + } + } + if(pp == 1){ + for(int i = 0; i < 13; i++){ + String[] info = cate[i].split("="); + String areaType = info[0]; + String area = info[1]; + if(!area.contains("all")) { + String urlft = "http://live.yj1211.work/api/live/getRecommendByAreaAll?areaType={areaType}&area={area}&page={pg}"; + srcurl = urlft.replace("{areaType}", URLEncoder.encode(areaType)).replace("{area}", URLEncoder.encode(area)).replace("{pg}", pg); + break; + } + } + }else if( pp == 0 || pp > 1 ){ + String urlft = "http://live.yj1211.work/api/live/getRecommend{tid}page={pg}&size=20"; + srcurl = urlft.replace("{tid}", tid).replace("{pg}", pg); + } + String srcOrignstr = ""; + for (int i = 0; i < 3; i++) { + srcOrignstr = OkHttpUtil.string(srcurl, getHeaders()); + if (srcOrignstr.length() > 0 ) { + break; + } else { + Thread.sleep(1000); + } + } + JSONObject srcori = new JSONObject(srcOrignstr); + JSONArray srcoria = srcori.getJSONArray("data"); + JSONObject result = new JSONObject(); + JSONArray videos = new JSONArray(); + for (int i = 0; i < srcoria.length(); i++) { + JSONObject srchome = new JSONObject(); + String platForm = srcoria.getJSONObject(i).getString("platForm"); + if(pp == 1 && !catt.equals("all")){ + if(!platForm.equals(catt) ){ + continue; + } + } + + String rd = srcoria.getJSONObject(i).getString("roomId"); + String id = platForm + "&" + rd; + String name = srcoria.getJSONObject(i).getString("ownerName"); + String pic = srcoria.getJSONObject(i).getString("ownerHeadPic"); + String mark = srcoria.getJSONObject(i).getString("categoryName"); + srchome.put("vod_id", id); + srchome.put("vod_name", name); + srchome.put("vod_pic", pic); + srchome.put("vod_remarks", mark); + videos.put(srchome); + } + if(videos.length() == 0 ) { + JSONObject srchome = new JSONObject(); + srchome.put("vod_id", 111); + srchome.put("vod_name", "此页无符合"); + srchome.put("vod_pic",""); + srchome.put("vod_remarks", "nothing"); + videos.put(srchome); + } + if (pp ==1 ) { + result.put("pagecount", 50); + result.put("limit",1 ); + } else{ + result.put("pagecount", Integer.MAX_VALUE); + result.put("limit",90 ); + } + result.put("list", videos); + result.put("page", pg); + result.put("total", Integer.MAX_VALUE); + + + + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + private HashMap getHeaders() { + HashMap headers = new HashMap<>(); + 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"); + return headers; + } + + @Override + public String detailContent(List ids) { + try { + String id = ids.get(0); + String[] info = id.split("&"); + String platform = info[0]; + String roomId = info[1]; + String srcurl = "http://live.yj1211.work/api/live/getRoomInfo?platform="+platform+"&roomId="+roomId; + String srcplayurl = "http://live.yj1211.work/api/live/getRealUrl?platform="+platform+"&roomId="+roomId; + String srcdtlstr = OkHttpUtil.string(srcurl, getHeaders()); + String srcdtlplay = OkHttpUtil.string(srcplayurl, getHeaders()); + JSONObject srcdtl = new JSONObject(srcdtlstr); + JSONObject srcdtlo = srcdtl.getJSONObject("data"); + JSONObject srcdtplay = new JSONObject(srcdtlplay); + JSONObject srcdtplayo = srcdtplay.getJSONObject("data"); + String title = srcdtlo.getString("roomName"); + String pic = srcdtlo.getString("roomPic"); + String director = srcdtlo.getString("ownerName") + " RoomID:"+ srcdtlo.getString("roomId"); + String content = srcdtlo.getString("categoryName"); + String actor = "观看人数:" + srcdtlo.getString("online"); + String area =srcdtlo.getString("platForm"); + String typechk =srcdtlo.optString("isLive"); + String type = typechk.equals("") ? "录播" : "正在直播中" ; + JSONObject result = new JSONObject(); + JSONObject vodList = new JSONObject(); + vodList.put("vod_id", ids.get(0)); + vodList.put("vod_pic",pic); + vodList.put("vod_name", title); + vodList.put("vod_area",area ); + vodList.put("type_name", type); + vodList.put("vod_actor", actor); + vodList.put("vod_director", director); + vodList.put("vod_content", content); + String playList = ""; + String pl=""; + List vodItems = new ArrayList<>(); + for(int i=0; i<5 ; i++){ + String[] qq = new String[] {"OD", "HD", "SD", "LD", "FD"}; + String qa = srcdtplayo.optString(qq[i]); + if (qa.isEmpty()) { + continue; + } + switch (qq[i]) { + case "OD": + pl = "原画" + "$" + qa; + break; + case "HD": + pl = "超清" + "$" + qa; + break; + case "SD": + pl = "高清" + "$" + qa; + break; + case "LD": + pl = "清晣" + "$" + qa; + break; + case "FD": + pl = "流畅" + "$" + qa; + break; + } + vodItems.add(pl); + } + if (vodItems.size() > 0) + playList = TextUtils.join("#", vodItems); + + if (playList.length() == 0) + playList = "NoStream$nolink"; + + Map vod_play = new TreeMap<>(); + vod_play.put("YJ1211", playList); + 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 { + JSONObject result = new JSONObject(); + result.put("header", getHeaders()); + result.put("parse", 1); + 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) { + try { + String url = "http://live.yj1211.work/api/live/search?platform=all&keyWords=" + URLEncoder.encode(key) + "&isLive=0"; + String content =""; + for(int i=0 ; i<3 ; i++){ + content =OkHttpUtil.string(url, getHeaders()); + if(content.length() >0){ + break; + }else{ + Thread.sleep(1000); + } + } + JSONObject searchResult = new JSONObject(content); + JSONArray sra = searchResult.getJSONArray("data"); + JSONObject result = new JSONObject(); + JSONArray videos = new JSONArray(); + if (sra.length() > 0) { + int ch = Math.min(sra.length(), 20); + for (int i = 0; i < ch; i++) { + JSONObject srat = new JSONObject(); + String platForm = sra.getJSONObject(i).getString("platform"); + String rd = sra.getJSONObject(i).getString("roomId"); + String id = platForm + "&" + rd; + String name = sra.getJSONObject(i).getString("nickName"); + String pic = sra.getJSONObject(i).getString("headPic"); + String mark =""; + if(!sra.getJSONObject(i).isNull("cateName")){ + mark = sra.getJSONObject(i).getString("cateName"); + } + srat.put("vod_remarks", mark); + srat.put("vod_id", id); + srat.put("vod_name", name); + srat.put("vod_pic", pic); + + videos.put(srat); + } + } + 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/Ysdq.java b/app/src/main/java/com/github/catvod/spider/Ysdq.java new file mode 100644 index 0000000..1153366 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Ysdq.java @@ -0,0 +1,275 @@ +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 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; + +public class Ysdq extends Spider { + private static HashMap sites = new HashMap<>(); + + protected void fetchRule() { + if (sites.size() == 0) { + try { + String json = OkHttpUtil.string("https://pj567.coding.net/p/source/d/source/git/raw/master/mobile/config.json", null); + JSONArray sources = new JSONObject(json).optJSONArray("source"); + for (int i = 0; i < sources.length(); i++) { + JSONObject obj = sources.getJSONObject(i); + String type = obj.optString("type"); + if (type.equals("AppV0") || type.equals("AppTv") || type.equals("aiKanTv")) { + String scName = obj.optString("sourceName"); + sites.put(scName, obj); + SpiderDebug.log("{\"key\":\"csp_ysdq_" + scName + "\", \"name\":\"" + scName + "(搜)\", \"type\":3, \"api\":\"csp_Ysdq\",\"searchable\":1,\"quickSearch\":0, \"ext\":\"" + scName + "\"},"); + } + } + } catch (Exception e) { + + } + } + } + + private JSONObject getJson() { + if (sites.containsKey(sourceName)) { + return sites.get(sourceName); + } + return null; + } + + private String sourceName = ""; + + @Override + public void init(Context context, String extend) { + super.init(context, extend); + this.sourceName = extend; + } + + private String jsonArr2Str(JSONArray array) { + try { + ArrayList strings = new ArrayList<>(); + for (int i = 0; i < array.length(); i++) { + strings.add(array.getString(i)); + } + return TextUtils.join(",", strings); + } catch (JSONException e) { + } + return ""; + } + + @Override + public String detailContent(List ids) { + try { + fetchRule(); + JSONObject cfg = getJson(); + if (cfg != null) { + String type = cfg.optString("type"); + JSONObject result = new JSONObject(); + JSONObject vod = new JSONObject(); + if (type.equals("AppV0")) { + String url = cfg.optString("detailUrl").replace("%s", ids.get(0)); + String json = OkHttpUtil.string(url, null); + JSONObject obj = new JSONObject(json).optJSONObject("data"); + vod.put("vod_id", obj.getString("vod_id")); + vod.put("vod_name", obj.getString("vod_name")); + vod.put("vod_pic", obj.getString("vod_pic")); + vod.put("type_name", obj.optString("vod_class")); + vod.put("vod_year", obj.optString("vod_year")); + vod.put("vod_lang", obj.optString("vod_lang")); + vod.put("vod_area", obj.optString("vod_area")); + vod.put("vod_remarks", obj.optString("vod_remarks")); + vod.put("vod_actor", obj.optString("vod_actor")); + vod.put("vod_director", obj.optString("vod_director")); + vod.put("vod_content", obj.optString("vod_content")); + vod.put("vod_play_from", obj.getString("vod_play_from")); + vod.put("vod_play_url", obj.getString("vod_play_url")); + } else if (type.equals("AppTV")) { + String url = ids.get(0); + String json = OkHttpUtil.string(url, null); + JSONObject obj = new JSONObject(json); + vod.put("vod_id", obj.getString("id")); + vod.put("vod_name", obj.getString("title")); + vod.put("vod_pic", obj.getString("img_url")); + vod.put("type_name", jsonArr2Str(obj.optJSONArray("type"))); + vod.put("vod_year", obj.optString("pubtime")); + vod.put("vod_area", jsonArr2Str(obj.optJSONArray("area"))); + vod.put("vod_remarks", obj.optString("trunk")); + vod.put("vod_actor", jsonArr2Str(obj.optJSONArray("actor"))); + vod.put("vod_director", jsonArr2Str(obj.optJSONArray("director"))); + vod.put("vod_content", obj.optString("intro")); + Map vod_play = new LinkedHashMap<>(); + JSONObject playList = obj.getJSONObject("videolist"); + Iterator playListKeys = playList.keys(); + while (playListKeys.hasNext()) { + String from = playListKeys.next(); + JSONArray playListUrls = playList.getJSONArray(from); + ArrayList urls = new ArrayList<>(); + for (int j = 0; j < playListUrls.length(); j++) { + JSONObject urlObj = playListUrls.getJSONObject(j); + urls.add(urlObj.getString("title") + "$" + urlObj.getString("url")); + } + vod_play.put(from, TextUtils.join("#", urls)); + } + String vod_play_from = TextUtils.join("$$$", vod_play.keySet()); + String vod_play_url = TextUtils.join("$$$", vod_play.values()); + vod.put("vod_play_from", vod_play_from); + vod.put("vod_play_url", vod_play_url); + } else if (type.equals("aiKanTv")) { + String url = cfg.optString("detailUrl").replace("%s", ids.get(0)); + String json = OkHttpUtil.string(url, null); + JSONObject obj = new JSONObject(json).optJSONObject("data"); + vod.put("vod_id", obj.getString("vod_id")); + vod.put("vod_name", obj.getString("vod_name")); + vod.put("vod_pic", obj.getString("vod_pic")); + vod.put("type_name", obj.optString("vod_class")); + vod.put("vod_year", obj.optString("vod_year")); + vod.put("vod_lang", obj.optString("vod_lang")); + vod.put("vod_area", obj.optString("vod_area")); + vod.put("vod_remarks", obj.optString("vod_remarks")); + vod.put("vod_actor", obj.optString("vod_actor")); + vod.put("vod_director", obj.optString("vod_director")); + vod.put("vod_content", obj.optString("vod_content")); + + Map vod_play = new LinkedHashMap<>(); + JSONArray playList = obj.getJSONArray("vod_play_list"); + for (int i = 0; i < playList.length(); i++) { + JSONObject playListObj = playList.getJSONObject(i); + String from = playListObj.getString("from"); + String playUrls = playListObj.getString("url"); + if (playUrls.length() > 0) { + vod_play.put(from, playUrls); + } + } + String vod_play_from = TextUtils.join("$$$", vod_play.keySet()); + String vod_play_url = TextUtils.join("$$$", vod_play.values()); + vod.put("vod_play_from", vod_play_from); + vod.put("vod_play_url", vod_play_url); + } + JSONArray list = new JSONArray(); + list.put(vod); + result.put("list", list); + return result.toString(); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public String searchContent(String key, boolean quick) { + try { + if (quick) + return ""; + fetchRule(); + JSONObject cfg = getJson(); + if (cfg != null) { + String type = cfg.optString("type"); + String url = cfg.optString("searchUrl"); + if (!url.isEmpty()) { + JSONObject result = new JSONObject(); + JSONArray videos = new JSONArray(); + url = url.replace("%s", URLEncoder.encode(key)); + String json = OkHttpUtil.string(url, null); + if (type.equals("AppV0")) { + JSONArray list = new JSONObject(json).optJSONArray("list"); + for (int i = 0; i < list.length(); i++) { + JSONObject obj = list.getJSONObject(i); + JSONObject v = new JSONObject(); + v.put("vod_id", obj.getString("vod_id")); + v.put("vod_name", obj.getString("vod_name")); + v.put("vod_pic", obj.getString("vod_pic")); + v.put("vod_remarks", obj.getString("vod_remarks")); + videos.put(v); + } + } else if (type.equals("AppTV")) { + JSONArray list = new JSONObject(json).optJSONArray("data"); + for (int i = 0; i < list.length(); i++) { + JSONObject obj = list.getJSONObject(i); + JSONObject v = new JSONObject(); + v.put("vod_id", obj.getString("nextlink")); + v.put("vod_name", obj.getString("title")); + v.put("vod_pic", obj.getString("pic")); + v.put("vod_remarks", obj.getString("state")); + videos.put(v); + } + } else if (type.equals("aiKanTv")) { + JSONArray list = new JSONObject(json).optJSONObject("data").optJSONArray("list"); + for (int i = 0; i < list.length(); i++) { + JSONObject obj = list.getJSONObject(i); + JSONObject v = new JSONObject(); + v.put("vod_id", obj.getString("vod_id")); + v.put("vod_name", obj.getString("vod_name")); + v.put("vod_pic", obj.getString("vod_pic")); + v.put("vod_remarks", obj.getString("vod_remarks")); + videos.put(v); + } + } + result.put("list", videos); + return result.toString(); + } + } + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public String playerContent(String flag, String id, List vipFlags) { + try { + fetchRule(); + if (vipFlags.contains(flag)) { + try { + JSONObject result = new JSONObject(); + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", id); + result.put("header", ""); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + // 如果是视频直连 直接返回免解 + else if (isVideoFormat(id)) { + try { + JSONObject result = new JSONObject(); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", id); + result.put("header", ""); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + } catch (Exception e) { + SpiderDebug.log(e); + } + // 尝试解析 + try { + JSONObject result = new JSONObject(); + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", id); + result.put("header", ""); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/Ysgc.java b/app/src/main/java/com/github/catvod/spider/Ysgc.java new file mode 100644 index 0000000..ffc446a --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Ysgc.java @@ -0,0 +1,394 @@ +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.JSONObject; + +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.Set; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 影视工厂 + *

+ * Author: 小黄瓜 + */ +public class Ysgc extends Spider { + + private static final String siteUrl = "https://www.ik4.cc"; + private static final String siteHost = "www.ik4.cc"; + + protected JSONObject playerConfig = new JSONObject(); + + @Override + public void init(Context context) { + super.init(context); + } + + protected HashMap getHeaders(String url) { + HashMap headers = new HashMap<>(); + headers.put("user-agent", "Dart/2.14 (dart:io)"); + headers.put("version", "1.9.8"); + headers.put("copyright", "xiaogui"); + headers.put("host", siteHost); + headers.put("platform", "android"); + return headers; + } + + @Override + public String homeContent(boolean filter) { + try { + String url = siteUrl + "/xgapp.php/v1/nav?token="; + JSONObject jsonObject = new JSONObject(OkHttpUtil.string(url, getHeaders(url))); + JSONArray jsonArray = jsonObject.getJSONArray("data"); + 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("type_name"); + if (typeName.equals("电视直播")) + continue; + String typeId = jObj.getString("type_id"); + JSONObject newCls = new JSONObject(); + newCls.put("type_id", typeId); + newCls.put("type_name", typeName); + classes.put(newCls); + try { + JSONObject typeExtend = jObj.getJSONObject("type_extend"); + Iterator typeExtendKeys = typeExtend.keys(); + JSONArray extendsAll = new JSONArray(); + while (typeExtendKeys.hasNext()) { + String typeExtendKey = typeExtendKeys.next(); + String typeExtendName = null; + switch (typeExtendKey) { + case "class": + typeExtendName = "类型"; + break; + case "area": + typeExtendName = "地区"; + break; + case "lang": + typeExtendName = "语言"; + break; + case "year": + typeExtendName = "年代"; + break; + } + if (typeExtendName == null) { + SpiderDebug.log(typeExtendKey); + continue; + } + String typeExtendStr = typeExtend.getString(typeExtendKey); + if (typeExtendStr.trim().length() == 0) + continue; + String[] newTypeExtendKeys = typeExtendStr.split(","); + 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 (String k : newTypeExtendKeys) { + if (typeExtendName.equals("伦理")) + continue; + JSONObject kv = new JSONObject(); + kv.put("n", k); + kv.put("v", 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 + "/xgapp.php/v1/index_video?token="; + JSONObject jsonObject = new JSONObject(OkHttpUtil.string(url, getHeaders(url))); + JSONArray jsonArray = jsonObject.getJSONArray("data"); + JSONArray videos = new JSONArray(); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jObj = jsonArray.getJSONObject(i); + JSONArray videoList = jObj.getJSONArray("vlist"); + for (int j = 0; j < videoList.length() && j < 6; j++) { + JSONObject vObj = videoList.getJSONObject(j); + 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 (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { + try { + String url = siteUrl + "/xgapp.php/v1/video?tid=" + tid + "&pg=" + pg + "&token="; + Set keys = extend.keySet(); + for (String key : keys) { + url += "&" + key + "=" + URLEncoder.encode(extend.get(key)); + } + JSONObject dataObject = new JSONObject(OkHttpUtil.string(url, getHeaders(url))); + JSONArray jsonArray = dataObject.getJSONArray("data"); + 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 = dataObject.getInt("pagecount"); + 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 + "/xgapp.php/v1/video_detail?id=" + ids.get(0) + "&token="; + JSONObject jsonObject = new JSONObject(OkHttpUtil.string(url, getHeaders(url))); + JSONObject dataObject = jsonObject.getJSONObject("data"); + if (dataObject.has("vod_info")) { + try { + dataObject = dataObject.getJSONObject("vod_info"); + } catch (Exception e) { + + } + } + JSONObject vodList = new JSONObject(); + vodList.put("vod_id", dataObject.getString("vod_id")); + vodList.put("vod_name", dataObject.getString("vod_name")); + vodList.put("vod_pic", dataObject.getString("vod_pic")); + vodList.put("type_name", dataObject.getString("vod_class")); + vodList.put("vod_year", dataObject.getString("vod_year")); + vodList.put("vod_area", dataObject.getString("vod_area")); + vodList.put("vod_remarks", dataObject.getString("vod_remarks")); + vodList.put("vod_actor", dataObject.getString("vod_actor")); + vodList.put("vod_director", dataObject.getString("vod_director")); + vodList.put("vod_content", dataObject.getString("vod_content")); + JSONArray playerList = dataObject.getJSONArray("vod_url_with_player"); + List playFlags = new ArrayList<>(); + HashMap playUrls = new HashMap<>(); + for (int i = 0; i < playerList.length(); i++) { + JSONObject playerListObj = playerList.getJSONObject(i); + String from = playerListObj.getString("code"); + playUrls.put(from, playerListObj.getString("url")); + playerListObj.remove("url"); + playerConfig.put(from, playerListObj); + playFlags.add(from); + } + + Map vod_play = new TreeMap<>(new Comparator() { + @Override + public int compare(String o1, String o2) { + int sort1 = playFlags.indexOf(o1); + int sort2 = playFlags.indexOf(o2); + + if (sort1 == sort2) { + return 1; + } + return sort1 - sort2 > 0 ? 1 : -1; + } + }); + + String[] vod_play_from_list = dataObject.getString("vod_play_from").split("\\$\\$\\$"); + String[] vod_play_url_list = dataObject.getString("vod_play_url").split("\\$\\$\\$"); + + for (int i = 0; i < vod_play_from_list.length; i++) { + String from = vod_play_from_list[i]; + if (i >= vod_play_url_list.length || vod_play_url_list[i].trim().length() == 0) { + if (playUrls.containsKey(from) && playUrls.get(from).trim().length() > 0) { + vod_play.put(vod_play_from_list[i], playUrls.get(from)); + } + continue; + } + vod_play.put(vod_play_from_list[i], vod_play_url_list[i]); + } + + 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); + + 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 ""; + } + + private HashMap getHeaderJxs(String url) { + HashMap headers = new HashMap<>(); + headers.put("platform_version", "LMY47I"); + headers.put("user-agent", "Dart/2.12 (dart:io)"); + headers.put("version", "1.6.4"); + headers.put("copyright", "xiaogui"); + headers.put("platform", "android"); + headers.put("client_name", "6L+95Ymn6L6+5Lq6"); + return headers; + } + + @Override + public String playerContent(String flag, String id, List vipFlags) { + try { + JSONObject result = new JSONObject(); + if (id.contains("hsl.ysgc.xyz")) { + String uuu = "https://www.ysgc.cc/static/player/dplayer.php?url=" + id; + HashMap headers = new HashMap(); + headers.put("referer", "https://www.ysgc.cc/"); + String content = OkHttpUtil.string(uuu, headers); + Matcher matcher = Pattern.compile("url: url\\+'(.+?)',").matcher(content); + if (matcher.find()) { + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", id + matcher.group(1)); + result.put("header", "{\"Referer\":\" https://www.ysgc.cc\"}"); + } else { + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", uuu); + result.put("header", "{\"Referer\":\"https://www.ysgc.cc/\"}"); + } + return result.toString(); + } else if (id.contains("duoduozy.com") || id.contains("m3u8.cache.suoyo.cc")) { + String uuu = "https://www.6080kan.cc/app.php?url=" + id; + String content = OkHttpUtil.string(uuu, null); + return Misc.jsonParse(id, content).toString(); + } + if (vipFlags.contains(flag)) { + try { + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", id); + return result.toString(); + } catch (Exception ee) { + SpiderDebug.log(ee); + } + } + JSONObject playerObj = playerConfig.getJSONObject(flag); + String parseUrl = playerObj.getString("parse_api") + id; + String content = OkHttpUtil.string(parseUrl, getHeaderJxs(parseUrl)); + JSONObject playerData = new JSONObject(content); + JSONObject headers = new JSONObject(); + String ua = playerData.optString("user-agent", ""); + if (ua.trim().length() > 0) { + headers.put("User-Agent", " " + ua); + } + String referer = playerData.optString("referer", ""); + if (referer.trim().length() > 0) { + headers.put("Referer", " " + referer); + } + result.put("parse", 0); + result.put("header", headers.toString()); + result.put("playUrl", ""); + result.put("url", playerData.getString("url")); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + if (vipFlags.contains(flag)) { + try { + JSONObject result = new JSONObject(); + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", id); + return result.toString(); + } catch (Exception ee) { + SpiderDebug.log(ee); + } + } + } + return ""; + } + + @Override + public String searchContent(String key, boolean quick) { + if (quick) + return ""; + try { + String url = siteUrl + "/xgapp.php/v1/search?text=" + URLEncoder.encode(key) + "&pg=1"; + String content = OkHttpUtil.string(url, getHeaders(url)); + JSONObject dataObject = new JSONObject(content); + JSONArray jsonArray = dataObject.getJSONArray("data"); + 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 (Exception e) { + SpiderDebug.log(e); + } + return ""; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/YydsAli1.java b/app/src/main/java/com/github/catvod/spider/YydsAli1.java new file mode 100644 index 0000000..f3df733 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/YydsAli1.java @@ -0,0 +1,517 @@ +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 org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +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; + +public class YydsAli1 extends Spider { + private static final String siteUrl = "https://cmn.yyds.fans"; + + @Override + public void init(Context context) { + super.init(context); + } + + private HashMap getHeaders(String url) { + HashMap headers = new HashMap<>(); + headers.put("accept", "application/json, text/plain, */*"); + headers.put("origin", "https://yyds.fans"); + headers.put("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36"); + return headers; + } + + @Override + public String homeContent(boolean filter) { + try { + String url = siteUrl + "/api/categories"; + String content = OkHttpUtil.string(url, getHeaders(url)); + JSONObject jsonObject = new JSONObject(content); + JSONArray jsonArray = jsonObject.getJSONArray("data"); + JSONArray classes = new JSONArray(); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jObj = jsonArray.getJSONObject(i); + String typeName = jObj.getString("title"); + if (typeName.equals("首页") || typeName.equals("热门精选")) { + continue; + } + String typeId = jObj.getString("id"); + JSONObject newCls = new JSONObject(); + newCls.put("type_id", typeId); + newCls.put("type_name", typeName); + classes.put(newCls); + } + JSONObject result = new JSONObject(); + result.put("class", classes); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public String homeVideoContent() { + try { + JSONArray videos = new JSONArray(); + try { + String url = siteUrl + "/api/posts"; + JSONObject json = new JSONObject(); + json.put("category_id", "0"); + json.put("skip", "0"); + json.put("limit", "30"); + json.put("keyword", ""); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), url, json.toString(), getHeaders(url), new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception e) { + } + + @Override + public void onResponse(String response) { + try { + JSONObject jsonObject = new JSONObject(response); + JSONArray jsonArray = jsonObject.getJSONArray("data"); + 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("title")); + v.put("vod_pic", vObj.optString("cover")); + String mark = vObj.optString("subtitle"); + if (mark.equals("null")) + mark = ""; + v.put("vod_remarks", mark); + videos.put(v); + } + } catch (JSONException e) { + } + } + }); + } catch (Exception e) { + + } + 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 { + int limit = 30; + int page = Integer.parseInt(pg); + if (page == 0) { + page = 1; + } + String url = siteUrl + "/api/posts"; + JSONObject json = new JSONObject(); + json.put("category_id", tid); + json.put("skip", ((page - 1) * limit) + ""); + json.put("limit", limit + ""); + json.put("keyword", ""); + JSONArray videos = new JSONArray(); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), url, json.toString(), getHeaders(url), new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception e) { + } + + @Override + public void onResponse(String response) { + try { + JSONObject jsonObject = new JSONObject(response); + JSONArray jsonArray = jsonObject.getJSONArray("data"); + 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("title")); + v.put("vod_pic", vObj.optString("cover")); + String mark = vObj.optString("subtitle"); + if (mark.equals("null")) + mark = ""; + v.put("vod_remarks", mark); + videos.put(v); + } + } catch (JSONException e) { + } + } + }); + JSONObject result = new JSONObject(); + 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 ""; + } + + Pattern aliyun = Pattern.compile(".*?aliyundrive.com/s/(\\w+)[^\\w]?"); + Pattern aliyunShort = Pattern.compile(".*?alywp.net/(\\w+)[^\\w]?"); + + @Override + public String detailContent(List ids) { + try { + String url = siteUrl + "/api/post-info"; + JSONObject json = new JSONObject(); + json.put("id", ids.get(0)); + JSONObject vodAtom = new JSONObject(); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), url, json.toString(), getHeaders(url), new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception e) { + } + + @Override + public void onResponse(String response) { + try { + JSONObject dataObject = new JSONObject(response); + JSONObject vObj = dataObject.getJSONObject("data"); + + vodAtom.put("vod_id", vObj.getString("id")); + vodAtom.put("vod_name", vObj.getString("title")); + vodAtom.put("vod_pic", vObj.getString("cover")); + vodAtom.put("type_name", ""); + vodAtom.put("vod_year", vObj.getString("year")); + vodAtom.put("vod_area", vObj.getString("region")); + String mark = vObj.optString("subtitle"); + if (mark.equals("null")) + mark = ""; + vodAtom.put("vod_remarks", mark); + vodAtom.put("vod_actor", vObj.getString("actors")); + vodAtom.put("vod_director", vObj.getString("director")); + String desc = vObj.optString("desc"); + if (desc.equals("null")) + desc = ""; + vodAtom.put("vod_content", desc); + + Map vod_play = new LinkedHashMap<>(); + JSONArray jsonArray = vObj.getJSONArray("links"); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject obj = jsonArray.getJSONObject(i); + String link = obj.optString("link", ""); + updatePlaylist(link, vod_play); + } + if (vod_play.size() == 0 && vObj.optString("content").length() > 0) { + updatePlaylist(vObj.optString("content"), vod_play); + } + if (vod_play.size() > 0) { + String vod_play_from = TextUtils.join("$$$", vod_play.keySet()); + String vod_play_url = TextUtils.join("$$$", vod_play.values()); + vodAtom.put("vod_play_from", vod_play_from); + vodAtom.put("vod_play_url", vod_play_url); + } + } catch (JSONException e) { + } + } + }); + JSONObject result = new JSONObject(); + JSONArray list = new JSONArray(); + list.put(vodAtom); + result.put("list", list); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + private void updatePlaylist(String link, Map vod_play) { + String shareId = null; + Matcher matcher = aliyun.matcher(link); + if (matcher.find()) { + shareId = matcher.group(1); + } else { + matcher = aliyunShort.matcher(link); + if (matcher.find()) { + shareId = matcher.group(1); + Map> respHeaders = new TreeMap<>(); + OkHttpUtil.stringNoRedirect("https://alywp.net/" + shareId, null, respHeaders); + shareId = OkHttpUtil.getRedirectLocation(respHeaders); + if (shareId != null) { + matcher = aliyun.matcher(shareId); + if (matcher.find()) { + shareId = matcher.group(1); + } + } + } + } + if (shareId != null) { + String shareToken = getShareTk(shareId, ""); + ArrayList vodItems = new ArrayList<>(); + getFileList(shareToken, shareId, "", "root", vodItems); + vod_play.put("阿里云盘" + (vod_play.size() > 0 ? vod_play.size() : ""), TextUtils.join("#", vodItems)); + } + } + + @Override + public String playerContent(String flag, String id, List vipFlags) { + try { + String[] infos = id.split("\\+"); + String shareTk = getShareTk(infos[0], ""); + refreshTk(); + if (!accessTk.isEmpty()) { + JSONObject json = new JSONObject(); + json.put("share_id", infos[0]); + json.put("category", "live_transcoding"); + json.put("file_id", infos[1]); + json.put("template_id", ""); + HashMap headers = new HashMap<>(); + headers.put("x-share-token", shareTk); + headers.put("authorization", accessTk); + OKCallBack.OKCallBackString callback = new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception e) { + } + + @Override + public void onResponse(String response) { + String videoUrl = ""; + try { + JSONArray playList = new JSONObject(response).getJSONObject("video_preview_play_info").getJSONArray("live_transcoding_task_list"); + String[] orders = new String[]{"FHD", "HD", "SD"}; + for (String or : orders) { + for (int i = 0; i < playList.length(); i++) { + JSONObject obj = playList.getJSONObject(i); + if (obj.optString("template_id").equals(or)) { + videoUrl = obj.getString("url"); + break; + } + } + if (!videoUrl.isEmpty()) + break; + } + if (videoUrl.isEmpty() && playList.length() > 0) { + videoUrl = playList.getJSONObject(0).getString("url"); + } + } catch (JSONException e) { + } finally { + setResult(videoUrl); + } + } + }; + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), "https://api.aliyundrive.com/v2/file/get_share_link_video_preview_play_info", json.toString(), headers, callback); + JSONArray playList = new JSONObject(callback.getResult()).getJSONObject("video_preview_play_info").getJSONArray("live_transcoding_task_list"); + String videoUrl = ""; + String[] orders = new String[]{"FHD", "HD", "SD"}; + for (String or : orders) { + for (int i = 0; i < playList.length(); i++) { + JSONObject obj = playList.getJSONObject(i); + if (obj.optString("template_id").equals(or)) { + videoUrl = obj.getString("url"); + break; + } + } + if (!videoUrl.isEmpty()) + break; + } + if (videoUrl.isEmpty() && playList.length() > 0) { + videoUrl = playList.getJSONObject(0).getString("url"); + } + JSONObject headerObj = new JSONObject(); + headerObj.put("user-agent", " Dalvik/2.1.0 (Linux; U; Android 7.0; ZTE BA520 Build/MRA58K)"); + headerObj.put("referer", " https://www.aliyundrive.com/"); + JSONObject result = new JSONObject(); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", videoUrl); + result.put("header", headerObj.toString()); + return result.toString(); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public String searchContent(String key, boolean quick) { + try { + if (quick) + return ""; + JSONArray videos = new JSONArray(); + try { + String url = siteUrl + "/api/posts"; + JSONObject json = new JSONObject(); + json.put("category_id", "-1"); + json.put("skip", "0"); + json.put("limit", "30"); + json.put("keyword", key); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), url, json.toString(), getHeaders(url), new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception e) { + } + + @Override + public void onResponse(String response) { + try { + JSONObject jsonObject = new JSONObject(response); + JSONArray jsonArray = jsonObject.getJSONArray("data"); + 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("title")); + v.put("vod_pic", vObj.getString("cover")); + v.put("vod_remarks", vObj.getString("subtitle")); + videos.put(v); + } + } catch (JSONException e) { + } + } + }); + + } catch (Exception e) { + + } + JSONObject result = new JSONObject(); + result.put("list", videos); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + private String aliTk = ""; + + private void fetchAliTk() { + if (aliTk.isEmpty()) { + try { + HashMap headers = new HashMap<>(); + headers.put("User-Agent", "okhttp/4.5.0"); + aliTk = new JSONObject(OkHttpUtil.string("http://81.68.244.5/tv/alitk", headers)).optString("alitk"); + } catch (JSONException e) { + SpiderDebug.log(e); + } + } + } + + private String accessTk = ""; + + private void refreshTk() { + fetchAliTk(); + if (!aliTk.isEmpty() && accessTk.isEmpty()) { + try { + JSONObject json = new JSONObject(); + json.put("refresh_token", aliTk); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), "https://api.aliyundrive.com/token/refresh", json.toString(), new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception e) { + + } + + @Override + public void onResponse(String response) { + try { + JSONObject obj = new JSONObject(response); + accessTk = obj.getString("token_type") + " " + obj.getString("access_token"); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + }); + } catch (JSONException e) { + SpiderDebug.log(e); + } + } + } + + private String getShareTk(String shareId, String sharePwd) { + try { + JSONObject json = new JSONObject(); + json.put("share_id", shareId); + json.put("share_pwd", ""); + OKCallBack.OKCallBackString callback = new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception e) { + + } + + @Override + public void onResponse(String response) { + + } + }; + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), "https://api.aliyundrive.com/v2/share_link/get_share_token", json.toString(), callback); + return new JSONObject(callback.getResult()).optString("share_token"); + } catch (JSONException e) { + SpiderDebug.log(e); + } + return ""; + } + + + private void getFileList(String shareTk, String shareId, String sharePwd, String root, ArrayList vodItems) { + try { + // 取文件夹 + JSONObject json = new JSONObject(); + json.put("share_id", shareId); + json.put("parent_file_id", root); + json.put("limit", 100); + json.put("image_thumbnail_process", "image/resize,w_160/format,jpeg"); + json.put("image_url_process", "image/resize,w_1920/format,jpeg"); + json.put("video_thumbnail_process", "video/snapshot,t_1000,f_jpg,ar_auto,w_300"); + json.put("order_by", "name"); + json.put("order_direction", "ASC"); + HashMap headers = new HashMap<>(); + headers.put("x-share-token", shareTk); + OKCallBack.OKCallBackString callback = new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception e) { + + } + + @Override + public void onResponse(String response) { + + } + }; + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), "https://api.aliyundrive.com/adrive/v3/file/list", json.toString(), headers, callback); + JSONArray rootList = new JSONObject(callback.getResult()).optJSONArray("items"); + if (rootList != null && rootList.length() > 0) { + for (int i = 0; i < rootList.length(); i++) { + JSONObject item = rootList.getJSONObject(i); + if (item.getString("type").equals("folder")) { + String dirId = item.getString("file_id"); + getFileList(shareTk, shareId, sharePwd, dirId, vodItems); + } else { + if (item.getString("type").equals("file") && !item.getString("file_extension").equals("txt")) { + String fileId = item.getString("file_id"); + String fileName = item.getString("name"); + vodItems.add(fileName + "$" + shareId + "+" + fileId); + } + } + } + } + // 取文件列表 + } catch (JSONException e) { + SpiderDebug.log(e); + } + } +} diff --git a/app/src/main/java/com/github/catvod/spider/merge/RSA.java b/app/src/main/java/com/github/catvod/spider/merge/RSA.java new file mode 100644 index 0000000..ccca061 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/merge/RSA.java @@ -0,0 +1,96 @@ +// +// Decompiled by Jadx - 632ms +// +package com.github.catvod.spider.merge; + +import android.util.Base64; +import java.io.ByteArrayOutputStream; +import java.nio.charset.Charset; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import javax.crypto.Cipher; + +public class RSA { + public static final Charset qb = Charset.forName("UTF8"); + + public static String l(String str, String str2) { + try { + byte[] bytes = str.getBytes(qb); + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(1, n8(str2)); + int length = bytes.length; + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + int i = 0; + int i2 = 0; + while (true) { + int i3 = length - i; + if (i3 > 0) { + byte[] doFinal = i3 > 117 ? cipher.doFinal(bytes, i, 117) : cipher.doFinal(bytes, i, i3); + byteArrayOutputStream.write(doFinal, 0, doFinal.length); + i2++; + i = i2 * 117; + } else { + byte[] byteArray = byteArrayOutputStream.toByteArray(); + byteArrayOutputStream.close(); + return new String(Base64.encode(byteArray, 0)); + } + } + } catch (Exception e) { + ug(e); + return null; + } + } + + public static PublicKey n8(String str) { + try { + return KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.decode(str, 0))); + } catch (Exception e) { + ug(e); + return null; + } + } + + public static String qb(String str, String str2) { + try { + byte[] decode = Base64.decode(str, 0); + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(2, zC(str2)); + int length = decode.length; + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + int i = 0; + int i2 = 0; + while (true) { + int i3 = length - i; + if (i3 > 0) { + byte[] doFinal = i3 > 128 ? cipher.doFinal(decode, i, 128) : cipher.doFinal(decode, i, i3); + byteArrayOutputStream.write(doFinal, 0, doFinal.length); + i2++; + i = i2 * 128; + } else { + byte[] byteArray = byteArrayOutputStream.toByteArray(); + byteArrayOutputStream.close(); + return new String(byteArray, qb); + } + } + } catch (Exception e) { + ug(e); + return null; + } + } + + private static void ug(Exception exc) { + exc.printStackTrace(); + } + + public static PrivateKey zC(String str) { + try { + return KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.decode(str, 0))); + } catch (Exception e) { + ug(e); + return null; + } + } +}