commit a5d2e8f43e51276740c34d94d3645a5f717433df Author: Osma <> Date: Sat Jul 30 20:05:08 2022 +0800 Bye diff --git a/.github/workflows/genJar.yml b/.github/workflows/genJar.yml new file mode 100644 index 0000000..b640f9a --- /dev/null +++ b/.github/workflows/genJar.yml @@ -0,0 +1,27 @@ +name: Spider Jar Gen CI + +on: workflow_dispatch + +jobs: + build: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + - name: set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + cache: gradle + + - name: Build with Gradle + run: ./buildAndGenJar.bat ec + + - name: Update spider jar + uses: EndBug/add-and-commit@v7 + with: + default_author: github_actions + message: 'update spider jar' + add: "['./jar/custom_spider.jar', './jar/custom_spider.jar.md5']" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e1cd42 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/app/proguardMapping.txt +/LTDecodeSpace +/adb.exe +/LTDecodeNew3.exe diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..3474274 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +CatVodSpider \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..7643783 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,123 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..fb7f4a8 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..56d6814 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..0620071 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..ef61796 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..91c89c9 --- /dev/null +++ b/README.md @@ -0,0 +1,261 @@ +# 猫影视TV客户端爬虫自定义接口工程 + +``` +思维没有边界 一切皆有可能 +``` +:rocket:[**TG交流群**](https://t.me/catvodtv_offical) + +本工程最终食用需配合 猫影视TV新版(一下简称为软件) **v2.0.0**及以上版本。 + +![logo](app/src/main/res/drawable-xhdpi/app_icon.png) + +### 欢迎各路大佬踊跃提PR,分享爬虫代码。 + +### 这里是用户分享的爬虫代码打包的共享包,可以配合自定义配置,直接食用 [custom_spider.jar](/jar/) + +## 快速开始 +---- +本工程是一个完整的AndroidStudio工程,请你用AS打开编辑。 + +工程调试完毕后要需要导出生成jar文件配合软件使用,执行根目录下的 `buildAndGenJar.bat` 会在`jar`目录生成一个名为`custom_spider.jar`的jar文件,这个文件就是我们最终要是用的代码包。 + +### 代码包食用方式 +---- +本地加载:将`custom_spider.jar`放入设备sd卡根目录即可。 **注意,如需本地加载,请手动赋予App存储空间读写权限,App默认不申请存储空间读写权限** + +远程加载:将`custom_spider.jar`上传到你的网络空间,获取对应的文件下载地址,在软件自定义配置的json文件中加入下面格式的键值对。 +```json +"spider": "http://xxx.xxx.xxx/custom_spider.jar" +``` +支持jar文件本地缓存(需v2.0.5及以上版本) +```json +"spider": "http://xxx.xxx.xxx/custom_spider.jar;md5;jar文件md5" +// 例如 +"spider": "https://github.com/catvod/CatVodTVSpider/blob/master/jar/custom_spider.jar?raw=true;md5;c6ed6bc8285f0aca90e7cb3abf7f9caa", +``` + +### 如何在自定义配置中调用我们代码包中的Spider +---- +同样在自定义json中加入相应的播放源即可,**type=3, api对应你代码工程中自定义的爬虫类名(api必须是`csp_`开头),例如实例工程中的`Aidi`** +```json +{ + "key": "csp_Aidi", + "name": "爱迪", + "type": 3, + "api": "csp_Aidi", + "searchable": 1, + "quickSearch": 0, + "filterable": 1 +} +``` +--- +**Json解析扩展(需v2.0.2及以上版本)** + +通过jar包可以实现json解析并发、轮询等相关功能,**参与并发和轮询的json解析地址,默认为解析地址列表中的所有json解析(即type=1)**。 + +在自定义json中的`parse`里加入相应的解析配置(type=2)即可启用。**调用扩展类的名称配置在`parse`的`url`字段里,例如扩展类`JsonParallel`的json配置`url`字段值为`Parallel`**。如下: + +```json +{ + "name": "Json并发", + "type": 2, + "url": "Parallel" +}, +{ + "name": "Json轮询", + "type": 2, + "url": "Sequence" +} +``` + +**XPath规则套娃(需v2.0.4及以上版本)** +套娃规则祥见[XPath.md](/XPath.md) + +--- + +**M浏览器中APP影视规则支持**(2022.01.17 by 小黄瓜)支持筛选。 + +因App影视接口收集地址停止维护,代码里不再读取相关json地址。 + +如果你有对应影视Api地址请在ext字段中直接配置Api地址。 + +
+配置代码示例 点我展开 + +```json +{"key":"csp_appysv2_追剧达人", "name":"追剧推荐(M2)", "type":3,"api":"csp_AppYsV2", "searchable":1, "quickSearch":0, "filterable":1, "ext":"https://vipmv.co/xgapp.php/v1/"}, +{"key":"csp_appysv2_天空影视", "name":"天空推荐(M2)", "type":3,"api":"csp_AppYsV2", "searchable":1, "quickSearch":0, "filterable":1, "ext":"https://tkys.tv/xgapp.php/v1/"}, +{"key":"csp_appys_HG影视", "name":"HG影视(M)", "type":3, "api":"csp_AppYs", "searchable":1, "quickSearch":0, "filterable":1, "ext":"http://hgyx.vip/api.php/v1.vod"}, +{"key":"csp_appys_瑞丰资源", "name":"瑞丰资源(M)", "type":3, "api":"csp_AppYs", "searchable":1, "quickSearch":0, "filterable":1, "ext":"https://ts.yjhan.com:4433/ruifenglb_api.php/v1.vod"}, +``` +
+ +--- + +**部分内置代理接口使用(需v2.0.9及以上版本)** + +入口 [Proxy](/app/src/main/java/com/github/catvod/spider/Proxy.java) + +图片代理,示例参考[Nekk](/app/src/main/java/com/github/catvod/spider/Nekk.java#L449) + +直播配置重定向代理,示例参考[TxtSubscribe](/app/src/main/java/com/github/catvod/live/TxtSubscribe.java) + +--- + +**推送功能扩展(需v2.1.0.Beta6及以上版本)** + +入口 [PushAgent](/app/src/main/java/com/github/catvod/spider/PushAgent.java) + +需要在配置文件中,加入key为`push_agent`的站点,数据返回格式和普通爬虫一致 + +```json +{ + "key": "push_agent", + "name": "推送", + "type": 3, + "api": "csp_PushAgent", + "searchable": 0, + "quickSearch": 0, + "filterable": 0 +} +``` +--- + +## 基础类 +---- + +> com.github.catvod.crawler.Spider 爬虫基类 + +> com.github.catvod.crawler.SpiderReq 用于发起网络请求 获取网络数据,请使用[OkHttpUtil](/app/src/main/java/com/github/catvod/utils/okhttp/OkHttpUtil.java)类,SpiderReq后续将删除 + +> com.github.catvod.crawler.SpiderReqResult 网络请求结果 + +> com.github.catvod.crawler.SpiderUrl 用于定义一个网络请求 + + +## 示例 +---- + +请查看 仓库中的爱迪影视 相关实现 ,调试可参考 `com.github.catvod.demo.MainActivity` ,直接调用对应爬虫相关接口 + +> com.github.catvod.spider.Aidi + +## 注意事项!! +---- +1. 除了`com.github.catvod.spider`包以外的代码,最终都会被软件本身内置的代码代替掉,所以,建议你不要修改除`com.github.catvod.spider`包以外的代码。 + +2. 不要在`Spider`中使用`Gson` + +3. 待补充 + +## 爬虫类返回的相关Json字符串格式说明 +---- +### homeContent +```json +{ + "class": [{ // 分类 + "type_id": "dianying", // 分类id + "type_name": "电影" // 分类名 + }, { + "type_id": "lianxuju", + "type_name": "连续剧" + }], + "filters": { // 筛选 + "dianying": [{ // 分类id 就是上面class中的分类id + "key": "0", // 筛选key + "name": "分类", // 筛选名称 + "value": [{ // 筛选选项 + "n": "全部", // 选项展示的名称 + "v": "dianying" // 选项最终在url中的展现 + }, { + "n": "动作片", + "v": "dongzuopian" + }] + }], + "lianxuju": [{ + "key": 0, + "name": "分类", + "value": [{ + "n": "全部", + "v": "lianxuju" + }, { + "n": "国产剧", + "v": "guochanju" + }, { + "n": "港台剧", + "v": "gangtaiju" + }] + }] + }, + "list": [{ // 首页最近更新视频列表 + "vod_id": "1901", // 视频id + "vod_name": "判决", // 视频名 + "vod_pic": "https:\/\/pic.imgdb.cn\/item\/614631e62ab3f51d918e9201.jpg", // 展示图片 + "vod_remarks": "6.8" // 视频信息 展示在 视频名上方 + }, { + "vod_id": "1908", + "vod_name": "移山的父亲", + "vod_pic": "https:\/\/pic.imgdb.cn\/item\/6146fab82ab3f51d91c01af1.jpg", + "vod_remarks": "6.7" + }] +} +``` + +### categoryContent +```json +{ + "page": 1, // 当前页 + "pagecount": 2, // 总共几页 + "limit": 60, // 每页几条数据 + "total": 120, // 总共多少调数据 + "list": [{ // 视频列表 下面的视频结构 同上面homeContent中的 + "vod_id": "1897", + "vod_name": "北区侦缉队", + "vod_pic": "https:\/\/pic.imgdb.cn\/item\/6145d4b22ab3f51d91bd98b6.jpg", + "vod_remarks": "7.3" + }, { + "vod_id": "1879", + "vod_name": "浪客剑心 最终章 人诛篇", + "vod_pic": "https:\/\/pic.imgdb.cn\/item\/60e3f37e5132923bf82ef95e.jpg", + "vod_remarks": "8.0" + }] +} +``` + +### detailContent +```json +{ + "list": [{ + "vod_id": "1902", + "vod_name": "海岸村恰恰恰", + "vod_pic": "https:\/\/pic.imgdb.cn\/item\/61463fd12ab3f51d91a0f44d.jpg", + "type_name": "剧情", + "vod_year": "2021", + "vod_area": "韩国", + "vod_remarks": "更新至第8集", + "vod_actor": "申敏儿,金宣虎,李相二,孔敏晶,徐尚沅,禹美华,朴艺荣,李世亨,边胜泰,金贤佑,金英玉", + "vod_director": "柳济元", + "vod_content": "海岸村恰恰恰剧情:  韩剧海岸村恰恰恰 갯마을 차차차改编自2004年的电影《我的百事通男友洪班长》,海岸村恰恰恰 갯마을 차차차讲述来自大都市的牙医(申敏儿 饰)到充满人情味的海岸村开设牙医诊所,那里住着一位各方面都", + // 播放源 多个用$$$分隔 + "vod_play_from": "qiepian$$$yun3edu", + // 播放列表 注意分隔符 分别是 多个源$$$分隔,源中的剧集用#分隔,剧集的名称和地址用$分隔 + "vod_play_url": "第1集$1902-1-1#第2集$1902-1-2#第3集$1902-1-3#第4集$1902-1-4#第5集$1902-1-5#第6集$1902-1-6#第7集$1902-1-7#第8集$1902-1-8$$$第1集$1902-2-1#第2集$1902-2-2#第3集$1902-2-3#第4集$1902-2-4#第5集$1902-2-5#第6集$1902-2-6#第7集$1902-2-7#第8集$1902-2-8" + }] +} +``` + +### searchContent +```json +{ + "list": [{ // 视频列表 下面的视频结构 同上面homeContent中的 + "vod_id": "1606", + "vod_name": "陪你一起长大", + "vod_pic": "https:\/\/img.aidi.tv\/img\/upload\/vod\/20210417-1\/e27d4eb86f7cde375171dd324b2c19ae.jpg", + "vod_remarks": "更新至第37集" + }] +} +``` + + + + diff --git a/XPath.md b/XPath.md new file mode 100644 index 0000000..a5a8b80 --- /dev/null +++ b/XPath.md @@ -0,0 +1,340 @@ +### XPath规则套娃(需v2.0.4及以上版本) +---- +套娃依赖自定义爬虫jar,同样需要在自定义json中加入相应的配置,**type=3, api为csp_XPath**,套娃相关规则配置在`ext`字段中,注意:ext字段值**只能是字符串** + +为控制配置文件容量,同时支持在ext字段中直接配置规则和拉取规则的网址。 2021.10.21 by 小黄瓜 + +```json + { + "key": "csp_xpath_94sm", + "name": "94神马(XPath)", + "type": 3, + "api": "csp_XPath", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/94sm.json" + }, + { + "key": "csp_xpath_jpys", + "name": "极品影视(XPath)", + "type": 3, + "api": "csp_XPath", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/jpys.json" + }, + { + "key": "csp_xpath_age", + "name": "AGE动漫(XPath)", + "type": 3, + "api": "csp_XPath", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/agefans.json" + }, + { + "key": "csp_xpath_jpyszl", + "name": "极品直链(XPath)", + "type": 3, + "api": "csp_XPathMac", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/jpys.json" + }, + { + "key": "csp_xpath_cjt", + "name": "CJT影视(XPath)", + "type": 3, + "api": "csp_XPathMac", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/cjtys.json" + }, + { + "key": "csp_xpath_tvci", + "name": "大师兄(XPath)", + "type": 3, + "api": "csp_XPathFilter", + "searchable": 1, + "quickSearch": 1, + "filterable": 1, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/tvci.json" + }, + { + "key": "csp_xpath_saohuotv", + "name": "骚火电影(XPath)", + "type": 3, + "api": "csp_XPath", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/saohuotv2.json" + }, + { + "key": "csp_xpath_dm84", + "name": "动漫巴士(XPath)", + "type": 3, + "api": "csp_XPath", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/dm84.json" + }, + { + "key": "csp_xpath_egg", + "name": "蛋蛋影院(XPath)", + "type": 3, + "api": "csp_XPathEgg", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/egg.json" + }, + { + "key": "csp_xpath_555", + "name": "555电影(XPath)", + "type": 3, + "api": "csp_XPath", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/555.json" + }, + { + "key": "csp_xpath_4kyu", + "name": "一只鱼4K(XPath)", + "type": 3, + "api": "csp_XPath", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/4kyu.json" + }, + { + "key": "csp_xpath_miniku", + "name": "Miniku(XPath)", + "type": 3, + "api": "csp_XPath", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/miniku.json" + }, + { + "key": "csp_xpath_pianba", + "name": "Pianba(XPath)", + "type": 3, + "api": "csp_XPath", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/pianba.json" + }, + { + "key": "csp_xpath_Ole", + "name": "Ole(EXO)", + "type": 3, + "api": "csp_XPath", + "searchable": 1, + "quickSearch": 1, + "filterable": 0, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/olevod.json" + }, + { + "key": "唐人街", + "name": "唐人街(P)", + "type": 3, + "api": "csp_XPathMacFilter", + "searchable": 1, + "quickSearch": 1, + "filterable": 1, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/Renjie.json" + }, + { + "key": "Gimy", + "name": "Gimy(P)", + "type": 3, + "api": "csp_XPathMacFilter", + "searchable": 1, + "quickSearch": 1, + "filterable": 1, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/Gimy.json" + }, + { + "key": "Jumi", + "name": "Jumi(P)", + "type": 3, + "api": "csp_XPathMacFilter", + "searchable": 1, + "quickSearch": 1, + "filterable": 1, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/Jumi.json" + }, + { + "key": "Djx", + "name": "瓜皮TV(P)", + "type": 3, + "api": "csp_XPathFilter", + "searchable": 1, + "quickSearch": 1, + "filterable": 1, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/Djx.json" + }, + { + "key": "独播库", + "name": "独播库(P)", + "type": 3, + "api": "csp_XPathMacFilter", + "searchable": 1, + "quickSearch": 1, + "filterable": 1, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/Duboku.json" + }, + { + "key": "Sky4k", + "name": "Sky4k(P)[en]", + "type": 3, + "api": "csp_XPathMacFilter", + "searchable": 1, + "quickSearch": 1, + "filterable": 1, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/Sky4k.json" + }, + { + "key": "Nfuxs", + "name": "南府(P)", + "type": 3, + "api": "csp_XPathFilter", + "searchable": 1, + "quickSearch": 1, + "filterable": 1, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/Nfuxs.json" + }, + { + "key": "Aixixi", + "name": "爱西西(P)", + "type": 3, + "api": "csp_XPathFilter", + "searchable": 1, + "quickSearch": 1, + "filterable": 1, + "ext": "https://cdn.jsdelivr.net/gh/catvod/CatVodTVSpider@master/xpath/Aixixi.json" + } + +``` + +### 套娃规则 + +demo配置写的比较细,不一定所有字段都要有,具体还是自己多试一试 + +```json +{ + "ua": "", + // 首页地址 用于获取 分类和首页推荐 + "homeUrl": "http://www.9rmb.com", + // 分类节点 + "cateNode": "//ul[contains(@class,'navbar-nav')]/li/a[contains(@href, '.html') and not(contains(@href, '6'))]", + // 分类名 + "cateName": "/text()", + // 分类id + "cateId": "/@href", + // 分类id二次处理正则 + "cateIdR": "/type/(\\d+).html", + // 手动设置分类,如果手动设置了分类则不使用上面的分类xpath获取分类 例如 "cateManual": {"电影": "1", "电视剧": "2"}, + "cateManual": {}, + // 首页推荐视频的节点 + "homeVodNode": "//div[@class='col-md-12 movie-item-out']//a[not(contains(@href, '6'))]/parent::*/parent::*/parent::*/div[contains(@class, 'movie-item-out') and position()<10]/div[@class='movie-item']/a", + // 首页推荐视频的名称 + "homeVodName": "/@title", + // 二次处理正则 + "homeVodNameR": "", + // 首页推荐视频的id + "homeVodId": "/@href", + // 二次处理正则 + "homeVodIdR": "/show/(\\w+).html", + // 首页推荐视频的图片 + "homeVodImg": "/img/@src", + // 二次处理正则 + "homeVodImgR": "", + // 首页推荐视频的简介 + "homeVodMark": "/button/text()", + // 二次处理正则 + "homeVodMarkR": "", + // 分类页地址 {cateId} 分类id {catePg} 当前页 + "cateUrl": "http://www.9rmb.com/type/{cateId}/{catePg}.html", + // 同上面的homeVod字段 分类列表中的视频信息 + "cateVodNode": "//div[@class='movie-item']/a", + "cateVodName": "/@title", + "cateVodId": "/@href", + "cateVodIdR": "/show/(\\w+).html", + "cateVodImg": "/img/@src", + "cateVodMark": "/button/text()", + // 详情页地址 用于获取详情页信息 及 播放列表和地址 + "dtUrl": "http://www.9rmb.com/show/{vid}.html", + // 详情节点 + "dtNode": "//div[@class='container-fluid']", + // 视频名 + "dtName": "//div[@class='col-md-9']//div[@class='col-md-4']//img/@alt", + "dtNameR": "", + // 视频图片 + "dtImg": "//div[@class='col-md-9']//div[@class='col-md-4']//img/@src", + "dtImgR": "", + // 视频分类 + "dtCate": "//div[@class='col-md-8']//span[@class='info-label' and contains(text(), '类型')]/parent::*/following-sibling::*/text()", + "dtCateR": "", + // 视频年份 + "dtYear": "//div[@class='col-md-8']//span[@class='info-label' and contains(text(), '日期')]/parent::*/following-sibling::*/text()", + "dtYearR": "", + // 视频地区 + "dtArea": "//div[@class='col-md-8']//span[@class='info-label' and contains(text(), '国家')]/parent::*/following-sibling::*/text()", + "dtAreaR": "", + // 视频状态 + "dtMark": "//div[@class='col-md-8']//span[@class='info-label' and contains(text(), '状态')]/parent::*/following-sibling::*/text()", + "dtMarkR": "", + // 主演 + "dtActor": "//div[@class='col-md-8']//span[@class='info-label' and contains(text(), '主演')]/parent::*/following-sibling::*/text()", + "dtActorR": "", + // 导演 + "dtDirector": "//div[@class='col-md-8']//span[@class='info-label' and contains(text(), '导演')]/parent::*/following-sibling::*/text()", + "dtDirectorR": "", + // 视频简介 + "dtDesc": "//p[@class='summary']/text()", + "dtDescR": "", + // 播放源节点 + "dtFromNode": "//div[contains(@class,'resource-list')]/div[@class='panel-heading']/strong", + // 播放源名称 + "dtFromName": "/text()", + // 二次处理正则 + "dtFromNameR": "\\S+\\.(\\S+) \\(", + // 播放列表节点 + "dtUrlNode": "//div[contains(@class,'resource-list')]/ul[@class='dslist-group']", + // 播放地址节点 + "dtUrlSubNode": "/li/a", + // 播放地址 + "dtUrlId": "@href", + // 二次处理正则 + "dtUrlIdR": "/play/(\\S+).html", + // 剧集名称 + "dtUrlName": "/text()", + // 二次处理正则 + "dtUrlNameR": "", + // 播放页面的地址 {playUrl} 对应上面 dtUrlId 获取到的地址 + "playUrl": "http://www.9rmb.com/play/{playUrl}.html", + // 解析webview的user-agent + "playUa": "", + // 搜索地址 + "searchUrl": "http://www.9rmb.com/search?wd={wd}", + // 同上面的homeVod字段 搜索结果中的视频信息, 这里有对苹果cms suggest搜索接口的特殊支持,参考示例中的极品影视 + "scVodNode": "//div[@class='movie-item']/a", + "scVodName": "/@title", + "scVodId": "/@href", + "scVodIdR": "/show/(\\w+).html", + "scVodImg": "/img/@src", + "scVodMark": "/button/text()" +} +``` diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..9cd7510 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,47 @@ +plugins { + id 'com.android.application' + id 'ru.cleverpumpkin.proguard-dictionaries-generator' +} + +android { + compileSdkVersion rootProject.compileSdkVersion + + defaultConfig { + applicationId "com.github.catvod.demo" + minSdkVersion rootProject.miniSdkVersion + targetSdkVersion rootProject.targetSdkVersion + versionCode rootProject.appVersionCode + versionName rootProject.appVersionName + } + + buildTypes { + release { + minifyEnabled true + proguardFiles 'proguard-rules.pro' + proguardDictionaries { + dictionaryNames = [ + "build/class-dictionary", + "build/package-dictionary", + "build/obfuscation-dictionary" + ] + minLineLength 1 + maxLineLength 3 + linesCountInDictionary 100000 + } + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + implementation "org.jsoup:jsoup:$jsoup_version" + implementation "cn.wanghaomiao:JsoupXpath:$jsoupxpath_version" + implementation "com.squareup.okhttp3:okhttp:$okhttp_version" + implementation ("com.github.liujingxing.rxhttp:rxhttp:$rxhttp_version") { + exclude group: "com.squareup.okhttp3" + } + annotationProcessor "com.github.liujingxing.rxhttp:rxhttp-compiler:$rxhttp_version" +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..72bb832 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,42 @@ +-optimizationpasses 0 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontskipnonpubliclibraryclassmembers +-dontpreverify +-dontoptimize +-verbose +-printmapping proguardMapping.txt +-optimizations !code/simplification/cast,!field/*,!class/merging/* +-keepattributes *Annotation*,InnerClasses +-keepattributes EnclosingMethod, InnerClasses +-keepattributes *Annotation* +-keepattributes Signature +-keepattributes LineNumberTable +-renamesourcefileattribute SourceFile + +-obfuscationdictionary build/obfuscation-dictionary.txt +-classobfuscationdictionary build/class-dictionary.txt +-packageobfuscationdictionary build/package-dictionary.txt + +-flattenpackagehierarchy com.github.catvod.spider.merge +-repackageclasses com.github.catvod.spider.merge + +-dontwarn okio.** +-keep class okio.**{*;} +-dontwarn com.squareup.okhttp.** +-dontwarn okhttp3.** +-keep class okhttp3.**{*;} +-dontwarn com.google.** +-keep class com.google.**{*;} +-dontwarn com.android.** +-keep class com.android.**{*;} +-dontwarn rxhttp.** +-keep class rxhttp.**{*;} +-dontwarn kotlin.** +-keep class kotlin.**{*;} +-dontwarn kotlinx.** +-keep class kotlinx.**{*;} + +-keep class com.github.catvod.crawler.* { *; } +-keep class com.github.catvod.spider.* { public ; } +-keep class com.github.catvod.parser.* { public ; } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..3620cef --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/crawler/Spider.java b/app/src/main/java/com/github/catvod/crawler/Spider.java new file mode 100644 index 0000000..9f3bf4a --- /dev/null +++ b/app/src/main/java/com/github/catvod/crawler/Spider.java @@ -0,0 +1,103 @@ +package com.github.catvod.crawler; + +import android.content.Context; + +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.List; + +public abstract class Spider { + + public static JSONObject empty = new JSONObject(); + + public void init(Context context) { + } + + public void init(Context context, String extend) { + init(context); + } + + /** + * 首页数据内容 + * + * @param filter 是否开启筛选 + * @return + */ + public String homeContent(boolean filter) { + return ""; + } + + /** + * 首页最近更新数据 如果上面的homeContent中不包含首页最近更新视频的数据 可以使用这个接口返回 + * + * @return + */ + public String homeVideoContent() { + return ""; + } + + /** + * 分类数据 + * + * @param tid + * @param pg + * @param filter + * @param extend + * @return + */ + public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { + return ""; + } + + /** + * 详情数据 + * + * @param ids + * @return + */ + public String detailContent(List ids) { + return ""; + } + + /** + * 搜索数据内容 + * + * @param key + * @param quick + * @return + */ + public String searchContent(String key, boolean quick) { + return ""; + } + + /** + * 播放信息 + * + * @param flag + * @param id + * @return + */ + public String playerContent(String flag, String id, List vipFlags) { + return ""; + } + + /** + * webview解析时使用 可自定义判断当前加载的 url 是否是视频 + * + * @param url + * @return + */ + public boolean isVideoFormat(String url) { + return false; + } + + /** + * 是否手动检测webview中加载的url + * + * @return + */ + public boolean manualVideoCheck() { + return false; + } +} diff --git a/app/src/main/java/com/github/catvod/crawler/SpiderDebug.java b/app/src/main/java/com/github/catvod/crawler/SpiderDebug.java new file mode 100644 index 0000000..fc155a1 --- /dev/null +++ b/app/src/main/java/com/github/catvod/crawler/SpiderDebug.java @@ -0,0 +1,19 @@ +package com.github.catvod.crawler; + +public class SpiderDebug { + public static void log(Throwable th) { + try { + android.util.Log.d("SpiderLog", th.getMessage(), th); + } catch (Throwable th1) { + + } + } + + public static void log(String msg) { + try { + android.util.Log.d("SpiderLog", msg); + } catch (Throwable th1) { + + } + } +} diff --git a/app/src/main/java/com/github/catvod/crawler/SpiderReq.java b/app/src/main/java/com/github/catvod/crawler/SpiderReq.java new file mode 100644 index 0000000..6b5265f --- /dev/null +++ b/app/src/main/java/com/github/catvod/crawler/SpiderReq.java @@ -0,0 +1,299 @@ +package com.github.catvod.crawler; + +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import okhttp3.OkHttpClient; +import okhttp3.RequestBody; +import okhttp3.Response; +import rxhttp.RxHttpPlugins; +import rxhttp.wrapper.param.RxHttp; +import rxhttp.wrapper.parse.Parser; + +public class SpiderReq { + + private static final String defaultTag = "sp_req_default"; + + private static OkHttpClient defaultClient = initDefaultClient(); + + private static OkHttpClient initDefaultClient() { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + builder.readTimeout(15, TimeUnit.SECONDS); + builder.writeTimeout(15, TimeUnit.SECONDS); + builder.connectTimeout(15, TimeUnit.SECONDS); + builder.retryOnConnectionFailure(true); + return builder.build(); + } + + /** + * 取消请求 + * + * @param tag + */ + public static void cancel(String tag) { + try { + RxHttpPlugins.cancelAll(tag); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + + /** + * Get + * + * @param su + * @return + */ + public static SpiderReqResult get(SpiderUrl su) { + return get(defaultClient, su.url, defaultTag, su.headers); + } + + /** + * Get whit custom tag + * + * @param su + * @param tag + * @return + */ + public static SpiderReqResult get(SpiderUrl su, String tag) { + return get(defaultClient, su.url, tag, su.headers); + } + + /** + * Get with custom http client + * + * @param client + * @param su + * @return + */ + public static SpiderReqResult get(OkHttpClient client, SpiderUrl su) { + return get(client, su.url, defaultTag, su.headers); + } + + /** + * Get with custom http client & tag + * + * @param client + * @param su + * @param tag + * @return + */ + + public static SpiderReqResult get(OkHttpClient client, SpiderUrl su, String tag) { + return get(client, su.url, tag, su.headers); + } + + /** + * Get base + * + * @param client + * @param url + * @param tag + * @param headers + * @return + */ + public static SpiderReqResult get(OkHttpClient client, String url, String tag, HashMap headers) { + try { + return RxHttp.get(url) + .setOkClient(client) + .tag(tag) + .addAllHeader(headers) + .execute(new Parser() { + @Override + public SpiderReqResult onParse(@NotNull Response response) throws IOException { + String content = ""; + if (response.body() != null) { + content = response.body().string(); + } + Map> headers = response.headers().toMultimap(); + return new SpiderReqResult(headers, content); + } + }); + } catch (Throwable e) { + SpiderDebug.log(e); + } + return SpiderReqResult.empty; + } + + /** + * Header + * + * @param url + * @param headers + * @return + */ + public static SpiderReqResult header(String url, HashMap headers) { + return header(defaultClient, url, defaultTag, headers); + } + + /** + * Header + * + * @param client + * @param url + * @param tag + * @param headers + * @return + */ + public static SpiderReqResult header(OkHttpClient client, String url, String tag, HashMap headers) { + try { + return RxHttp.head(url) + .setOkClient(client) + .tag(tag) + .addAllHeader(headers) + .execute(new Parser() { + @Override + public SpiderReqResult onParse(@NotNull Response response) throws IOException { + Map> headers = response.headers().toMultimap(); + return new SpiderReqResult(headers, ""); + } + }); + } catch (Throwable e) { + SpiderDebug.log(e); + } + return SpiderReqResult.empty; + } + + /** + * Post Body + * + * @param url + * @param body + * @param headers + * @return + */ + public static SpiderReqResult postBody(String url, RequestBody body, HashMap headers) { + return postBody(defaultClient, url, body, defaultTag, headers); + } + + /** + * Post Body + * + * @param client + * @param url + * @param body + * @param tag + * @param headers + * @return + */ + public static SpiderReqResult postBody(OkHttpClient client, String url, RequestBody body, String tag, HashMap headers) { + try { + return RxHttp.postBody(url) + .setOkClient(client) + .setBody(body) + .tag(tag) + .addAllHeader(headers) + .execute(new Parser() { + @Override + public SpiderReqResult onParse(@NotNull Response response) throws IOException { + String content = ""; + if (response.body() != null) { + content = response.body().string(); + } + Map> headers = response.headers().toMultimap(); + return new SpiderReqResult(headers, content); + } + }); + } catch (Throwable e) { + SpiderDebug.log(e); + } + return SpiderReqResult.empty; + } + + /** + * Post Form + * + * @param url + * @param form + * @param headers + * @return + */ + public static SpiderReqResult postForm(String url, HashMap form, HashMap headers) { + return postForm(defaultClient, url, form, defaultTag, headers); + } + + /** + * Post Form + * + * @param client + * @param url + * @param form + * @param tag + * @param headers + * @return + */ + public static SpiderReqResult postForm(OkHttpClient client, String url, HashMap form, String tag, HashMap headers) { + try { + return RxHttp.postForm(url) + .setOkClient(client) + .addAll(form) + .tag(tag) + .addAllHeader(headers) + .execute(new Parser() { + @Override + public SpiderReqResult onParse(@NotNull Response response) throws IOException { + String content = ""; + if (response.body() != null) { + content = response.body().string(); + } + Map> headers = response.headers().toMultimap(); + return new SpiderReqResult(headers, content); + } + }); + } catch (Throwable e) { + SpiderDebug.log(e); + } + return SpiderReqResult.empty; + } + + /** + * Post Json + * + * @param url + * @param json + * @param headers + * @return + */ + public static SpiderReqResult postJson(String url, HashMap json, HashMap headers) { + return postJson(defaultClient, url, json, defaultTag, headers); + } + + /** + * Post Json + * + * @param client + * @param url + * @param json + * @param tag + * @param headers + * @return + */ + public static SpiderReqResult postJson(OkHttpClient client, String url, HashMap json, String tag, HashMap headers) { + try { + return RxHttp.postJson(url) + .setOkClient(client) + .addAll(json) + .tag(tag) + .addAllHeader(headers) + .execute(new Parser() { + @Override + public SpiderReqResult onParse(@NotNull Response response) throws IOException { + String content = ""; + if (response.body() != null) { + content = response.body().string(); + } + Map> headers = response.headers().toMultimap(); + return new SpiderReqResult(headers, content); + } + }); + } catch (Throwable e) { + SpiderDebug.log(e); + } + return SpiderReqResult.empty; + } +} diff --git a/app/src/main/java/com/github/catvod/crawler/SpiderReqResult.java b/app/src/main/java/com/github/catvod/crawler/SpiderReqResult.java new file mode 100644 index 0000000..808f665 --- /dev/null +++ b/app/src/main/java/com/github/catvod/crawler/SpiderReqResult.java @@ -0,0 +1,17 @@ +package com.github.catvod.crawler; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SpiderReqResult { + SpiderReqResult(Map> headers, String content) { + this.headers = headers; + this.content = content; + } + + public static SpiderReqResult empty = new SpiderReqResult(new HashMap>(), ""); + + public Map> headers; + public String content; +} diff --git a/app/src/main/java/com/github/catvod/crawler/SpiderUrl.java b/app/src/main/java/com/github/catvod/crawler/SpiderUrl.java new file mode 100644 index 0000000..7260f92 --- /dev/null +++ b/app/src/main/java/com/github/catvod/crawler/SpiderUrl.java @@ -0,0 +1,20 @@ +package com.github.catvod.crawler; + +import java.util.HashMap; + +public class SpiderUrl { + + public static SpiderUrl Empty = new SpiderUrl(); + + public String url = ""; + public HashMap headers = new HashMap<>(); + + public SpiderUrl() { + } + + public SpiderUrl(String url, HashMap headers) { + this.url = url; + if (headers != null) + this.headers = headers; + } +} diff --git a/app/src/main/java/com/github/catvod/demo/MainActivity.java b/app/src/main/java/com/github/catvod/demo/MainActivity.java new file mode 100644 index 0000000..51f11a9 --- /dev/null +++ b/app/src/main/java/com/github/catvod/demo/MainActivity.java @@ -0,0 +1,28 @@ +package com.github.catvod.demo; + +import android.app.Activity; +import android.os.Bundle; + +import org.json.JSONObject; + +public class MainActivity extends Activity { + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + new Thread(new Runnable() { + + @Override + public void run() { + + + + } + }). + start(); + } +} + + diff --git a/app/src/main/java/com/github/catvod/live/TxtSubscribe.java b/app/src/main/java/com/github/catvod/live/TxtSubscribe.java new file mode 100644 index 0000000..38ab7b8 --- /dev/null +++ b/app/src/main/java/com/github/catvod/live/TxtSubscribe.java @@ -0,0 +1,144 @@ +package com.github.catvod.live; + +import android.util.Base64; + +import com.github.catvod.utils.okhttp.OkHttpUtil; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; + +public class TxtSubscribe { + + public static void subscribe(LinkedHashMap>> allLives, String url, HashMap headers) { + if (url.contains(".bmp")) { + String content = OkHttpUtil.string(url, headers); + String[] split = content.split("\\*\\*"); + String a = new String(Base64.decode(split[1], Base64.DEFAULT)); + parse(allLives, a); + } else { + String content = OkHttpUtil.string(url, headers); + parse(allLives, content); + } + } + + public static void parse(LinkedHashMap>> allLives, String txt) { + try { + BufferedReader br = new BufferedReader(new StringReader(txt)); + String line = br.readLine(); + LinkedHashMap> noGroup = new LinkedHashMap<>(); + LinkedHashMap> groupLives = noGroup; + while (line != null) { + if (line.trim().isEmpty()) { + line = br.readLine(); + continue; + } + String[] lineInfo = line.split(","); + if (lineInfo.length < 2) { + line = br.readLine(); + continue; + } + if (line.contains("#genre#")) { + String group = lineInfo[0].trim(); + if (!allLives.containsKey(group)) { + groupLives = new LinkedHashMap<>(); + allLives.put(group, groupLives); + } else { + groupLives = allLives.get(group); + } + } else { + String title = lineInfo[0].trim(); + String[] urlMix = lineInfo[1].trim().split("#"); + for (int j = 0; j < urlMix.length; j++) { + String url = urlMix[j].trim(); + if (url.isEmpty()) + continue; + if (url.startsWith("http") || url.startsWith("rtsp") || url.startsWith("rtmp")) { + ArrayList urls = null; + if (!groupLives.containsKey(title)) { + urls = new ArrayList<>(); + groupLives.put(title, urls); + } else { + urls = groupLives.get(title); + } + if (!urls.contains(url)) + urls.add(url); + } else { + // SpiderDebug.log("Skip " + url); + } + } + } + line = br.readLine(); + } + br.close(); + if (!noGroup.isEmpty()) { + allLives.put("未分组", noGroup); + } + } catch (Throwable th) { + + } + } + + public static String live2Json(LinkedHashMap>> lives) { + JSONArray groups = new JSONArray(); + Iterator groupKeys = lives.keySet().iterator(); + while (groupKeys.hasNext()) { + String group = groupKeys.next(); + JSONArray channels = new JSONArray(); + LinkedHashMap> allChannel = lives.get(group); + if (allChannel.isEmpty()) + continue; + Iterator channelKeys = allChannel.keySet().iterator(); + while (channelKeys.hasNext()) { + String channel = channelKeys.next(); + ArrayList allUrls = allChannel.get(channel); + if (allUrls.isEmpty()) + continue; + JSONArray urls = new JSONArray(); + for (int i = 0; i < allUrls.size(); i++) { + urls.put(allUrls.get(i)); + } + JSONObject newChannel = new JSONObject(); + try { + newChannel.put("name", channel); + newChannel.put("urls", urls); + } catch (JSONException e) { + } + channels.put(newChannel); + } + JSONObject newGroup = new JSONObject(); + try { + newGroup.put("group", group); + newGroup.put("channels", channels); + } catch (JSONException e) { + } + groups.put(newGroup); + } + return groups.toString(); + } + + public static Object[] load(String ext) { + try { + LinkedHashMap>> allLives = new LinkedHashMap<>(); + TxtSubscribe.subscribe(allLives, ext, null); + String json = TxtSubscribe.live2Json(allLives); + Object[] result = new Object[3]; + result[0] = 200; + result[1] = "text/plain; charset=utf-8"; + ByteArrayInputStream baos = new ByteArrayInputStream(json.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/parser/JsonBasic.java b/app/src/main/java/com/github/catvod/parser/JsonBasic.java new file mode 100644 index 0000000..940001b --- /dev/null +++ b/app/src/main/java/com/github/catvod/parser/JsonBasic.java @@ -0,0 +1,73 @@ +package com.github.catvod.parser; + +import android.util.Base64; + +import com.github.catvod.crawler.SpiderDebug; +import com.github.catvod.utils.Misc; +import com.github.catvod.utils.okhttp.OkHttpUtil; + +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Set; + +public class JsonBasic { + public static JSONObject parse(LinkedHashMap jx, String url) { + try { + SpiderDebug.log("Load Json Parse Basic..."); + if (jx.size() > 0) { + Set jxNames = jx.keySet(); + for (String jxName : jxNames) { + String parseUrl = jx.get(jxName); + HashMap reqHeaders = getReqHeader(parseUrl); + try { + String realUrl = reqHeaders.get("url"); + reqHeaders.remove("url"); + SpiderDebug.log(realUrl + url); + String json = OkHttpUtil.string(realUrl + url, reqHeaders); + JSONObject taskResult = Misc.jsonParse(url, json); + if (taskResult == null) + continue; + taskResult.put("jxFrom", jxName); + SpiderDebug.log(taskResult.toString()); + return taskResult; + } catch (Throwable th) { + SpiderDebug.log(th); + } + } + } + } catch (Throwable th) { + SpiderDebug.log(th); + } + return new JSONObject(); + } + + public static HashMap getReqHeader(String url) { + HashMap reqHeaders = new HashMap<>(); + reqHeaders.put("url", url); + if (url.contains("cat_ext")) { + try { + int start = url.indexOf("cat_ext="); + int end = url.indexOf("&", start); + String ext = url.substring(start + 8, end); + ext = new String(Base64.decode(ext, Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP)); + String newUrl = url.substring(0, start) + url.substring(end + 1); + JSONObject jsonObject = new JSONObject(ext); + if (jsonObject.has("header")) { + JSONObject headerJson = jsonObject.optJSONObject("header"); + Iterator keys = headerJson.keys(); + while (keys.hasNext()) { + String key = keys.next(); + reqHeaders.put(key, headerJson.optString(key, "")); + } + } + reqHeaders.put("url", newUrl); + } catch (Throwable th) { + + } + } + return reqHeaders; + } +} diff --git a/app/src/main/java/com/github/catvod/parser/JsonParallel.java b/app/src/main/java/com/github/catvod/parser/JsonParallel.java new file mode 100644 index 0000000..c8efa1c --- /dev/null +++ b/app/src/main/java/com/github/catvod/parser/JsonParallel.java @@ -0,0 +1,94 @@ +package com.github.catvod.parser; + +import com.github.catvod.crawler.SpiderDebug; +import com.github.catvod.utils.Misc; +import com.github.catvod.utils.okhttp.OkHttpUtil; + +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.CompletionService; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +/** + * 并发解析,直到获得第一个结果 + *

+ * 默认解析超时时间为15秒,如果需要请自定义SpiderReq的HttpClient + *

+ * Author: CatVod + */ +public class JsonParallel { + private static final String ParseOKTag = "p_json_parse"; + + public static JSONObject parse(LinkedHashMap jx, String url) { + try { + if (jx.size() > 0) { + ExecutorService executorService = Executors.newFixedThreadPool(3); + CompletionService completionService = new ExecutorCompletionService(executorService); + List> futures = new ArrayList<>(); + Set jxNames = jx.keySet(); + for (String jxName : jxNames) { + String parseUrl = jx.get(jxName); + futures.add(completionService.submit(new Callable() { + @Override + public JSONObject call() throws Exception { + try { + HashMap reqHeaders = JsonBasic.getReqHeader(parseUrl); + String realUrl = reqHeaders.get("url"); + reqHeaders.remove("url"); + SpiderDebug.log(realUrl + url); + String json = OkHttpUtil.string(realUrl + url, ParseOKTag, reqHeaders); + JSONObject taskResult = Misc.jsonParse(url, json); + taskResult.put("jxFrom", jxName); + SpiderDebug.log(taskResult.toString()); + return taskResult; + } catch (Throwable th) { + SpiderDebug.log(th); + return null; + } + } + })); + } + JSONObject pTaskResult = null; + for (int i = 0; i < futures.size(); ++i) { + Future completed = completionService.take(); + try { + pTaskResult = completed.get(); + if (pTaskResult != null) { + OkHttpUtil.cancel(ParseOKTag); + for (int j = 0; j < futures.size(); j++) { + try { + futures.get(j).cancel(true); + } catch (Throwable th) { + SpiderDebug.log(th); + } + } + futures.clear(); + break; + } + } catch (Throwable th) { + SpiderDebug.log(th); + } + } + try { + executorService.shutdownNow(); + } catch (Throwable th) { + SpiderDebug.log(th); + } + if (pTaskResult != null) + return pTaskResult; + } + } catch (Throwable th) { + SpiderDebug.log(th); + } + return new JSONObject(); + } +} diff --git a/app/src/main/java/com/github/catvod/parser/JsonSequence.java b/app/src/main/java/com/github/catvod/parser/JsonSequence.java new file mode 100644 index 0000000..e850558 --- /dev/null +++ b/app/src/main/java/com/github/catvod/parser/JsonSequence.java @@ -0,0 +1,48 @@ +package com.github.catvod.parser; + +import com.github.catvod.crawler.SpiderDebug; +import com.github.catvod.utils.Misc; +import com.github.catvod.utils.okhttp.OkHttpUtil; + +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Set; + +/** + * 依次解析,失败尝试下一个 + *

+ * 默认解析超时时间为15秒,如果需要请自定义SpiderReq的HttpClient + *

+ * Author: CatVod + */ +public class JsonSequence { + public static JSONObject parse(LinkedHashMap jx, String url) { + try { + if (jx.size() > 0) { + Set jxNames = jx.keySet(); + for (String jxName : jxNames) { + String parseUrl = jx.get(jxName); + try { + HashMap reqHeaders = JsonBasic.getReqHeader(parseUrl); + String realUrl = reqHeaders.get("url"); + reqHeaders.remove("url"); + SpiderDebug.log(realUrl + url); + String json = OkHttpUtil.string(realUrl + url, reqHeaders); + JSONObject taskResult = Misc.jsonParse(url, json); + if (taskResult == null) + continue; + taskResult.put("jxFrom", jxName); + return taskResult; + } catch (Throwable th) { + SpiderDebug.log(th); + } + } + } + } catch (Throwable th) { + SpiderDebug.log(th); + } + return new JSONObject(); + } +} diff --git a/app/src/main/java/com/github/catvod/parser/MixDemo.java b/app/src/main/java/com/github/catvod/parser/MixDemo.java new file mode 100644 index 0000000..4db3f25 --- /dev/null +++ b/app/src/main/java/com/github/catvod/parser/MixDemo.java @@ -0,0 +1,189 @@ +package com.github.catvod.parser; + +import android.util.Base64; + +import com.github.catvod.crawler.SpiderDebug; + +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 MixDemo { + + /* + "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("1") || type.equals("0")) { + try { + JSONArray flags = new JSONObject(parseBean.get("ext")).getJSONArray("flag"); + for (int j = 0; j < flags.length(); j++) { + String flagKey = flags.getString(j); + ArrayList flagJx = configs.get(flagKey); + if (flagJx == null) { + flagJx = new ArrayList<>(); + configs.put(flagKey, flagJx); + } + flagJx.add(key); + } + } catch (Throwable th) { + + } + } + } + } + // 通过上面的配置获得解析列表 + LinkedHashMap jsonJx = new LinkedHashMap<>(); + ArrayList webJx = new ArrayList<>(); + ArrayList flagJx = configs.get(flag); + 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("1")) { + jsonJx.put(key, mixUrl(parseBean.get("url"), parseBean.get("ext"))); + } else if (type.equals("0")) { + 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("1")) { + jsonJx.put(key, mixUrl(parseBean.get("url"), parseBean.get("ext"))); + } else if (type.equals("0")) { + webJx.add(parseBean.get("url")); + } + } + } + if (!webJx.isEmpty()) { + flagWebJx.put(flag, webJx); + } + // 优先使用json并发解析 + JSONObject jsonResult = JsonParallel.parse(jsonJx, url); + if (jsonResult != null && jsonResult.has("url")) { + return jsonResult; + } + // json解析没有得到结果 用webview解析 + if (!webJx.isEmpty()) { + JSONObject webResult = new JSONObject(); + webResult.put("url", "proxy://do=MixDemo&flag=" + flag + "&url=" + Base64.encodeToString(url.getBytes(), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP)); + webResult.put("parse", 1); + return webResult; + } + } catch (Throwable th) { + SpiderDebug.log(th); + } + return new JSONObject(); + } + + private static String mixUrl(String url, String ext) { + if (ext.trim().length() > 0) { + int idx = url.indexOf("?"); + if (idx > 0) { + return url.substring(0, idx + 1) + "cat_ext=" + Base64.encodeToString(ext.getBytes(), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP) + "&" + url.substring(idx + 1); + } + } + return url; + } + + 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/AliPS.java b/app/src/main/java/com/github/catvod/spider/AliPS.java new file mode 100644 index 0000000..d7d2cf6 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/AliPS.java @@ -0,0 +1,108 @@ +package com.github.catvod.spider; + +import android.content.Context; + +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.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 AliPS extends Spider { + private PushAgent pushAgent; + private static String b = "https://www.alipansou.com"; + private static Pattern a = 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 = a; + if (pattern.matcher(list.get(0)).find()) { + return pushAgent.detailContent(list); + } + Matcher matcher = pattern.matcher(OkHttpUtil.string("https://www.alipansou.com" + list.get(0), null)); + 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 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 z) { + try { + HashMap hashMap = new HashMap(); + hashMap.put("7", "文件夹"); + hashMap.put("1", "视频"); + JSONArray jSONArray = new JSONArray(); + Iterator entries = hashMap.entrySet().iterator(); + while (entries.hasNext()) { + Map.Entry entry = (Map.Entry) entries.next(); + String str2 = (String) entry.getValue(); + String sb2 = b + "/search?k=" + URLEncoder.encode(key) + "&t=" + (String) entry.getKey(); + Document doc = Jsoup.parse(OkHttpUtil.string(sb2, sHeaders())); + Elements Data = doc.select("van-row a"); + for (int i = 0; i < Data.size(); i++) { + Element next = Data.get(i); + String filename = next.select("template div").text(); + Pattern pattern = Pattern.compile("(时间: \\S+)"); + Matcher matcher = pattern.matcher(filename); + if (!matcher.find()) + continue; + String remark = matcher.group(1); + if (filename.contains(key)) { + JSONObject v = new JSONObject(); + String id = next.attr("href"); + String title = "[" + str2 + "]" + filename; + v.put("vod_id", id); + v.put("vod_name", title); + v.put("remark", remark); + v.put("vod_pic", "https://inews.gtimg.com/newsapp_bt/0/13263837859/1000"); + jSONArray.put(v); + } + } + } + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("list", jSONArray); + return jSONObject2.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/AppYs.java b/app/src/main/java/com/github/catvod/spider/AppYs.java new file mode 100644 index 0000000..051eaef --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/AppYs.java @@ -0,0 +1,1124 @@ +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 java.net.URLEncoder; +import java.util.ArrayList; +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; + +/** + * M浏览器中的App影视 + *

+ * Author: 群友 不负此生 + */ +public class AppYs extends Spider { + + private String extString = ""; + + @Override + public void init(Context context, String extend) { + super.init(context, extend); + this.extString = extend; + } + + @Override + public String homeContent(boolean filter) { + try { + String url = getCateUrl(extString); + JSONArray jsonArray = null; + if (!url.isEmpty()) { + SpiderDebug.log(url); + String json = OkHttpUtil.string(url, getHeaders(url)); + JSONObject obj = new JSONObject(json); + if (obj.has("list") && obj.get("list") instanceof JSONArray) { + jsonArray = obj.getJSONArray("list"); + } else if (obj.has("data") && obj.get("data") instanceof JSONObject && obj.getJSONObject("data").has("list") && obj.getJSONObject("data").get("list") instanceof JSONArray) { + jsonArray = obj.getJSONObject("data").getJSONArray("list"); + } else if (obj.has("data") && obj.get("data") instanceof JSONArray) { + jsonArray = obj.getJSONArray("data"); + } + } else { // 通过filter列表读分类 + String filterStr = getFilterTypes(url, null); + String[] classes = filterStr.split("\n")[0].split("\\+"); + jsonArray = new JSONArray(); + for (int i = 1; i < classes.length; i++) { + String[] kv = classes[i].trim().split("="); + if (kv.length < 2) + continue; + JSONObject newCls = new JSONObject(); + newCls.put("type_name", kv[0].trim()); + newCls.put("type_id", kv[1].trim()); + jsonArray.put(newCls); + } + } + JSONObject result = new JSONObject(); + JSONArray classes = new JSONArray(); + if (jsonArray != null) { + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jObj = jsonArray.getJSONObject(i); + String typeName = jObj.getString("type_name"); + if (isBan(typeName)) + continue; + String typeId = jObj.getString("type_id"); + JSONObject newCls = new JSONObject(); + newCls.put("type_id", typeId); + newCls.put("type_name", typeName); + JSONObject typeExtend = jObj.optJSONObject("type_extend"); + if (filter) { + String filterStr = getFilterTypes(url, typeExtend); + String[] filters = filterStr.split("\n"); + JSONArray filterArr = new JSONArray(); + for (int k = url.isEmpty() ? 1 : 0; k < filters.length; k++) { + String l = filters[k].trim(); + if (l.isEmpty()) + continue; + String[] oneLine = l.split("\\+"); + String type = oneLine[0].trim(); + String typeN = type; + if (type.contains("筛选")) { + type = type.replace("筛选", ""); + if (type.equals("class")) + typeN = "类型"; + else if (type.equals("area")) + typeN = "地区"; + else if (type.equals("lang")) + typeN = "语言"; + else if (type.equals("year")) + typeN = "年份"; + } + JSONObject jOne = new JSONObject(); + jOne.put("key", type); + jOne.put("name", typeN); + JSONArray valueArr = new JSONArray(); + for (int j = 1; j < oneLine.length; j++) { + JSONObject kvo = new JSONObject(); + String kv = oneLine[j].trim(); + int sp = kv.indexOf("="); + if (sp == -1) { + if (isBan(kv)) + continue; + kvo.put("n", kv); + kvo.put("v", kv); + } else { + String n = kv.substring(0, sp); + if (isBan(n)) + continue; + kvo.put("n", n.trim()); + kvo.put("v", kv.substring(sp + 1).trim()); + } + valueArr.put(kvo); + } + jOne.put("value", valueArr); + filterArr.put(jOne); + } + if (!result.has("filters")) { + result.put("filters", new JSONObject()); + } + result.getJSONObject("filters").put(typeId, filterArr); + } + classes.put(newCls); + } + } + result.put("class", classes); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public String homeVideoContent() { + try { + String apiUrl = extString; + String url = getRecommendUrl(apiUrl); + boolean isTV = false; + if (url.isEmpty()) { + url = getCateFilterUrlPrefix(apiUrl) + "movie&page=1&area=&type=&start="; + isTV = true; + } + SpiderDebug.log(url); + String json = OkHttpUtil.string(url, getHeaders(url)); + JSONObject obj = new JSONObject(json); + JSONArray videos = new JSONArray(); + if (isTV) { + JSONArray jsonArray = obj.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("nextlink")); + v.put("vod_name", vObj.getString("title")); + v.put("vod_pic", vObj.getString("pic")); + v.put("vod_remarks", vObj.getString("state")); + videos.put(v); + } + } else { + ArrayList arrays = new ArrayList<>(); + findJsonArray(obj, "vlist", arrays); + if (arrays.isEmpty()) { + findJsonArray(obj, "vod_list", arrays); + } + List ids = new ArrayList<>(); + for (JSONArray jsonArray : arrays) { + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject vObj = jsonArray.getJSONObject(i); + String vid = vObj.getString("vod_id"); + if (ids.contains(vid)) + continue; + ids.add(vid); + JSONObject v = new JSONObject(); + v.put("vod_id", vid); + 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 apiUrl = extString; + String url = getCateFilterUrlPrefix(apiUrl) + tid + getCateFilterUrlSuffix(apiUrl); + url = url.replace("#PN#", pg); + url = url.replace("筛选class", (extend != null && extend.containsKey("class")) ? extend.get("class") : ""); + url = url.replace("筛选area", (extend != null && extend.containsKey("area")) ? extend.get("area") : ""); + url = url.replace("筛选lang", (extend != null && extend.containsKey("lang")) ? extend.get("lang") : ""); + url = url.replace("筛选year", (extend != null && extend.containsKey("year")) ? extend.get("year") : ""); + url = url.replace("排序", (extend != null && extend.containsKey("排序")) ? extend.get("排序") : ""); + SpiderDebug.log(url); + String json = OkHttpUtil.string(url, getHeaders(url)); + JSONObject obj = new JSONObject(json); + int totalPg = Integer.MAX_VALUE; + try { + if (obj.has("totalpage") && obj.get("totalpage") instanceof Integer) { + totalPg = obj.getInt("totalpage"); + } else if (obj.has("pagecount") && obj.get("pagecount") instanceof Integer) { + totalPg = obj.getInt("pagecount"); + } else if (obj.has("data") && obj.get("data") instanceof JSONObject && + (obj.getJSONObject("data").has("total") && obj.getJSONObject("data").get("total") instanceof Integer && + obj.getJSONObject("data").has("limit") && obj.getJSONObject("data").get("limit") instanceof Integer)) { + int limit = obj.getJSONObject("data").getInt("limit"); + int total = obj.getJSONObject("data").getInt("total"); + totalPg = total % limit == 0 ? (total / limit) : (total / limit + 1); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + + JSONArray jsonArray = null; + JSONArray videos = new JSONArray(); + if (obj.has("list") && obj.get("list") instanceof JSONArray) { + jsonArray = obj.getJSONArray("list"); + } else if (obj.has("data") && obj.get("data") instanceof JSONObject && obj.getJSONObject("data").has("list") && obj.getJSONObject("data").get("list") instanceof JSONArray) { + jsonArray = obj.getJSONObject("data").getJSONArray("list"); + } else if (obj.has("data") && obj.get("data") instanceof JSONArray) { + jsonArray = obj.getJSONArray("data"); + } + if (jsonArray != null) { + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject vObj = jsonArray.getJSONObject(i); + if (vObj.has("vod_id")) { + 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); + } else { + JSONObject v = new JSONObject(); + v.put("vod_id", vObj.getString("nextlink")); + v.put("vod_name", vObj.getString("title")); + v.put("vod_pic", vObj.getString("pic")); + v.put("vod_remarks", vObj.getString("state")); + videos.put(v); + } + } + } + JSONObject result = new JSONObject(); + result.put("page", pg); + result.put("pagecount", totalPg); + result.put("limit", 90); + 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 apiUrl = extString; + String url = getPlayUrlPrefix(apiUrl) + ids.get(0); + SpiderDebug.log(url); + String json = OkHttpUtil.string(url, getHeaders(url)); + JSONObject obj = new JSONObject(json); + JSONObject result = new JSONObject(); + JSONObject vod = new JSONObject(); + genPlayList(apiUrl, obj, json, vod, ids.get(0)); + 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 { + String apiUrl = extString; + String url = getSearchUrl(apiUrl, URLEncoder.encode(key)); + String json = OkHttpUtil.string(url, getHeaders(url)); + JSONObject obj = new JSONObject(json); + JSONArray jsonArray = null; + JSONArray videos = new JSONArray(); + if (obj.has("list") && obj.get("list") instanceof JSONArray) { + jsonArray = obj.getJSONArray("list"); + } else if (obj.has("data") && obj.get("data") instanceof JSONObject && obj.getJSONObject("data").has("list") && obj.getJSONObject("data").get("list") instanceof JSONArray) { + jsonArray = obj.getJSONObject("data").getJSONArray("list"); + } else if (obj.has("data") && obj.get("data") instanceof JSONArray) { + jsonArray = obj.getJSONArray("data"); + } + if (jsonArray != null) { + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject vObj = jsonArray.getJSONObject(i); + if (vObj.has("vod_id")) { + 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); + } else { + JSONObject v = new JSONObject(); + v.put("vod_id", vObj.getString("nextlink")); + v.put("vod_name", vObj.getString("title")); + v.put("vod_pic", vObj.getString("pic")); + v.put("vod_remarks", vObj.getString("state")); + videos.put(v); + } + } + } + JSONObject result = new JSONObject(); + 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 { + String apiUrl = extString; + String parseUrl = getParseUrl(apiUrl, flag); + String playerUrl = getPlayerUrl(apiUrl, parseUrl, id); + JSONObject result = new JSONObject(); + getFinalVideo(playerUrl, result); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + private void findJsonArray(JSONObject obj, String match, ArrayList result) { + Iterator keys = obj.keys(); + while (keys.hasNext()) { + String k = keys.next(); + try { + Object o = obj.get(k); + if (k.equals(match) && o instanceof JSONArray) + result.add((JSONArray) o); + if (o instanceof JSONObject) { + findJsonArray((JSONObject) o, match, result); + } else if (o instanceof JSONArray) { + JSONArray array = (JSONArray) o; + for (int i = 0; i < array.length(); i++) { + findJsonArray(array.getJSONObject(i), match, result); + } + } + } catch (JSONException e) { + SpiderDebug.log(e); + } + } + } + + 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 ""; + } + + private static HashMap fakeVips = null; + private static final Object lock = new Object(); + + private static String stopVipFlag(String flag) { + synchronized (lock) { + if (fakeVips == null) { + fakeVips = new HashMap<>(); + fakeVips.put("youku", "优酷M"); + fakeVips.put("qq", "腾讯M"); + fakeVips.put("iqiyi", "爱奇艺M"); + fakeVips.put("qiyi", "奇艺M"); + fakeVips.put("letv", "乐视M"); + fakeVips.put("sohu", "搜狐M"); + fakeVips.put("tudou", "土豆M"); + fakeVips.put("pptv", "PPTVM"); + fakeVips.put("mgtv", "芒果TVM"); + fakeVips.put("wasu", "华数M"); + fakeVips.put("bilibili", "哔哩M"); + } + if (fakeVips.containsKey(flag)) { + return fakeVips.get(flag); + } + return flag; + } + } + + private HashMap getHeaders(String URL) { + HashMap headers = new HashMap<>(); + headers.put("User-Agent", UA(URL)); + return headers; + } + + private boolean isBan(String key) { + return key.equals("伦理") || key.equals("情色") || key.equals("福利"); + } + + // M 扩展方法 + + // ######重组搜索 + private String getSearchUrl(String URL, String KEY) { + if (URL.contains(".vod")) { + if (URL.contains("iopenyun.com")) { + return URL + "/list?wd=" + KEY + "&page="; + } else { + return URL + "?wd=" + KEY + "&page="; + } + } else if (URL.contains("api.php/app") || URL.contains("xgapp")) { + return URL + "search?text=" + KEY + "&pg="; + } else if (urlPattern1.matcher(URL).find()) { + if (URL.contains("esellauto") + || URL.contains("1.14.63.101") + || URL.contains("zjys") + || URL.contains("dcd") + || URL.contains("lxue") + || URL.contains("weetai.cn") + || URL.contains("haokanju1") + || URL.contains("fit:8") + || URL.contains("zjj.life") + || URL.contains("love9989") + || URL.contains("8d8q") + || URL.contains("lk.pxun") + || URL.contains("hgyx") + || URL.contains("521x5") + || URL.contains("lxyyy") + || URL.contains("0818tv") + || URL.contains("diyoui") + || URL.contains("diliktv") + || URL.contains("ppzhu") + || URL.contains("aitesucai") + || URL.contains("zz.ci") + || URL.contains("chxjon") + || URL.contains("watchmi") + || URL.contains("vipbp") + || URL.contains("bhtv") + || URL.contains("xfykl")) { + return URL + "?ac=list&" + "wd=" + KEY + "&page="; + } else { + return URL + "?ac=list&" + "zm=" + KEY + "&page="; + } + } + return ""; + } + + // ######UA + private static final Pattern urlPattern1 = Pattern.compile("api\\.php/.*?/vod"); + private static final Pattern urlPattern2 = Pattern.compile("api\\.php/.+?\\.vod"); + private static final Pattern parsePattern = Pattern.compile("/.+\\?.+="); + private static final Pattern parsePattern1 = Pattern.compile(".*(url|v|vid|php\\?id)="); + private static final Pattern parsePattern2 = Pattern.compile("https?://[^/]*"); + private static final Pattern[] parseMatchForDotVod = new Pattern[]{ + Pattern.compile("jx\\.+huimaojia\\.+com/player"), + Pattern.compile("py\\.+789pan\\.+cn/player/tm\\.php\\?url="), + Pattern.compile("ztys\\.+waruanzy\\.+com/player/\\?url="), + Pattern.compile("yingshi\\.+waruanzy\\.+com/789pan/\\?url="), + Pattern.compile("vip\\.+parwix\\.+com:4433/player/\\?url="), + Pattern.compile("api\\.+cxitco\\.+cn"), + Pattern.compile("/vip\\.+renrenmi.cc"), + Pattern.compile("yanbing\\.+parwix\\.+com:4433/player"), + Pattern.compile("json\\.+cantin\\.+cc/apijson\\.php"), + Pattern.compile("ffdm\\.+miaoletv\\.+com/\\?url="), + Pattern.compile("vip\\.+sylwl\\.+cn/api/\\?key="), + Pattern.compile("jx\\.+dikotv\\.+com/\\?url="), + Pattern.compile("zly\\.+xjqxz\\.+top/player/\\?url="), + Pattern.compile("5znn\\.+xyz/m3u8\\.+php"), + Pattern.compile("uid=1735&my="), + Pattern.compile("api\\.+xkvideo\\.+design/m3u8\\.+php\\?url="), + Pattern.compile("play\\.+szbodankyy\\.+com/xxoocnmb"), + Pattern.compile("vip\\.+fj6080\\.+xyz/player/\\?url="), + Pattern.compile("a\\.+dxzj88\\.+com/jiexi"), + Pattern.compile("host\\.+q-q\\.+wang/api"), + Pattern.compile("保佑") + }; + + private static final Pattern[] htmlVideoKeyMatch = new Pattern[]{ + Pattern.compile("player=new"), + Pattern.compile("

typeExtendKeys = typeExtend.keys(); + while (typeExtendKeys.hasNext()) { + String key = typeExtendKeys.next(); + if (key.equals("class") || key.equals("area") || key.equals("lang") || key.equals("year")) { + try { + str = str + "筛选" + key + "+全部=+" + typeExtend.getString(key).replace(",", "+") + "\n"; + } catch (JSONException e) { + } + } + } + } + if (URL.contains(".vod")) { + str += "\n" + "排序+全部=+最新=time+最热=hits+评分=score"; + } else if (URL.contains("api.php/app") || URL.contains("xgapp")) { + } else { + str = "分类+全部=+电影=movie+连续剧=tvplay+综艺=tvshow+动漫=comic+4K=movie_4k+体育=tiyu\n筛选class+全部=+喜剧+爱情+恐怖+动作+科幻+剧情+战争+警匪+犯罪+动画+奇幻+武侠+冒险+枪战+恐怖+悬疑+惊悚+经典+青春+文艺+微电影+古装+历史+运动+农村+惊悚+惊悚+伦理+情色+福利+三级+儿童+网络电影\n筛选area+全部=+大陆+香港+台湾+美国+英国+法国+日本+韩国+德国+泰国+印度+西班牙+加拿大+其他\n筛选year+全部=+2022+2021+2020+2019+2018+2017+2016+2015+2014+2013+2012+2011+2010+2009+2008+2007+2006+2005+2004+2003+2002+2001+2000"; + } + return str; + } + + // ######推荐地址 + String getRecommendUrl(String URL) { + if (URL.contains("api.php/app") || URL.contains("xgapp")) { + return URL + "index_video?token="; + } else if (URL.contains(".vod")) { + return URL + "/vodPhbAll"; + } else { + return ""; + } + } + + // ######播放器前缀地址 + String getPlayUrlPrefix(String URL) { + if (URL.contains("api.php/app") || URL.contains("xgapp")) { + if (URL.contains("dijiaxia")) { + URL = "https://www.dijiaxia.com/api.php/app/"; + return URL + "video_detail?id="; + } else if (URL.contains("1010dy")) { + URL = "http://www.1010dy.cc/api.php/app/"; + return URL + "video_detail?id="; + } else { + return URL + "video_detail?id="; + } + } else if (URL.contains(".vod")) { + if (URL.contains("iopenyun")) { + return URL + "/detailID?vod_id="; + } else { + return URL + "/detail?vod_id="; + } + } else { + return ""; + } + } + + // ######选集 + private final HashMap parseUrlMap = new HashMap<>(); + + private void genPlayList(String URL, JSONObject object, String json, JSONObject vod, String vid) throws JSONException { + ArrayList playUrls = new ArrayList<>(); + ArrayList playFlags = new ArrayList<>(); + if (URL.contains("api.php/app/")) { + JSONObject data = object.getJSONObject("data"); + vod.put("vod_id", data.optString("vod_id", vid)); + vod.put("vod_name", data.getString("vod_name")); + vod.put("vod_pic", data.getString("vod_pic")); + vod.put("type_name", data.optString("vod_class")); + vod.put("vod_year", data.optString("vod_year")); + vod.put("vod_area", data.optString("vod_area")); + vod.put("vod_remarks", data.optString("vod_remarks")); + vod.put("vod_actor", data.optString("vod_actor")); + vod.put("vod_director", data.optString("vod_director")); + vod.put("vod_content", data.optString("vod_content")); + JSONArray vodUrlWithPlayer = data.getJSONArray("vod_url_with_player"); + for (int i = 0; i < vodUrlWithPlayer.length(); i++) { + JSONObject from = vodUrlWithPlayer.getJSONObject(i); + String flag = stopVipFlag(from.getString("name")); + playFlags.add(flag); + playUrls.add(from.getString("url")); + String purl = from.optString("parse_api"); + if (purl.contains("jpg.hou.lu/jm/za/index.php")) { + purl = "http://vip.mengx.vip/home/api?type=ys&uid=3249696&key=aefqrtuwxyEFHKNOQY&url="; + } + parseUrlMap.put(flag, purl); + } + } else if (URL.contains("xgapp")) { + JSONObject data = object.getJSONObject("data").getJSONObject("vod_info"); + vod.put("vod_id", data.optString("vod_id", vid)); + vod.put("vod_name", data.getString("vod_name")); + vod.put("vod_pic", data.getString("vod_pic")); + vod.put("type_name", data.optString("vod_class")); + vod.put("vod_year", data.optString("vod_year")); + vod.put("vod_area", data.optString("vod_area")); + vod.put("vod_remarks", data.optString("vod_remarks")); + vod.put("vod_actor", data.optString("vod_actor")); + vod.put("vod_director", data.optString("vod_director")); + vod.put("vod_content", data.optString("vod_content")); + JSONArray vodUrlWithPlayer = data.getJSONArray("vod_url_with_player"); + for (int i = 0; i < vodUrlWithPlayer.length(); i++) { + JSONObject from = vodUrlWithPlayer.getJSONObject(i); + String flag = stopVipFlag(from.getString("name")); + playFlags.add(flag); + playUrls.add(from.getString("url")); + String purl = from.optString("parse_api"); + if (purl.contains("jpg.hou.lu/jm/za/index.php")) { + purl = "http://vip.mengx.vip/home/api?type=ys&uid=3249696&key=aefqrtuwxyEFHKNOQY&url="; + } + parseUrlMap.put(flag, purl); + } + } else if (/*urlPattern2.matcher(URL).find()*/URL.contains(".vod")) { + JSONObject data = object.getJSONObject("data"); + vod.put("vod_id", data.optString("vod_id", vid)); + vod.put("vod_name", data.getString("vod_name")); + vod.put("vod_pic", data.getString("vod_pic")); + vod.put("type_name", data.optString("vod_class")); + vod.put("vod_year", data.optString("vod_year")); + vod.put("vod_area", data.optString("vod_area")); + vod.put("vod_remarks", data.optString("vod_remarks")); + vod.put("vod_actor", data.optString("vod_actor")); + vod.put("vod_director", data.optString("vod_director")); + vod.put("vod_content", data.optString("vod_content")); + JSONArray vodUrlWithPlayer = data.getJSONArray("vod_play_list"); + for (int i = 0; i < vodUrlWithPlayer.length(); i++) { + JSONObject from = vodUrlWithPlayer.getJSONObject(i); + String flag = stopVipFlag(from.getJSONObject("player_info").getString("show")); + playFlags.add(flag); + playUrls.add(from.getString("url")); + try { + ArrayList parses = new ArrayList<>(); + String[] parse1 = from.getJSONObject("player_info").optString("parse").split(","); + String[] parse2 = from.getJSONObject("player_info").optString("parse2").split(","); + for (String p : parse1) { + if (parsePattern.matcher(p).find()) { + boolean add = true; + for (Pattern pt : parseMatchForDotVod) { + if (pt.matcher(p).find()) { + add = false; + break; + } + } + if (add) { + parses.add(p); + } + } + } + for (String p : parse2) { + if (parsePattern.matcher(p).find()) { + boolean add = true; + for (Pattern pt : parseMatchForDotVod) { + if (pt.matcher(p).find()) { + add = false; + break; + } + } + if (add) { + parses.add(p); + } + } + } + if (parses.size() > 0 && parses.get(0).contains("=")) { + String purl = parses.get(0); + if (purl.contains("http")) { + Matcher matcher = parsePattern1.matcher(purl); + if (matcher.find()) { + purl = matcher.group(0).replace("..", ".").replace("vip.aotian.love", "vip.gaotian.love"); + } + } else if (purl.contains("//")) { + Matcher matcher = parsePattern1.matcher(purl); + if (matcher.find()) { + purl = "http:" + matcher.group(0).replace("..", "."); + } + } else { + Matcher matcher = parsePattern2.matcher(URL); + if (matcher.find()) { + Matcher matcher1 = parsePattern1.matcher(URL); + if (matcher1.find()) { + purl = matcher.group(0) + matcher1.group(0).replace("..", "."); + } + } + } + parseUrlMap.put(flag, purl); + } else { + parseUrlMap.put(flag, "http://1.117.152.239:39000/?url="); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + } + } else if (urlPattern1.matcher(URL).find()) { + JSONObject data = object; + vod.put("vod_id", data.optString("vod_id", vid)); + vod.put("vod_name", data.getString("title")); + vod.put("vod_pic", data.getString("img_url")); + vod.put("type_name", jsonArr2Str(data.optJSONArray("type"))); + vod.put("vod_year", data.optString("pubtime")); + vod.put("vod_area", jsonArr2Str(data.optJSONArray("area"))); + vod.put("vod_remarks", data.optString("trunk")); + vod.put("vod_actor", jsonArr2Str(data.optJSONArray("actor"))); + vod.put("vod_director", jsonArr2Str(data.optJSONArray("director"))); + vod.put("vod_content", data.optString("intro")); + JSONObject playList = data.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")); + } + playFlags.add(stopVipFlag(from)); + playUrls.add(TextUtils.join("#", urls)); + } + } +// for (int i = 0; i < playFlags.size(); i++) { +// String pu = playUrls.get(i).split("#")[0].split("\\$")[1]; +// System.out.println(pu + " is video?" + isVideoFormat(pu)); +// playerContent(playFlags.get(i), pu, new ArrayList<>()); +// } + vod.put("vod_play_from", TextUtils.join("$$$", playFlags)); + vod.put("vod_play_url", TextUtils.join("$$$", playUrls)); + } + + private String getParseUrl(String URL, String flag) { + String parseUrl = ""; + if (urlPattern2.matcher(URL).find()) { + if (parseUrlMap.containsKey(flag)) + parseUrl = parseUrlMap.get(flag); + } else if (URL.contains("api.php/app/") || URL.contains("xgapp")) { + if (parseUrlMap.containsKey(flag)) + parseUrl = parseUrlMap.get(flag); + } else { + parseUrl = URL; + } + if (parseUrl.contains("svip.jhyun.jx.cn") || parseUrl.contains("svip.jhdyw.vip")) { + if (flag.contains("人人迷")) { + parseUrl = "http://www.1080kan.cc/jiexi/rrmi.php?url="; + } else if (flag.contains("人人")) { + parseUrl = "http://www.1080kan.cc/jiexi/rr.php?url="; + } else if (flag.contains("番茄")) { + parseUrl = "http://www.1080kan.cc/jiexi/fq.php?url="; + } else { + parseUrl = "https://jx.parwix.com:4433/player/?url="; + } + } else if (parseUrl.contains("jhsj.manduhu.com") || parseUrl.contains("v.jhdyw.vip/nhdz666")) { + parseUrl = "https://jx.parwix.com:4433/player/?url="; + } else if (parseUrl.contains("x-n.cc")) { + parseUrl = "https://jx.parwix.com:4433/player/?url="; + } + return parseUrl; + } + + private String getPlayerUrl(String URL, String parseUrl, String playUrl) { + if (URL.contains("xgapp") || URL.contains("api.php/app/") || /*urlPattern2.matcher(URL).find()*/URL.contains(".vod")) { + if (playUrl.indexOf(".m3u8") > 15 || playUrl.indexOf(".mp4") > 15 || playUrl.contains("/obj/tos")) { + if (playUrl.contains("url=")) { + return "https://www.baidu.com/s?wd=" + playUrl.split("url=")[1]; + } else { + return "https://www.baidu.com/s?wd=" + playUrl; + } + } else if (!parseUrl.contains("url=") && playUrl.contains("RongXingVR")) { + return "https://www.baidu.com/s?wd=https://fast.rongxingvr.cn:8866/api/?key=nShWumGdMIbTwngTbI&url=" + playUrl; + } else if (!parseUrl.contains("url=") && playUrl.contains("LT")) { + return "https://www.baidu.com/s?wd=https://f7.pyxddc.com/bcjx/4k.php?url=" + playUrl; + } else if (!parseUrl.contains("url=") && playUrl.contains("renrenmi")) { + return "https://www.baidu.com/s?wd=https://kuba.renrenmi.cc:2266/api/?key=Y6UYLYtjImTCKe98JD&url=" + playUrl; + } else if (!parseUrl.contains("url=") && playUrl.contains(".html")) { + return "https://www.baidu.com/s?wd=http://1.117.152.239:39000/?url=" + playUrl; + } else if (playUrl.contains("xfy")) { + return "https://www.baidu.com/s?wd=http://jiexi.yunl.cc/api/?key=xYNESYSvHp1DV2ckKs&url=" + playUrl; + } else { + return "https://www.baidu.com/s?wd=" + parseUrl + playUrl; + } + } else if (urlPattern1.matcher(URL).find()) { + if (playUrl.indexOf(".m3u8") > 15 || playUrl.indexOf(".mp4") > 15 || playUrl.contains("/obj/tos")) { + if (playUrl.contains("url=")) { + return "https://www.baidu.com/s?wd=" + playUrl.split("url=")[1]; + } else { + return "https://www.baidu.com/s?wd=" + playUrl; + } + } else if (playUrl.contains("xfy")) { + if (playUrl.contains("url=")) { + return "https://www.baidu.com/s?wd=http://cache.dmtt.xyz/xfyjx/xfyjx.php?url=" + playUrl.split("url=")[1]; + } else { + return "https://www.baidu.com/s?wd=https://json.hfyrw.com/mao.go?url=" + playUrl; + } + } else if (playUrl.contains("www.bilibili.com")) { + String spUrl = playUrl.split("url=")[1]; + return "https://www.baidu.com/s?wd=https://jx.parwix.com:4433/player/?url=" + spUrl; + } else if (URL.contains("zhenfy") || URL.contains("cztv") || URL.contains("1.14.63.101") || URL.contains("fit:8") || URL.contains("diliktv.xyz") || URL.contains("ppzhu.vip") || URL.contains("api.8d8q.com") || URL.contains("haokanju1.cc") || URL.contains("cztv")) { + return "https://www.baidu.com/s?wd=" + playUrl + "&app=10000&account=272775028&password=qq272775028"; + } else if (URL.contains("lxyyy") || URL.contains("j.zjj.life") || URL.contains("lktv") || URL.contains("0818tv") || URL.contains("ruoxinew")) { + return "https://www.baidu.com/s?wd=https://play.tkys.tv/?url=" + playUrl.split("url=")[1]; + } else { + return "https://www.baidu.com/s?wd=" + playUrl; + } + } else { + return "https://www.baidu.com/s?wd=" + playUrl; + } + } + + // ######视频地址 + private void getFinalVideo(String uu, JSONObject result) throws JSONException { + if (uu.contains("baidu.com")) { + String playurl = uu.split("wd=")[1]; + if (playurl.contains("duoduozy.com") || playurl.contains("suoyo.cc")) { + String uuu = "https://www.6080kan.cc/app.php?url=" + playurl; + String content = OkHttpUtil.string(uuu, null); + JSONObject obj = new JSONObject(content); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", obj.getString("url")); + result.put("header", "{\"User-Agent\":\" Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 SE 2.X MetaSr 1.0\",\"referer\":\" https://player.duoduozy.com\",\"origin\":\" https://dp.duoduozy.com\",\"Host\":\" cache.m3u8.suoyo.cc\"}"); + } else if (playurl.contains("xfy")) { + String content = OkHttpUtil.string(playurl, null); + JSONObject obj = new JSONObject(content); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", obj.getString("url")); + result.put("header", "{\"referer\":\" appguapi.lihaoyun.top:11543\",\"User-Agent\":\" Dart/2.14 (dart:io)\"}}"); + } else if (playurl.contains("api.iopenyun.com:88")) { + if (playurl.contains("html")) { + String content = OkHttpUtil.string("https://api.m3u8.tv:5678/home/api?type=ys&uid=233711&key=dgilouvFKNRSWX2467&url=" + playurl.split("=")[1], null); + JSONObject obj = new JSONObject(content); + String ppurl = obj.getString("url"); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", ppurl); + } else { + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", playurl); + result.put("ua", "Mozilla/5.0 Windows10"); + result.put("header", "{\"Referer\":\"https://user.iopenyun.com:520/user/video/\"}"); + } + } else if (playurl.contains("cat.wkfile.com")) { + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", playurl); + result.put("header", "{\"User-Agent\":\" Lavf/58.12.100\",\"Referer\":\" wkfile.com\"}"); + } else if (!playurl.contains("=") && playurl.indexOf(".m3u8") > 15 || playurl.indexOf(".mp4") > 15 || playurl.contains("/obj/tos")) { + if (playurl.contains("hsl.ysgc.xyz")) { + String content = OkHttpUtil.string("https://jx.ysgc.xyz/?url=" + playurl, null); + JSONObject obj = new JSONObject(content); + String ppurl = obj.getString("url"); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", ppurl); + result.put("header", "{\"Referer\":\" https://ysgc.cc\"}"); + } else if (playurl.contains("1.ruifenglb.com")) { + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", playurl); + result.put("header", "{\"Referer\":\" https://1.ruifenglb.com\"}"); + } else { + Matcher matcher = Pattern.compile(".*(http.*)").matcher(playurl); + if (matcher.find()) { + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", matcher.group(1)); + } else { + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", playurl); + } + } + } else if (playurl.contains("=")) { + HashMap headers = new HashMap(); + headers.put("User-Agent", "Mozilla/5.0 Android"); + Map> respHeaders = new TreeMap<>(); + String content = OkHttpUtil.stringNoRedirect(playurl, headers, respHeaders); + String redLoc = OkHttpUtil.getRedirectLocation(respHeaders); + if (redLoc != null) { + String finalurl = ""; + while (redLoc != null) { + finalurl = redLoc; + if (redLoc.indexOf(".mp4") > 30) { + break; + } else { + headers.put("User-Agent", "Mozilla/5.0 Android"); + content = OkHttpUtil.stringNoRedirect(finalurl, headers, respHeaders); + redLoc = OkHttpUtil.getRedirectLocation(respHeaders); + } + } + String realurl = finalurl; + if (realurl.contains("=http") || realurl.contains("url=")) { + if (content.contains(" 1) { + String realurl = jsonUrl; + if (playurl.contains("mgtv.com")) { + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", realurl); + result.put("header", "{\"User-Agent\":\" Mozilla/5.0\", \"Referer\":\" \"}"); + } else if (playurl.contains("bilibili.com")) { + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", realurl); + } else { + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", realurl); + } + } else if (playurl.split("url=")[1].contains("http")) { + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", "http://1.117.152.239:39000/?url=" + playurl.split("url=")[1]); + } else if (playurl.split("url=")[1].contains("renrenmi")) { + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", "http://www.1080kan.cc/jiexi/rrmi.php?url=" + playurl.split("url=")[1]); + result.put("header", "{\"Referer\":\"http://www.1080kan.cc/\"}"); + } else { + String id = playurl.split("url=")[1]; + /* + String uuu = "https://vip.gaotian.love/api/?key=sRy0QAq8hqXRlrEtrq&url=" + id; + content = OkHttpUtil.string(uuu, null); + JSONObject obj = new JSONObject(content); + String realurl = obj.optString("url", ""); + if (realurl.isEmpty()) + realurl = obj.optString("msg", ""); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", realurl); + */ + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", "https://jx.banyung.xyz:7799/player/?url=" + playurl.split("url=")[1]); + } + } + } + } else { + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", playurl); + } + } else { + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", uu); + } + } + + @Override + public boolean manualVideoCheck() { + return true; + } + + @Override + public boolean isVideoFormat(String url) { + return Misc.isVideoFormat(url); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/AppYsV2.java b/app/src/main/java/com/github/catvod/spider/AppYsV2.java new file mode 100644 index 0000000..08fb0a5 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/AppYsV2.java @@ -0,0 +1,845 @@ +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 java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * M浏览器中的App影视 + *

+ * Author: 群友 不负此生 + */ +public class AppYsV2 extends Spider { + + @Override + public void init(Context context, String extend) { + super.init(context, extend); + try { + extInfos = extend.split("###"); + } catch (Throwable th) { + } + } + + @Override + public String homeContent(boolean filter) { + try { + String url = getCateUrl(getApiUrl()); + JSONArray jsonArray = null; + if (!url.isEmpty()) { + SpiderDebug.log(url); + String json = desc(OkHttpUtil.string(url, getHeaders(url)), (byte) 0); + JSONObject obj = new JSONObject(json); + if (obj.has("list") && obj.get("list") instanceof JSONArray) { + jsonArray = obj.getJSONArray("list"); + } else if (obj.has("data") && obj.get("data") instanceof JSONObject && obj.getJSONObject("data").has("list") && obj.getJSONObject("data").get("list") instanceof JSONArray) { + jsonArray = obj.getJSONObject("data").getJSONArray("list"); + } else if (obj.has("data") && obj.get("data") instanceof JSONArray) { + jsonArray = obj.getJSONArray("data"); + } + } else { // 通过filter列表读分类 + String filterStr = getFilterTypes(url, null); + String[] classes = filterStr.split("\n")[0].split("\\+"); + jsonArray = new JSONArray(); + for (int i = 1; i < classes.length; i++) { + String[] kv = classes[i].trim().split("="); + if (kv.length < 2) + continue; + JSONObject newCls = new JSONObject(); + newCls.put("type_name", kv[0].trim()); + newCls.put("type_id", kv[1].trim()); + jsonArray.put(newCls); + } + } + JSONObject result = new JSONObject(); + JSONArray classes = new JSONArray(); + if (jsonArray != null) { + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jObj = jsonArray.getJSONObject(i); + String typeName = jObj.getString("type_name"); + if (isBan(typeName)) + continue; + String typeId = jObj.getString("type_id"); + JSONObject newCls = new JSONObject(); + newCls.put("type_id", typeId); + newCls.put("type_name", typeName); + JSONObject typeExtend = jObj.optJSONObject("type_extend"); + if (filter) { + String filterStr = getFilterTypes(url, typeExtend); + String[] filters = filterStr.split("\n"); + JSONArray filterArr = new JSONArray(); + for (int k = url.isEmpty() ? 1 : 0; k < filters.length; k++) { + String l = filters[k].trim(); + if (l.isEmpty()) + continue; + String[] oneLine = l.split("\\+"); + String type = oneLine[0].trim(); + String typeN = type; + if (type.contains("筛选")) { + type = type.replace("筛选", ""); + if (type.equals("class")) + typeN = "类型"; + else if (type.equals("area")) + typeN = "地区"; + else if (type.equals("lang")) + typeN = "语言"; + else if (type.equals("year")) + typeN = "年份"; + } + JSONObject jOne = new JSONObject(); + jOne.put("key", type); + jOne.put("name", typeN); + JSONArray valueArr = new JSONArray(); + for (int j = 1; j < oneLine.length; j++) { + JSONObject kvo = new JSONObject(); + String kv = oneLine[j].trim(); + int sp = kv.indexOf("="); + if (sp == -1) { + if (isBan(kv)) + continue; + kvo.put("n", kv); + kvo.put("v", kv); + } else { + String n = kv.substring(0, sp); + if (isBan(n)) + continue; + kvo.put("n", n.trim()); + kvo.put("v", kv.substring(sp + 1).trim()); + } + valueArr.put(kvo); + } + jOne.put("value", valueArr); + filterArr.put(jOne); + } + if (!result.has("filters")) { + result.put("filters", new JSONObject()); + } + result.getJSONObject("filters").put(typeId, filterArr); + } + classes.put(newCls); + } + } + result.put("class", classes); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public String homeVideoContent() { + try { + String apiUrl = getApiUrl(); + String url = getRecommendUrl(apiUrl); + boolean isTV = false; + if (url.isEmpty()) { + url = getCateFilterUrlPrefix(apiUrl) + "movie&page=1&area=&type=&start="; + isTV = true; + } + SpiderDebug.log(url); + String json = desc(OkHttpUtil.string(url, getHeaders(url)), (byte) 1); + JSONObject obj = new JSONObject(json); + JSONArray videos = new JSONArray(); + if (isTV) { + JSONArray jsonArray = obj.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("nextlink")); + v.put("vod_name", vObj.getString("title")); + v.put("vod_pic", vObj.getString("pic")); + v.put("vod_remarks", vObj.getString("state")); + videos.put(v); + } + } else { + ArrayList arrays = new ArrayList<>(); + findJsonArray(obj, "vlist", arrays); + if (arrays.isEmpty()) { + findJsonArray(obj, "vod_list", arrays); + } + List ids = new ArrayList<>(); + for (JSONArray jsonArray : arrays) { + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject vObj = jsonArray.getJSONObject(i); + String vid = vObj.getString("vod_id"); + if (ids.contains(vid)) + continue; + ids.add(vid); + JSONObject v = new JSONObject(); + v.put("vod_id", vid); + 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 apiUrl = getApiUrl(); + String url = getCateFilterUrlPrefix(apiUrl) + tid + getCateFilterUrlSuffix(apiUrl); + url = url.replace("#PN#", pg); + url = url.replace("筛选class", (extend != null && extend.containsKey("class")) ? extend.get("class") : ""); + url = url.replace("筛选area", (extend != null && extend.containsKey("area")) ? extend.get("area") : ""); + url = url.replace("筛选lang", (extend != null && extend.containsKey("lang")) ? extend.get("lang") : ""); + url = url.replace("筛选year", (extend != null && extend.containsKey("year")) ? extend.get("year") : ""); + url = url.replace("排序", (extend != null && extend.containsKey("排序")) ? extend.get("排序") : ""); + SpiderDebug.log(url); + String json = desc(OkHttpUtil.string(url, getHeaders(url)), (byte) 2); + JSONObject obj = new JSONObject(json); + int totalPg = Integer.MAX_VALUE; + try { + if (obj.has("totalpage") && obj.get("totalpage") instanceof Integer) { + totalPg = obj.getInt("totalpage"); + } else if (obj.has("pagecount") && obj.get("pagecount") instanceof Integer) { + totalPg = obj.getInt("pagecount"); + } else if (obj.has("data") && obj.get("data") instanceof JSONObject && + (obj.getJSONObject("data").has("total") && obj.getJSONObject("data").get("total") instanceof Integer && + obj.getJSONObject("data").has("limit") && obj.getJSONObject("data").get("limit") instanceof Integer)) { + int limit = obj.getJSONObject("data").getInt("limit"); + int total = obj.getJSONObject("data").getInt("total"); + totalPg = total % limit == 0 ? (total / limit) : (total / limit + 1); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + + JSONArray jsonArray = null; + JSONArray videos = new JSONArray(); + if (obj.has("list") && obj.get("list") instanceof JSONArray) { + jsonArray = obj.getJSONArray("list"); + } else if (obj.has("data") && obj.get("data") instanceof JSONObject && obj.getJSONObject("data").has("list") && obj.getJSONObject("data").get("list") instanceof JSONArray) { + jsonArray = obj.getJSONObject("data").getJSONArray("list"); + } else if (obj.has("data") && obj.get("data") instanceof JSONArray) { + jsonArray = obj.getJSONArray("data"); + } + if (jsonArray != null) { + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject vObj = jsonArray.getJSONObject(i); + if (vObj.has("vod_id")) { + 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); + } else { + JSONObject v = new JSONObject(); + v.put("vod_id", vObj.getString("nextlink")); + v.put("vod_name", vObj.getString("title")); + v.put("vod_pic", vObj.getString("pic")); + v.put("vod_remarks", vObj.getString("state")); + videos.put(v); + } + } + } + JSONObject result = new JSONObject(); + result.put("page", pg); + result.put("pagecount", totalPg); + result.put("limit", 90); + 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 apiUrl = getApiUrl(); + String url = getPlayUrlPrefix(apiUrl) + ids.get(0); + SpiderDebug.log(url); + String json = desc(OkHttpUtil.string(url, getHeaders(url)), (byte) 3); + JSONObject obj = new JSONObject(json); + JSONObject result = new JSONObject(); + JSONObject vod = new JSONObject(); + genPlayList(apiUrl, obj, json, vod, ids.get(0)); + 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 { + String apiUrl = getApiUrl(); + String url = getSearchUrl(apiUrl, URLEncoder.encode(key)); + //System.out.println(url); + String json = desc(OkHttpUtil.string(url, getHeaders(url)), (byte) 5); + JSONObject obj = new JSONObject(json); + JSONArray jsonArray = null; + JSONArray videos = new JSONArray(); + if (obj.has("list") && obj.get("list") instanceof JSONArray) { + jsonArray = obj.getJSONArray("list"); + } else if (obj.has("data") && obj.get("data") instanceof JSONObject && obj.getJSONObject("data").has("list") && obj.getJSONObject("data").get("list") instanceof JSONArray) { + jsonArray = obj.getJSONObject("data").getJSONArray("list"); + } else if (obj.has("data") && obj.get("data") instanceof JSONArray) { + jsonArray = obj.getJSONArray("data"); + } + if (jsonArray != null) { + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject vObj = jsonArray.getJSONObject(i); + if (vObj.has("vod_id")) { + 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); + } else { + JSONObject v = new JSONObject(); + v.put("vod_id", vObj.getString("nextlink")); + v.put("vod_name", vObj.getString("title")); + v.put("vod_pic", vObj.getString("pic")); + v.put("vod_remarks", vObj.getString("state")); + videos.put(v); + } + } + } + JSONObject result = new JSONObject(); + 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 { + ArrayList parseUrls = parseUrlMap.get(flag); + if (parseUrls == null) + parseUrls = new ArrayList<>(); + if (!parseUrls.isEmpty()) { + JSONObject result = getFinalVideo(flag, parseUrls, id); + if (result != null) + return result.toString(); + } + if (Misc.isVideoFormat(id)) { + JSONObject result = new JSONObject(); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", id); + return result.toString(); + } else { + JSONObject result = new JSONObject(); + result.put("parse", 1); + result.put("jx", "1"); + result.put("url", id); + return result.toString(); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + private void findJsonArray(JSONObject obj, String match, ArrayList result) { + Iterator keys = obj.keys(); + while (keys.hasNext()) { + String k = keys.next(); + try { + Object o = obj.get(k); + if (k.equals(match) && o instanceof JSONArray) + result.add((JSONArray) o); + if (o instanceof JSONObject) { + findJsonArray((JSONObject) o, match, result); + } else if (o instanceof JSONArray) { + JSONArray array = (JSONArray) o; + for (int i = 0; i < array.length(); i++) { + findJsonArray(array.getJSONObject(i), match, result); + } + } + } catch (JSONException e) { + SpiderDebug.log(e); + } + } + } + + 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 ""; + } + + private HashMap getHeaders(String URL) { + HashMap headers = new HashMap<>(); + headers.put("User-Agent", UA(URL)); + return headers; + } + + private boolean isBan(String key) { + return key.equals("伦理") || key.equals("情色") || key.equals("福利"); + } + + // M 扩展方法 + + // ######重组搜索 + private String getSearchUrl(String URL, String KEY) { + if (URL.contains(".vod")) { + if (URL.contains("iopenyun.com")) { + return URL + "/list?wd=" + KEY + "&page="; + } else { + return URL + "?wd=" + KEY + "&page="; + } + } else if (URL.contains("api.php/app") || URL.contains("xgapp")) { + return URL + "search?text=" + KEY + "&pg="; + } else if (urlPattern1.matcher(URL).find()) { + if (URL.contains("esellauto") + || URL.contains("1.14.63.101") + || URL.contains("zjys") + || URL.contains("dcd") + || URL.contains("lxue") + || URL.contains("weetai.cn") + || URL.contains("haokanju1") + || URL.contains("fit:8") + || URL.contains("zjj.life") + || URL.contains("love9989") + || URL.contains("8d8q") + || URL.contains("lk.pxun") + || URL.contains("hgyx") + || URL.contains("521x5") + || URL.contains("lxyyy") + || URL.contains("0818tv") + || URL.contains("diyoui") + || URL.contains("diliktv") + || URL.contains("ppzhu") + || URL.contains("aitesucai") + || URL.contains("zz.ci") + || URL.contains("chxjon") + || URL.contains("watchmi") + || URL.contains("vipbp") + || URL.contains("bhtv") + || URL.contains("xfykl")) { + return URL + "?ac=list&" + "wd=" + KEY + "&page="; + } else { + return URL + "?ac=list&" + "zm=" + KEY + "&page="; + } + } + return ""; + } + + // ######UA + private static final Pattern urlPattern1 = Pattern.compile("api\\.php/.*?/vod"); + private static final Pattern urlPattern2 = Pattern.compile("api\\.php/.+?\\.vod"); + private static final Pattern parsePattern = Pattern.compile("/.+\\?.+="); + private static final Pattern parsePattern1 = Pattern.compile(".*(url|v|vid|php\\?id)="); + private static final Pattern parsePattern2 = Pattern.compile("https?://[^/]*"); + + protected static final Pattern[] htmlVideoKeyMatch = new Pattern[]{ + Pattern.compile("player=new"), + Pattern.compile("

typeExtendKeys = typeExtend.keys(); + while (typeExtendKeys.hasNext()) { + String key = typeExtendKeys.next(); + if (key.equals("class") || key.equals("area") || key.equals("lang") || key.equals("year")) { + try { + str = str + "筛选" + key + "+全部=+" + typeExtend.getString(key).replace(",", "+") + "\n"; + } catch (JSONException e) { + } + } + } + } + if (URL.contains(".vod")) { + str += "\n" + "排序+全部=+最新=time+最热=hits+评分=score"; + } else if (URL.contains("api.php/app") || URL.contains("xgapp")) { + } else { + str = "分类+全部=+电影=movie+连续剧=tvplay+综艺=tvshow+动漫=comic+4K=movie_4k+体育=tiyu\n筛选class+全部=+喜剧+爱情+恐怖+动作+科幻+剧情+战争+警匪+犯罪+动画+奇幻+武侠+冒险+枪战+恐怖+悬疑+惊悚+经典+青春+文艺+微电影+古装+历史+运动+农村+惊悚+惊悚+伦理+情色+福利+三级+儿童+网络电影\n筛选area+全部=+大陆+香港+台湾+美国+英国+法国+日本+韩国+德国+泰国+印度+西班牙+加拿大+其他\n筛选year+全部=+2022+2021+2020+2019+2018+2017+2016+2015+2014+2013+2012+2011+2010+2009+2008+2007+2006+2005+2004+2003+2002+2001+2000"; + } + return str; + } + + // ######推荐地址 + String getRecommendUrl(String URL) { + if (URL.contains("api.php/app") || URL.contains("xgapp")) { + return URL + "index_video?token="; + } else if (URL.contains(".vod")) { + return URL + "/vodPhbAll"; + } else { + return ""; + } + } + + // ######播放器前缀地址 + String getPlayUrlPrefix(String URL) { + if (URL.contains("api.php/app") || URL.contains("xgapp")) { + if (URL.contains("dijiaxia")) { + URL = "https://www.dijiaxia.com/api.php/app/"; + return URL + "video_detail?id="; + } else if (URL.contains("1010dy")) { + URL = "http://www.1010dy.cc/api.php/app/"; + return URL + "video_detail?id="; + } else { + return URL + "video_detail?id="; + } + } else if (URL.contains(".vod")) { + if (URL.contains("iopenyun")) { + return URL + "/detailID?vod_id="; + } else { + return URL + "/detail?vod_id="; + } + } else { + return ""; + } + } + + // ######选集 + protected final HashMap> parseUrlMap = new HashMap<>(); + + private void genPlayList(String URL, JSONObject object, String json, JSONObject vod, String vid) throws JSONException { + ArrayList playUrls = new ArrayList<>(); + ArrayList playFlags = new ArrayList<>(); + if (URL.contains("api.php/app/")) { + JSONObject data = object.getJSONObject("data"); + vod.put("vod_id", data.optString("vod_id", vid)); + vod.put("vod_name", data.getString("vod_name")); + vod.put("vod_pic", data.getString("vod_pic")); + vod.put("type_name", data.optString("vod_class")); + vod.put("vod_year", data.optString("vod_year")); + vod.put("vod_area", data.optString("vod_area")); + vod.put("vod_remarks", data.optString("vod_remarks")); + vod.put("vod_actor", data.optString("vod_actor")); + vod.put("vod_director", data.optString("vod_director")); + vod.put("vod_content", data.optString("vod_content")); + JSONArray vodUrlWithPlayer = data.getJSONArray("vod_url_with_player"); + for (int i = 0; i < vodUrlWithPlayer.length(); i++) { + JSONObject from = vodUrlWithPlayer.getJSONObject(i); + String flag = from.optString("code").trim(); + if (flag.isEmpty()) + flag = from.getString("name").trim(); + playFlags.add(flag); + playUrls.add(from.getString("url")); + String purl = from.optString("parse_api").trim(); + ArrayList parseUrls = parseUrlMap.get(flag); + if (parseUrls == null) { + parseUrls = new ArrayList<>(); + parseUrlMap.put(flag, parseUrls); + } + if (!purl.isEmpty() && !parseUrls.contains(purl)) + parseUrls.add(purl); + } + } else if (URL.contains("xgapp")) { + JSONObject data = object.getJSONObject("data").getJSONObject("vod_info"); + vod.put("vod_id", data.optString("vod_id", vid)); + vod.put("vod_name", data.getString("vod_name")); + vod.put("vod_pic", data.getString("vod_pic")); + vod.put("type_name", data.optString("vod_class")); + vod.put("vod_year", data.optString("vod_year")); + vod.put("vod_area", data.optString("vod_area")); + vod.put("vod_remarks", data.optString("vod_remarks")); + vod.put("vod_actor", data.optString("vod_actor")); + vod.put("vod_director", data.optString("vod_director")); + vod.put("vod_content", data.optString("vod_content")); + JSONArray vodUrlWithPlayer = data.getJSONArray("vod_url_with_player"); + for (int i = 0; i < vodUrlWithPlayer.length(); i++) { + JSONObject from = vodUrlWithPlayer.getJSONObject(i); + String flag = from.optString("code").trim(); + if (flag.isEmpty()) + flag = from.getString("name").trim(); + playFlags.add(flag); + playUrls.add(from.getString("url")); + String purl = from.optString("parse_api").trim(); + ArrayList parseUrls = parseUrlMap.get(flag); + if (parseUrls == null) { + parseUrls = new ArrayList<>(); + parseUrlMap.put(flag, parseUrls); + } + if (!purl.isEmpty() && !parseUrls.contains(purl)) + parseUrls.add(purl); + } + } else if (/*urlPattern2.matcher(URL).find()*/URL.contains(".vod")) { + JSONObject data = object.getJSONObject("data"); + vod.put("vod_id", data.optString("vod_id", vid)); + vod.put("vod_name", data.getString("vod_name")); + vod.put("vod_pic", data.getString("vod_pic")); + vod.put("type_name", data.optString("vod_class")); + vod.put("vod_year", data.optString("vod_year")); + vod.put("vod_area", data.optString("vod_area")); + vod.put("vod_remarks", data.optString("vod_remarks")); + vod.put("vod_actor", data.optString("vod_actor")); + vod.put("vod_director", data.optString("vod_director")); + vod.put("vod_content", data.optString("vod_content")); + JSONArray vodUrlWithPlayer = data.getJSONArray("vod_play_list"); + for (int i = 0; i < vodUrlWithPlayer.length(); i++) { + JSONObject from = vodUrlWithPlayer.getJSONObject(i); + String flag = from.getJSONObject("player_info").optString("from").trim(); + if (flag.isEmpty()) + flag = from.getJSONObject("player_info").optString("show").trim(); + playFlags.add(flag); + playUrls.add(from.getString("url")); + try { + ArrayList parses = new ArrayList<>(); + String[] parse1 = from.getJSONObject("player_info").optString("parse").split(","); + String[] parse2 = from.getJSONObject("player_info").optString("parse2").split(","); + parses.addAll(Arrays.asList(parse1)); + parses.addAll(Arrays.asList(parse2)); + ArrayList parseUrls = parseUrlMap.get(flag); + if (parseUrls == null) { + parseUrls = new ArrayList<>(); + parseUrlMap.put(flag, parseUrls); + } + for (String purl : parses) { + if (purl.contains("http")) { + Matcher matcher = parsePattern1.matcher(purl); + if (matcher.find()) { + purl = matcher.group(0); + } + } else if (purl.contains("//")) { + Matcher matcher = parsePattern1.matcher(purl); + if (matcher.find()) { + purl = "http:" + matcher.group(0); + } + } else { + Matcher matcher = parsePattern2.matcher(URL); + if (matcher.find()) { + Matcher matcher1 = parsePattern1.matcher(URL); + if (matcher1.find()) { + purl = matcher.group(0) + matcher1.group(0); + } + } + } + purl = purl.replace("..", ".").trim(); + if (!purl.isEmpty() && !parseUrls.contains(purl)) + parseUrls.add(purl); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + } + } else if (urlPattern1.matcher(URL).find()) { + JSONObject data = object; + vod.put("vod_id", data.optString("vod_id", vid)); + vod.put("vod_name", data.getString("title")); + vod.put("vod_pic", data.getString("img_url")); + vod.put("type_name", jsonArr2Str(data.optJSONArray("type"))); + vod.put("vod_year", data.optString("pubtime")); + vod.put("vod_area", jsonArr2Str(data.optJSONArray("area"))); + vod.put("vod_remarks", data.optString("trunk")); + vod.put("vod_actor", jsonArr2Str(data.optJSONArray("actor"))); + vod.put("vod_director", jsonArr2Str(data.optJSONArray("director"))); + vod.put("vod_content", data.optString("intro")); + JSONObject playList = data.getJSONObject("videolist"); + Iterator playListKeys = playList.keys(); + while (playListKeys.hasNext()) { + String flag = playListKeys.next(); + ArrayList parseUrls = parseUrlMap.get(flag); + if (parseUrls == null) { + parseUrls = new ArrayList<>(); + parseUrlMap.put(flag, parseUrls); + } + JSONArray playListUrls = playList.getJSONArray(flag); + ArrayList urls = new ArrayList<>(); + for (int j = 0; j < playListUrls.length(); j++) { + JSONObject urlObj = playListUrls.getJSONObject(j); + String url = urlObj.getString("url"); + if (url.contains("url=")) { + int spIdx = url.indexOf("url=") + 4; + String pUrl = url.substring(0, spIdx).trim(); + if (!pUrl.isEmpty() && !parseUrls.contains(pUrl)) + parseUrls.add(pUrl); + urls.add(urlObj.getString("title") + "$" + url.substring(spIdx).trim()); + } else { + urls.add(urlObj.getString("title") + "$" + url); + } + } + playFlags.add(flag); + playUrls.add(TextUtils.join("#", urls)); + } + } + vod.put("vod_play_from", TextUtils.join("$$$", playFlags)); + vod.put("vod_play_url", TextUtils.join("$$$", playUrls)); + } + + // ######视频地址 + protected JSONObject getFinalVideo(String flag, ArrayList parseUrls, String url) throws JSONException { + String htmlPlayUrl = ""; + for (String parseUrl : parseUrls) { + if (parseUrl.isEmpty() || parseUrl.equals("null")) + continue; + String playUrl = parseUrl + url; + String content = desc(OkHttpUtil.string(playUrl, null), (byte) 4); + if (parseUrl.contains("49.233.47.42:9898")) { + + HashMap hashMap = new HashMap(); + OkHttpUtil.stringNoRedirect(playUrl,null, hashMap); + String d = OkHttpUtil.getRedirectLocation(hashMap); + JSONObject result = new JSONObject(); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", d); + return result; + } + JSONObject tryJson = null; + try { + tryJson = Misc.jsonParse(url, content); + } catch (Throwable th) { + + } + if (tryJson != null && tryJson.has("url") && tryJson.has("header")) { + tryJson.put("header", tryJson.getJSONObject("header").toString()); + return tryJson; + } + if (content.contains(" 1) { + String descFlag = extInfos[1]; + if (descFlag.equals("nftv")) { + + } + } + return src; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/Auete.java b/app/src/main/java/com/github/catvod/spider/Auete.java new file mode 100644 index 0000000..2f96e71 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Auete.java @@ -0,0 +1,540 @@ +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.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 Auete extends Spider { + private static final String siteUrl = "https://auete.com"; + private static final String siteHost = "auete.com"; + + /** + * 播放源配置 + */ + private JSONObject playerConfig; + /** + * 筛选配置 + */ + private JSONObject filterConfig; + //分类页URL规则 + private Pattern regexCategory = Pattern.compile("/(\\w+)/index.html"); + //详情页URL规则 + private Pattern regexVid = Pattern.compile("/(\\w+/\\w+/\\w+)/"); + //播放页URL规则 + private Pattern regexPlay = Pattern.compile("(/\\w+/\\w+/\\w+/play-\\d+-\\d+.html)"); + //筛选页URL规则 + //private Pattern regexPage = Pattern.compile("/\\w+/\\w+/index(\\d+).html"); + private Pattern regexPage = Pattern.compile("/index(\\d+).html"); + + @Override + public void init(Context context) { + super.init(context); + try { + playerConfig = new JSONObject("{\"byun\":{\"sh\":\"云播B线\",\"pu\":\"\",\"sn\":0,\"or\":999},\"dphd\":{\"sh\":\"云播A线\",\"pu\":\"\",\"sn\":0,\"or\":999},\"cyun\":{\"sh\":\"云播C线\",\"pu\":\"\",\"sn\":0,\"or\":999},\"dbm3u8\":{\"sh\":\"云播D线\",\"pu\":\"\",\"sn\":0,\"or\":999},\"i8i\":{\"sh\":\"云播E线\",\"pu\":\"\",\"sn\":0,\"or\":999},\"m3u8hd\":{\"sh\":\"云播F线\",\"pu\":\"https://auete.com/api/?url=\",\"sn\":1,\"or\":999},\"languang\":{\"sh\":\"云播G线\",\"pu\":\"https://auete.com/api/?url=\",\"sn\":1,\"or\":999},\"hyun\":{\"sh\":\"云播H线\",\"pu\":\"https://auete.com/api/?url=\",\"sn\":1,\"or\":999},\"kyun\":{\"sh\":\"云播K线\",\"pu\":\"https://auete.com/api/?url=\",\"sn\":1,\"or\":999},\"bpyueyu\":{\"sh\":\"云播粤语\",\"pu\":\"\",\"sn\":0,\"or\":999},\"bpguoyu\":{\"sh\":\"云播国语\",\"pu\":\"\",\"sn\":0,\"or\":999},\"lyun\":{\"sh\":\"云播L线\",\"pu\":\"https://auete.com/api/?url=\",\"sn\":1,\"or\":999},\"myun\":{\"sh\":\"云播M线\",\"pu\":\"\",\"sn\":0,\"or\":999},\"dp\":{\"sh\":\"Dplayer\",\"pu\":\"\",\"sn\":0,\"or\":999}}"); + filterConfig = new JSONObject("{\"Movie\":[{\"key\":0,\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"喜剧片\",\"v\":\"xjp\"},{\"n\":\"动作片\",\"v\":\"dzp\"},{\"n\":\"爱情片\",\"v\":\"aqp\"},{\"n\":\"科幻片\",\"v\":\"khp\"},{\"n\":\"恐怖片\",\"v\":\"kbp\"},{\"n\":\"惊悚片\",\"v\":\"jsp\"},{\"n\":\"战争片\",\"v\":\"zzp\"},{\"n\":\"剧情片\",\"v\":\"jqp\"}]}],\"Tv\":[{\"key\":0,\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"美剧\",\"v\":\"oumei\"},{\"n\":\"韩剧\",\"v\":\"hanju\"},{\"n\":\"日剧\",\"v\":\"riju\"},{\"n\":\"泰剧\",\"v\":\"yataiju\"},{\"n\":\"网剧\",\"v\":\"wangju\"},{\"n\":\"台剧\",\"v\":\"taiju\"},{\"n\":\"国产\",\"v\":\"neidi\"},{\"n\":\"港剧\",\"v\":\"tvbgj\"}]}],\"Zy\":[{\"key\":0,\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国综\",\"v\":\"guozong\"},{\"n\":\"韩综\",\"v\":\"hanzong\"},{\"n\":\"美综\",\"v\":\"meizong\"}]}],\"Dm\":[{\"key\":0,\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"动画\",\"v\":\"donghua\"},{\"n\":\"日漫\",\"v\":\"riman\"},{\"n\":\"国漫\",\"v\":\"guoman\"},{\"n\":\"美漫\",\"v\":\"meiman\"}]}],\"qita\":[{\"key\":0,\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"纪录片\",\"v\":\"Jlp\"},{\"n\":\"经典片\",\"v\":\"Jdp\"},{\"n\":\"经典剧\",\"v\":\"Jdj\"},{\"n\":\"网大电影\",\"v\":\"wlp\"},{\"n\":\"国产老电影\",\"v\":\"laodianying\"}]}]}"); + } 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[class='navbar-nav mr-auto']> li a"); + JSONArray classes = new JSONArray(); + for (Element ele : elements) { + //分类名 + String name = ele.text(); + 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("ul.threadlist").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("h2 a").attr("title"); + String cover = vod.selectFirst("a img").attr("src"); + String remark = vod.selectFirst("a button").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("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) { + // 获取分类数据的url + 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 + "/" + tid + "/" + value; + } else { + url = siteUrl + "/" + tid; + } + ; + } + } else { + url = siteUrl + "/" + tid; + } + ; + if (pg.equals("1")) { + url = url + "/index.html"; + } else { + url = url + "/index" + pg + ".html"; + } + //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("ul.pagination 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(); + //System.out.println("名称"+name); + if (page == -1 && li.hasClass("active")) { + Matcher matcher = regexPage.matcher(a.attr("href")); + if (matcher.find()) { + //System.out.println("哈哈"+matcher.group(1)); + page = Integer.parseInt(matcher.group(1)); + } else { + Elements list = doc.select("ul.threadlist li"); + if (list.size() > 0) { + page = 1; + } else { + page = 0; + } + } + } + if (name.equals("尾页")) { + Matcher matcher = regexPage.matcher(a.attr("href")); + 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("ul.threadlist li"); + for (int i = 0; i < list.size(); i++) { + Element vod = list.get(i); + String title = vod.selectFirst("h2 a").attr("title"); + String cover = vod.selectFirst("a img").attr("src"); + String remark = vod.selectFirst("a button").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", 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 url = siteUrl + "/" + 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.cover a").attr("href"); + String title = doc.selectFirst("div.cover a").attr("title"); + Elements list1 = doc.select("div.message>p"); + String desc = doc.select("div.message>p").get(list1.size() - 1).text(); + String category = "", area = "", year = "", remark = "", director = "", actor = ""; + Elements span_text_muted = doc.select("div.message>p"); + 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 { + category = text.text().split(": ")[1]; + } catch (Exception e) { + category = ""; + } + } else if (info.contains("年份")) { + try { + year = text.text().split(": ")[1]; + } catch (Exception e) { + year = ""; + } + } else if (info.contains("地区")) { + try { + area = text.text().split(": ")[1]; + } catch (Exception e) { + area = ""; + } + } else if (info.contains("影片备注")) { + try { + remark = text.text().split(": ")[1]; + } catch (Exception e) { + remark = ""; + } + } else if (info.contains("导演")) { + try { + director = text.text().split(": ")[1]; + } catch (Exception e) { + director = ""; + } + } else if (info.contains("主演")) { + try { + actor = text.text().split(": ")[1]; + } catch (Exception e) { + 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); + //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#player_list>h2"); + //System.out.println(sources.size()); + Elements sourceList = doc.select("div#player_list>ul"); + //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().split("』")[1].split(":")[0]; + 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"); + //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); + 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 + id; + Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url))); + /*取得script下面的JS变量*/ + Elements e = doc.select("div>script"); + /*循环遍历script下面的JS变量*/ + String player = ""; + String pn = ""; + JSONObject result = new JSONObject(); + for (Element element : e) { + /*取得JS变量数组*/ + String[] data = element.data().toString().split("var"); + /*取得单个JS变量*/ + for (String variable : data) { + /*过滤variable为空的数据*/ + if (variable.contains("=")) { + /*取到满足条件的JS变量*/ + if (variable.contains("now")) { + String[] kvp = variable.split("="); + player = kvp[1].replaceAll("\"", "").replaceAll(";", ""); + if (player.startsWith("base64")) { + String[] plist1 = player.split("\\("); + String[] plist2 = plist1[1].split("\\)"); + // 解码 + player = new String(Base64.decode(plist2[0].getBytes(), Base64.DEFAULT)); + //byte[] base64Data = Base64.getDecoder().decode(plist2[0]); + //player = new String(base64Data, "utf-8"); + } + if (player.startsWith("http")) { + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", player); + result.put("header", ""); + } else if (player.contains("m3u8")) { + String finalvideo = "https://datas-s8pwfqdu9yystn90fb----------------cache.haozhansou.com/" + player; + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", finalvideo); + result.put("header", ""); + + } + } + if (variable.contains("pn")) { + String[] kvp = variable.split("="); + pn = kvp[1].replaceAll("\"", "").replaceAll(";", ""); + } + } + } + if (playerConfig.has(pn)) { + JSONObject pCfg = playerConfig.getJSONObject(pn); + String videoUrl = player; + String playUrl = pCfg.getString("pu"); + result.put("parse", pCfg.getInt("sn")); + result.put("playUrl", playUrl); + result.put("url", videoUrl); + result.put("header", ""); + } + } + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + /** + * 搜索 + * + * @param key + * @param quick 是否播放页的快捷搜索 + * @return + */ + @Override + public String searchContent(String key, boolean quick) { + try { + String url = siteUrl + "/search.php?searchword=" + key; + Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url))); + JSONObject result = new JSONObject(); + + JSONArray videos = new JSONArray(); + Elements list = doc.select("div.card-body>ul>li.media"); + for (int i = 0; i < list.size(); i++) { + Element vod = list.get(i); + String title = vod.select("div.media-body>div.subject>a>span").text(); + String cover = ""; + String remark = vod.selectFirst("div.media-body>div.d-flex>div.text-muted>span").text(); + Matcher matcher = regexVid.matcher(vod.select("div.media-body>div.subject>a").attr("href")); + if (!matcher.find()) + continue; + String id = matcher.group(1); + JSONObject v = new JSONObject(); + + // 视频封面 + String vodurl = siteUrl + "/" + id + "/"; + Document voddoc = Jsoup.parse(OkHttpUtil.string(vodurl, getHeaders(vodurl))); + cover = voddoc.selectFirst("div.cover a").attr("href"); + + 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/Bili.java b/app/src/main/java/com/github/catvod/spider/Bili.java new file mode 100644 index 0000000..0accb46 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Bili.java @@ -0,0 +1,273 @@ +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 java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +public class Bili extends Spider { + + protected JSONObject ext = null; + + @Override + public void init(Context context, String extend) { + super.init(context, extend); + try { + String content = OkHttpUtil.string(extend, null); + ext = new JSONObject(content); + } catch (JSONException ex) { + ex.printStackTrace(); + } + } + + @Override + public String homeContent(boolean filter) { + JSONObject results = new JSONObject(); + try { + results.put("class", ext.getJSONArray("classes")); + if (filter) { + results.put("filters", ext.getJSONObject("filter")); + } + } catch (JSONException e) { + SpiderDebug.log(e); + } + return results.toString(); + } + + @Override + public String homeVideoContent() { + try { + JSONArray videos = new JSONArray(); + try { + String url = "https://api.bilibili.com/x/web-interface/search/type?search_type=video&keyword=窗 白噪音"; + String content = OkHttpUtil.string(url, null); + JSONObject data = new JSONObject(content).getJSONObject("data"); + JSONArray RArray = data.getJSONArray("result"); + for (int i = 0; i < RArray.length(); i++) { + JSONObject info = RArray.getJSONObject(i); + JSONObject result = new JSONObject(); + String pic = info.getString("pic"); + if (pic.startsWith("//")) { + pic = "https:" + pic; + } + result.put("vod_id", info.getString("bvid")); + String title = info.getString("title"); + Document KS = Jsoup.parse(title); + String name = KS.text(); + result.put("vod_name", name); + result.put("vod_pic", pic); + String duration = info.getString("duration"); + String words = duration.split(":")[0]; + String remark = words + "分钟"; + result.put("vod_remarks", remark); + videos.put(result); + } + } 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 = "https://api.bilibili.com/x/web-interface/search/type?search_type=video&keyword="; + 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; + String content = OkHttpUtil.string(url, null); + JSONObject data = new JSONObject(content).getJSONObject("data"); + JSONArray list = new JSONArray(); + JSONArray RSArray = data.getJSONArray("result"); + for (int i = 0; i < RSArray.length(); i++) { + JSONObject info = RSArray.getJSONObject(i); + JSONObject result = new JSONObject(); + String pic = info.getString("pic"); + if (pic.startsWith("//")) { + pic = "https:" + pic; + } + result.put("vod_id", info.getString("bvid")); + String title = info.getString("title"); + Document doc = Jsoup.parse(title); + String name = doc.text(); + result.put("vod_name", name); + result.put("vod_pic", pic); + String duration = info.getString("duration"); + String Split = duration.split(":")[0]; + String remark = Split + "分钟"; + result.put("vod_remarks", remark); + list.put(result); + } + JSONObject result = new JSONObject(); + int limit = 20; + int page = Integer.parseInt(pg); + result.put("page", page); + int pageCount = list.length() == limit ? page + 1 : page; + result.put("pagecount", pageCount); + result.put("limit", limit); + result.put("total", Integer.MAX_VALUE); + result.put("list", list); + return result.toString(); + + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + @Override + public String detailContent(List ids) { + int i = 0; + try { + String str = ids.get(0); + String sb2 = "https://api.bilibili.com/x/web-interface/archive/stat?bvid=" + str; + JSONObject jSONObject = new JSONObject(OkHttpUtil.string(sb2, null)); + JSONObject jSONObject2 = jSONObject.getJSONObject("data"); + long j = jSONObject2.getLong("aid"); + String sb4 = j + ""; + String sb6 = "https://api.bilibili.com/x/web-interface/view?aid=" + sb4; + JSONObject jSONObject3 = new JSONObject(OkHttpUtil.string(sb6, null)); + JSONObject jSONObject4 = jSONObject3.getJSONObject("data"); + JSONObject v = new JSONObject(); + v.put("vod_id", str); + String string = jSONObject4.getString("title"); + v.put("vod_name", string); + String string2 = jSONObject4.getString("pic"); + v.put("vod_pic", string2); + String string3 = jSONObject4.getString("tname"); + v.put("type_name", string3); + v.put("vod_year", ""); + v.put("vod_area", ""); + String sb7 = jSONObject4.getLong("duration") / 60 + "分钟"; + v.put("vod_remarks", sb7); + v.put("vod_actor", ""); + v.put("vod_director", ""); + String string4 = jSONObject4.getString("desc"); + v.put("vod_content", string4); + v.put("vod_play_from", "B站"); + ArrayList arrayList = new ArrayList(); + JSONArray jSONArray = jSONObject4.getJSONArray("pages"); + while (true) { + int length = jSONArray.length(); + if (i < length) { + JSONObject jSONObject6 = jSONArray.getJSONObject(i); + String string5 = jSONObject6.getString("part"); + String replace = string5.replace("$", "_").replace("#", "_"); + StringBuilder sb8 = new StringBuilder(); + sb8.append(replace); + sb8.append("$"); + sb8.append(sb4); + sb8.append("+ "); + long j2 = jSONObject6.getLong("cid"); + sb8.append(j2); + String sb9 = sb8.toString(); + arrayList.add(sb9); + i++; + } else { + v.put("vod_play_url", TextUtils.join("#", arrayList)); + JSONArray jSONArray2 = new JSONArray(); + jSONArray2.put(v); + JSONObject jSONObject7 = new JSONObject(); + jSONObject7.put("list", jSONArray2); + return jSONObject7.toString(); + } + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + @Override + public String playerContent(String str, String str2, List list) { + try { + String[] split = str2.split("\\+"); + String str3 = split[0]; + String str4 = split[1]; + String sb2 = "https://api.bilibili.com/x/player/playurl?avid=" + str3 + "&cid= " + str4 + "&qn=120&fourk=1"; + JSONObject jSONObject = new JSONObject(OkHttpUtil.string(sb2, null)); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("parse", "0"); + jSONObject2.put("playUrl", ""); + JSONObject jSONObject3 = jSONObject.getJSONObject("data"); + JSONObject jSONObject4 = jSONObject3.getJSONArray("durl").getJSONObject(0); + String string = jSONObject4.getString("url"); + jSONObject2.put("url", string); + jSONObject2.put("header", "{\"Referer\":\"https://www.bilibili.com\",\"User-Agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36\"}"); + jSONObject2.put("contentType", "video/x-flv"); + return jSONObject2.toString(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + @Override + public String searchContent(String key, boolean quick) { + try { + JSONObject result = new JSONObject(); + String url = "https://api.bilibili.com/x/web-interface/search/type?search_type=video&keyword=" + URLEncoder.encode(key); + String content = OkHttpUtil.string(url, null); + JSONObject data = new JSONObject(content).getJSONObject("data"); + JSONArray videos = new JSONArray(); + JSONArray RSArray = data.getJSONArray("result"); + for (int i = 0; i < RSArray.length(); i++) { + JSONObject info = RSArray.getJSONObject(i); + JSONObject v = new JSONObject(); + String pic = info.getString("pic"); + if (pic.startsWith("//")) { + pic = "https:" + pic; + } + v.put("vod_id", info.getString("bvid")); + String title = info.getString("title"); + Document doc = Jsoup.parse(title); + String name = doc.text(); + v.put("vod_name", name); + v.put("vod_pic", pic); + String duration = info.getString("duration"); + String Split = duration.split(":")[0]; + String remark = Split + "分钟"; + v.put("vod_remarks", remark); + videos.put(v); + } + result.put("list", videos); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/Cokemv.java b/app/src/main/java/com/github/catvod/spider/Cokemv.java new file mode 100644 index 0000000..fc82c81 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Cokemv.java @@ -0,0 +1,467 @@ +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; + +import okhttp3.Headers; + +public class Cokemv extends Spider { + private static final String siteUrl = "https://cokemv.me"; + private static final String siteHost = "cokemv.me"; + + /** + * 播放源配置 + */ + 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("{\"cokemv0555\":{\"sh\":\"COKEMV\",\"pu\":\"\",\"sn\":0,\"or\":999},\"cokeqie01\":{\"sh\":\"極速路線\",\"pu\":\"\",\"sn\":0,\"or\":999},\"xin\":{\"sh\":\"高速路線\",\"pu\":\"\",\"sn\":0,\"or\":999},\"90mm\":{\"sh\":\"藍光號路\",\"pu\":\"\",\"sn\":0,\"or\":999},\"age01\":{\"sh\":\"動漫一線\",\"pu\":\"\",\"sn\":0,\"or\":999},\"age02\":{\"sh\":\"動漫二線\",\"pu\":\"\",\"sn\":0,\"or\":999},\"mahua\":{\"sh\":\"海外(禁國內)\",\"pu\":\"\",\"sn\":0,\"or\":999},\"toutiao\":{\"sh\":\"蓝光不卡\",\"pu\":\"\",\"sn\":0,\"or\":999}}"); + filterConfig = new JSONObject("{\"5\":[{\"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\":\"微電影\"}]},{\"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\"}]},{\"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\":5,\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"},{\"n\":\"0-9\",\"v\":\"0-9\"}]},{\"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\":\"20\"},{\"n\":\"台湾剧\",\"v\":\"21\"},{\"n\":\"泰国剧\",\"v\":\"22\"}]},{\"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\":\"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\"}]},{\"key\":4,\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":5,\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"},{\"n\":\"0-9\",\"v\":\"0-9\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"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\":\"23\"},{\"n\":\"奇幻片\",\"v\":\"24\"},{\"n\":\"悬疑片\",\"v\":\"25\"},{\"n\":\"记录片\",\"v\":\"27\"}]},{\"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\"}]},{\"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\":5,\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"},{\"n\":\"0-9\",\"v\":\"0-9\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"4\":[{\"key\":0,\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"4\"},{\"n\":\"动画电影\",\"v\":\"41\"}]},{\"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\":\"中国台湾\"},{\"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\"}]},{\"key\":4,\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":5,\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"},{\"n\":\"0-9\",\"v\":\"0-9\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"3\":[{\"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\"}]},{\"key\":4,\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":5,\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"},{\"n\":\"0-9\",\"v\":\"0-9\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}]}"); + } catch (JSONException e) { + SpiderDebug.log(e); + } + } + + 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("Referer", siteUrl); + return headers; + } + + /** + * 爬虫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.navbar-items>li.navbar-item>a"); + JSONArray classes = new JSONArray(); + for (Element ele : elements) { + String name = ele.text(); + 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.module-main").get(0); + Elements list = homeList.select("div.module-items>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.selectFirst("img.lazyload").attr("data-original"); + String remark = vod.selectFirst("div.module-item-note").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) + ".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("div[id=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("a"); + if (a == null) + continue; + String span = doc.select("span.page-current").text(); + String wy = doc.select("div[id=page] 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).split("-")[8]); + } else { + pageCount = 0; + } + break; + + } + } + JSONArray videos = new JSONArray(); + if (!html.contains("没有找到您想要的结果哦")) { + // 取当前分类页的视频列表 + Elements list = doc.select("div.module-main>div.module-items>a"); + for (int i = 0; i < list.size(); i++) { + Element vod = list.get(i); + String title = vod.attr("title"); + String cover = vod.selectFirst("img.lazyload").attr("data-original"); + String remark = vod.selectFirst("div.module-item-note").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) + ".html"; + Document doc = Jsoup.parse(OkHttpUtil.string(url, Headers())); + JSONObject result = new JSONObject(); + JSONObject vodList = new JSONObject(); + + // 取基本数据 + Elements sourcediv = doc.select("div.module-item-cover>div"); + String cover = sourcediv.get(0).select("div.module-item-pic>img").attr("data-original"); + String title = sourcediv.get(0).select("div.module-item-pic>img").attr("alt"); + String category = "", area = "", year = "", remark = "", director = "", actor = "", desc = ""; + Elements data = doc.select("div.module-info-tag-link"); + category = data.get(2).select("a").text(); + area = data.get(1).select("a").text(); + year = data.get(0).select("a").text(); + remark = doc.select("div.module-info-item-content").get(4).text(); + List actors = new ArrayList<>(); + Elements aa = doc.select("div.module-info-item-content").get(2).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("div.module-info-item-content").get(0).select("a"); + for (int j = 0; j < bb.size(); j++) { + directors.add(bb.get(j).text()); + } + director = TextUtils.join(",", directors); + desc = doc.selectFirst("div.module-info-introduction-content>p").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.module-tab-items-box>div>span"); + Elements sourceList = doc.select("div.module-list>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("sh").equals(sourceName)) { + sourceName = playerConfig.getJSONObject(flag).getString("sh"); + found = true; + break; + } + } + if (!found) + continue; + String playList = ""; + Elements playListA = sourceList.get(i).select("div.module-play-list-content>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://cokemv.me"); + 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 + ".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 ""; + } + + 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"); + 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%3Acokemv.me%2Fvoddetail+" + URLEncoder.encode(key); + Document docs = Jsoup.parse(OkHttpUtil.string(url, sHeaders())); + 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); + if (matcher.find()) { + + String group = matcher.group(1); + String cover = link.select("div.module-item-pic>img").attr("data-original"); + String title = link.select("div.module-item-pic>img").attr("alt"); + String remark = link.select("div.module-info-item-content").get(4).text(); + + v.put("vod_name", title); + 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 ""; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/Czsapp.java b/app/src/main/java/com/github/catvod/spider/Czsapp.java new file mode 100644 index 0000000..60f0e5a --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Czsapp.java @@ -0,0 +1,435 @@ +package com.github.catvod.spider; + +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.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 java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.StringReader; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +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; + +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 Czsapp extends Spider { + private static final Pattern Y = Pattern.compile("\"([^\"]+)\";var [\\d\\w]+=function dncry.*md5.enc.Utf8.parse\\(\"([\\d\\w]+)\".*md5.enc.Utf8.parse\\(([\\d]+)\\)"); + private static final Pattern pY = Pattern.compile("video: \\{url: \"([^\"]+)\""); + private static final Pattern m = Pattern.compile("subtitle: \\{url:\"([^\"]+\\.vtt)\""); + private static final Pattern Q = Pattern.compile("src: '([^']+\\.css)',"); + private static final Pattern Db = Pattern.compile("/movie/(\\d+).html"); + private static final Pattern I = Pattern.compile("/page/(\\d+)"); + private static final Pattern d = Pattern.compile("/v_play/(.*)\\.html"); + private static final Pattern K = Pattern.compile("var vkey = ['\"]([^'\"]+)['\"]"); + private static final Pattern Oe = Pattern.compile("var fvkey = ['\"]([^'\"]+)['\"]"); + private static final Pattern fi = Pattern.compile("var ua = ['\"]([^'\"]+)['\"]"); + private static final Pattern M = Pattern.compile("var cip = ['\"]([^'\"]+)['\"]"); + private static final Pattern X = Pattern.compile("var time = ['\"]([^'\"]+)['\"]"); + private static final Pattern a = Pattern.compile("var url = ['\"]([^'\"]+)['\"]"); + + + private String mmd5(String str) { + try { + MessageDigest messageDigest = MessageDigest.getInstance("MD5"); + messageDigest.update(str.getBytes()); + byte[] digest = messageDigest.digest(); + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + String hexString = Integer.toHexString(b & 255); + while (hexString.length() < 2) { + hexString = "0" + hexString; + } + sb.append(hexString); + } + return sb.toString(); + } catch (Exception e) { + e.printStackTrace(); + 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"); + vtt = vtt.replaceAll("<.*><.*>(.*)<.*><.*>", "$1"); + vtt = vtt.replaceAll("&(.*);", ""); + vtt = vtt.replaceAll(".*NOTE.*", ""); + 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; + } + } + + public String categoryContent(String str, String str2, boolean z, HashMap hashMap) { + try { + JSONObject jSONObject = new JSONObject(); + Document doc = Jsoup.parse(OkHttpUtil.string("https://czspp.com/" + str + "/page/" + str2, Headers())); + int parseInt = Integer.parseInt(str2); + int parseInt2 = Integer.parseInt(str2); + Matcher matcher = I.matcher(doc.select("div.pagenavi_txt > a.extend").last().attr("href")); + if (matcher.find()) { + parseInt2 = Integer.parseInt(matcher.group(1)); + } + Elements jS = doc.select("div.mi_ne_kd > ul > li"); + JSONArray jSONArray = new JSONArray(); + for (Element next : jS) { + Matcher matcher2 = Db.matcher(next.select("a").attr("href")); + if (matcher2.find()) { + String group = matcher2.group(1); + String trim = next.select("img").attr("alt").trim(); + String trim2 = next.select("img").attr("data-original").trim(); + String trim3 = next.select("div.hdinfo > span").text().trim(); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("vod_id", group); + jSONObject2.put("vod_name", trim); + jSONObject2.put("vod_pic", trim2); + jSONObject2.put("vod_remarks", trim3); + jSONArray.put(jSONObject2); + } + } + jSONObject.put("list", jSONArray); + jSONObject.put("page", parseInt); + jSONObject.put("pagecount", parseInt2); + jSONObject.put("limit", 24); + jSONObject.put("total", parseInt2 <= 1 ? jSONArray.length() : parseInt2 * 24); + return jSONObject.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } + + public String detailContent(List list) { + String str2 = ""; + try { + + JSONObject jSONObject = new JSONObject(); + JSONArray jSONArray = new JSONArray(); + JSONObject jSONObject2 = new JSONObject(); + Document doc = Jsoup.parse(OkHttpUtil.string("https://czspp.com/movie/" + list.get(0) + ".html", Headers())); + String trim = doc.select("div.moviedteail_tt > h1").text().trim(); + String pY2 = doc.select("div.dyimg > img").attr("src"); + Iterator it = doc.select("ul.moviedteail_list > li").iterator(); + String str3 = str2; + String str4 = str3; + String str5 = str4; + String str6 = str5; + String str7 = str6; + String str8 = str7; + while (it.hasNext()) { + String trim2 = it.next().text().trim(); + if (trim2.length() >= 4) { + try { + String substring = trim2.substring(0, 2); + String substring2 = trim2.substring(3); + if (substring.equals("类型")) { + str3 = substring2; + } else if (substring.equals("地区")) { + str5 = substring2; + } else if (substring.equals("年份")) { + str4 = substring2; + } else if (substring.equals("导演")) { + str8 = substring2; + } else if (substring.equals("主演")) { + str7 = substring2; + } else if (substring.equals("豆瓣")) { + str6 = substring2; + } + } catch (Exception e) { + SpiderDebug.log(e); + } + } + } + jSONObject2.put("vod_id", list.get(0)); + jSONObject2.put("vod_name", trim); + jSONObject2.put("vod_pic", pY2); + jSONObject2.put("type_name", str3); + jSONObject2.put("vod_year", str4); + jSONObject2.put("vod_area", str5); + jSONObject2.put("vod_remarks", str6); + jSONObject2.put("vod_actor", str7); + jSONObject2.put("vod_director", str8); + jSONObject2.put("vod_content", doc.select("div.yp_context").text().trim()); + jSONObject2.put("vod_play_from", "厂长资源"); + ArrayList arrayList = new ArrayList(); + for (Element next : doc.select("div.paly_list_btn > a")) { + Matcher matcher = d.matcher(next.attr("href")); + if (matcher.find()) { + arrayList.add(next.text() + "$" + matcher.group(1)); + } + } + jSONObject2.put("vod_play_url", TextUtils.join("#", arrayList)); + jSONArray.put(jSONObject2); + jSONObject.put("list", jSONArray); + return jSONObject.toString(); + } catch (Exception e3) { + }return ""; + } + + public String homeContent(boolean z) { + try { + + JSONObject jSONObject = new JSONObject(); + Document doc = Jsoup.parse(OkHttpUtil.string("https://czspp.com", Headers())); + Elements jS = doc.select(".navlist > li > a"); + JSONArray jSONArray = new JSONArray(); + for (Element next : jS) { + String pY2 = next.attr("href"); + if (pY2.length() > 1) { + String substring = pY2.substring(1); + String trim = next.text().trim(); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("type_id", substring); + jSONObject2.put("type_name", trim); + jSONArray.put(jSONObject2); + } + } + jSONObject.put("class", jSONArray); + Elements jS2 = doc.select("div.mi_ne_kd > ul > li"); + JSONArray jSONArray2 = new JSONArray(); + for (Element next2 : jS2) { + Matcher matcher = Db.matcher(next2.select("a").attr("href")); + if (matcher.find()) { + String group = matcher.group(1); + String trim2 = next2.select("img").attr("alt").trim(); + String trim3 = next2.select("img").attr("data-original").trim(); + String trim4 = next2.select("div.hdinfo > span").text().trim(); + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put("vod_id", group); + jSONObject3.put("vod_name", trim2); + jSONObject3.put("vod_pic", trim3); + jSONObject3.put("vod_remarks", trim4); + jSONArray2.put(jSONObject3); + } + } + jSONObject.put("list", jSONArray2); + return jSONObject.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } + + protected static HashMap Headers() { + 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/100.0.4896.75 Safari/537.36"); + return hashMap; + } + + + public String playerContent(String str, String str2, List list) { + String str3; + String str4; + Elements G8; + try { + String K2 = OkHttpUtil.string("https://czspp.com/v_play/" + str2 + ".html", Headers()); + Document UR = Jsoup.parse(K2); + Matcher matcher = Y.matcher(K2); + if (matcher.find()) { + String group = matcher.group(1); + String KEY = matcher.group(2); + String IV = matcher.group(3); + String str5 = AES.CBC(group, KEY, IV); + Matcher matcher2 = pY.matcher(str5); + str3 = matcher2.find() ? matcher2.group(1) : ""; + Matcher matcher3 = m.matcher(str5); + str4 = matcher3.find() ? matcher3.group(1) : ""; + } else { + str4 = ""; + str3 = str4; + } + if (TextUtils.isEmpty(str3) && (G8 = UR.select("iframe.viframe")) != null) { + String pY2 = G8.attr("src"); + if (pY2.contains("jx.xmflv.com")) { + String K3 = OkHttpUtil.string(pY2, Headers()); + Matcher matcher4 = X.matcher(K3); + if (!matcher4.find()) { + return ""; + } + String group2 = matcher4.group(1); + Matcher matcher5 = a.matcher(K3); + if (!matcher5.find()) { + return ""; + } + String group3 = matcher5.group(1); + String K4 = OkHttpUtil.string("https://jx.xmflv.com/player.php?time=" + group2 + "&url=" + group3, Headers()); + Matcher matcher6 = K.matcher(K4); + if (!matcher6.find()) { + return ""; + } + String group4 = matcher6.group(1); + Matcher matcher7 = Oe.matcher(K4); + if (!matcher7.find()) { + return ""; + } + String group5 = matcher7.group(1); + Matcher matcher8 = fi.matcher(K4); + if (!matcher8.find()) { + return ""; + } + String group6 = matcher8.group(1); + Matcher matcher9 = M.matcher(K4); + if (!matcher9.find()) { + return ""; + } + String group7 = matcher9.group(1); + Matcher matcher10 = X.matcher(K4); + if (!matcher10.find()) { + return ""; + } + String group8 = matcher10.group(1); + byte[] bytes3 = mmd5(group5).getBytes(); + byte[] bytes4 = "UVE1NTY4MDY2NQ==".getBytes(); + Cipher cipher2 = Cipher.getInstance("AES/CBC/NoPadding"); + cipher2.init(1, new SecretKeySpec(bytes3, "AES"), new IvParameterSpec(bytes4)); + String encodeToString = Base64.encodeToString(cipher2.doFinal(group5.getBytes()), 0); + OKCallBack.OKCallBackDefault callBack = new OKCallBack.OKCallBackDefault() { + + public void onResponse(Response response) { + } + + @Override + protected void onFailure(Call call, Exception exc) { + } + }; + HashMap hashMap = new HashMap(); + hashMap.put("url", group3); + hashMap.put("time", group8); + hashMap.put("ua", group6); + hashMap.put("cip", group7); + hashMap.put("vkey", group4); + hashMap.put("fvkey", encodeToString); + OkHttpUtil.post(OkHttpUtil.defaultClient(), "https://jx.xmflv.com/xmflv-1.SVG", hashMap, Headers(), callBack); + str3 = new JSONObject(callBack.getResult().body().string()).getString("url"); + } else { + Matcher matcher11 = Q.matcher(OkHttpUtil.string(pY2, Headers())); + if (matcher11.find()) { + str3 = matcher11.group(1); + } + } + } + JSONObject jSONObject = new JSONObject(); + jSONObject.put("parse", "0"); + jSONObject.put("playUrl", ""); + jSONObject.put("url", str3); + jSONObject.put("header", ""); + if (!TextUtils.isEmpty(str4)) { + jSONObject.put("subf", "/vtt/utf-8"); + jSONObject.put("subt", Proxy.localProxyUrl() + "?do=czspp&url=" + URLEncoder.encode(str4)); + } + return jSONObject.toString(); + } catch (Exception e) { + e.printStackTrace(); + SpiderDebug.log(e); + return ""; + } + } + + public String searchContent(String str, boolean z) { + try { + JSONObject jSONObject = new JSONObject(); + Elements jS = Jsoup.parse(OkHttpUtil.string("https://czspp.com/xssearch?q=" + URLEncoder.encode(str), Headers())).select("div.mi_ne_kd > ul > li"); + JSONArray jSONArray = new JSONArray(); + for (Element next : jS) { + Matcher matcher = Db.matcher(next.select("a").attr("href")); + JSONObject jSONObject2 = new JSONObject(); + if (matcher.find()) { + String group = matcher.group(1); + String trim = next.select("img").attr("alt").trim(); + if (trim.contains(str)) { + String trim2 = next.select("img").attr("src").trim(); + if (next.hasClass(".jidi")) { + String remark = next.select(".jidi span").text(); + jSONObject2.put("vod_remarks", remark); + } else { + String id = next.select("a").attr("href"); + Document doc = Jsoup.parse(OkHttpUtil.string(id, Headers())); + String remark = doc.select("ul.moviedteail_list li span").get(0).text(); + jSONObject2.put("vod_id", group); + jSONObject2.put("vod_name", trim); + jSONObject2.put("vod_pic", trim2); + jSONObject2.put("vod_remarks", remark); + jSONArray.put(jSONObject2); + } + } + } + } + jSONObject.put("list", jSONArray); + return jSONObject.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/Gitcafe.java b/app/src/main/java/com/github/catvod/spider/Gitcafe.java new file mode 100644 index 0000000..71c97ec --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Gitcafe.java @@ -0,0 +1,309 @@ +package com.github.catvod.spider; + +import android.content.Context; +import android.util.TimeUtils; + +import com.github.catvod.crawler.Spider; +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.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.json.JSONArray; +import org.json.JSONObject; + +public class Gitcafe extends Spider { + private Map a; + private List b; + private PushAgent pushAgent; + private JSONObject d; + private JSONObject Home; + + + @Override + public void init(Context context, String extend) { + super.init(context, extend); + pushAgent = new PushAgent(); + pushAgent.init(context, extend); + try { + d = new JSONObject("{\"hyds\":\"华语电视\",\"rhds\":\"日韩电视\",\"omds\":\"欧美电视\",\"qtds\":\"其他电视\",\"hydy\":\"华语电影\",\"rhdy\":\"日韩电影\",\"omdy\":\"欧美电影\",\"qtdy\":\"其他电影\",\"hydm\":\"华语动漫\",\"rhdm\":\"日韩动漫\",\"omdm\":\"欧美动漫\",\"jlp\":\"纪录片\",\"zyp\":\"综艺片\",\"jypx\":\"教育培训\",\"qtsp\":\"其他视频\",\"hyyy\":\"华语音乐\",\"rhyy\":\"日韩音乐\",\"omyy\":\"欧美音乐\",\"qtyy\":\"其他音乐\",\"kfrj\":\"娱乐软件\",\"xtrj\":\"系统软件\",\"wlrj\":\"网络软件\",\"bgrj\":\"办公软件\",\"qtrj\":\"其他软件\",\"mh\":\"漫画\",\"xs\":\"小说\",\"cbs\":\"出版书\",\"zspx\":\"知识培训\",\"qtwd\":\"其他文档\",\"bz\":\"壁纸\",\"rw\":\"人物\",\"fj\":\"风景\",\"qttp\":\"其他图片\",\"qt\":\"其他\"}"); + } catch (Exception e) { + e.printStackTrace(); + } + + ArrayList arrayList = new ArrayList(); + this.b = arrayList; + arrayList.add("hydm"); + List list = this.b; + list.add("hyds"); + List list2 = this.b; + list2.add("hydy"); + List list3 = this.b; + list3.add("omdm"); + List list4 = this.b; + list4.add("omds"); + List list5 = this.b; + list5.add("omdy"); + List list6 = this.b; + list6.add("rhdm"); + List list7 = this.b; + list7.add("rhds"); + List list8 = this.b; + list8.add("rhdy"); + List list9 = this.b; + list9.add("qtds"); + List list10 = this.b; + list10.add("qtdy"); + List list11 = this.b; + list11.add("qtsp"); + List list12 = this.b; + list12.add("jlp"); + List list13 = this.b; + list13.add("zyp"); + } + + protected HashMap LT() { + HashMap hashMap = new HashMap<>(); + hashMap.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 hashMap; + } + + @Override + public String categoryContent(String str, String str2, boolean z, HashMap hashMap) { + try { + Map allData = getAllData(this, this, this); + JSONArray jSONArray = new JSONArray(); + Set keySet = allData.keySet(); + for (String str3 : keySet) { + JSONObject jSONObject = (JSONObject) allData.get(str3); + if (jSONObject.has("cat")) { + String string = jSONObject.getString("cat"); + if (string.equals(str)) { + JSONObject jSONObject2 = new JSONObject(); + String sb2 = "https://www.aliyundrive.com/s/" + jSONObject.getString("key"); + jSONObject2.put("vod_id", sb2); + String string2 = jSONObject.getString("title"); + jSONObject2.put("vod_name", string2); + jSONObject2.put("vod_pic", "https://www.lgstatic.com/i/image2/M01/15/7E/CgoB5lysLXCADg6ZAABapAHUnQM321.jpg"); + jSONArray.put(jSONObject2); + } + } + } + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put("page", 1); + jSONObject3.put("pagecount", 1); + int length = jSONArray.length(); + jSONObject3.put("limit", length); + TimeUtils.getTimeZoneDatabaseVersion(); + int length2 = jSONArray.length(); + jSONObject3.put("total", length2); + jSONObject3.put("list", jSONArray); + return jSONObject3.toString(); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + @Override + public String detailContent(List list) { + try { + Map allData = getAllData(this, this, this); + JSONObject jSONObject = new JSONObject(pushAgent.detailContent(list)); + JSONArray jSONArray = jSONObject.getJSONArray("list"); + int i = 0; + while (true) { + if (i >= list.size()) { + break; + } + if (i >= jSONArray.length()) { + break; + } + JSONObject jSONObject2 = jSONArray.getJSONObject(i); + Pattern pattern = PushAgent.Folder; + Matcher matcher = pattern.matcher(list.get(i)); + if (matcher.find()) { + String group = matcher.group(1); + if (allData.containsKey(group)) { + JSONObject jSONObject3 = (JSONObject) allData.get(group); + jSONObject2.put("vod_pic", "https://www.lgstatic.com/i/image2/M01/15/7E/CgoB5lysLXCADg6ZAABapAHUnQM321.jpg"); + + } + } + i++; + } + return jSONObject.toString(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public synchronized Map getAllData(Object obj, Object obj2, Object obj3) { + Map map; + obj.getClass(); + obj2.getClass(); + obj3.getClass(); + synchronized (this) { + try { + if (a == null) { + HashMap hashMap = new HashMap(); + HashMap LT = LT(); + 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"); + for (int i = 0; i < jSONArray.length(); i++) { + JSONObject jSONObject = jSONArray.getJSONObject(i); + hashMap.put(jSONObject.getString("key"), jSONObject); + } + } + a = hashMap; + } + } catch (Exception e) { + e.printStackTrace(); + } + map = a; + } + return map; + } + + public JSONObject getHomeData(Object obj) { + obj.getClass(); + try { + if (Home == null) { + HashMap LT = LT(); + Home = new JSONObject(OkHttpUtil.string("https://gitcafe.net/alipaper/home.json", LT)); + } + } catch (Exception e) { + e.printStackTrace(); + } + return Home; + } + + @Override + public String homeContent(boolean z) { + String str = "https://www.lgstatic.com/i/image2/M01/15/7E/CgoB5lysLXCADg6ZAABapAHUnQM321.jpg"; + + try { + JSONObject homeData = getHomeData(this); + JSONObject jSONObject = homeData.getJSONObject("info"); + JSONArray jSONArray = jSONObject.getJSONArray("new"); + JSONArray jSONArray2 = new JSONArray(); + List list = b; + Iterator it = list.iterator(); + while (true) { + if (!it.hasNext()) { + break; + } + String next = it.next(); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("type_id", next); + JSONObject jSONObject3 = d; + String string = jSONObject3.getString(next); + jSONObject2.put("type_name", string); + jSONArray2.put(jSONObject2); + } + Map allData = getAllData(this, this, this); + JSONArray jSONArray3 = new JSONArray(); + for (int i = 0; i < jSONArray.length(); i++) { + JSONObject jSONObject4 = jSONArray.getJSONObject(i); + String string2 = jSONObject4.getString("cat"); + List list2 = b; + if (list2.contains(string2)) { + String string3 = jSONObject4.getString("key"); + if (allData.containsKey(string3)) { + JSONObject jSONObject5 = (JSONObject) allData.get(string3); + JSONObject jSONObject6 = new JSONObject(); + StringBuilder sb = new StringBuilder(); + sb.append("https://www.aliyundrive.com/s/"); + String string4 = jSONObject4.getString("key"); + sb.append(string4); + String sb2 = sb.toString(); + jSONObject6.put("vod_id", sb2); + String string5 = jSONObject4.getString("title"); + jSONObject6.put("vod_name", string5); + jSONObject6.put("vod_pic", str); + String string6 = jSONObject4.getString("date"); + jSONObject6.put("vod_remarks", string6); + jSONArray3.put(jSONObject6); + + } + JSONObject jSONObject62 = new JSONObject(); + StringBuilder sb3 = new StringBuilder(); + sb3.append("https://www.aliyundrive.com/s/"); + String string42 = jSONObject4.getString("key"); + sb3.append(string42); + String sb22 = sb3.toString(); + jSONObject62.put("vod_id", sb22); + String string52 = jSONObject4.getString("title"); + jSONObject62.put("vod_name", string52); + jSONObject62.put("vod_pic", str); + String string62 = jSONObject4.getString("date"); + jSONObject62.put("vod_remarks", string62); + jSONArray3.put(jSONObject62); + } + } + JSONObject jSONObject7 = new JSONObject(); + jSONObject7.put("class", jSONArray2); + jSONObject7.put("list", jSONArray3); + return jSONObject7.toString(); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + @Override + public String playerContent(String str, String str2, List list) { + return pushAgent.playerContent(str, str2, list); + } + + @Override + public String searchContent(String str, boolean z) { + try { + Map allData = getAllData(this, this, this); + JSONArray jSONArray = new JSONArray(); + Set keySet = allData.keySet(); + Iterator it = keySet.iterator(); + while (true) { + if (it.hasNext()) { + Object next = it.next(); + JSONObject jSONObject = (JSONObject) allData.get(next); + if (jSONObject.has("cat")) { + String string = jSONObject.getString("cat"); + List list = b; + if (list.contains(string)) { + String string2 = jSONObject.getString("title"); + if (string2.contains(str)) { + JSONObject jSONObject2 = new JSONObject(); + StringBuilder sb = new StringBuilder(); + sb.append("https://www.aliyundrive.com/s/"); + String string3 = jSONObject.getString("key"); + sb.append(string3); + String sb2 = sb.toString(); + jSONObject2.put("vod_id", sb2); + jSONObject2.put("vod_name", string2); + jSONArray.put(jSONObject2); + } + } + } + } else { + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put("list", jSONArray); + return jSONObject3.toString(); + } + } + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/IKan.java b/app/src/main/java/com/github/catvod/spider/IKan.java new file mode 100644 index 0000000..6a43855 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/IKan.java @@ -0,0 +1,234 @@ +package com.github.catvod.spider; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Base64; + +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.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.TreeMap; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import okhttp3.Call; +import okhttp3.Cookie; +import okhttp3.CookieJar; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; + +public class IKan extends AppYsV2 { + private final OkHttpClient y; + private boolean K = false; + private Context cccc = null; + + public IKan() { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + TimeUnit timeUnit = TimeUnit.SECONDS; + y = builder.readTimeout(15L, timeUnit).writeTimeout(15L, timeUnit).connectTimeout(15L, timeUnit).cookieJar(new CookieJar() { + final List Mf = new ArrayList(); + + public List loadForRequest(HttpUrl httpUrl) { + ArrayList arrayList = new ArrayList(); + ArrayList arrayList2 = new ArrayList(); + for (Cookie cookie : Mf) { + if (cookie.expiresAt() < System.currentTimeMillis()) { + arrayList.add(cookie); + } else if (cookie.matches(httpUrl)) { + arrayList2.add(cookie); + } + } + Mf.removeAll(arrayList); + return arrayList2; + } + + public void saveFromResponse(HttpUrl httpUrl, List list) { + Mf.addAll(list); + } + }).retryOnConnectionFailure(true).build(); + } + + private void S(final String str, final String str2) { + HashMap hashMap = new HashMap(); + hashMap.put("user_name", str); + hashMap.put("user_pwd", str2); + hashMap.put("user_pwd2", str2); + try { + HashMap hashMap2 = new HashMap(); + hashMap2.put("Host", "tvcms.ikan6.vip"); + hashMap2.put("User-Agent", "okhttp/3.11.0"); + OkHttpUtil.post(this.y, "http://tvcms.ikan6.vip/api.php/gctvapi.auth/register", hashMap, hashMap2, new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception exc) { + } + + public void onResponse(String str3) { + try { + if (new JSONObject(str3).optInt("code", 0) == 200) { + cccc.getSharedPreferences("spider_IKan", 0).edit().putString("user", str).putString("pwd", str2).commit(); + login(str, str2); + } + } catch (JSONException unused) { + } + } + }); + } catch (Throwable unused) { + } + } + + private void iq() { + SharedPreferences sharedPreferences = cccc.getSharedPreferences("spider_IKan", 0); + try { + String string = sharedPreferences.getString("user", null); + String string2 = sharedPreferences.getString("pwd", null); + if (!(string == null || string2 == null)) { + login(string, string2); + return; + } + } catch (Throwable unused) { + } + S(random(18), random(8)); + } + + public static String random(int i) { + Random random = new Random(); + StringBuffer stringBuffer = new StringBuffer(); + for (int i2 = 0; i2 < i; i2++) { + stringBuffer.append("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456".charAt(random.nextInt(59))); + } + return stringBuffer.toString(); + } + + + public void init(Context context) { + cccc = context; + } + + public void login(String str, String str2) { + HashMap headers = new HashMap(); + headers.put("user_name", str); + headers.put("user_pwd", str2); + try { + HashMap hashMap2 = new HashMap(); + hashMap2.put("Host", "tvcms.ikan6.vip"); + hashMap2.put("User-Agent", "okhttp/3.11.0"); + OkHttpUtil.post(y, "http://tvcms.ikan6.vip/api.php/gctvapi.auth/login", headers, hashMap2, new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception exc) { + } + + public void onResponse(String str3) { + try { + if (new JSONObject(str3).optInt("code", 0) == 200) { + K = true; + } + } catch (JSONException unused) { + } + } + }); + } catch (Throwable unused) { + } + } + + private HashMap getHeaders(String URL) { + HashMap headers = new HashMap<>(); + headers.put("User-Agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36"); + return headers; + } + + @Override + public String homeVideoContent() { + try { + String url = "http://tvcms.ikan6.vip/api.php/gctvapi.vod"; + String json = OkHttpUtil.string(url, getHeaders(url)); + JSONObject obj = new JSONObject(json); + JSONArray videos = new JSONArray(); + JSONArray jsonArray = obj.getJSONObject("data").getJSONArray("list"); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject vObj = jsonArray.getJSONObject(i); + String vid = vObj.getString("vod_id"); + JSONObject v = new JSONObject(); + v.put("vod_id", vid); + 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 playerContent(String str, String str2, List list) { + try { + if (str.equals("lekanzyw")) { + if (!K) { + iq(); + } + + JSONObject headers = new JSONObject(); + 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("Connection", " Keep-Alive"); + + String parseUrl = "https://player.4kan.top/?url=" + str2; + Document doc = Jsoup.parse(OkHttpUtil.string(parseUrl, null)); + Pattern pattern = Pattern.compile("(?<=getrandom\\S\").*?(?=\")"); + Elements allScripts = doc.select("body script"); + for (int j = 0; j < allScripts.size(); j++) { + String scContents = allScripts.get(j).html().trim(); + Matcher matcher = pattern.matcher(scContents); + if (!matcher.find()) + continue; + String players = new String(Base64.decode(matcher.group(0), Base64.DEFAULT)); + int start = players.indexOf("http"); + int end = players.lastIndexOf("key=") + 36; + String url = players.substring(start, end); + Map> respHeaders = new TreeMap<>(); + OkHttpUtil.stringNoRedirect(url, null, respHeaders); + String redLoc = OkHttpUtil.getRedirectLocation(respHeaders); + + + JSONObject result = new JSONObject(); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", redLoc); + result.put("header", headers.toString()); + return result.toString(); + + } + } + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public void init(Context context, String str) { + super.init(context, "http://tvcms.ikan6.vip/api.php/gctvapi.vod"); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/If101.java b/app/src/main/java/com/github/catvod/spider/If101.java new file mode 100644 index 0000000..4430c40 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/If101.java @@ -0,0 +1,482 @@ +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; + +public class If101 extends Spider { + private static final String siteUrl = "https://oulevod.tv"; + private static final String siteHost = "oulevod.tv"; + + /** + * 播放源配置 + */ + private JSONObject playerConfig; + /** + * 筛选配置 + */ + private JSONObject filterConfig; + private Pattern regexCategory = Pattern.compile("/index.php/vod/type/id/(\\d+).html"); + private Pattern regexVid = Pattern.compile("/index.php/vod/detail/id/(\\d+).html"); + private Pattern regexPlay = Pattern.compile("/index.php/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\":{\"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\"},{\"n\":\"悬疑\",\"v\":\"21\"},{\"n\":\"惊悚\",\"v\":\"22\"},{\"n\":\"战争\",\"v\":\"23\"},{\"n\":\"歌舞\",\"v\":\"24\"},{\"n\":\"灾难\",\"v\":\"25\"},{\"n\":\"爱情\",\"v\":\"26\"},{\"n\":\"犯罪\",\"v\":\"27\"},{\"n\":\"科幻\",\"v\":\"28\"},{\"n\":\"经典\",\"v\":\"29\"},{\"n\":\"网络电影\",\"v\":\"30\"}]},{\"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\":\"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\":\"lang\",\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"法语\",\"v\":\"法语\"},{\"n\":\"德语\",\"v\":\"德语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":\"version\",\"name\":\"版本\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"高清版\",\"v\":\"高清版\"},{\"n\":\"剧场版\",\"v\":\"剧场版\"},{\"n\":\"抢先版\",\"v\":\"抢先版\"},{\"n\":\"OVA\",\"v\":\"OVA\"},{\"n\":\"TV\",\"v\":\"TV\"},{\"n\":\"影院版\",\"v\":\"影院版\"}]},{\"key\":\"state\",\"name\":\"资源\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"正片\",\"v\":\"正片\"},{\"n\":\"预告片\",\"v\":\"预告片\"},{\"n\":\"花絮\",\"v\":\"花絮\"}]},{\"key\":\"letter\",\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"}]},{\"key\":\"by\",\"name\":\"By\",\"value\":[{\"n\":\"按最新\",\"v\":\"time\"},{\"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\":\"31\"},{\"n\":\"港剧\",\"v\":\"32\"},{\"n\":\"台剧\",\"v\":\"33\"},{\"n\":\"新马剧\",\"v\":\"34\"},{\"n\":\"其它剧\",\"v\":\"35\"}]},{\"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\":\"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\":\"lang\",\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":\"version\",\"name\":\"版本\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"高清版\",\"v\":\"高清版\"},{\"n\":\"剧场版\",\"v\":\"剧场版\"},{\"n\":\"抢先版\",\"v\":\"抢先版\"},{\"n\":\"OVA\",\"v\":\"OVA\"},{\"n\":\"TV\",\"v\":\"TV\"},{\"n\":\"影院版\",\"v\":\"影院版\"}]},{\"key\":\"state\",\"name\":\"资源\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"正片\",\"v\":\"正片\"},{\"n\":\"预告片\",\"v\":\"预告片\"},{\"n\":\"花絮\",\"v\":\"花絮\"}]},{\"key\":\"letter\",\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"}]},{\"key\":\"by\",\"name\":\"By\",\"value\":[{\"n\":\"按最新\",\"v\":\"time\"},{\"n\":\"按最热\",\"v\":\"hits\"},{\"n\":\"按评分\",\"v\":\"score\"}]}],\"3\":[{\"key\":\"tid\",\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"欧美动漫\",\"v\":\"36\"},{\"n\":\"日本动漫\",\"v\":\"37\"},{\"n\":\"韩国动漫\",\"v\":\"38\"},{\"n\":\"国产动漫\",\"v\":\"39\"},{\"n\":\"新马泰动漫\",\"v\":\"40\"},{\"n\":\"港台动漫\",\"v\":\"41\"},{\"n\":\"其他动漫\",\"v\":\"42\"}]},{\"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\":\"欧美\"}]},{\"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\":\"lang\",\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":\"letter\",\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"}]},{\"key\":\"by\",\"name\":\"By\",\"value\":[{\"n\":\"按最新\",\"v\":\"time\"},{\"n\":\"按最热\",\"v\":\"hits\"},{\"n\":\"按评分\",\"v\":\"score\"}]}],\"4\":[{\"key\":\"tid\",\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"欧美综艺\",\"v\":\"43\"},{\"n\":\"日本综艺\",\"v\":\"44\"},{\"n\":\"韩国综艺\",\"v\":\"45\"},{\"n\":\"国产综艺\",\"v\":\"46\"},{\"n\":\"新马泰综艺\",\"v\":\"47\"},{\"n\":\"港台综艺\",\"v\":\"48\"},{\"n\":\"其他综艺\",\"v\":\"49\"}]},{\"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\":\"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\":\"lang\",\"name\":\"语言\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国语\",\"v\":\"国语\"},{\"n\":\"英语\",\"v\":\"英语\"},{\"n\":\"粤语\",\"v\":\"粤语\"},{\"n\":\"闽南语\",\"v\":\"闽南语\"},{\"n\":\"韩语\",\"v\":\"韩语\"},{\"n\":\"日语\",\"v\":\"日语\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":\"version\",\"name\":\"版本\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"TV版\",\"v\":\"TV版\"},{\"n\":\"电影版\",\"v\":\"电影版\"},{\"n\":\"OVA版\",\"v\":\"OVA版\"},{\"n\":\"真人版\",\"v\":\"真人版\"}]},{\"key\":\"letter\",\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"}]},{\"key\":\"by\",\"name\":\"By\",\"value\":[{\"n\":\"按最新\",\"v\":\"time\"},{\"n\":\"按最热\",\"v\":\"hits\"},{\"n\":\"按评分\",\"v\":\"score\"}]}],\"50\":[{\"key\":\"letter\",\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"}]},{\"key\":\"by\",\"name\":\"By\",\"value\":[{\"n\":\"按最新\",\"v\":\"time\"},{\"n\":\"按最热\",\"v\":\"hits\"},{\"n\":\"按评分\",\"v\":\"score\"}]}],\"51\":[{\"key\":\"letter\",\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"}]},{\"key\":\"by\",\"name\":\"By\",\"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("div.conch-nav div ul li a"); + JSONArray classes = new JSONArray(); + for (Element ele : elements) { + String name = ele.text(); + boolean show = name.equals("电影") || + 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("ul.hl-vod-list").get(0); + Elements list = homeList.select("li.hl-list-item"); + JSONArray videos = new JSONArray(); + for (int i = 0; i < list.size(); i++) { + Element vod = list.get(i); + String title = vod.selectFirst("div.hl-item-title a").text(); + String cover = vod.selectFirst(".hl-item-thumb").attr("data-original"); + String remark = vod.selectFirst(".hl-pic-text span").text(); + Matcher matcher = regexVid.matcher(vod.selectFirst("div.hl-item-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) { + try { + String url = siteUrl + "/index.php/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.hl-page-wrap"); + 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 a.active").text(); + String wy = doc.select("ul.hl-page-wrap 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("li.hl-list-item"); + for (int i = 0; i < list.size(); i++) { + Element vod = list.get(i); + String title = vod.selectFirst("div.hl-item-title a").text(); + String cover = vod.selectFirst(".hl-item-thumb").attr("data-original"); + String remark = vod.selectFirst(".hl-pic-text span").text(); + Matcher matcher = regexVid.matcher(vod.selectFirst("div.hl-item-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 + "/index.php/vod/detail/id/" + 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("a.digg_link").attr("data-id"); + + String cover = doc.selectFirst("div.hl-dc-pic span").attr("data-original"); + String title = doc.selectFirst("h2.hl-dc-title").text(); + String desc = doc.selectFirst("span.hl-content-text em").text(); + String category = "", area = "", year = "", director = "", actor = "", remark = ""; + Elements span_text_muted = doc.select("li.hl-col-xs-12 em"); + 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 { + category = text.parent().select("a").text(); + } catch (Exception e) { + category = ""; + } + } else if (info.contains("年份")) { + try { + year = text.parent().text().split(":")[1]; + } catch (Exception e) { + year = ""; + } + } else if (info.contains("地区")) { + try { + area = text.parent().text().split(":")[1]; + } catch (Exception e) { + area = ""; + } + } else if (info.contains("上映")) { + try { + remark = text.text(); + } catch (Exception e) { + remark = ""; + } + } else if (info.contains("导演")) { + try { + director = text.parent().select("a").text(); + } catch (Exception e) { + director = ""; + } + } else if (info.contains("主演")) { + try { + actor = text.parent().select("a").text(); + } catch (Exception e) { + actor = ""; + } + } + } + + 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.hl-plays-from a"); + Elements sourceList = doc.select("div.hl-list-wrap"); + + for (int i = 0; i < sources.size(); i++) { + Element source = sources.get(i); + String sourceName = source.text(); + sourceName = sourceName.replaceAll("[^\u4E00-\u9FA5]", ""); + 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) + "/sid/" + matcher.group(2) + "/nid/" + 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 + "/index.php/vod/play/id/" + 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 ""; + } + + @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"); + if (title.contains(key)) { + 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 ""; + } + + 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/Init.java b/app/src/main/java/com/github/catvod/spider/Init.java new file mode 100644 index 0000000..3337ace --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Init.java @@ -0,0 +1,17 @@ +package com.github.catvod.spider; + + + + +import android.content.Context; + +import com.github.catvod.crawler.SpiderDebug; +import com.github.catvod.demo.MainActivity; + +public class Init { + + + public static void init(Context context) { + SpiderDebug.log("自定义爬虫代码加载成功!"); + } +} diff --git a/app/src/main/java/com/github/catvod/spider/Kuaikan.java b/app/src/main/java/com/github/catvod/spider/Kuaikan.java new file mode 100644 index 0000000..2f47a15 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Kuaikan.java @@ -0,0 +1,681 @@ +package com.github.catvod.spider; + +import android.content.Context; +import android.content.SharedPreferences; +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 java.io.ByteArrayOutputStream; +import java.security.KeyFactory; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.UUID; +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import okhttp3.Call; +import okhttp3.OkHttpClient; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +public class Kuaikan extends Spider { + private static String Cb; + private static long QH; + private static String dW; + private HashMap> Ji = new HashMap<>(); + + private void Q() { + if (System.currentTimeMillis() > QH) { + try { + JSONObject jSONObject = new JSONObject(); + long currentTimeMillis = System.currentTimeMillis() / 1000; + String f = f("bf70a456195ae394184b2e0b1b471cae1000300001dc431681b806089dac1153fb13960f87" + currentTimeMillis + "notice"); + jSONObject.put("appId", "1000300001"); + jSONObject.put("sign", f); + jSONObject.put("timestamp", currentTimeMillis); + String O = Decrypt("bf70a456195ae394", "184b2e0b1b471cae", jSONObject.toString()); + String tg = tg("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDitX/rWP6WWc3h\nDzUcfD8Hbw79yCB7rz18GEkjDapjlUVIa3P8FEQFoOchu7N+vdK6HQNsl2Bql4lv\nWOYuzRWNbLGQ7mNtMca28iCuPHck0AcJzOs9F6qruPL73eY7Ai7yvzs2IfEdyXSz\nHP/yXgEOi5ZEBfsBZEPMJw6vfHJVueuD/lh/LkoJ/gXEKMCM/pkIzGpBPd2TsIg8\nZdvOGMPy+MOnJb1Qfe0y3QQdc5VPVdZFWoWsM9RAenHmE3d1THb+uNZZZcnM1tV7\nxYgBbIhgHtXAZnWDWDRBM3xJPR3O9dfBHHt/tbyrZrSwK1IgwFgqfYm/tRbmp4y/\n1DhIF6mDAgMBAAECggEAIzDjS2gEFNiZ0a6nouVSb1f47sHq8OgR1jp619seMNkR\n6Rzs4xtON8VzO1REl47lsAgi6O9SgxlEtykIiglBqDNQGNw4SNHqM6nAEuvF3sv/\n27CYb2JGFuPdq+UVAOHk4b93dH6uS95ipA8DV97psRVP3P1EqkGjGISTjf/2S4IG\n10Q0UhP4xxiRS2iCtaIq0fbvnrChqYRlYQYpkkRCCH+Q4FNKquSsqmWyCu5yfeQM\nMek+aT9KgvmCh05UCeqC1x7xPtSneNbpJpLD5zW8CcG7EYFDtIP8b9BPDlud47ZH\n5Y4/wyQQFHHLOaniTJVvEJZ7cIoXy2gOhvgcHpNryQKBgQDxNNtXnCfVK0JYNhnU\n5WCOX9NeW9Q79HldhTM5/EqsjA5H21j5S7A/duBSRfX7iou1hyXaa2p+J7rxF9sj\nNlwHPsKhprskxXaHJ7qU84gSmwORsTQQPmtTsizGwVsM330+Q2ZROaSEfDoUqH9+\nKBKs6K+FOldcTOrCZ+ILk8werwKBgQDwnQUrKATzRThVdD6Hcgt/F/SAizDmvtiT\nVvRcGkiV3EtB5Rx8zFNJ9GWrqSAArwIxTWgfYCYsvpUjbJW02Mg0Ufj2+YhjT713\nO9yViwUq996St9eLwGQO5FDMD8FYi7bRAiZEAeAeIEeveDRsNK15++8VVJVo7b2l\nzcapp5k3bQKBgQDSiJNHRhqSet6+xgIIDGoZ+1Qv0TFPX5UrZt8OpsK7FshEOhXQ\nCxt8WZN03HHXK9fEC4GjwwxBrwYB+BOjCYiMHmCd3j0M3HoXgDrgViyYKMuVuDk8\nUG83r5ZbqVuCwfO8i/HbxddueEvtyiD2CZ47ZCIHxKOKAe0K4Mex2UBaKwKBgQDi\nrEouOelP9Kn5dyVhHENQXBTu9DIBb1FAnO5fxjMTWxFa5qhLuYHNbfxKF24atsRu\nBepNhJryFCkT0jvGv2L8Ry0wHiwqwvhO14obJ3ia3iBEQAVDlt+sV9L2KvGOpTB4\n/nlmIA4u02I1IBziw02aWYkGo0SOMUo0ZQL+2PEykQKBgAV1uqiJlWuA9uPdFFJP\nZPL2YoOuTWdWfIwIb/UdsbUuTckCgqPIqUPi3HhiVSunOgcO7HWK3GD3j8k4XEbW\nG4y+Ik0lLrWzBl728tZe1GENzTf8aapElHlUfFSM4OlrTRBsbMOsQBcJNh7QbyoZ\nBHiZZTbRUY6xUR4DGYkCOksF", "bf70a456195ae394184b2e0b1b471cae"); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("body", O); + jSONObject2.put("ticket", tg); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), "http://ctlook.facaishiyi.com/api/v1/user/login.do", jSONObject2.toString(), j(currentTimeMillis), new OKCallBack.OKCallBackString() { + @Override + public void onFailure(Call call, Exception exc) { + } + + public void onResponse(String str) { + try { + JSONObject jSONObject3 = new JSONObject(str); + String lX = Kuaikan.this.lX("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiYJ5UFjeEgeUi5ynLKhj5EMF0\n3sawTyAKoPbfUCSZZQ5QdrHhrINggrYxDtB/TWXoqSF+BJP85F0vq8B6gOqFWhK/\n1PIKe2wKlRRuZSOdUzK/3vzRHmR3J3KGrvNzvwARH8gg8xZjbsalc/gBkcVxSxGd\n8j8rJ4QhOSFh9F8B2wIDAQAB", jSONObject3.getString("ticket")); + JSONObject jSONObject4 = new JSONObject(Kuaikan.this.UO(lX.substring(0, 16), lX.substring(16, 32), jSONObject3.getString("body"))); + long unused = Kuaikan.QH = jSONObject4.getLong("duration") * 1000; + String unused2 = Kuaikan.Cb = jSONObject4.getString("data"); + Kuaikan.this.Uf(); + } catch (JSONException e) { + } + } + }); + } catch (Throwable th) { + th.printStackTrace(); + } + } + } + + public void Uf() { + try { + JSONObject jSONObject = new JSONObject(); + long currentTimeMillis = System.currentTimeMillis() / 1000; + String f = f("1000300001dc431681b806089dac1153fb13960f8700" + dW + currentTimeMillis + "notice"); + jSONObject.put("adv", 0); + jSONObject.put("appId", "1000300001"); + jSONObject.put("nav", 0); + jSONObject.put("sign", f); + jSONObject.put("timestamp", currentTimeMillis); + jSONObject.put("umId", dW); + String O = Decrypt(Cb.substring(0, 16), Cb.substring(16, 32), jSONObject.toString()); + String tg = tg("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDitX/rWP6WWc3h\nDzUcfD8Hbw79yCB7rz18GEkjDapjlUVIa3P8FEQFoOchu7N+vdK6HQNsl2Bql4lv\nWOYuzRWNbLGQ7mNtMca28iCuPHck0AcJzOs9F6qruPL73eY7Ai7yvzs2IfEdyXSz\nHP/yXgEOi5ZEBfsBZEPMJw6vfHJVueuD/lh/LkoJ/gXEKMCM/pkIzGpBPd2TsIg8\nZdvOGMPy+MOnJb1Qfe0y3QQdc5VPVdZFWoWsM9RAenHmE3d1THb+uNZZZcnM1tV7\nxYgBbIhgHtXAZnWDWDRBM3xJPR3O9dfBHHt/tbyrZrSwK1IgwFgqfYm/tRbmp4y/\n1DhIF6mDAgMBAAECggEAIzDjS2gEFNiZ0a6nouVSb1f47sHq8OgR1jp619seMNkR\n6Rzs4xtON8VzO1REl47lsAgi6O9SgxlEtykIiglBqDNQGNw4SNHqM6nAEuvF3sv/\n27CYb2JGFuPdq+UVAOHk4b93dH6uS95ipA8DV97psRVP3P1EqkGjGISTjf/2S4IG\n10Q0UhP4xxiRS2iCtaIq0fbvnrChqYRlYQYpkkRCCH+Q4FNKquSsqmWyCu5yfeQM\nMek+aT9KgvmCh05UCeqC1x7xPtSneNbpJpLD5zW8CcG7EYFDtIP8b9BPDlud47ZH\n5Y4/wyQQFHHLOaniTJVvEJZ7cIoXy2gOhvgcHpNryQKBgQDxNNtXnCfVK0JYNhnU\n5WCOX9NeW9Q79HldhTM5/EqsjA5H21j5S7A/duBSRfX7iou1hyXaa2p+J7rxF9sj\nNlwHPsKhprskxXaHJ7qU84gSmwORsTQQPmtTsizGwVsM330+Q2ZROaSEfDoUqH9+\nKBKs6K+FOldcTOrCZ+ILk8werwKBgQDwnQUrKATzRThVdD6Hcgt/F/SAizDmvtiT\nVvRcGkiV3EtB5Rx8zFNJ9GWrqSAArwIxTWgfYCYsvpUjbJW02Mg0Ufj2+YhjT713\nO9yViwUq996St9eLwGQO5FDMD8FYi7bRAiZEAeAeIEeveDRsNK15++8VVJVo7b2l\nzcapp5k3bQKBgQDSiJNHRhqSet6+xgIIDGoZ+1Qv0TFPX5UrZt8OpsK7FshEOhXQ\nCxt8WZN03HHXK9fEC4GjwwxBrwYB+BOjCYiMHmCd3j0M3HoXgDrgViyYKMuVuDk8\nUG83r5ZbqVuCwfO8i/HbxddueEvtyiD2CZ47ZCIHxKOKAe0K4Mex2UBaKwKBgQDi\nrEouOelP9Kn5dyVhHENQXBTu9DIBb1FAnO5fxjMTWxFa5qhLuYHNbfxKF24atsRu\nBepNhJryFCkT0jvGv2L8Ry0wHiwqwvhO14obJ3ia3iBEQAVDlt+sV9L2KvGOpTB4\n/nlmIA4u02I1IBziw02aWYkGo0SOMUo0ZQL+2PEykQKBgAV1uqiJlWuA9uPdFFJP\nZPL2YoOuTWdWfIwIb/UdsbUuTckCgqPIqUPi3HhiVSunOgcO7HWK3GD3j8k4XEbW\nG4y+Ik0lLrWzBl728tZe1GENzTf8aapElHlUfFSM4OlrTRBsbMOsQBcJNh7QbyoZ\nBHiZZTbRUY6xUR4DGYkCOksF", Cb); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("body", O); + jSONObject2.put("ticket", tg); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), "http://ctlook.facaishiyi.com/api/v1/user/config.do", jSONObject2.toString(), j(currentTimeMillis), new OKCallBack.OKCallBackString() { // from class: com.github.catvod.spider.Kuaikan.1 + @Override + public void onFailure(Call call, Exception exc) { + } + + public void onResponse(String str) { + try { + JSONObject jSONObject3 = new JSONObject(str); + String lX = Kuaikan.this.lX("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiYJ5UFjeEgeUi5ynLKhj5EMF0\n3sawTyAKoPbfUCSZZQ5QdrHhrINggrYxDtB/TWXoqSF+BJP85F0vq8B6gOqFWhK/\n1PIKe2wKlRRuZSOdUzK/3vzRHmR3J3KGrvNzvwARH8gg8xZjbsalc/gBkcVxSxGd\n8j8rJ4QhOSFh9F8B2wIDAQAB", jSONObject3.getString("ticket")); + JSONArray jSONArray = new JSONObject(Kuaikan.this.UO(lX.substring(0, 16), lX.substring(16, 32), jSONObject3.getString("body"))).getJSONObject("data").getJSONArray("newAnalysis"); + Kuaikan.this.Ji.clear(); + for (int i = 0; i < jSONArray.length(); i++) { + JSONObject jSONObject4 = jSONArray.getJSONObject(i); + ArrayList arrayList = new ArrayList(); + Kuaikan.this.Ji.put(jSONObject4.getString("id"), arrayList); + JSONArray jSONArray2 = jSONObject4.getJSONArray("analyses"); + for (int i2 = 0; i2 < jSONArray2.length(); i2++) { + arrayList.add(jSONArray2.getJSONObject(i2).getString("url")); + } + } + } catch (JSONException e) { + } + } + }); + } catch (Throwable th) { + th.printStackTrace(); + } + } + + public HashMap j(long j) { + HashMap hashMap = new HashMap<>(); + hashMap.put("appId", "1000300001"); + hashMap.put("version", "4"); + hashMap.put("timestamp", j + ""); + hashMap.put("token", f("1000300001dc431681b806089dac1153fb13960f874" + j + "notice")); + hashMap.put("User-Agent", "okhttp/5.0.0-alpha.2"); + return hashMap; + } + + String Decrypt(String str, String str2, String str3) { + try { + SecretKeySpec secretKeySpec = new SecretKeySpec(str.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(1, secretKeySpec, new IvParameterSpec(str2.getBytes())); + return Base64.encodeToString(cipher.doFinal(str3.getBytes()), 2); + } catch (Throwable th) { + th.printStackTrace(); + return ""; + } + } + + String UO(String str, String str2, String str3) { + try { + SecretKeySpec secretKeySpec = new SecretKeySpec(str.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(2, secretKeySpec, new IvParameterSpec(str2.getBytes())); + return new String(cipher.doFinal(Base64.decode(str3, 0)), "UTF-8"); + } catch (Throwable th) { + th.printStackTrace(); + return ""; + } + } + + public String categoryContent(String str, final String str2, boolean z, HashMap hashMap) { + try { + Q(); + int parseInt = hashMap.containsKey("areaId") ? Integer.parseInt(hashMap.get("areaId")) : 0; + int parseInt2 = hashMap.containsKey("tagId") ? Integer.parseInt(hashMap.get("tagId")) : 0; + int parseInt3 = hashMap.containsKey("yearId") ? Integer.parseInt(hashMap.get("yearId")) : 0; + JSONObject jSONObject = new JSONObject(); + long currentTimeMillis = System.currentTimeMillis() / 1000; + String f = f("1000300001dc431681b806089dac1153fb13960f87" + str2 + 18 + str + parseInt2 + parseInt + parseInt3 + currentTimeMillis + "notice"); + jSONObject.put("appId", "1000300001"); + jSONObject.put("typeId", str); + jSONObject.put("areaId", parseInt); + jSONObject.put("tagId", parseInt2); + jSONObject.put("yearId", parseInt3); + jSONObject.put("page", Integer.parseInt(str2)); + jSONObject.put("pageSize", 18); + jSONObject.put("sign", f); + jSONObject.put("timestamp", currentTimeMillis); + String O = Decrypt(Cb.substring(0, 16), Cb.substring(16, 32), jSONObject.toString()); + String tg = tg("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDitX/rWP6WWc3h\nDzUcfD8Hbw79yCB7rz18GEkjDapjlUVIa3P8FEQFoOchu7N+vdK6HQNsl2Bql4lv\nWOYuzRWNbLGQ7mNtMca28iCuPHck0AcJzOs9F6qruPL73eY7Ai7yvzs2IfEdyXSz\nHP/yXgEOi5ZEBfsBZEPMJw6vfHJVueuD/lh/LkoJ/gXEKMCM/pkIzGpBPd2TsIg8\nZdvOGMPy+MOnJb1Qfe0y3QQdc5VPVdZFWoWsM9RAenHmE3d1THb+uNZZZcnM1tV7\nxYgBbIhgHtXAZnWDWDRBM3xJPR3O9dfBHHt/tbyrZrSwK1IgwFgqfYm/tRbmp4y/\n1DhIF6mDAgMBAAECggEAIzDjS2gEFNiZ0a6nouVSb1f47sHq8OgR1jp619seMNkR\n6Rzs4xtON8VzO1REl47lsAgi6O9SgxlEtykIiglBqDNQGNw4SNHqM6nAEuvF3sv/\n27CYb2JGFuPdq+UVAOHk4b93dH6uS95ipA8DV97psRVP3P1EqkGjGISTjf/2S4IG\n10Q0UhP4xxiRS2iCtaIq0fbvnrChqYRlYQYpkkRCCH+Q4FNKquSsqmWyCu5yfeQM\nMek+aT9KgvmCh05UCeqC1x7xPtSneNbpJpLD5zW8CcG7EYFDtIP8b9BPDlud47ZH\n5Y4/wyQQFHHLOaniTJVvEJZ7cIoXy2gOhvgcHpNryQKBgQDxNNtXnCfVK0JYNhnU\n5WCOX9NeW9Q79HldhTM5/EqsjA5H21j5S7A/duBSRfX7iou1hyXaa2p+J7rxF9sj\nNlwHPsKhprskxXaHJ7qU84gSmwORsTQQPmtTsizGwVsM330+Q2ZROaSEfDoUqH9+\nKBKs6K+FOldcTOrCZ+ILk8werwKBgQDwnQUrKATzRThVdD6Hcgt/F/SAizDmvtiT\nVvRcGkiV3EtB5Rx8zFNJ9GWrqSAArwIxTWgfYCYsvpUjbJW02Mg0Ufj2+YhjT713\nO9yViwUq996St9eLwGQO5FDMD8FYi7bRAiZEAeAeIEeveDRsNK15++8VVJVo7b2l\nzcapp5k3bQKBgQDSiJNHRhqSet6+xgIIDGoZ+1Qv0TFPX5UrZt8OpsK7FshEOhXQ\nCxt8WZN03HHXK9fEC4GjwwxBrwYB+BOjCYiMHmCd3j0M3HoXgDrgViyYKMuVuDk8\nUG83r5ZbqVuCwfO8i/HbxddueEvtyiD2CZ47ZCIHxKOKAe0K4Mex2UBaKwKBgQDi\nrEouOelP9Kn5dyVhHENQXBTu9DIBb1FAnO5fxjMTWxFa5qhLuYHNbfxKF24atsRu\nBepNhJryFCkT0jvGv2L8Ry0wHiwqwvhO14obJ3ia3iBEQAVDlt+sV9L2KvGOpTB4\n/nlmIA4u02I1IBziw02aWYkGo0SOMUo0ZQL+2PEykQKBgAV1uqiJlWuA9uPdFFJP\nZPL2YoOuTWdWfIwIb/UdsbUuTckCgqPIqUPi3HhiVSunOgcO7HWK3GD3j8k4XEbW\nG4y+Ik0lLrWzBl728tZe1GENzTf8aapElHlUfFSM4OlrTRBsbMOsQBcJNh7QbyoZ\nBHiZZTbRUY6xUR4DGYkCOksF", Cb); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("body", O); + jSONObject2.put("ticket", tg); + final JSONObject jSONObject3 = new JSONObject(); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), "http://ctlook.facaishiyi.com/api/v1/search/video.do", jSONObject2.toString(), j(currentTimeMillis), new OKCallBack.OKCallBackString() { // from class: com.github.catvod.spider.Kuaikan.5 + @Override + public void onFailure(Call call, Exception exc) { + } + + public void onResponse(String str3) { + try { + JSONObject jSONObject4 = new JSONObject(str3); + String lX = Kuaikan.this.lX("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiYJ5UFjeEgeUi5ynLKhj5EMF0\n3sawTyAKoPbfUCSZZQ5QdrHhrINggrYxDtB/TWXoqSF+BJP85F0vq8B6gOqFWhK/\n1PIKe2wKlRRuZSOdUzK/3vzRHmR3J3KGrvNzvwARH8gg8xZjbsalc/gBkcVxSxGd\n8j8rJ4QhOSFh9F8B2wIDAQAB", jSONObject4.getString("ticket")); + JSONObject jSONObject5 = new JSONObject(Kuaikan.this.UO(lX.substring(0, 16), lX.substring(16, 32), jSONObject4.getString("body"))); + JSONArray jSONArray = new JSONArray(); + JSONArray jSONArray2 = jSONObject5.getJSONArray("results"); + for (int i = 0; i < jSONArray2.length(); i++) { + JSONObject jSONObject6 = jSONArray2.getJSONObject(i); + JSONObject jSONObject7 = new JSONObject(); + jSONObject7.put("vod_id", jSONObject6.getString("id")); + jSONObject7.put("vod_name", jSONObject6.getString("name")); + jSONObject7.put("vod_pic", jSONObject6.getString("pic")); + jSONObject7.put("vod_remarks", jSONObject6.getString("progress")); + jSONArray.put(jSONObject7); + } + jSONObject3.put("page", Integer.parseInt(str2)); + int i2 = jSONObject5.getInt("count"); + int i3 = 20; + jSONObject3.put("pagecount", i2 % i3 == 0 ? i2 / i3 : (i2 / i3) + 1); + jSONObject3.put("limit", i3); + jSONObject3.put("total", i2); + jSONObject3.put("list", jSONArray); + } catch (JSONException e) { + } + } + }); + return jSONObject3.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } + + public String detailContent(final List list) { + try { + Q(); + JSONObject jSONObject = new JSONObject(); + long currentTimeMillis = System.currentTimeMillis() / 1000; + String f = f("1000300001dc431681b806089dac1153fb13960f87" + list.get(0) + currentTimeMillis + "notice"); + jSONObject.put("appId", "1000300001"); + jSONObject.put("id", list.get(0)); + jSONObject.put("sign", f); + jSONObject.put("timestamp", currentTimeMillis); + String O = Decrypt(Cb.substring(0, 16), Cb.substring(16, 32), jSONObject.toString()); + String tg = tg("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDitX/rWP6WWc3h\nDzUcfD8Hbw79yCB7rz18GEkjDapjlUVIa3P8FEQFoOchu7N+vdK6HQNsl2Bql4lv\nWOYuzRWNbLGQ7mNtMca28iCuPHck0AcJzOs9F6qruPL73eY7Ai7yvzs2IfEdyXSz\nHP/yXgEOi5ZEBfsBZEPMJw6vfHJVueuD/lh/LkoJ/gXEKMCM/pkIzGpBPd2TsIg8\nZdvOGMPy+MOnJb1Qfe0y3QQdc5VPVdZFWoWsM9RAenHmE3d1THb+uNZZZcnM1tV7\nxYgBbIhgHtXAZnWDWDRBM3xJPR3O9dfBHHt/tbyrZrSwK1IgwFgqfYm/tRbmp4y/\n1DhIF6mDAgMBAAECggEAIzDjS2gEFNiZ0a6nouVSb1f47sHq8OgR1jp619seMNkR\n6Rzs4xtON8VzO1REl47lsAgi6O9SgxlEtykIiglBqDNQGNw4SNHqM6nAEuvF3sv/\n27CYb2JGFuPdq+UVAOHk4b93dH6uS95ipA8DV97psRVP3P1EqkGjGISTjf/2S4IG\n10Q0UhP4xxiRS2iCtaIq0fbvnrChqYRlYQYpkkRCCH+Q4FNKquSsqmWyCu5yfeQM\nMek+aT9KgvmCh05UCeqC1x7xPtSneNbpJpLD5zW8CcG7EYFDtIP8b9BPDlud47ZH\n5Y4/wyQQFHHLOaniTJVvEJZ7cIoXy2gOhvgcHpNryQKBgQDxNNtXnCfVK0JYNhnU\n5WCOX9NeW9Q79HldhTM5/EqsjA5H21j5S7A/duBSRfX7iou1hyXaa2p+J7rxF9sj\nNlwHPsKhprskxXaHJ7qU84gSmwORsTQQPmtTsizGwVsM330+Q2ZROaSEfDoUqH9+\nKBKs6K+FOldcTOrCZ+ILk8werwKBgQDwnQUrKATzRThVdD6Hcgt/F/SAizDmvtiT\nVvRcGkiV3EtB5Rx8zFNJ9GWrqSAArwIxTWgfYCYsvpUjbJW02Mg0Ufj2+YhjT713\nO9yViwUq996St9eLwGQO5FDMD8FYi7bRAiZEAeAeIEeveDRsNK15++8VVJVo7b2l\nzcapp5k3bQKBgQDSiJNHRhqSet6+xgIIDGoZ+1Qv0TFPX5UrZt8OpsK7FshEOhXQ\nCxt8WZN03HHXK9fEC4GjwwxBrwYB+BOjCYiMHmCd3j0M3HoXgDrgViyYKMuVuDk8\nUG83r5ZbqVuCwfO8i/HbxddueEvtyiD2CZ47ZCIHxKOKAe0K4Mex2UBaKwKBgQDi\nrEouOelP9Kn5dyVhHENQXBTu9DIBb1FAnO5fxjMTWxFa5qhLuYHNbfxKF24atsRu\nBepNhJryFCkT0jvGv2L8Ry0wHiwqwvhO14obJ3ia3iBEQAVDlt+sV9L2KvGOpTB4\n/nlmIA4u02I1IBziw02aWYkGo0SOMUo0ZQL+2PEykQKBgAV1uqiJlWuA9uPdFFJP\nZPL2YoOuTWdWfIwIb/UdsbUuTckCgqPIqUPi3HhiVSunOgcO7HWK3GD3j8k4XEbW\nG4y+Ik0lLrWzBl728tZe1GENzTf8aapElHlUfFSM4OlrTRBsbMOsQBcJNh7QbyoZ\nBHiZZTbRUY6xUR4DGYkCOksF", Cb); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("body", O); + jSONObject2.put("ticket", tg); + final JSONObject jSONObject3 = new JSONObject(); + OkHttpClient QH2 = OkHttpUtil.defaultClient(); + OkHttpUtil.postJson(QH2, "http://ctlook.facaishiyi.com/api/v1/video/play/" + list.get(0) + ".do ", jSONObject2.toString(), j(currentTimeMillis), new OKCallBack.OKCallBackString() { // from class: com.github.catvod.spider.Kuaikan.6 + @Override + public void onFailure(Call call, Exception exc) { + } + + public void onResponse(String str) { + try { + JSONObject jSONObject4 = new JSONObject(str); + String lX = Kuaikan.this.lX("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiYJ5UFjeEgeUi5ynLKhj5EMF0\n3sawTyAKoPbfUCSZZQ5QdrHhrINggrYxDtB/TWXoqSF+BJP85F0vq8B6gOqFWhK/\n1PIKe2wKlRRuZSOdUzK/3vzRHmR3J3KGrvNzvwARH8gg8xZjbsalc/gBkcVxSxGd\n8j8rJ4QhOSFh9F8B2wIDAQAB", jSONObject4.getString("ticket")); + JSONObject jSONObject5 = new JSONObject(Kuaikan.this.UO(lX.substring(0, 16), lX.substring(16, 32), jSONObject4.getString("body"))).getJSONObject("data"); + JSONArray jSONArray = new JSONArray(); + JSONObject jSONObject6 = new JSONObject(); + jSONObject6.put("vod_id", jSONObject5.getString("id")); + jSONObject6.put("vod_name", jSONObject5.getString("name")); + jSONObject6.put("vod_pic", jSONObject5.getString("pic")); + jSONObject6.put("vod_year", jSONObject5.getString("year")); + jSONObject6.put("vod_remarks", jSONObject5.getString("progress")); + jSONObject6.put("vod_actor", jSONObject5.getString("actor")); + jSONObject6.put("vod_director", jSONObject5.getString("director")); + jSONObject6.put("vod_content", jSONObject5.getString("content").trim()); + JSONArray jSONArray2 = new JSONArray(Kuaikan.this.UO("5551e2a82a21a9a1", "a586c5236206a2cb", jSONObject5.getString("newPlayback"))); + LinkedHashMap linkedHashMap = new LinkedHashMap(); + for (int i = 0; i < jSONArray2.length(); i++) { + JSONObject jSONObject7 = jSONArray2.getJSONObject(i); + String string = jSONObject7.getString("name"); + String string2 = jSONObject7.getString("id"); + JSONArray jSONArray3 = jSONObject7.getJSONArray("episodes"); + ArrayList arrayList = new ArrayList(); + for (int i2 = 0; i2 < jSONArray3.length(); i2++) { + JSONObject jSONObject8 = jSONArray3.getJSONObject(i2); + String string3 = jSONObject8.getString("title"); + StringBuilder sb = new StringBuilder(); + sb.append(string3); + sb.append("|"); + sb.append((String) list.get(0)); + sb.append("|"); + sb.append(string2); + sb.append("|"); + sb.append(jSONObject8.getString("url")); + String encodeToString = Base64.encodeToString(sb.toString().getBytes("UTF-8"), 10); + arrayList.add(string3 + "$" + encodeToString); + } + linkedHashMap.put(string, TextUtils.join("#", arrayList)); + } + String join = TextUtils.join("$$$", linkedHashMap.keySet()); + String join2 = TextUtils.join("$$$", linkedHashMap.values()); + jSONObject6.put("vod_play_from", join); + jSONObject6.put("vod_play_url", join2); + jSONArray.put(jSONObject6); + jSONObject3.put("list", jSONArray); + } catch (Throwable th) { + } + } + }); + return jSONObject3.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } + + String f(String str) { + try { + byte[] digest = MessageDigest.getInstance("MD5").digest(str.getBytes()); + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + String hexString = Integer.toHexString(b & 255); + if (hexString.length() < 2) { + sb.append(0); + } + sb.append(hexString); + } + return sb.toString().toLowerCase(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return ""; + } + } + + public String homeContent(boolean z) { + try { + Q(); + JSONObject jSONObject = new JSONObject(); + long currentTimeMillis = System.currentTimeMillis() / 1000; + String f = f("1000300001dc431681b806089dac1153fb13960f87" + currentTimeMillis + "notice"); + jSONObject.put("appId", "1000300001"); + jSONObject.put("sign", f); + jSONObject.put("timestamp", currentTimeMillis); + String O = Decrypt(Cb.substring(0, 16), Cb.substring(16, 32), jSONObject.toString()); + String tg = tg("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDitX/rWP6WWc3h\nDzUcfD8Hbw79yCB7rz18GEkjDapjlUVIa3P8FEQFoOchu7N+vdK6HQNsl2Bql4lv\nWOYuzRWNbLGQ7mNtMca28iCuPHck0AcJzOs9F6qruPL73eY7Ai7yvzs2IfEdyXSz\nHP/yXgEOi5ZEBfsBZEPMJw6vfHJVueuD/lh/LkoJ/gXEKMCM/pkIzGpBPd2TsIg8\nZdvOGMPy+MOnJb1Qfe0y3QQdc5VPVdZFWoWsM9RAenHmE3d1THb+uNZZZcnM1tV7\nxYgBbIhgHtXAZnWDWDRBM3xJPR3O9dfBHHt/tbyrZrSwK1IgwFgqfYm/tRbmp4y/\n1DhIF6mDAgMBAAECggEAIzDjS2gEFNiZ0a6nouVSb1f47sHq8OgR1jp619seMNkR\n6Rzs4xtON8VzO1REl47lsAgi6O9SgxlEtykIiglBqDNQGNw4SNHqM6nAEuvF3sv/\n27CYb2JGFuPdq+UVAOHk4b93dH6uS95ipA8DV97psRVP3P1EqkGjGISTjf/2S4IG\n10Q0UhP4xxiRS2iCtaIq0fbvnrChqYRlYQYpkkRCCH+Q4FNKquSsqmWyCu5yfeQM\nMek+aT9KgvmCh05UCeqC1x7xPtSneNbpJpLD5zW8CcG7EYFDtIP8b9BPDlud47ZH\n5Y4/wyQQFHHLOaniTJVvEJZ7cIoXy2gOhvgcHpNryQKBgQDxNNtXnCfVK0JYNhnU\n5WCOX9NeW9Q79HldhTM5/EqsjA5H21j5S7A/duBSRfX7iou1hyXaa2p+J7rxF9sj\nNlwHPsKhprskxXaHJ7qU84gSmwORsTQQPmtTsizGwVsM330+Q2ZROaSEfDoUqH9+\nKBKs6K+FOldcTOrCZ+ILk8werwKBgQDwnQUrKATzRThVdD6Hcgt/F/SAizDmvtiT\nVvRcGkiV3EtB5Rx8zFNJ9GWrqSAArwIxTWgfYCYsvpUjbJW02Mg0Ufj2+YhjT713\nO9yViwUq996St9eLwGQO5FDMD8FYi7bRAiZEAeAeIEeveDRsNK15++8VVJVo7b2l\nzcapp5k3bQKBgQDSiJNHRhqSet6+xgIIDGoZ+1Qv0TFPX5UrZt8OpsK7FshEOhXQ\nCxt8WZN03HHXK9fEC4GjwwxBrwYB+BOjCYiMHmCd3j0M3HoXgDrgViyYKMuVuDk8\nUG83r5ZbqVuCwfO8i/HbxddueEvtyiD2CZ47ZCIHxKOKAe0K4Mex2UBaKwKBgQDi\nrEouOelP9Kn5dyVhHENQXBTu9DIBb1FAnO5fxjMTWxFa5qhLuYHNbfxKF24atsRu\nBepNhJryFCkT0jvGv2L8Ry0wHiwqwvhO14obJ3ia3iBEQAVDlt+sV9L2KvGOpTB4\n/nlmIA4u02I1IBziw02aWYkGo0SOMUo0ZQL+2PEykQKBgAV1uqiJlWuA9uPdFFJP\nZPL2YoOuTWdWfIwIb/UdsbUuTckCgqPIqUPi3HhiVSunOgcO7HWK3GD3j8k4XEbW\nG4y+Ik0lLrWzBl728tZe1GENzTf8aapElHlUfFSM4OlrTRBsbMOsQBcJNh7QbyoZ\nBHiZZTbRUY6xUR4DGYkCOksF", Cb); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("body", O); + jSONObject2.put("ticket", tg); + final JSONObject jSONObject3 = new JSONObject(); + final JSONArray jSONArray = new JSONArray(); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), "http://ctlook.facaishiyi.com/api/v1/user/genres.do", jSONObject2.toString(), j(currentTimeMillis), new OKCallBack.OKCallBackString() { // from class: com.github.catvod.spider.Kuaikan.3 + @Override + public void onFailure(Call call, Exception exc) { + } + + public void onResponse(String str) { + try { + JSONObject jSONObject4 = new JSONObject(str); + String lX = Kuaikan.this.lX("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiYJ5UFjeEgeUi5ynLKhj5EMF0\n3sawTyAKoPbfUCSZZQ5QdrHhrINggrYxDtB/TWXoqSF+BJP85F0vq8B6gOqFWhK/\n1PIKe2wKlRRuZSOdUzK/3vzRHmR3J3KGrvNzvwARH8gg8xZjbsalc/gBkcVxSxGd\n8j8rJ4QhOSFh9F8B2wIDAQAB", jSONObject4.getString("ticket")); + JSONArray jSONArray2 = new JSONObject(Kuaikan.this.UO(lX.substring(0, 16), lX.substring(16, 32), jSONObject4.getString("body"))).getJSONArray("genres"); + for (int i = 0; i < jSONArray2.length(); i++) { + JSONObject jSONObject5 = jSONArray2.getJSONObject(i); + String string = jSONObject5.getString("name"); + final int i2 = jSONObject5.getInt("typeId"); + if (i2 > 0) { + JSONObject jSONObject6 = new JSONObject(); + jSONObject6.put("type_id", i2 + ""); + jSONObject6.put("type_name", string); + jSONArray.put(jSONObject6); + JSONObject jSONObject7 = new JSONObject(); + long currentTimeMillis2 = System.currentTimeMillis() / 1000; + Kuaikan kuaikan = Kuaikan.this; + String f2 = kuaikan.f("1000300001dc431681b806089dac1153fb13960f87" + i2 + currentTimeMillis2 + "notice"); + jSONObject7.put("appId", "1000300001"); + jSONObject7.put("tid", i2); + jSONObject7.put("sign", f2); + jSONObject7.put("timestamp", currentTimeMillis2); + String O2 = Kuaikan.this.Decrypt(Kuaikan.Cb.substring(0, 16), Kuaikan.Cb.substring(16, 32), jSONObject7.toString()); + String tg2 = Kuaikan.this.tg("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDitX/rWP6WWc3h\nDzUcfD8Hbw79yCB7rz18GEkjDapjlUVIa3P8FEQFoOchu7N+vdK6HQNsl2Bql4lv\nWOYuzRWNbLGQ7mNtMca28iCuPHck0AcJzOs9F6qruPL73eY7Ai7yvzs2IfEdyXSz\nHP/yXgEOi5ZEBfsBZEPMJw6vfHJVueuD/lh/LkoJ/gXEKMCM/pkIzGpBPd2TsIg8\nZdvOGMPy+MOnJb1Qfe0y3QQdc5VPVdZFWoWsM9RAenHmE3d1THb+uNZZZcnM1tV7\nxYgBbIhgHtXAZnWDWDRBM3xJPR3O9dfBHHt/tbyrZrSwK1IgwFgqfYm/tRbmp4y/\n1DhIF6mDAgMBAAECggEAIzDjS2gEFNiZ0a6nouVSb1f47sHq8OgR1jp619seMNkR\n6Rzs4xtON8VzO1REl47lsAgi6O9SgxlEtykIiglBqDNQGNw4SNHqM6nAEuvF3sv/\n27CYb2JGFuPdq+UVAOHk4b93dH6uS95ipA8DV97psRVP3P1EqkGjGISTjf/2S4IG\n10Q0UhP4xxiRS2iCtaIq0fbvnrChqYRlYQYpkkRCCH+Q4FNKquSsqmWyCu5yfeQM\nMek+aT9KgvmCh05UCeqC1x7xPtSneNbpJpLD5zW8CcG7EYFDtIP8b9BPDlud47ZH\n5Y4/wyQQFHHLOaniTJVvEJZ7cIoXy2gOhvgcHpNryQKBgQDxNNtXnCfVK0JYNhnU\n5WCOX9NeW9Q79HldhTM5/EqsjA5H21j5S7A/duBSRfX7iou1hyXaa2p+J7rxF9sj\nNlwHPsKhprskxXaHJ7qU84gSmwORsTQQPmtTsizGwVsM330+Q2ZROaSEfDoUqH9+\nKBKs6K+FOldcTOrCZ+ILk8werwKBgQDwnQUrKATzRThVdD6Hcgt/F/SAizDmvtiT\nVvRcGkiV3EtB5Rx8zFNJ9GWrqSAArwIxTWgfYCYsvpUjbJW02Mg0Ufj2+YhjT713\nO9yViwUq996St9eLwGQO5FDMD8FYi7bRAiZEAeAeIEeveDRsNK15++8VVJVo7b2l\nzcapp5k3bQKBgQDSiJNHRhqSet6+xgIIDGoZ+1Qv0TFPX5UrZt8OpsK7FshEOhXQ\nCxt8WZN03HHXK9fEC4GjwwxBrwYB+BOjCYiMHmCd3j0M3HoXgDrgViyYKMuVuDk8\nUG83r5ZbqVuCwfO8i/HbxddueEvtyiD2CZ47ZCIHxKOKAe0K4Mex2UBaKwKBgQDi\nrEouOelP9Kn5dyVhHENQXBTu9DIBb1FAnO5fxjMTWxFa5qhLuYHNbfxKF24atsRu\nBepNhJryFCkT0jvGv2L8Ry0wHiwqwvhO14obJ3ia3iBEQAVDlt+sV9L2KvGOpTB4\n/nlmIA4u02I1IBziw02aWYkGo0SOMUo0ZQL+2PEykQKBgAV1uqiJlWuA9uPdFFJP\nZPL2YoOuTWdWfIwIb/UdsbUuTckCgqPIqUPi3HhiVSunOgcO7HWK3GD3j8k4XEbW\nG4y+Ik0lLrWzBl728tZe1GENzTf8aapElHlUfFSM4OlrTRBsbMOsQBcJNh7QbyoZ\nBHiZZTbRUY6xUR4DGYkCOksF", Kuaikan.Cb); + JSONObject jSONObject8 = new JSONObject(); + jSONObject8.put("body", O2); + jSONObject8.put("ticket", tg2); + new JSONArray(); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), "http://ctlook.facaishiyi.com/api/v1/search/category.do", jSONObject8.toString(), Kuaikan.this.j(currentTimeMillis2), new OKCallBack.OKCallBackString() { // from class: com.github.catvod.spider.Kuaikan.3.1 + @Override + public void onFailure(Call call, Exception exc) { + } + + public void onResponse(String str2) { + try { + JSONObject jSONObject9 = new JSONObject(str2); + String lX2 = Kuaikan.this.lX("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiYJ5UFjeEgeUi5ynLKhj5EMF0\n3sawTyAKoPbfUCSZZQ5QdrHhrINggrYxDtB/TWXoqSF+BJP85F0vq8B6gOqFWhK/\n1PIKe2wKlRRuZSOdUzK/3vzRHmR3J3KGrvNzvwARH8gg8xZjbsalc/gBkcVxSxGd\n8j8rJ4QhOSFh9F8B2wIDAQAB", jSONObject9.getString("ticket")); + JSONObject jSONObject10 = new JSONObject(Kuaikan.this.UO(lX2.substring(0, 16), lX2.substring(16, 32), jSONObject9.getString("body"))); + JSONArray jSONArray3 = jSONObject10.getJSONArray("areas"); + JSONArray jSONArray4 = jSONObject10.getJSONArray("years"); + JSONArray jSONArray5 = jSONObject10.getJSONArray("tags"); + JSONArray jSONArray6 = new JSONArray(); + JSONObject jSONObject11 = new JSONObject(); + jSONObject11.put("key", "tagId"); + jSONObject11.put("name", "类型"); + JSONArray jSONArray7 = new JSONArray(); + for (int i3 = 0; i3 < jSONArray5.length(); i3++) { + JSONObject jSONObject12 = jSONArray5.getJSONObject(i3); + JSONObject jSONObject13 = new JSONObject(); + jSONObject13.put("n", jSONObject12.getString("name")); + jSONObject13.put("v", jSONObject12.getString("id")); + jSONArray7.put(jSONObject13); + } + jSONObject11.put("value", jSONArray7); + jSONArray6.put(jSONObject11); + JSONObject jSONObject14 = new JSONObject(); + jSONObject14.put("key", "areaId"); + jSONObject14.put("name", "地区"); + JSONArray jSONArray8 = new JSONArray(); + for (int i4 = 0; i4 < jSONArray3.length(); i4++) { + JSONObject jSONObject15 = jSONArray3.getJSONObject(i4); + JSONObject jSONObject16 = new JSONObject(); + jSONObject16.put("n", jSONObject15.getString("name")); + jSONObject16.put("v", jSONObject15.getString("id")); + jSONArray8.put(jSONObject16); + } + jSONObject14.put("value", jSONArray8); + jSONArray6.put(jSONObject14); + JSONObject jSONObject17 = new JSONObject(); + jSONObject17.put("key", "yearId"); + jSONObject17.put("name", "年份"); + JSONArray jSONArray9 = new JSONArray(); + for (int i5 = 0; i5 < jSONArray4.length(); i5++) { + JSONObject jSONObject18 = jSONArray4.getJSONObject(i5); + JSONObject jSONObject19 = new JSONObject(); + jSONObject19.put("n", jSONObject18.getString("name")); + jSONObject19.put("v", jSONObject18.getString("id")); + jSONArray9.put(jSONObject19); + } + jSONObject17.put("value", jSONArray9); + jSONArray6.put(jSONObject17); + jSONObject3.put(i2 + "", jSONArray6); + } catch (JSONException e) { + } + } + }); + } + } + } catch (JSONException e) { + } + } + }); + JSONObject jSONObject4 = new JSONObject(); + jSONObject4.put("class", jSONArray); + if (z) { + jSONObject4.put("filters", jSONObject3); + } + return jSONObject4.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } + + public String homeVideoContent() { + try { + Q(); + JSONObject jSONObject = new JSONObject(); + long currentTimeMillis = System.currentTimeMillis() / 1000; + String f = f("1000300001dc431681b806089dac1153fb13960f87115" + currentTimeMillis + "notice"); + jSONObject.put("appId", "1000300001"); + jSONObject.put("id", 115); + jSONObject.put("sign", f); + jSONObject.put("timestamp", currentTimeMillis); + String O = Decrypt(Cb.substring(0, 16), Cb.substring(16, 32), jSONObject.toString()); + String tg = tg("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDitX/rWP6WWc3h\nDzUcfD8Hbw79yCB7rz18GEkjDapjlUVIa3P8FEQFoOchu7N+vdK6HQNsl2Bql4lv\nWOYuzRWNbLGQ7mNtMca28iCuPHck0AcJzOs9F6qruPL73eY7Ai7yvzs2IfEdyXSz\nHP/yXgEOi5ZEBfsBZEPMJw6vfHJVueuD/lh/LkoJ/gXEKMCM/pkIzGpBPd2TsIg8\nZdvOGMPy+MOnJb1Qfe0y3QQdc5VPVdZFWoWsM9RAenHmE3d1THb+uNZZZcnM1tV7\nxYgBbIhgHtXAZnWDWDRBM3xJPR3O9dfBHHt/tbyrZrSwK1IgwFgqfYm/tRbmp4y/\n1DhIF6mDAgMBAAECggEAIzDjS2gEFNiZ0a6nouVSb1f47sHq8OgR1jp619seMNkR\n6Rzs4xtON8VzO1REl47lsAgi6O9SgxlEtykIiglBqDNQGNw4SNHqM6nAEuvF3sv/\n27CYb2JGFuPdq+UVAOHk4b93dH6uS95ipA8DV97psRVP3P1EqkGjGISTjf/2S4IG\n10Q0UhP4xxiRS2iCtaIq0fbvnrChqYRlYQYpkkRCCH+Q4FNKquSsqmWyCu5yfeQM\nMek+aT9KgvmCh05UCeqC1x7xPtSneNbpJpLD5zW8CcG7EYFDtIP8b9BPDlud47ZH\n5Y4/wyQQFHHLOaniTJVvEJZ7cIoXy2gOhvgcHpNryQKBgQDxNNtXnCfVK0JYNhnU\n5WCOX9NeW9Q79HldhTM5/EqsjA5H21j5S7A/duBSRfX7iou1hyXaa2p+J7rxF9sj\nNlwHPsKhprskxXaHJ7qU84gSmwORsTQQPmtTsizGwVsM330+Q2ZROaSEfDoUqH9+\nKBKs6K+FOldcTOrCZ+ILk8werwKBgQDwnQUrKATzRThVdD6Hcgt/F/SAizDmvtiT\nVvRcGkiV3EtB5Rx8zFNJ9GWrqSAArwIxTWgfYCYsvpUjbJW02Mg0Ufj2+YhjT713\nO9yViwUq996St9eLwGQO5FDMD8FYi7bRAiZEAeAeIEeveDRsNK15++8VVJVo7b2l\nzcapp5k3bQKBgQDSiJNHRhqSet6+xgIIDGoZ+1Qv0TFPX5UrZt8OpsK7FshEOhXQ\nCxt8WZN03HHXK9fEC4GjwwxBrwYB+BOjCYiMHmCd3j0M3HoXgDrgViyYKMuVuDk8\nUG83r5ZbqVuCwfO8i/HbxddueEvtyiD2CZ47ZCIHxKOKAe0K4Mex2UBaKwKBgQDi\nrEouOelP9Kn5dyVhHENQXBTu9DIBb1FAnO5fxjMTWxFa5qhLuYHNbfxKF24atsRu\nBepNhJryFCkT0jvGv2L8Ry0wHiwqwvhO14obJ3ia3iBEQAVDlt+sV9L2KvGOpTB4\n/nlmIA4u02I1IBziw02aWYkGo0SOMUo0ZQL+2PEykQKBgAV1uqiJlWuA9uPdFFJP\nZPL2YoOuTWdWfIwIb/UdsbUuTckCgqPIqUPi3HhiVSunOgcO7HWK3GD3j8k4XEbW\nG4y+Ik0lLrWzBl728tZe1GENzTf8aapElHlUfFSM4OlrTRBsbMOsQBcJNh7QbyoZ\nBHiZZTbRUY6xUR4DGYkCOksF", Cb); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("body", O); + jSONObject2.put("ticket", tg); + final JSONArray jSONArray = new JSONArray(); + OkHttpClient QH2 = OkHttpUtil.defaultClient(); + OkHttpUtil.postJson(QH2, "http://ctlook.facaishiyi.com/api/v1/user/genre/115.do", jSONObject2.toString(), j(currentTimeMillis), new OKCallBack.OKCallBackString() { // from class: com.github.catvod.spider.Kuaikan.4 + @Override + public void onFailure(Call call, Exception exc) { + } + + public void onResponse(String str) { + try { + JSONObject jSONObject3 = new JSONObject(str); + String lX = Kuaikan.this.lX("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiYJ5UFjeEgeUi5ynLKhj5EMF0\n3sawTyAKoPbfUCSZZQ5QdrHhrINggrYxDtB/TWXoqSF+BJP85F0vq8B6gOqFWhK/\n1PIKe2wKlRRuZSOdUzK/3vzRHmR3J3KGrvNzvwARH8gg8xZjbsalc/gBkcVxSxGd\n8j8rJ4QhOSFh9F8B2wIDAQAB", jSONObject3.getString("ticket")); + JSONArray jSONArray2 = new JSONObject(Kuaikan.this.UO(lX.substring(0, 16), lX.substring(16, 32), jSONObject3.getString("body"))).getJSONArray("subGenres"); + for (int i = 0; i < jSONArray2.length(); i++) { + if (jSONArray2.getJSONObject(i).getInt("template") == 1) { + JSONArray jSONArray3 = jSONArray2.getJSONObject(i).getJSONArray("video"); + for (int i2 = 0; i2 < jSONArray3.length(); i2++) { + JSONObject jSONObject4 = jSONArray3.getJSONObject(i2); + JSONObject jSONObject5 = new JSONObject(); + jSONObject5.put("vod_id", jSONObject4.getString("id")); + jSONObject5.put("vod_name", jSONObject4.getString("name")); + jSONObject5.put("vod_pic", jSONObject4.getString("pic")); + jSONObject5.put("vod_remarks", jSONObject4.getString("progress")); + jSONArray.put(jSONObject5); + } + } + } + } catch (JSONException e) { + } + } + }); + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put("list", jSONArray); + return jSONObject3.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } + + public void init(Context context, String str) { + Kuaikan.super.init(context, str); + SharedPreferences sharedPreferences = context.getSharedPreferences("spider_Kuaikan", 0); + try { + String string = sharedPreferences.getString("umId", null); + dW = string; + if (string != null) { + return; + } + } catch (Throwable th) { + if (dW != null) { + return; + } + } + dW = f(UUID.randomUUID().toString()).toLowerCase(); + sharedPreferences.edit().putString("umId", dW).commit(); + } + + String lX(String str, String str2) { + int i = 0; + try { + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(2, (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.decode(str, 0)))); + byte[] decode = Base64.decode(str2, 0); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + if (decode.length <= 256) { + byteArrayOutputStream.write(cipher.doFinal(decode)); + } else { + int length = decode.length; + while (i < length) { + int i2 = i + 256; + byteArrayOutputStream.write(cipher.doFinal(decode, i, i2 > length ? length - i : 256)); + i = i2; + } + } + byteArrayOutputStream.flush(); + byteArrayOutputStream.close(); + return new String(byteArrayOutputStream.toByteArray(), "UTF-8"); + } catch (Exception e) { + return ""; + } + } + + public String playerContent(String str, String str2, List list) { + try { + Q(); + String[] split = new String(Base64.decode(str2, 10), "UTF-8").split("\\|"); + ArrayList arrayList = this.Ji.get(split[2]); + final JSONObject jSONObject = new JSONObject(); + if (arrayList != null && arrayList.size() > 0) { + Iterator it = arrayList.iterator(); + while (it.hasNext()) { + String next = it.next(); + if (jSONObject.has("url")) { + break; + } + JSONObject jSONObject2 = new JSONObject(); + long currentTimeMillis = System.currentTimeMillis() / 1000; + String f = f("1000300001dc431681b806089dac1153fb13960f87" + split[1] + split[0] + split[3] + currentTimeMillis + "notice"); + jSONObject2.put("appId", "1000300001"); + jSONObject2.put("id", split[1]); + jSONObject2.put("title", split[0]); + jSONObject2.put("url", split[3]); + jSONObject2.put("sign", f); + jSONObject2.put("timestamp", currentTimeMillis); + String O = Decrypt(Cb.substring(0, 16), Cb.substring(16, 32), jSONObject2.toString()); + String tg = tg("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDitX/rWP6WWc3h\nDzUcfD8Hbw79yCB7rz18GEkjDapjlUVIa3P8FEQFoOchu7N+vdK6HQNsl2Bql4lv\nWOYuzRWNbLGQ7mNtMca28iCuPHck0AcJzOs9F6qruPL73eY7Ai7yvzs2IfEdyXSz\nHP/yXgEOi5ZEBfsBZEPMJw6vfHJVueuD/lh/LkoJ/gXEKMCM/pkIzGpBPd2TsIg8\nZdvOGMPy+MOnJb1Qfe0y3QQdc5VPVdZFWoWsM9RAenHmE3d1THb+uNZZZcnM1tV7\nxYgBbIhgHtXAZnWDWDRBM3xJPR3O9dfBHHt/tbyrZrSwK1IgwFgqfYm/tRbmp4y/\n1DhIF6mDAgMBAAECggEAIzDjS2gEFNiZ0a6nouVSb1f47sHq8OgR1jp619seMNkR\n6Rzs4xtON8VzO1REl47lsAgi6O9SgxlEtykIiglBqDNQGNw4SNHqM6nAEuvF3sv/\n27CYb2JGFuPdq+UVAOHk4b93dH6uS95ipA8DV97psRVP3P1EqkGjGISTjf/2S4IG\n10Q0UhP4xxiRS2iCtaIq0fbvnrChqYRlYQYpkkRCCH+Q4FNKquSsqmWyCu5yfeQM\nMek+aT9KgvmCh05UCeqC1x7xPtSneNbpJpLD5zW8CcG7EYFDtIP8b9BPDlud47ZH\n5Y4/wyQQFHHLOaniTJVvEJZ7cIoXy2gOhvgcHpNryQKBgQDxNNtXnCfVK0JYNhnU\n5WCOX9NeW9Q79HldhTM5/EqsjA5H21j5S7A/duBSRfX7iou1hyXaa2p+J7rxF9sj\nNlwHPsKhprskxXaHJ7qU84gSmwORsTQQPmtTsizGwVsM330+Q2ZROaSEfDoUqH9+\nKBKs6K+FOldcTOrCZ+ILk8werwKBgQDwnQUrKATzRThVdD6Hcgt/F/SAizDmvtiT\nVvRcGkiV3EtB5Rx8zFNJ9GWrqSAArwIxTWgfYCYsvpUjbJW02Mg0Ufj2+YhjT713\nO9yViwUq996St9eLwGQO5FDMD8FYi7bRAiZEAeAeIEeveDRsNK15++8VVJVo7b2l\nzcapp5k3bQKBgQDSiJNHRhqSet6+xgIIDGoZ+1Qv0TFPX5UrZt8OpsK7FshEOhXQ\nCxt8WZN03HHXK9fEC4GjwwxBrwYB+BOjCYiMHmCd3j0M3HoXgDrgViyYKMuVuDk8\nUG83r5ZbqVuCwfO8i/HbxddueEvtyiD2CZ47ZCIHxKOKAe0K4Mex2UBaKwKBgQDi\nrEouOelP9Kn5dyVhHENQXBTu9DIBb1FAnO5fxjMTWxFa5qhLuYHNbfxKF24atsRu\nBepNhJryFCkT0jvGv2L8Ry0wHiwqwvhO14obJ3ia3iBEQAVDlt+sV9L2KvGOpTB4\n/nlmIA4u02I1IBziw02aWYkGo0SOMUo0ZQL+2PEykQKBgAV1uqiJlWuA9uPdFFJP\nZPL2YoOuTWdWfIwIb/UdsbUuTckCgqPIqUPi3HhiVSunOgcO7HWK3GD3j8k4XEbW\nG4y+Ik0lLrWzBl728tZe1GENzTf8aapElHlUfFSM4OlrTRBsbMOsQBcJNh7QbyoZ\nBHiZZTbRUY6xUR4DGYkCOksF", Cb); + JSONObject jSONObject3 = new JSONObject(); + jSONObject3.put("body", O); + jSONObject3.put("ticket", tg); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), next, jSONObject3.toString(), j(currentTimeMillis), new OKCallBack.OKCallBackString() { // from class: com.github.catvod.spider.Kuaikan.7 + @Override // com.github.catvod.spider.merge.OKCallBack + public void onFailure(Call call, Exception exc) { + } + + public void onResponse(String str3) { + try { + JSONObject jSONObject4 = new JSONObject(str3); + String lX = Kuaikan.this.lX("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiYJ5UFjeEgeUi5ynLKhj5EMF0\n3sawTyAKoPbfUCSZZQ5QdrHhrINggrYxDtB/TWXoqSF+BJP85F0vq8B6gOqFWhK/\n1PIKe2wKlRRuZSOdUzK/3vzRHmR3J3KGrvNzvwARH8gg8xZjbsalc/gBkcVxSxGd\n8j8rJ4QhOSFh9F8B2wIDAQAB", jSONObject4.getString("ticket")); + JSONObject jSONObject5 = new JSONObject(Kuaikan.this.UO(lX.substring(0, 16), lX.substring(16, 32), jSONObject4.getString("body"))); + if (jSONObject5.optString("msg", "").equals("success") && jSONObject5.optInt("code", -1) == 0) { + jSONObject.put("parse", 0); + jSONObject.put("header", ""); + jSONObject.put("playUrl", ""); + jSONObject.put("url", jSONObject5.getString("url")); + } + } catch (JSONException e) { + } + } + }); + } + } + if (jSONObject.has("url")) { + return jSONObject.toString(); + } + if (!Misc.isVideoFormat(split[3])) { + return ""; + } + jSONObject.put("parse", 0); + jSONObject.put("header", ""); + jSONObject.put("playUrl", ""); + jSONObject.put("url", split[3]); + return jSONObject.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } + + public String searchContent(String str, boolean z) { + try { + Q(); + JSONObject jSONObject = new JSONObject(); + long currentTimeMillis = System.currentTimeMillis() / 1000; + String f = f("1000300001dc431681b806089dac1153fb13960f87112" + str + currentTimeMillis + "notice"); + jSONObject.put("appId", "1000300001"); + jSONObject.put("keyword", str); + jSONObject.put("page", 1); + jSONObject.put("pageSize", 12); + jSONObject.put("sign", f); + jSONObject.put("timestamp", currentTimeMillis); + String O = Decrypt(Cb.substring(0, 16), Cb.substring(16, 32), jSONObject.toString()); + String tg = tg("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDitX/rWP6WWc3h\nDzUcfD8Hbw79yCB7rz18GEkjDapjlUVIa3P8FEQFoOchu7N+vdK6HQNsl2Bql4lv\nWOYuzRWNbLGQ7mNtMca28iCuPHck0AcJzOs9F6qruPL73eY7Ai7yvzs2IfEdyXSz\nHP/yXgEOi5ZEBfsBZEPMJw6vfHJVueuD/lh/LkoJ/gXEKMCM/pkIzGpBPd2TsIg8\nZdvOGMPy+MOnJb1Qfe0y3QQdc5VPVdZFWoWsM9RAenHmE3d1THb+uNZZZcnM1tV7\nxYgBbIhgHtXAZnWDWDRBM3xJPR3O9dfBHHt/tbyrZrSwK1IgwFgqfYm/tRbmp4y/\n1DhIF6mDAgMBAAECggEAIzDjS2gEFNiZ0a6nouVSb1f47sHq8OgR1jp619seMNkR\n6Rzs4xtON8VzO1REl47lsAgi6O9SgxlEtykIiglBqDNQGNw4SNHqM6nAEuvF3sv/\n27CYb2JGFuPdq+UVAOHk4b93dH6uS95ipA8DV97psRVP3P1EqkGjGISTjf/2S4IG\n10Q0UhP4xxiRS2iCtaIq0fbvnrChqYRlYQYpkkRCCH+Q4FNKquSsqmWyCu5yfeQM\nMek+aT9KgvmCh05UCeqC1x7xPtSneNbpJpLD5zW8CcG7EYFDtIP8b9BPDlud47ZH\n5Y4/wyQQFHHLOaniTJVvEJZ7cIoXy2gOhvgcHpNryQKBgQDxNNtXnCfVK0JYNhnU\n5WCOX9NeW9Q79HldhTM5/EqsjA5H21j5S7A/duBSRfX7iou1hyXaa2p+J7rxF9sj\nNlwHPsKhprskxXaHJ7qU84gSmwORsTQQPmtTsizGwVsM330+Q2ZROaSEfDoUqH9+\nKBKs6K+FOldcTOrCZ+ILk8werwKBgQDwnQUrKATzRThVdD6Hcgt/F/SAizDmvtiT\nVvRcGkiV3EtB5Rx8zFNJ9GWrqSAArwIxTWgfYCYsvpUjbJW02Mg0Ufj2+YhjT713\nO9yViwUq996St9eLwGQO5FDMD8FYi7bRAiZEAeAeIEeveDRsNK15++8VVJVo7b2l\nzcapp5k3bQKBgQDSiJNHRhqSet6+xgIIDGoZ+1Qv0TFPX5UrZt8OpsK7FshEOhXQ\nCxt8WZN03HHXK9fEC4GjwwxBrwYB+BOjCYiMHmCd3j0M3HoXgDrgViyYKMuVuDk8\nUG83r5ZbqVuCwfO8i/HbxddueEvtyiD2CZ47ZCIHxKOKAe0K4Mex2UBaKwKBgQDi\nrEouOelP9Kn5dyVhHENQXBTu9DIBb1FAnO5fxjMTWxFa5qhLuYHNbfxKF24atsRu\nBepNhJryFCkT0jvGv2L8Ry0wHiwqwvhO14obJ3ia3iBEQAVDlt+sV9L2KvGOpTB4\n/nlmIA4u02I1IBziw02aWYkGo0SOMUo0ZQL+2PEykQKBgAV1uqiJlWuA9uPdFFJP\nZPL2YoOuTWdWfIwIb/UdsbUuTckCgqPIqUPi3HhiVSunOgcO7HWK3GD3j8k4XEbW\nG4y+Ik0lLrWzBl728tZe1GENzTf8aapElHlUfFSM4OlrTRBsbMOsQBcJNh7QbyoZ\nBHiZZTbRUY6xUR4DGYkCOksF", Cb); + JSONObject jSONObject2 = new JSONObject(); + jSONObject2.put("body", O); + jSONObject2.put("ticket", tg); + final JSONObject jSONObject3 = new JSONObject(); + OkHttpUtil.postJson(OkHttpUtil.defaultClient(), "http://ctlook.facaishiyi.com/api/v1/search/page.do", jSONObject2.toString(), j(currentTimeMillis), new OKCallBack.OKCallBackString() { // from class: com.github.catvod.spider.Kuaikan.8 + @Override + public void onFailure(Call call, Exception exc) { + } + + public void onResponse(String str2) { + try { + JSONObject jSONObject4 = new JSONObject(str2); + String lX = Kuaikan.this.lX("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiYJ5UFjeEgeUi5ynLKhj5EMF0\n3sawTyAKoPbfUCSZZQ5QdrHhrINggrYxDtB/TWXoqSF+BJP85F0vq8B6gOqFWhK/\n1PIKe2wKlRRuZSOdUzK/3vzRHmR3J3KGrvNzvwARH8gg8xZjbsalc/gBkcVxSxGd\n8j8rJ4QhOSFh9F8B2wIDAQAB", jSONObject4.getString("ticket")); + JSONObject jSONObject5 = new JSONObject(Kuaikan.this.UO(lX.substring(0, 16), lX.substring(16, 32), jSONObject4.getString("body"))); + JSONArray jSONArray = new JSONArray(); + JSONArray jSONArray2 = jSONObject5.getJSONArray("results"); + for (int i = 0; i < jSONArray2.length(); i++) { + JSONObject jSONObject6 = jSONArray2.getJSONObject(i); + JSONObject jSONObject7 = new JSONObject(); + jSONObject7.put("vod_id", jSONObject6.getString("id")); + jSONObject7.put("vod_name", jSONObject6.getString("name")); + jSONObject7.put("vod_pic", jSONObject6.getString("pic")); + jSONArray.put(jSONObject7); + } + jSONObject3.put("list", jSONArray); + } catch (JSONException e) { + } + } + }); + return jSONObject3.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + return ""; + } + } + + String tg(String str, String str2) { + int i = 0; + try { + PrivateKey generatePrivate = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.decode(str, 0))); + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(1, generatePrivate); + byte[] bytes = str2.getBytes(); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + if (bytes.length <= 256) { + byteArrayOutputStream.write(cipher.doFinal(bytes)); + } else { + int length = bytes.length; + while (i < bytes.length) { + int i2 = i + 256; + byteArrayOutputStream.write(cipher.doFinal(bytes, i, i2 > length ? length - i : 256)); + i = i2; + } + } + byteArrayOutputStream.flush(); + byteArrayOutputStream.close(); + return Base64.encodeToString(byteArrayOutputStream.toByteArray(), 2); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } +} \ 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 new file mode 100644 index 0000000..ef6d1ff --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Kunyu77.java @@ -0,0 +1,370 @@ +package com.github.catvod.spider; + +import android.os.Build; +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.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; + + +/** + * Author: @SDL + */ +public class Kunyu77 extends Spider { + private static final String siteUrl = "http://api.kunyu77.com"; + + private String uAgent = "Dalvik/2.1.0 (Linux; U; Android " + Build.VERSION.RELEASE + "; " + Build.MODEL + " Build/" + Build.ID + ")"; + + private HashMap getHeaders(String url) { + HashMap headers = new HashMap<>(); + headers.put("user-agent", uAgent); + return headers; + } + + @Override + public String homeContent(boolean filter) { + try { + String url = siteUrl + "/api.php/provide/filter"; + String content = OkHttpUtil.string(url, getHeaders(url)); + JSONObject jsonObject = new JSONObject(decryptResponse(content)).getJSONObject("data"); + Iterator keys = jsonObject.keys(); + JSONArray classes = new JSONArray(); + JSONObject filterConfig = new JSONObject(); + JSONArray extendsAll = null; + while (keys.hasNext()) { + String typeId = keys.next(); + String typeName = jsonObject.getJSONArray(typeId).getJSONObject(0).getString("cat"); + JSONObject newCls = new JSONObject(); + newCls.put("type_id", typeId); + newCls.put("type_name", typeName); + classes.put(newCls); + try { + if (extendsAll == null) { + String filterUrl = siteUrl + "/api.php/provide/searchFilter?type_id=0&pagenum=1&pagesize=1"; + String filterContent = OkHttpUtil.string(filterUrl, getHeaders(filterUrl)); + JSONObject filterObj = new JSONObject(filterContent).getJSONObject("data").getJSONObject("conditions"); + extendsAll = new JSONArray(); + // 年份 + JSONObject newTypeExtend = new JSONObject(); + newTypeExtend.put("key", "year"); + newTypeExtend.put("name", "年份"); + JSONArray newTypeExtendKV = new JSONArray(); + JSONObject kv = new JSONObject(); + kv.put("n", "全部"); + kv.put("v", ""); + newTypeExtendKV.put(kv); + kv = new JSONObject(); + kv.put("n", "2022"); + kv.put("v", "2022"); + newTypeExtendKV.put(kv); + kv = new JSONObject(); + kv.put("n", "2021"); + kv.put("v", "2021"); + newTypeExtendKV.put(kv); + JSONArray years = filterObj.getJSONArray("y"); + for (int j = 0; j < years.length(); j++) { + JSONObject child = years.getJSONObject(j); + kv = new JSONObject(); + kv.put("n", child.getString("name")); + kv.put("v", child.getString("value")); + newTypeExtendKV.put(kv); + } + newTypeExtend.put("value", newTypeExtendKV); + extendsAll.put(newTypeExtend); + // 地区 + newTypeExtend = new JSONObject(); + newTypeExtend.put("key", "area"); + newTypeExtend.put("name", "地区"); + newTypeExtendKV = new JSONArray(); + kv = new JSONObject(); + kv.put("n", "全部"); + kv.put("v", ""); + newTypeExtendKV.put(kv); + JSONArray areas = filterObj.getJSONArray("a"); + for (int j = 0; j < areas.length(); j++) { + JSONObject child = areas.getJSONObject(j); + kv = new JSONObject(); + kv.put("n", child.getString("name")); + kv.put("v", child.getString("value")); + newTypeExtendKV.put(kv); + } + newTypeExtend.put("value", newTypeExtendKV); + extendsAll.put(newTypeExtend); + // 类型 + newTypeExtend = new JSONObject(); + newTypeExtend.put("key", "category"); + newTypeExtend.put("name", "类型"); + newTypeExtendKV = new JSONArray(); + kv = new JSONObject(); + kv.put("n", "全部"); + kv.put("v", ""); + newTypeExtendKV.put(kv); + JSONArray scat = filterObj.getJSONArray("scat"); + for (int j = 0; j < scat.length(); j++) { + JSONObject child = scat.getJSONObject(j); + kv = new JSONObject(); + kv.put("n", child.getString("name")); + kv.put("v", child.getString("value")); + newTypeExtendKV.put(kv); + } + newTypeExtend.put("value", newTypeExtendKV); + extendsAll.put(newTypeExtend); + } + if (extendsAll != null && extendsAll.length() > 0) { + 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 (Throwable th) { + + } + return ""; + } + + @Override + public String homeVideoContent() { + try { + JSONArray videos = new JSONArray(); + try { + String url = siteUrl + "/api.php/provide/homeBlock?type_id=0"; + String content = OkHttpUtil.string(url, getHeaders(url)); + JSONObject jsonObject = new JSONObject(decryptResponse(content)); + JSONArray jsonArray = jsonObject.getJSONObject("data").getJSONArray("blocks"); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject blockObj = jsonArray.getJSONObject(i); + String blockName = blockObj.getString("block_name"); + if (!blockName.startsWith("热播")) { + continue; + } + JSONArray contents = blockObj.getJSONArray("contents"); + for (int j = 0; j < contents.length() && j < 3; j++) { + JSONObject vObj = contents.getJSONObject(j); + JSONObject v = new JSONObject(); + v.put("vod_id", vObj.getString("id")); + v.put("vod_name", vObj.getString("title")); + v.put("vod_pic", vObj.getString("videoCover")); + v.put("vod_remarks", vObj.getString("msg")); + 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/provide/searchFilter?type_id=" + tid + "&pagenum=" + pg + "&pagesize=24"; + 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("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("title")); + v.put("vod_pic", vObj.getString("videoCover")); + v.put("vod_remarks", vObj.getString("msg")); + videos.put(v); + } + JSONObject result = new JSONObject(); + int limit = 24; + int page = Integer.parseInt(dataObject.getString("page")); + int total = dataObject.getInt("total"); + int pageCount = dataObject.getInt("pagesize"); + result.put("page", page); + result.put("pagecount", pageCount); + 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/provide/videoDetail?ids=" + 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 vodAtom = new JSONObject(); + String title = vObj.getString("videoName"); + vodAtom.put("vod_id", vObj.getString("id")); + vodAtom.put("vod_name", title); + vodAtom.put("vod_pic", vObj.getString("videoCover")); + vodAtom.put("type_name", vObj.getString("subCategory")); + vodAtom.put("vod_year", vObj.getString("year")); + vodAtom.put("vod_area", vObj.getString("area")); + vodAtom.put("vod_remarks", vObj.getString("msg")); + vodAtom.put("vod_actor", vObj.getString("actor")); + vodAtom.put("vod_director", vObj.getString("director")); + vodAtom.put("vod_content", vObj.getString("brief").trim()); + + url = siteUrl + "/api.php/provide/videoPlaylist?ids=" + ids.get(0); + content = OkHttpUtil.string(url, getHeaders(url)); + JSONArray episodes = new JSONObject(content).getJSONObject("data").getJSONArray("episodes"); + LinkedHashMap> playlist = new LinkedHashMap<>(); + for (int i = 0; i < episodes.length(); i++) { + JSONArray playurls = episodes.getJSONObject(i).getJSONArray("playurls"); + for (int j = 0; j < playurls.length(); j++) { + JSONObject purl = playurls.getJSONObject(j); + String from = purl.getString("playfrom"); + ArrayList urls = playlist.get(from); + if (urls == null) { + urls = new ArrayList<>(); + playlist.put(from, urls); + } + String name = purl.getString("title").replace(title, "").trim(); + if (name.isEmpty()) { + name = (i + 1) + ""; + } + String pid = purl.getString("playurl"); + urls.add(name + "$" + 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 videoUrl = id; + try { + String url = siteUrl + "/api.php/provide/parserUrl?url=" + id; + String content = OkHttpUtil.string(url, getHeaders(url)); + JSONObject dataObj = new JSONObject(decryptResponse(content)).getJSONObject("data"); + JSONObject playHeader = dataObj.optJSONObject("playHeader"); + String jxUrl = dataObj.getString("url"); + content = OkHttpUtil.string(jxUrl, getHeaders(jxUrl)); + JSONObject result = Misc.jsonParse(jxUrl, content); + if (result != null) { + result.put("parse", 0); + result.put("playUrl", ""); + if (playHeader != null) { + JSONObject header = result.getJSONObject("header"); + Iterator iter = playHeader.keys(); + while (iter.hasNext()) { + String key = iter.next(); + header.put(key, " " + playHeader.getString(key)); + } + result.put("header", header.toString()); + } + return result.toString(); + } + } catch (Throwable th) { + + } + if (Misc.isVip(videoUrl)) { + JSONObject result = new JSONObject(); + result.put("parse", 1); + result.put("jx", "1"); + result.put("url", videoUrl); + return result.toString(); + } + JSONObject result = new JSONObject(); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", id); + return result.toString(); + } catch (Throwable th) { + + } + return ""; + } + + @Override + public String searchContent(String key, boolean quick) { + try { + String url = siteUrl + "/api.php/provide/searchVideo?searchName=" + URLEncoder.encode(key); + String content = OkHttpUtil.string(url, getHeaders(url)); + JSONObject dataObject = new JSONObject(decryptResponse(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(); + String title = vObj.getString("videoName"); + if (!title.contains(key)) + continue; + v.put("vod_id", vObj.getString("id")); + v.put("vod_name", title); + v.put("vod_pic", vObj.getString("videoCover")); + v.put("vod_remarks", vObj.getString("msg")); + 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; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/Lib.java b/app/src/main/java/com/github/catvod/spider/Lib.java new file mode 100644 index 0000000..9eb5235 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Lib.java @@ -0,0 +1,504 @@ +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; + +public class Lib extends Spider { + private static final String siteUrl = "https://www.libvio.me/"; + private static final String siteHost = "www.libvio.me"; + + /** + * 播放源配置 + */ + private JSONObject playerConfig; + /** + * 筛选配置 + */ + private JSONObject filterConfig; + private Pattern regexCategory = Pattern.compile("/type/(\\d+).html"); + private Pattern regexVid = Pattern.compile("/detail/(\\d+).html"); + private Pattern regexPlay = Pattern.compile("/play/(\\d+)-(\\d+)-(\\d+).html"); + private Pattern regexPage = Pattern.compile("/show/(\\S+).html"); + + protected String ext = null; + + @Override + 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}}"); + 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); + } + } + + + 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("Referer", siteUrl); + return headers; + } + + /** + * 爬虫headers + * + * @param url + * @return + */ + protected HashMap getHeaders(String url) { + HashMap headers = new HashMap<>(); + headers.put("method", "GET"); + 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.stui-header__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("日韩剧") || + 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.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); + String title = vod.select("a").attr("title"); + String cover = vod.select("a").attr("data-original"); + String remark = vod.select("a .pic-text").text(); + Matcher matcher = regexVid.matcher(vod.select("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 + "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.stui-page__item 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()) { + //System.out.println("哈哈"+matcher.group(1)); + page = Integer.parseInt(matcher.group(1).split("-")[8]); + } else { + page = 0; + } + } + if (name.equals("尾页")) { + Matcher matcher = regexPage.matcher(a.attr("href")); + if (matcher.find()) { + //System.out.println("尾页" + matcher.group(1)); + pageCount = Integer.parseInt(matcher.group(1).split("-")[8]); + } 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.select("a").attr("title"); + String cover = vod.select("a").attr("data-original"); + String remark = vod.select("a .pic-text").text(); + Matcher matcher = regexVid.matcher(vod.select("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 + "/detail/" + ids.get(0) + ".html"; + Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url))); + JSONObject result = new JSONObject(); + JSONObject vodList = new JSONObject(); + + // 取基本数据 + String cover = doc.select("div.stui-content__thumb a img").attr("data-original"); + String title = doc.select("div.stui-content__detail h1").text(); + String category = "", area = "", year = "", remark = "", director = "", actor = "", desc = ""; + Elements data = doc.select("p.data"); + Pattern cate = Pattern.compile("类型:(\\S+)"); + category = doReplaceRegex(cate, data.get(0).text()); + Pattern areas = Pattern.compile("地区:(\\S+)"); + area = doReplaceRegex(areas, data.get(0).text()); + Pattern years = Pattern.compile("年份:(\\S+)"); + year = doReplaceRegex(years, data.get(0).text()); + Pattern rms = Pattern.compile("更新:(\\S+)"); + remark = doReplaceRegex(rms, data.get(3).text()); + Pattern acs = Pattern.compile("主演:(\\S+)"); + actor = doReplaceRegex(acs, data.get(1).text()); + Pattern dis = Pattern.compile("导演:(\\S+)"); + director = doReplaceRegex(dis, data.get(1).text()); + + desc = doc.selectFirst("span.detail-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-vodlist__head h3"); + Elements sourceList = doc.select("ul.stui-content__playlist"); + + 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("origin", " https://www.libvio.me/"); + 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://www.libvio.me/"); + // 播放页 url + String url = siteUrl + "/play/" + id + ".html"; + Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url))); + + 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); + if (playerConfig.has(player.getString("from"))) { + JSONObject pCfg = playerConfig.getJSONObject(player.getString("from")); + if (player.getString("from").contains("LINE")) { + String videoUrl = pCfg.getString("pu") + player.getString("url"); + Document docs = Jsoup.parse(OkHttpUtil.string(videoUrl, Headers())); + Pattern pattern = Pattern.compile("(?<=urls\\s=\\s').*?(?=')"); + Elements allScripts = docs.select("body script"); + for (int j = 0; j < allScripts.size(); j++) { + String scContents = allScripts.get(j).html().trim(); + Matcher matcher = pattern.matcher(scContents); + if (matcher.find()) { + JSONObject result = new JSONObject(); + String players = matcher.group(0); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", players); + return result.toString(); + } + } + } + else { + SpiderDebug.log(url); + JSONObject result = new JSONObject(); + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", url); + // result.put("header", "{\"Referer\", \"https://www.libvio.me/\"}"); + return result.toString(); + } + break; + } + } + } + } catch (Exception e) { + SpiderDebug.log(e); + } + 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; + } + + @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())); + 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); + } + } + } + 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; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/LiteApple.java b/app/src/main/java/com/github/catvod/spider/LiteApple.java new file mode 100644 index 0000000..452b824 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/LiteApple.java @@ -0,0 +1,466 @@ +package com.github.catvod.spider; + +import android.content.Context; +import android.content.SharedPreferences; +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.OKCallBack; +import com.github.catvod.utils.okhttp.OkHttpUtil; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Random; +import java.util.Set; + +import okhttp3.Call; + +public class LiteApple extends Spider { + private static final String siteUrl = "http://ht.grelighting.cn/api.php"; + + private HashMap getHeaders(String url, String data) { + HashMap headers = new HashMap<>(); + if (data != null) { + String token = ""; + try { + token = Base64.encodeToString(b(fakeDevice.getBytes("UTF-8"), tokenKey == null ? "XPINGGUO" : tokenKey), 2); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + int currentTimeMillis = (int) (System.currentTimeMillis() / ((long) 1000)); + String hash = md5(fakeDevice + data + currentTimeMillis).substring(8, 12); + headers.put("token", token); + headers.put("hash", hash); + headers.put("timestamp", currentTimeMillis + ""); + if (tokenKey == null) { + headers.put("version", "ANDROID cn.grelighting.xpg1.1.5"); + } + } + headers.put("User-Agent", "okhttp/4.9.1"); + return headers; + } + + private String fakeDevice = null; + private String tokenKey = null; + + @Override + public void init(Context context, String extend) { + super.init(context, extend); + SharedPreferences sharedPreferences = context.getSharedPreferences("spider_LiteApple", Context.MODE_PRIVATE); + try { + fakeDevice = sharedPreferences.getString("didd", null); + } catch (Throwable th) { + } finally { + if (fakeDevice == null) { + fakeDevice = fakeDid(); + sharedPreferences.edit().putString("didd", fakeDevice).commit(); + } + } + } + + void getTokenKey() { + if (tokenKey != null) + return; + String url = siteUrl + "/v2.user/tokenlogin"; + OkHttpUtil.post(OkHttpUtil.defaultClient(), url, null, getHeaders(url, "ANDROID cn.grelighting.xpg1.1.5"), new OKCallBack.OKCallBackString() { + @Override + protected void onFailure(Call call, Exception e) { + + } + + @Override + protected void onResponse(String response) { + try { + tokenKey = new JSONObject(response).getJSONObject("data").getString("user_title"); + } catch (JSONException e) { + e.printStackTrace(); + } + } + }); + } + + @Override + public String homeContent(boolean filter) { + try { + getTokenKey(); + String url = siteUrl + "/v2.vod/androidtypes"; + String content = OkHttpUtil.string(url, getHeaders(url, null)); + JSONObject jsonObject = new JSONObject(decryptResponse(content)); + JSONArray jsonArray = jsonObject.getJSONArray("data"); + + JSONObject filterConfig = new JSONObject(); + JSONArray classes = new JSONArray(); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jObj = jsonArray.getJSONObject(i); + String typeName = jObj.getString("type_name"); + String typeId = jObj.getString("type_id"); + JSONObject newCls = new JSONObject(); + newCls.put("type_id", typeId); + newCls.put("type_name", typeName); + classes.put(newCls); + + JSONArray clses = jObj.getJSONArray("classes"); + JSONArray areas = jObj.getJSONArray("areas"); + JSONArray years = jObj.getJSONArray("years"); + + JSONArray extendsAll = new JSONArray(); + // 类型 + JSONObject newTypeExtend; + JSONArray newTypeExtendKV; + JSONObject kv; + newTypeExtend = new JSONObject(); + newTypeExtend.put("key", "class"); + newTypeExtend.put("name", "类型"); + newTypeExtendKV = new JSONArray(); + for (int j = 0; j < clses.length(); j++) { + String v = clses.getString(j); + kv = new JSONObject(); + kv.put("n", v); + kv.put("v", v); + newTypeExtendKV.put(kv); + } + newTypeExtend.put("value", newTypeExtendKV); + extendsAll.put(newTypeExtend); + // 地区 + newTypeExtend = new JSONObject(); + newTypeExtend.put("key", "area"); + newTypeExtend.put("name", "地区"); + newTypeExtendKV = new JSONArray(); + kv = new JSONObject(); + kv.put("n", "全部"); + kv.put("v", ""); + newTypeExtendKV.put(kv); + for (int j = 0; j < areas.length(); j++) { + String area = areas.getString(j); + kv = new JSONObject(); + kv.put("n", area); + kv.put("v", area); + 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", ""); + newTypeExtendKV.put(kv); + for (int j = 0; j < years.length(); j++) { + String year = years.getString(j); + 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); + // 排序 + newTypeExtend = new JSONObject(); + newTypeExtend.put("key", "sortby"); + newTypeExtend.put("name", "排序"); + newTypeExtendKV = new JSONArray(); + kv = new JSONObject(); + kv.put("n", "时间"); + kv.put("v", "updatetime"); + newTypeExtendKV.put(kv); + kv = new JSONObject(); + kv.put("n", "人气"); + kv.put("v", "hits"); + newTypeExtendKV.put(kv); + kv = new JSONObject(); + kv.put("n", "评分"); + kv.put("v", "score"); + newTypeExtendKV.put(kv); + newTypeExtend.put("value", newTypeExtendKV); + extendsAll.put(newTypeExtend); + } + + 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 { + JSONArray videos = new JSONArray(); + for (int id = 1; id < 5; id++) { + if (videos.length() > 30) + break; + try { + String url = siteUrl + "/v2.main/androidhome"; + String content = OkHttpUtil.string(url, getHeaders(url, null)); + JSONObject jsonObject = new JSONObject(decryptResponse(content)); + JSONArray jsonArray = jsonObject.getJSONObject("data").getJSONArray("list"); + for (int i = 0; i < jsonArray.length(); i++) { + JSONArray jsonArraySub = jsonArray.getJSONObject(i).getJSONArray("list"); + for (int j = 0; j < jsonArraySub.length() && j < 4; j++) { + JSONObject vObj = jsonArraySub.getJSONObject(j); + JSONObject v = new JSONObject(); + v.put("vod_id", vObj.getString("id")); + v.put("vod_name", vObj.getString("name")); + v.put("vod_pic", vObj.getString("pic")); + v.put("vod_remarks", vObj.getString("updateInfo")); + videos.put(v); + } + } + } 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 { + getTokenKey(); + String area = extend.containsKey("area") ? extend.get("area") : ""; + String year = extend.containsKey("year") ? extend.get("year") : ""; + String url = siteUrl + "/v2.vod/androidfilter?page=" + pg + "&type=" + tid; + 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, area + year)); + JSONObject dataObject = new JSONObject(decryptResponse(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("id")); + v.put("vod_name", vObj.getString("name")); + v.put("vod_pic", vObj.getString("pic")); + v.put("vod_remarks", vObj.getString("updateInfo")); + videos.put(v); + } + 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 url = siteUrl + "/v2.vod/androiddetail?vod_id=" + ids.get(0); + String content = OkHttpUtil.string(url, getHeaders(url, ids.get(0))); + JSONObject dataObject = new JSONObject(decryptResponse(content)); + JSONObject vObj = dataObject.getJSONObject("data"); + JSONObject result = new JSONObject(); + JSONArray list = new JSONArray(); + JSONObject vodAtom = new JSONObject(); + vodAtom.put("vod_id", vObj.getString("id")); + vodAtom.put("vod_name", vObj.getString("name")); + vodAtom.put("vod_pic", vObj.getString("pic")); + vodAtom.put("type_name", vObj.getString("className")); + vodAtom.put("vod_year", vObj.getString("year")); + vodAtom.put("vod_area", vObj.getString("area")); + vodAtom.put("vod_remarks", vObj.getString("updateInfo")); + vodAtom.put("vod_actor", vObj.getString("actor")); + vodAtom.put("vod_content", vObj.getString("content").trim()); + + ArrayList playUrls = new ArrayList<>(); + + JSONArray urls = vObj.getJSONArray("urls"); + for (int i = 0; i < urls.length(); i++) { + JSONObject u = urls.getJSONObject(i); + playUrls.add(u.getString("key") + "$" + u.getString("url")); + } + + vodAtom.put("vod_play_from", "LiteApple"); + vodAtom.put("vod_play_url", TextUtils.join("#", playUrls)); + list.put(vodAtom); + 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 { + if (Misc.isVideoFormat(id)) { + JSONObject result = new JSONObject(); + result.put("parse", 0); + result.put("header", ""); + result.put("playUrl", ""); + result.put("url", id); + return result.toString(); + } + return ""; + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + @Override + public String searchContent(String key, boolean quick) { + try { + getTokenKey(); + String url = siteUrl + "/v2.vod/androidsearch?page=1&wd=" + URLEncoder.encode(key); + String content = OkHttpUtil.string(url, getHeaders(url, key)); + JSONObject dataObject = new JSONObject(decryptResponse(content)); + JSONArray jsonArray = dataObject.getJSONArray("data"); + JSONArray videos = new JSONArray(); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject vObj = jsonArray.getJSONObject(i); + String title = vObj.getString("name"); + if (!title.contains(key)) + continue; + JSONObject v = new JSONObject(); + v.put("vod_id", vObj.getString("id")); + v.put("vod_name", title); + v.put("vod_pic", vObj.getString("pic")); + v.put("vod_remarks", vObj.getString("updateInfo")); + videos.put(v); + } + JSONObject result = new JSONObject(); + result.put("list", videos); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + protected String decryptResponse(String src) { + return src; + } + + byte[] a(String str) { + byte[] bytes = str.getBytes(); + byte[] bArr = new byte[333]; + for (int i9 = 0; i9 < 333; i9++) { + bArr[i9] = (byte) i9; + } + if (bytes.length == 0) { + return null; + } + int i10 = 0; + int i11 = 0; + for (int i12 = 0; i12 < 333; i12++) { + i11 = (((bytes[i10] & 255) + (bArr[i12] & 255)) + i11) % 333; + byte b = bArr[i12]; + bArr[i12] = bArr[i11]; + bArr[i11] = b; + i10 = (i10 + 1) % bytes.length; + } + return bArr; + } + + byte[] b(byte[] bArr, String str) { + byte[] a = a(str); + byte[] bArr2 = new byte[bArr.length]; + int i9 = 0; + int i10 = 0; + for (int i11 = 0; i11 < bArr.length; i11++) { + i9 = (i9 + 1) % 333; + i10 = ((a[i9] & 255) + i10) % 333; + byte b = a[i9]; + a[i9] = a[i10]; + a[i10] = b; + bArr2[i11] = (byte) (a[((a[i9] & 255) + (a[i10] & 255)) % 333] ^ bArr[i11]); + } + return bArr2; + } + + String randomString(int length) { + String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; i++) { + int number = random.nextInt(str.length()); + sb.append(str.charAt(number)); + } + return sb.toString(); + } + + String randomMACAddress() { + Random rand = new Random(); + byte[] macAddr = new byte[6]; + rand.nextBytes(macAddr); + macAddr[0] = (byte) (macAddr[0] & (byte) 254); //zeroing last 2 bytes to make it unicast and locally adminstrated + StringBuilder sb = new StringBuilder(18); + for (byte b : macAddr) { + sb.append(String.format("%02X", b)); + } + return sb.toString(); + } + + String fakeDid() { + String i = ""; + String f = ""; + String d = "N/A"; + try { + d = Build.class.getField("SERIAL").get((Object) null).toString(); + } catch (Exception unused) { + } + String e = ""; + try { + e = (String) Class.forName("android.os.SystemProperties").getDeclaredMethod("get", new Class[]{String.class}).invoke((Object) null, new Object[]{"ro.build.fingerprint"}); + } catch (Exception unused) { + return ""; + } + return (((((((((("" + i) + "||") + f) + "||") + randomMACAddress()) + "||") + randomString(16)) + "||") + d) + "||") + e; + } + + String md5(String str) { + try { + MessageDigest instance = MessageDigest.getInstance("MD5"); + instance.update(str.getBytes()); + return new BigInteger(1, instance.digest()).toString(16); + } catch (Exception e9) { + e9.printStackTrace(); + return str; + } + } + +} diff --git a/app/src/main/java/com/github/catvod/spider/Nfyun.java b/app/src/main/java/com/github/catvod/spider/Nfyun.java new file mode 100644 index 0000000..857644f --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Nfyun.java @@ -0,0 +1,503 @@ +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; + +public class Nfyun extends Spider { + private static final String siteUrl = "https://yanaifei.cn"; + private static final String siteHost = "yanaifei.cn"; + private static Pattern pic = Pattern.compile("(?<=url=).*"); + + /** + * 播放源配置 + */ + private JSONObject playerConfig; + /** + * 筛选配置 + */ + private JSONObject filterConfig; + private Pattern regexCategory = Pattern.compile("/vod/type/(\\d+).html"); + private Pattern regexVid = Pattern.compile("/vod/detail/(\\d+).html"); + private Pattern regexPlay = Pattern.compile("/vod/play/(\\d+)-(\\d+)-(\\d+).html"); + private Pattern regexPage = Pattern.compile("/vod/show/(\\S+).html"); + + protected String ext = null; + + @Override + public void init(Context context) { + super.init(context); + try { + playerConfig = new JSONObject("{\"VIP\":{\"sh\":\"VIP\",\"pu\":\"https://yanaifei.cn/player/?url=\",\"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\":\"32\"}]},{\"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\":4,\"name\":\"语言\",\"value\":[{\"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\"}]},{\"key\":5,\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"},{\"n\":\"0-9\",\"v\":\"0-9\"}]},{\"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\":\"20\"}]},{\"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\":\"其他\"}]},{\"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\"}]},{\"key\":5,\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"},{\"n\":\"0-9\",\"v\":\"0-9\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"3\":[{\"key\":0,\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"3\"},{\"n\":\"大陆综艺\",\"v\":\"22\"},{\"n\":\"港台综艺\",\"v\":\"23\"},{\"n\":\"日韩综艺\",\"v\":\"24\"},{\"n\":\"欧美综艺\",\"v\":\"25\"}]},{\"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\":4,\"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\":\"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\"}]},{\"key\":5,\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"},{\"n\":\"0-9\",\"v\":\"0-9\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"4\":[{\"key\":0,\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"4\"},{\"n\":\"大陆动漫\",\"v\":\"26\"},{\"n\":\"港台动漫\",\"v\":\"27\"},{\"n\":\"日韩动漫\",\"v\":\"28\"},{\"n\":\"欧美动漫\",\"v\":\"29\"}]},{\"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\":\"韩国\"},{\"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\":\"其他\"}]},{\"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\"}]},{\"key\":5,\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"},{\"n\":\"0-9\",\"v\":\"0-9\"}]},{\"key\":2,\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}]}"); + } catch (JSONException e) { + SpiderDebug.log(e); + } + } + + + 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("Referer", siteUrl); + return headers; + } + + /** + * 爬虫headers + * + * @param url + * @return + */ + protected HashMap getHeaders(String url) { + HashMap headers = new HashMap<>(); + headers.put("method", "GET"); + 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 { + JSONObject result = new JSONObject(); + Pattern redL = Pattern.compile("(?<=location.href =\").*?(?=\")"); + Document doc = Jsoup.parse(OkHttpUtil.string(siteUrl, getHeaders(siteUrl))); + /* Elements X = A.select("script"); + String url = ""; + for (int i = 0; i < X.size(); i++) { + String finalUrl = X.get(i).html().trim(); + Matcher matcher3 = redL.matcher(finalUrl); + if (matcher3.find()) { + url = siteUrl + matcher3.group(0); + } else { + url = siteUrl; + } + Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url))); */ + // 分类节点 + Elements elements = doc.select("ul.navbar-items 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); + classes.put(jsonObject); + } + } + + + if (filter) { + result.put("filters", filterConfig); + } + result.put("class", classes); + try { + // 取首页推荐视频列表 + Element homeList = doc.select("div.module").get(0); + Elements list = homeList.select("div.module-main div.module-items a"); + JSONArray videos = new JSONArray(); + for (int j = 0; j < list.size(); j++) { + Element vod = list.get(j); + String title = vod.attr("title"); + String cover = FixUrl(pic, vod.select("div.module-item-pic img").attr("data-original")); + String remark = vod.select("div.module-item-note").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 + "/vod/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("div[id=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("a"); + if (a == null) + continue; + String span = doc.select("span.page-current").text(); + String wy = doc.select("div[id=page] 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).split("-")[8]); + } else { + pageCount = 0; + } + break; + + } + } + + JSONArray videos = new JSONArray(); + if (!html.contains("没有找到您想要的结果哦")) { + // 取当前分类页的视频列表 + Elements list = doc.select("div.module-main div.module-items a"); + for (int i = 0; i < list.size(); i++) { + Element vod = list.get(i); + String title = vod.attr("title"); + String cover = FixUrl(pic, vod.select("div.module-item-pic img").attr("data-original")); + String remark = vod.select("div.module-item-note").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 + "/vod/detail/" + ids.get(0) + ".html"; + Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url))); + JSONObject result = new JSONObject(); + JSONObject vodList = new JSONObject(); + + String cover = FixUrl(pic, doc.selectFirst("div.module-info-poster div div img").attr("data-original")); + String title = doc.selectFirst("div.module-info-heading h1").text(); + + String category = "", area = "", year = "", director = "", actor = "", remark = "", desc = ""; + + category = doc.select("div.module-info-tag-link").get(2).text(); + year = doc.select("div.module-info-tag-link a").get(0).text(); + area = doc.select("div.module-info-tag-link a").get(1).text(); + desc = doc.select("div.module-info-introduction-content p").text(); + + Elements span_text_muted = doc.select("div.module-info-item span"); + for (int i = 0; i < span_text_muted.size() - 2; i++) { + Element Spantext = span_text_muted.get(i); + String info = Spantext.text(); + if (info.contains("更新:")) { + try { + remark = Spantext.parent().select("div").text(); + } catch (Exception e) { + remark = ""; + } + } else if (info.contains("导演:")) { + try { + director = Spantext.parent().select("div a").text(); + } catch (Exception e) { + director = ""; + } + } else if (info.contains("主演:")) { + try { + actor = Spantext.parent().select("div a").text(); + } catch (Exception e) { + 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-tab-items-box div 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("sh").equals(sourceName)) { + sourceName = flag; + found = true; + break; + } + } + if (!found) + continue; + String playList = ""; + Elements playListA = sourceList.get(i).select("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); + String vodName = vod.select("span").text(); + vodItems.add(vodName + "$" + 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", siteUrl); + 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 + "/vod/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 = pCfg.getString("pu") + player.getString("url"); + Document docs = Jsoup.parse(OkHttpUtil.string(videoUrl, getHeaders(videoUrl))); + Pattern pattern = Pattern.compile("(?<=url\"\\S\").*?(?=\")"); + Elements allScripts = docs.select("body script"); + for (int j = 0; j < allScripts.size(); j++) { + String scContents = allScripts.get(j).html().trim(); + Matcher matcher = pattern.matcher(scContents); + if (matcher.find()) { + String players = matcher.group(0); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", players); + 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 { + 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 ""; + } + + private static String FixUrl(Pattern pattern, String src) { + if (pattern == null) + return src; + try { + Matcher matcher = pattern.matcher(src); + if (matcher.find()) { + return matcher.group(0).trim(); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + return src; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/Olevod.java b/app/src/main/java/com/github/catvod/spider/Olevod.java new file mode 100644 index 0000000..82e4bbb --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Olevod.java @@ -0,0 +1,503 @@ +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 Olevod extends Spider { + private static final String siteUrl = "https://olevod.com"; + private static final String siteHost = "olevod.com"; + + + boolean pron = false; + /** + * 播放源配置 + */ + private JSONObject playerConfig; + /** + * 筛选配置 + */ + private JSONObject filterConfig; + private Pattern regexCategory = Pattern.compile("/index.php/vod/type/id/(\\d+).html"); + private Pattern regexVid = Pattern.compile("/index.php/vod/detail/id/(\\d+).html"); + private Pattern regexPlay = Pattern.compile("/index.php/vod/play/id/(\\d+)/sid/(\\d+)/nid/(\\d+).html"); + private Pattern regexPage = Pattern.compile("\\S+/page/(\\d+)\\S+"); + + @Override + public void init(Context context, String extend) { + super.init(context, extend); + if (extend != null && extend.trim().equals("ojbkporn")) { + pron = true; + } + } + + @Override + public void init(Context context) { + super.init(context); + try { + playerConfig = new JSONObject("{\"plyr\":{\"sh\":\"欧乐官方播放器\",\"sn\":0,\"pu\":\"\",\"or\":999},\"openplayer\":{\"sh\":\"欧乐影院\",\"sn\":0,\"pu\":\"\",\"or\":999},\"videojs\":{\"sh\":\"欧乐直播播放\",\"sn\":0,\"pu\":\"\",\"or\":999}}"); + filterConfig = new JSONObject("{\"1\":[{\"key\":\"tid\",\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"动作片\",\"v\":\"101\"},{\"n\":\"喜剧片\",\"v\":\"102\"},{\"n\":\"爱情片\",\"v\":\"103\"},{\"n\":\"科幻片\",\"v\":\"104\"},{\"n\":\"恐怖片\",\"v\":\"105\"},{\"n\":\"剧情片\",\"v\":\"106\"},{\"n\":\"战争片\",\"v\":\"107\"},{\"n\":\"动画片\",\"v\":\"108\"},{\"n\":\"悬疑片\",\"v\":\"109\"},{\"n\":\"惊悚片\",\"v\":\"110\"},{\"n\":\"纪录片\",\"v\":\"111\"},{\"n\":\"奇幻片\",\"v\":\"112\"},{\"n\":\"犯罪片\",\"v\":\"113\"}]},{\"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\":\"其它\"}]},{\"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\":\"lang\",\"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\":\"letter\",\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"}]},{\"key\":\"ifvip\",\"name\":\"权限\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"免费\",\"v\":\"2\"},{\"n\":\"会员\",\"v\":\"3\"}]}],\"2\":[{\"key\":\"tid\",\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"国产剧\",\"v\":\"202\"},{\"n\":\"欧美剧\",\"v\":\"201\"},{\"n\":\"港台剧\",\"v\":\"203\"},{\"n\":\"日韩剧\",\"v\":\"204\"}]},{\"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\":\"其它\"}]},{\"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\":\"lang\",\"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\":\"letter\",\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"}]},{\"key\":\"ifvip\",\"name\":\"权限\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"免费\",\"v\":\"2\"},{\"n\":\"会员\",\"v\":\"3\"}]}],\"3\":[{\"key\":\"tid\",\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"真人秀\",\"v\":\"305\"},{\"n\":\"音乐\",\"v\":\"302\"},{\"n\":\"搞笑\",\"v\":\"304\"},{\"n\":\"家庭\",\"v\":\"301\"},{\"n\":\"曲艺\",\"v\":\"303\"}]},{\"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\":\"其它\"}]},{\"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\":\"lang\",\"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\":\"letter\",\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"}]},{\"key\":\"ifvip\",\"name\":\"权限\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"免费\",\"v\":\"2\"},{\"n\":\"会员\",\"v\":\"3\"}]}],\"4\":[{\"key\":\"tid\",\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"日本\",\"v\":\"401\"},{\"n\":\"国产\",\"v\":\"402\"},{\"n\":\"欧美\",\"v\":\"403\"}]},{\"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\":\"其它\"}]},{\"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\":\"lang\",\"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\":\"letter\",\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"}]},{\"key\":\"ifvip\",\"name\":\"权限\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"免费\",\"v\":\"2\"},{\"n\":\"会员\",\"v\":\"3\"}]}],\"5\":[{\"key\":\"tid\",\"name\":\"分类\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"AV女优\",\"v\":\"505\"},{\"n\":\"日韩\",\"v\":\"502\"},{\"n\":\"欧美\",\"v\":\"501\"},{\"n\":\"动漫\",\"v\":\"503\"},{\"n\":\"国产\",\"v\":\"504\"}]},{\"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\":\"letter\",\"name\":\"字母\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"A\",\"v\":\"A\"},{\"n\":\"B\",\"v\":\"B\"},{\"n\":\"C\",\"v\":\"C\"},{\"n\":\"D\",\"v\":\"D\"},{\"n\":\"E\",\"v\":\"E\"},{\"n\":\"F\",\"v\":\"F\"},{\"n\":\"G\",\"v\":\"G\"},{\"n\":\"H\",\"v\":\"H\"},{\"n\":\"I\",\"v\":\"I\"},{\"n\":\"J\",\"v\":\"J\"},{\"n\":\"K\",\"v\":\"K\"},{\"n\":\"L\",\"v\":\"L\"},{\"n\":\"M\",\"v\":\"M\"},{\"n\":\"N\",\"v\":\"N\"},{\"n\":\"O\",\"v\":\"O\"},{\"n\":\"P\",\"v\":\"P\"},{\"n\":\"Q\",\"v\":\"Q\"},{\"n\":\"R\",\"v\":\"R\"},{\"n\":\"S\",\"v\":\"S\"},{\"n\":\"T\",\"v\":\"T\"},{\"n\":\"U\",\"v\":\"U\"},{\"n\":\"V\",\"v\":\"V\"},{\"n\":\"W\",\"v\":\"W\"},{\"n\":\"X\",\"v\":\"X\"},{\"n\":\"Y\",\"v\":\"Y\"},{\"n\":\"Z\",\"v\":\"Z\"}]},{\"key\":\"ifvip\",\"name\":\"权限\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"免费\",\"v\":\"2\"},{\"n\":\"会员\",\"v\":\"3\"}]}]}"); + } 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.top_nav li a"); + JSONArray classes = new JSONArray(); + for (Element ele : elements) { + String name = ele.text(); + boolean show = name.equals("电影") || + name.equals("连续剧") || + name.equals("动漫") || + name.equals("综艺") || + name.equals("午夜影院"); + + if (name.equals("午夜影院") && !pron) { + continue; + } + 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(0); + 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 = ""; + try { + remark = vod.select("span.pic_text em").text(); + } catch (Exception e) { + remark = vod.select("span.text_dy").get(0).text(); + } + Matcher matcher = regexVid.matcher(vod.selectFirst("a.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 + "/index.php/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 = ""; + try { + remark = vod.select("span.pic_text em").text(); + } catch (Exception e) { + remark = vod.select("span.text_dy").get(0).text(); + } + Matcher matcher = regexVid.matcher(vod.selectFirst("a.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", 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 url = siteUrl + "/index.php/vod/detail/id/" + 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("a.digg_link").attr("data-id"); + + 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.context span").text(); + String category = "", area = "", year = "", director = "", actor = "", remark = ""; + remark = doc.select("span.data_style").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 { + category = text.parent().select("a").get(2).text(); + } 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(1).text(); + } catch (Exception e) { + area = ""; + } + } + } + List actors = new ArrayList<>(); + Elements aa = doc.select("li.data").get(3).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(2).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("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) + "/sid/" + matcher.group(2) + "/nid/" + 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 + "/index.php/vod/play/id/" + 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 ""; + } + + @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"); + if (title.contains(key)) { + 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 ""; + } + + 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/Proxy.java b/app/src/main/java/com/github/catvod/spider/Proxy.java new file mode 100644 index 0000000..fd3a0bd --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Proxy.java @@ -0,0 +1,68 @@ +package com.github.catvod.spider; + +import android.util.Base64; + +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 java.io.ByteArrayInputStream; +import java.util.Map; + +public class Proxy extends Spider { + + public static int localPort = -1; + + static void adjustLocalPort() { + if (localPort > 0) + return; + int port = 9978; + while (port < 10000) { + String resp = OkHttpUtil.string("http://127.0.0.1:" + port + "/proxy?do=ck", null); + if (resp.equals("ok")) { + SpiderDebug.log("Found local server port " + port); + localPort = port; + break; + } + port++; + } + } + + public static String localProxyUrl() { + adjustLocalPort(); + return "http://127.0.0.1:" + Proxy.localPort + "/proxy"; + } + + public static Object[] proxy(Map params) { + try { + String what = params.get("do"); + if (what.equals("live")) { + String type = params.get("type"); + if (type.equals("txt")) { + String ext = params.get("ext"); + if (!ext.startsWith("http")) { + ext = new String(Base64.decode(ext, Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP), "UTF-8"); + } + return TxtSubscribe.load(ext); + } + } else if (what.equals("ck")) { + Object[] result = new Object[3]; + result[0] = 200; + result[1] = "text/plain; charset=utf-8"; + ByteArrayInputStream baos = new ByteArrayInputStream("ok".getBytes("UTF-8")); + result[2] = baos; + return result; + } else if (what.equals("push")) { + return PushAgent.vod(params); + } else if (what.equals("czspp")) { + return Czsapp.loadsub(params.get("url")); + } + + } catch (Throwable th) { + + } + 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 new file mode 100644 index 0000000..1e34978 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/PushAgent.java @@ -0,0 +1,656 @@ +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 diff --git a/app/src/main/java/com/github/catvod/spider/SP360.java b/app/src/main/java/com/github/catvod/spider/SP360.java new file mode 100644 index 0000000..674e201 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/SP360.java @@ -0,0 +1,345 @@ +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.URL; +import java.net.URLEncoder; +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; + + +public class SP360 extends Spider { + protected JSONObject ext = null; + private static final String SiteHost = "https://api.web.360kan.com/v1/rank?cat=1"; + private static final String SiteFilter = "https://api.web.360kan.com/v1/filter/list"; + private static final String SiteDetail = "https://api.web.360kan.com/v1/detail"; + private static final String SiteSearch = "https://api.so.360kan.com/index?force_v=1&kw=%s&from=&pageno=1&v_ap=1&tab=all"; + + + @Override + public void init(Context context) { + super.init(context); + try { + ext = new JSONObject("{\"classes\":[{\"type_name\":\"电影\",\"type_id\":\"1\"},{\"type_name\":\"电视剧\",\"type_id\":\"2\"},{\"type_name\":\"综艺\",\"type_id\":\"3\"},{\"type_name\":\"动漫\",\"type_id\":\"4\"}],\"filter\":{\"1\":[{\"key\":\"cat\",\"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\":\"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\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"更早\",\"v\":\"lt_year\"}]},{\"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\":\"rank\",\"name\":\"排序\",\"value\":[{\"n\":\"最近热映\",\"v\":\"rankhot\"},{\"n\":\"最近上映\",\"v\":\"ranklatest\"},{\"n\":\"最受好评\",\"v\":\"rankpoint\"}]}],\"2\":[{\"key\":\"cat\",\"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\":\"year\",\"name\":\"年代\",\"value\":[{\"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\":\"2010\",\"v\":\"2010\"},{\"n\":\"2009\",\"v\":\"2009\"},{\"n\":\"2008\",\"v\":\"2008\"},{\"n\":\"2007\",\"v\":\"2007\"},{\"n\":\"更早\",\"v\":\"lt_year\"}]},{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"内地\",\"v\":\"内地\"},{\"n\":\"中国香港\",\"v\":\"香港\"},{\"n\":\"中国台湾\",\"v\":\"台湾\"},{\"n\":\"泰国\",\"v\":\"泰国\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"韩国\",\"v\":\"韩国\"},{\"n\":\"美国\",\"v\":\"美国\"},{\"n\":\"英国\",\"v\":\"英国\"},{\"n\":\"新加坡\",\"v\":\"新加坡\"}]},{\"key\":\"rank\",\"name\":\"排序\",\"value\":[{\"n\":\"最近热映\",\"v\":\"rankhot\"},{\"n\":\"最近上映\",\"v\":\"ranklatest\"},{\"n\":\"最受好评\",\"v\":\"rankpoint\"}]}],\"3\":[{\"key\":\"cat\",\"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\":\"其他\"}]},{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"内地\",\"v\":\"大陆\"},{\"n\":\"中国香港\",\"v\":\"香港\"},{\"n\":\"中国台湾\",\"v\":\"台湾\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"欧美\",\"v\":\"欧美\"}]},{\"key\":\"rank\",\"name\":\"排序\",\"value\":[{\"n\":\"最近热映\",\"v\":\"rankhot\"},{\"n\":\"最近上映\",\"v\":\"ranklatest\"}]}],\"4\":[{\"key\":\"cat\",\"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\":\"社会\"},{\"n\":\"友情\",\"v\":\"友情\"},{\"n\":\"真人版\",\"v\":\"真人版\"},{\"n\":\"电影版\",\"v\":\"电影版\"},{\"n\":\"OVA版\",\"v\":\"OVA版\"},{\"n\":\"TV版\",\"v\":\"TV版\"},{\"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\":\"更早\",\"v\":\"更早\"}]},{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"内地\",\"v\":\"大陆\"},{\"n\":\"日本\",\"v\":\"日本\"},{\"n\":\"美国\",\"v\":\"美国\"}]},{\"key\":\"rank\",\"name\":\"排序\",\"value\":[{\"n\":\"最近热映\",\"v\":\"rankhot\"},{\"n\":\"最近上映\",\"v\":\"ranklatest\"}]}]}}"); + } catch (JSONException e) { + SpiderDebug.log(e); + } + } + + protected 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"); + return headers; + } + + @Override + public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { + String cover; + String remark; + try { + String url = SiteFilter + "?catid=" + tid + "&pageno=" + pg; + 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, Headers()); + JSONObject dataObject = new JSONObject(content).getJSONObject("data"); + JSONArray jsonArray = dataObject.getJSONArray("movies"); + JSONArray videos = new JSONArray(); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject vObj = jsonArray.getJSONObject(i); + JSONObject v = new JSONObject(); + cover = vObj.getString("cover"); + if (vObj.has("upinfo")) { + remark = vObj.getString("upinfo"); + v.put("vod_id", tid + "_" + vObj.getString("id")); + v.put("vod_name", vObj.getString("title")); + v.put("vod_pic", "https:" + cover); + v.put("vod_remarks", remark); + } else { + v.put("vod_id", tid + "_" + vObj.getString("id")); + v.put("vod_name", vObj.getString("title")); + v.put("vod_pic", "https:" + cover); + v.put("vod_remarks", ""); + } + videos.put(v); + } + JSONObject result = new JSONObject(); + int limit = 24; + int page = Integer.parseInt(dataObject.getString("current_page")); + int total = dataObject.getInt("total"); + int pageCount = total % limit == 0 ? (total / limit) : (total / limit + 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) { + Iterator it; + String str; + String str2; + Exception e2; + ArrayList arrayList = new ArrayList(); + Exception e3; + JSONObject result = new JSONObject(); + try { + String[] split = ids.get(0).split("_"); + String format = String.format("%s?cat=%s&id=%s", SiteDetail, split[0], split[1]); + JSONObject jSONObject6 = new JSONObject(OkHttpUtil.string(format, Headers())).getJSONObject("data"); + JSONArray jSONArray = new JSONArray(); + JSONObject list = new JSONObject(); + jSONArray.put(list); + result.put("list", jSONArray); + list.put("vod_id", split[0] + "_" + jSONObject6.optString("ent_id")); + list.put("vod_name", jSONObject6.optString("title")); + list.put("vod_pic", jSONObject6.optString("cdncover")); + JSONArray optJSONArray = jSONObject6.optJSONArray("moviecategory"); + ArrayList arrayList2 = new ArrayList(); + for (int i = 0; i < optJSONArray.length(); i++) { + arrayList2.add(optJSONArray.getString(i)); + } + list.put("type_name", TextUtils.join("/", arrayList2)); + list.put("vod_year", jSONObject6.optString("pubdate")); + JSONArray optJSONArray2 = jSONObject6.optJSONArray("area"); + ArrayList arrayList3 = new ArrayList(); + for (int i2 = 0; i2 < optJSONArray2.length(); i2++) { + arrayList3.add(optJSONArray2.getString(i2)); + } + list.put("vod_area", TextUtils.join("/", arrayList3)); + list.put("vod_remarks", jSONObject6.optString("doubanscore")); + JSONArray optJSONArray3 = jSONObject6.optJSONArray("actor"); + ArrayList arrayList4 = new ArrayList(); + for (int i3 = 0; i3 < optJSONArray3.length(); i3++) { + arrayList4.add(optJSONArray3.getString(i3)); + } + list.put("vod_actor", TextUtils.join("/", arrayList4)); + JSONArray optJSONArray4 = jSONObject6.optJSONArray("director"); + ArrayList arrayList5 = new ArrayList(); + for (int i4 = 0; i4 < optJSONArray4.length(); i4++) { + arrayList5.add(optJSONArray4.getString(i4)); + } + list.put("vod_director", TextUtils.join("/", arrayList5)); + list.put("vod_content", jSONObject6.optString("description")); + JSONArray optJSONArray5 = jSONObject6.optJSONArray("playlink_sites"); + ArrayList arrayList6 = new ArrayList(); + for (int i5 = 0; i5 < optJSONArray5.length(); i5++) { + arrayList6.add(optJSONArray5.getString(i5)); + } + list.put("vod_play_from", TextUtils.join("$$$", arrayList6)); + JSONObject optJSONObject = jSONObject6.optJSONObject("playlinksdetail"); + JSONObject optJSONObject2 = jSONObject6.optJSONObject("allepidetail"); + JSONArray optJSONArray6 = jSONObject6.optJSONArray("defaultepisode"); + JSONObject optJSONObject3 = jSONObject6.optJSONObject("allupinfo"); + String str7 = "vod_play_url"; + if (optJSONArray6 != null) { + ArrayList arrayList7 = new ArrayList(); + for (int i6 = 0; i6 < optJSONArray6.length(); i6++) { + try { + URL url2 = new URL(optJSONArray6.getJSONObject(i6).optString("url")); + arrayList7.add(optJSONArray6.getJSONObject(i6).optString("sort") + "$" + (url2.getProtocol() + "://" + url2.getHost() + url2.getPath())); + } catch (Exception e4) { + SpiderDebug.log(e4); + } + } + list.put(str7, TextUtils.join("#", arrayList7)); + return result.toString(); + } + if (optJSONObject2 == null) { + ArrayList arrayList8 = new ArrayList(); + for (String str8 : arrayList6) { + try { + URL url3 = new URL(optJSONObject.getJSONObject(str8).optString("default_url")); + arrayList8.add(optJSONObject.getJSONObject(str8).optString("sort") + "$" + (url3.getProtocol() + "://" + url3.getHost() + url3.getPath())); + } catch (Exception e5) { + SpiderDebug.log(e5); + } + } + list.put(str7, TextUtils.join("$$$", arrayList8)); + } else { + ArrayList videos = new ArrayList(); + Iterator it2 = arrayList6.iterator(); + while (it2.hasNext()) { + String str9 = (String) it2.next(); + int parseInt = Integer.parseInt(optJSONObject3.optString(str9, "0")); + if (parseInt > 50 || parseInt == 0) { + it = it2; + str = format + "&start=1&end=50&site=" + str9; + } else { + StringBuilder sb2 = new StringBuilder(); + sb2.append(format); + it = it2; + sb2.append("&start=1&end="); + sb2.append(parseInt); + sb2.append("&site="); + sb2.append(str9); + str = sb2.toString(); + } + JSONObject optJSONObject4 = new JSONObject(OkHttpUtil.string(str, Headers())).getJSONObject("data").optJSONObject("allepidetail"); + ArrayList arrayList10 = new ArrayList(); + JSONArray jSONArray2 = optJSONObject4.getJSONArray(str9); + int i7 = 0; + while (true) { + str2 = str7; + if (i7 >= jSONArray2.length()) { + break; + } + try { + String url5 = jSONArray2.getJSONObject(i7).optString("url"); + arrayList = videos; + arrayList10.add(jSONArray2.getJSONObject(i7).optString("playlink_num") + "$" + url5); + } catch (Exception e7) { + e3 = e7; + SpiderDebug.log(e3); + i7++; + } + i7++; + str7 = str2; + videos = arrayList; + } + ArrayList arrayList11 = videos; + if (parseInt >= jSONArray2.length()) { + int i8 = 51; + while (i8 < parseInt) { + int i9 = i8 + 49; + if (i9 > parseInt) { + i9 = parseInt; + } + JSONObject optJSONObject5 = new JSONObject(OkHttpUtil.string(String.format("%s?cat=%s&id=%s&start=%s&end=%s&site=%s", SiteDetail, split[0], split[1], Integer.valueOf(i8), Integer.valueOf(i9), str9), Headers())).optJSONObject("data"); + if (optJSONObject5 == null) { + break; + } + JSONArray jSONArray3 = optJSONObject5.getJSONObject("allepidetail").getJSONArray(str9); + int i10 = 0; + while (i10 < jSONArray3.length()) { + try { + String url4 = jSONArray3.getJSONObject(i10).optString("url"); + try { + arrayList10.add(jSONArray3.getJSONObject(i10).optString("playlink_num") + "$" + url4); + } catch (Exception e8) { + e2 = e8; + SpiderDebug.log(e2); + i10++; + } + } catch (Exception e9) { + } + i10++; + } + i8 = i9 + 1; + } + } + arrayList11.add(TextUtils.join("#", arrayList10)); + videos = arrayList11; + it2 = it; + str7 = str2; + } + list.put(str7, TextUtils.join("$$$", videos)); + } + return result.toString(); + } catch (Exception e10) { + SpiderDebug.log(e10); + return ""; + } + } + + @Override + public String homeContent(boolean filter) { + JSONObject results = new JSONObject(); + try { + results.put("class", ext.getJSONArray("classes")); + if (filter) { + results.put("filters", ext.getJSONObject("filter")); + } + } catch (JSONException e2) { + SpiderDebug.log(e2); + } + return results.toString(); + } + + @Override + public String homeVideoContent() { + JSONObject list = new JSONObject(); + try { + String str = SiteHost; + String i = OkHttpUtil.string(str, new HashMap()); + SpiderDebug.log("响应请求:" + str); + JSONArray optJSONArray = new JSONObject(i).optJSONArray("data"); + JSONArray jSONArray = new JSONArray(); + for (int j = 0; j < optJSONArray.length(); j++) { + JSONObject jSONObject2 = optJSONArray.getJSONObject(j); + JSONObject VideoAtom = new JSONObject(); + VideoAtom.put("vod_id", jSONObject2.optString("cat") + "_" + jSONObject2.optString("ent_id")); + VideoAtom.put("vod_name", jSONObject2.optString("title")); + VideoAtom.put("vod_pic", jSONObject2.optString("cover")); + VideoAtom.put("vod_remarks", jSONObject2.optString("upinfo")); + jSONArray.put(VideoAtom); + } + list.put("list", jSONArray); + } catch (Exception e2) { + SpiderDebug.log(e2); + } + return list.toString(); + } + + @Override + public String playerContent(String str, String str2, List list) { + JSONObject result = new JSONObject(); + try { + result.put("parse", 1); + result.put("url", str2); + result.put("jx", "1"); + result.put("playUrl", ""); + } catch (Exception e2) { + SpiderDebug.log(e2); + } + return result.toString(); + } + + @Override + public String searchContent(String str, boolean filter) { + JSONObject optJSONObject; + JSONObject list = new JSONObject(); + try { + JSONObject optJSONObject2 = new JSONObject(OkHttpUtil.string(String.format(SiteSearch, str), Headers())).optJSONObject("data"); + if (!(optJSONObject2 == null || (optJSONObject = optJSONObject2.optJSONObject("longData")) == null)) { + JSONArray jSONArray = optJSONObject.getJSONArray("rows"); + JSONArray videos = new JSONArray(); + list.put("list", videos); + for (int i = 0; i < jSONArray.length(); i++) { + JSONObject Obj = jSONArray.getJSONObject(i); + JSONObject v = new JSONObject(); + v.put("vod_id", Obj.optString("cat_id") + "_" + Obj.optString("en_id")); + v.put("vod_name", Obj.optString("titleTxt")); + v.put("vod_pic", Obj.optString("cover")); + v.put("vod_remarks", Obj.optString("score")); + videos.put(v); + } + } + } catch (Exception e2) { + SpiderDebug.log(e2); + } + return list.toString(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/Smdyy.java b/app/src/main/java/com/github/catvod/spider/Smdyy.java new file mode 100644 index 0000000..51fc818 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Smdyy.java @@ -0,0 +1,514 @@ +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.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: baddychen + */ +public class Smdyy extends Spider { + private static final String siteUrl = "https://www.smdyy.cc"; + /** + * 播放源配置 + */ + private JSONObject playerConfig; + /** + * 筛选配置 + */ + private JSONObject filterConfig; + private Pattern regexCategory = Pattern.compile("/list/(\\d+).html"); + private Pattern regexVid = Pattern.compile("/kan/(\\d+).html"); + private Pattern regexPlay = Pattern.compile("/play/(\\d+)-(\\d+)-(\\d+).html"); + private Pattern regexPage = Pattern.compile("/show/(\\S+).html"); + + protected String ext = null; + + @Override + public void init(Context context) { + super.init(context); + try { + playerConfig = new JSONObject("{\"duoduozy\":{\"show\":\"高清线路\",\"or\":999,\"ps\":\"0\",\"parse\":\"https://player.6080kan.cc/player/play.php?url=\"},\"sohu\":{\"show\":\"优选7\",\"or\":999,\"ps\":\"0\",\"parse\":\"https://player.6080kan.cc/player/play.php?url=\"},\"qq\":{\"show\":\"优选3\",\"or\":999,\"ps\":\"0\",\"parse\":\"https://player.6080kan.cc/player/play.php?url=\"},\"bilibili\":{\"show\":\"bilibili\",\"or\":999,\"ps\":\"0\",\"parse\":\"https://player.6080kan.cc/player/play.php?url=\"},\"youku\":{\"show\":\"优选1\",\"or\":999,\"ps\":\"0\",\"parse\":\"https://player.6080kan.cc/player/play.php?url=\"},\"qiyi\":{\"show\":\"优选2\",\"or\":999,\"ps\":\"0\",\"parse\":\"https://player.6080kan.cc/player/play.php?url=\"},\"letv\":{\"show\":\"优选6\",\"or\":999,\"ps\":\"0\",\"parse\":\"https://player.6080kan.cc/player/play.php?url=\"},\"xigua\":{\"show\":\"西瓜视频\",\"or\":999,\"ps\":\"0\",\"parse\":\"https://player.6080kan.cc/player/play.php?url=\"},\"mgtv\":{\"show\":\"优选4\",\"or\":999,\"ps\":\"0\",\"parse\":\"https://player.6080kan.cc/player/play.php?url=\"},\"tkm3u8\":{\"show\":\"备用\",\"or\":999,\"ps\":\"0\",\"parse\":\"https://player.6080kan.cc/player/play.php?url=\"},\"pptv\":{\"show\":\"优选5\",\"or\":999,\"ps\":\"0\",\"parse\":\"https://player.6080kan.cc/player/play.php?url=\"}}"); + filterConfig = new JSONObject("{\"1\":[{\"key\":\"tid\",\"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\":\"20\"},{\"n\":\"惊悚片\",\"v\":\"21\"},{\"n\":\"冒险片\",\"v\":\"22\"},{\"n\":\"悬疑片\",\"v\":\"23\"},{\"n\":\"武侠片\",\"v\":\"24\"},{\"n\":\"奇幻片\",\"v\":\"25\"},{\"n\":\"纪录片\",\"v\":\"26\"},{\"n\":\"动画片\",\"v\":\"27\"}]},{\"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\":\"\"}]}],\"2\":[{\"key\":\"tid\",\"name\":\"类型\",\"value\":[{\"n\":\"全部\",\"v\":\"2\"},{\"n\":\"国产剧\",\"v\":\"13\"},{\"n\":\"港台剧\",\"v\":\"14\"},{\"n\":\"日韩剧\",\"v\":\"15\"},{\"n\":\"欧美剧\",\"v\":\"16\"},{\"n\":\"泰国剧\",\"v\":\"28\"}]},{\"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\":\"其他\"}]},{\"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\":\"\"}]}],\"4\":[{\"key\":\"3\",\"name\":\"剧情\",\"value\":[{\"n\":\"全部\",\"v\":\"3\"},{\"n\":\"情感\",\"v\":\"情感\"},{\"n\":\"科幻\",\"v\":\"科幻\"},{\"n\":\"热血\",\"v\":\"热血\"},{\"n\":\"推理\",\"v\":\"推理\"},{\"n\":\"搞笑\",\"v\":\"搞笑\"},{\"n\":\"冒险\",\"v\":\"冒险\"},{\"n\":\"萝莉\",\"v\":\"萝莉\"},{\"n\":\"校园\",\"v\":\"校园\"},{\"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\":\"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\":\"\"}]}]}"); + } 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("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 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))); + // 分类节点 + Elements elements = doc.select("ul.stui-header__menu > 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("动漫"); + } + 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 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(".stui-vodlist__thumb").attr("title"); + String cover = vod.selectFirst(".stui-vodlist__thumb").attr("data-original"); + String remark = vod.selectFirst("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[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 + "/show/" + 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.stui-page__item 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; + 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; + } + } + String wy = doc.select("ul.stui-page__item li a").last().attr("href"); + Matcher matcher = regexPage.matcher(wy); + 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(".stui-vodlist__thumb").attr("title"); + String cover = vod.selectFirst(".stui-vodlist__thumb").attr("data-original"); + if (!TextUtils.isEmpty(cover) && !cover.startsWith("http")) { + cover = siteUrl + cover; + } + 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 ""; + } + + + 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 + "/kan/" + 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.pic 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 = Regex(Pattern.compile("类型:(\\S+)"), data.get(0).text()); + area = Regex(Pattern.compile("地区:(\\S+)"), data.get(0).text()); + year = Regex(Pattern.compile("年份:(\\S+)"), data.get(0).text()); + actor = Regex(Pattern.compile("主演:(\\S+)"), data.get(1).text()); + director = Regex(Pattern.compile("导演:(\\S+)"), data.get(1).text()); + + 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-vodlist__head"); + //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.selectFirst("h3").text().trim(); + 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 = 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 + */ + + private final Pattern urlt = Pattern.compile("\"url\": *\"([^\"]*)\","); + private final Pattern token = Pattern.compile("\"token\": *\"([^\"]*)\""); + private final Pattern vkey = Pattern.compile("\"vkey\": *\"([^\"]*)\","); + + @Override + public String playerContent(String flag, String id, List vipFlags) { + try { + JSONObject headers = new JSONObject(); + headers.put("Referer", " https://www.smdyy.cc/"); + 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(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/?url=" + player.getString("url"); + String jxurl = pCfg.getString("parse") + player.getString("url"); + Document doc = Jsoup.parse(OkHttpUtil.string(jxurl, getHeaders(jxurl))); + Elements script = doc.select("body>script"); + for (int j = 0; j < script.size(); j++) { + String Content = script.get(j).html().trim(); + Matcher matcher = urlt.matcher(Content); + if (!matcher.find()) { + return ""; + } + String urlt = matcher.group(1); + Matcher matcher1 = token.matcher(Content); + if (!matcher1.find()) { + return ""; + } + String token = matcher1.group(1); + Matcher matcher2 = vkey.matcher(Content); + if (!matcher2.find()) { + return ""; + } + String vkey = matcher2.group(1); + HashMap hashMap = new HashMap(); + hashMap.put("token", token); + hashMap.put("url", urlt); + hashMap.put("vkey", vkey); + hashMap.put("sign", "smdyycc"); + OkHttpUtil.post(OkHttpUtil.defaultClient(), "https://player.6080kan.cc/player/xinapi.php", hashMap, new OKCallBack.OKCallBackString() { + @Override + protected void onFailure(Call call, Exception exc) { + } + + public void onResponse(String str) { + try { + String url = new String(Base64.decode(new JSONObject(str).getString("url").substring(8).getBytes(), 0)); + result.put("url", url.substring(8, url.length() - 8)); + } catch (JSONException e) { + e.printStackTrace(); + } + } + }); + result.put("header", headers.toString()); + result.put("parse", 0); + result.put("playUrl", ""); + + } + } + } + } + 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/XBiubiu.java b/app/src/main/java/com/github/catvod/spider/XBiubiu.java new file mode 100644 index 0000000..623a671 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/XBiubiu.java @@ -0,0 +1,431 @@ +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 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 XBiubiu 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("UserW", 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(); + String webUrl = getRuleVal("url") + tid + pg + getRuleVal("houzhui"); + String html = fetch(webUrl); + 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 = 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); + } + } + 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); + 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 = getRuleVal("url") + idInfo[2]; + String html = fetch(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<>(); + + 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; + } + } + + String cover = idInfo[1], title = idInfo[0], area = ""; + String director = ""; + String actor = ""; + String desc = ""; + String remark = ""; + String year = ""; + String category = ""; + + 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<>(); + + for (int i = 0; i < playList.size(); i++) { + playFrom.add("播放列表" + (i + 1)); + } + + 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 = 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); + JSONObject v = new JSONObject(); + v.put("vod_id", name + "$$$" + pic + "$$$" + getRuleVal("sousuohouzhui") + id); + 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); + 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<>(); + try { + Pattern pattern = Pattern.compile(startFlag + "(.*?)" + endFlag); + Matcher matcher = pattern.matcher(content); + while (matcher.find()) { + result.add(matcher.group(1)); + } + } catch (Throwable th) { + th.printStackTrace(); + } + return result; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/XPath.java b/app/src/main/java/com/github/catvod/spider/XPath.java new file mode 100644 index 0000000..cd29071 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/XPath.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 XPath 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", 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 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<>(); + 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", 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", 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"}; + + @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/XPathFilter.java b/app/src/main/java/com/github/catvod/spider/XPathFilter.java new file mode 100644 index 0000000..76e75c1 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/XPathFilter.java @@ -0,0 +1,36 @@ +package com.github.catvod.spider; + +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Iterator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class XPathFilter extends XPath { + + @Override + protected void loadRuleExt(String json) { + super.loadRuleExt(json); + } + + @Override + protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) { + String cateUrl = rule.getCateUrl(); + 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; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/XPathMac.java b/app/src/main/java/com/github/catvod/spider/XPathMac.java new file mode 100644 index 0000000..f36ed55 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/XPathMac.java @@ -0,0 +1,196 @@ +package com.github.catvod.spider; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Base64; + +import com.github.catvod.crawler.SpiderDebug; +import com.github.catvod.utils.Misc; + +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.URLDecoder; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class XPathMac extends XPath { + // 尝试分析直连 + private boolean decodePlayUrl; + // 尝试匹配官源标识以调用应用配置中的解析列表 + private boolean decodeVipFlag; + // 播放器配置js + private String playerConfigJs = ""; + // 播放器配置js取值正则 + private String playerConfigJsRegex = "[\\W|\\S|.]*?MacPlayerConfig.player_list[\\W|\\S|.]*?=([\\W|\\S|.]*?),MacPlayerConfig.downer_list"; + // 站点里播放源对应的真实官源 + private HashMap show2VipFlag = new HashMap<>(); + + /** + * mac cms 直连和官源调用应用内播放列表支持 + * + * @param context + * @param extend + */ + public void init(Context context, String extend) { + super.init(context, extend); + + } + + @Override + protected void loadRuleExt(String json) { + try { + JSONObject jsonObj = new JSONObject(json); + decodePlayUrl = jsonObj.optBoolean("dcPlayUrl", false); + decodeVipFlag = jsonObj.optBoolean("dcVipFlag", false); + JSONObject dcShow2Vip = jsonObj.optJSONObject("dcShow2Vip"); + if (dcShow2Vip != null) { + Iterator keys = dcShow2Vip.keys(); + while (keys.hasNext()) { + String name = keys.next(); + show2VipFlag.put(name.trim(), dcShow2Vip.getString(name).trim()); + } + } + playerConfigJs = jsonObj.optString("pCfgJs").trim(); + playerConfigJsRegex = jsonObj.optString("pCfgJsR", playerConfigJsRegex).trim(); + } catch (JSONException e) { + SpiderDebug.log(e); + } + } + + @Override + public String homeContent(boolean filter) { + String result = super.homeContent(filter); + if (result.length() > 0 && playerConfigJs.length() > 0) { // 尝试通过playerConfigJs获取展示和flag匹配关系 + String webContent = fetch(playerConfigJs); + Matcher matcher = Pattern.compile(playerConfigJsRegex).matcher(webContent); + if (matcher.find()) { + try { + JSONObject jsonObject = new JSONObject(matcher.group(1)); + Iterator keys = jsonObject.keys(); + while (keys.hasNext()) { + String key = keys.next(); + JSONObject keyObj = jsonObject.optJSONObject(key); + if (keyObj == null) + continue; + String show = keyObj.optString("show").trim(); + if (show.isEmpty()) + continue; + show2VipFlag.put(show, key); + } + } catch (Exception e) { + SpiderDebug.log(e); + } + } + // SpiderDebug.log(webContent); + } + return result; + } + + @Override + public String detailContent(List ids) { + String result = super.detailContent(ids); + if (decodeVipFlag && result.length() > 0) { + try { + JSONObject jsonObject = new JSONObject(result); + String playFrom[] = jsonObject.optJSONArray("list").getJSONObject(0).optString("vod_play_from").split("\\$\\$\\$"); + if (playFrom.length > 0) { + for (int i = 0; i < playFrom.length; i++) { + if (show2VipFlag.containsKey(playFrom[i])) { + playFrom[i] = show2VipFlag.get(playFrom[i]); + } + } + jsonObject.optJSONArray("list").getJSONObject(0).put("vod_play_from", TextUtils.join("$$$", playFrom)); + result = jsonObject.toString(); + } + } catch (Throwable th) { + SpiderDebug.log(th); + } + } + return result; + } + + + @Override + public String playerContent(String flag, String id, List vipFlags) { + fetchRule(); + String webUrl = rule.getPlayUrl().isEmpty() ? id : rule.getPlayUrl().replace("{playUrl}", id); + String videoUrl = null; + // 尝试分析直连 + if (decodePlayUrl) { + 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"); + 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); + } + } + if (videoUrl != null) { + // 适配2.0.6的调用应用内解析列表的支持, 需要配合直连分析和匹配官源解析一起使用,参考cjt影视和极品直连 + if (decodeVipFlag && Misc.isVip(videoUrl)) { // 使用jx:1 + try { + JSONObject result = new JSONObject(); + result.put("parse", 1); + result.put("jx", "1"); + result.put("url", videoUrl); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + } else if (decodeVipFlag && vipFlags.contains(flag)) { // 是否使用应用内解析列表解析官源 + try { + JSONObject result = new JSONObject(); + result.put("parse", 1); + result.put("playUrl", ""); + result.put("url", videoUrl); + result.put("header", ""); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + // 如果是视频直连 直接返回免解 + else if (isVideoFormat(videoUrl)) { + try { + JSONObject result = new JSONObject(); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", videoUrl); + result.put("header", ""); + return result.toString(); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + } + // 上述都失败了就按默认模式走 + return super.playerContent(flag, id, vipFlags); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/XPathMacFilter.java b/app/src/main/java/com/github/catvod/spider/XPathMacFilter.java new file mode 100644 index 0000000..3cedd20 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/XPathMacFilter.java @@ -0,0 +1,30 @@ +package com.github.catvod.spider; + +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Iterator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class XPathMacFilter extends XPathMac { + @Override + protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) { + String cateUrl = rule.getCateUrl(); + 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; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/XPbd.java b/app/src/main/java/com/github/catvod/spider/XPbd.java new file mode 100644 index 0000000..c6c2905 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/XPbd.java @@ -0,0 +1,154 @@ +package com.github.catvod.spider; + +import android.text.TextUtils; + +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.seimicrawler.xpath.JXDocument; +import org.seimicrawler.xpath.JXNode; + +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class XPbd extends XPath { + + @Override + protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) { + String cateUrl = rule.getCateUrl(); + 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; + } + + @Override + public String detailContent(List ids) { + try { + String webUrl = rule.getDetailUrl().replace("{vid}", ids.get(0)); + String webContent = fetch(webUrl); + JXDocument doc = JXDocument.create(webContent); + JXNode vodNode = doc.selNOne(rule.getDetailNode()); + JSONObject vodAtom = new JSONObject(); + + 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); + } + } + + vodAtom.put("vod_name", title); + vodAtom.put("vod_pic", cover); + vodAtom.put("type_name", category); + vodAtom.put("vod_year", year); + vodAtom.put("vod_area", area); + vodAtom.put("vod_remarks", remark); + vodAtom.put("vod_actor", actor); + vodAtom.put("vod_director", director); + vodAtom.put("vod_content", desc); + + List urlListNodes = doc.selN(rule.getDetailUrlNode()); + for (int i = 0; i < urlListNodes.size(); i++) { + List urlNodes = urlListNodes.get(i).sel(rule.getDetailUrlSubNode()); + for (int j = 0; j < urlNodes.size(); j++) { + String id = urlNodes.get(j).selOne(rule.getDetailUrlId()).asString().trim(); + id = rule.getDetailUrlIdR(id); + JSONObject result = new JSONObject(); + JSONArray lists = new JSONArray(); + vodAtom.put("vod_id", id); + vodAtom.put("vod_play_from", "磁力测试"); + vodAtom.put("vod_play_url", "网站没资源$" + id); + lists.put(vodAtom); + result.put("list", lists); + return result.toString(); + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + return ""; + } + +} diff --git a/app/src/main/java/com/github/catvod/spider/Xiaoh.java b/app/src/main/java/com/github/catvod/spider/Xiaoh.java new file mode 100644 index 0000000..8f543d0 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Xiaoh.java @@ -0,0 +1,471 @@ +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; + +public class Xiaoh extends Spider { + private static final String siteUrl = "https://www.xiaoheimi.net"; + private static final String siteHost = "www.xiaoheimi.net"; + + /** + * 播放源配置 + */ + private JSONObject playerConfig; + /** + * 筛选配置 + */ + private JSONObject filterConfig; + private Pattern regexCategory = Pattern.compile("/index.php/vod/type/id/(\\d+).html"); + private Pattern regexVid = Pattern.compile("/index.php/vod/detail/id/(\\d+).html"); + private Pattern regexPlay = Pattern.compile("/index.php/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("{\"gqy2\":{\"sh\":\"高清2\",\"sn\":0,\"pu\":\"\",\"or\":999},\"xbyy\":{\"sh\":\"高清\",\"sn\":0,\"pu\":\"\",\"or\":999},\"ysgc\":{\"sh\":\"高清源\",\"sn\":0,\"pu\":\"\",\"or\":999},\"if101\":{\"sh\":\"小宝影院\",\"sn\":0,\"pu\":\"\",\"or\":999},\"bili\":{\"sh\":\"bili\",\"sn\":0,\"pu\":\"\",\"or\":999},\"dplayer\":{\"sh\":\"DPlayer-H5播放器\",\"sn\":0,\"pu\":\"\",\"or\":999}}"); + filterConfig = new JSONObject("{\"1\":[{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"大陆\",\"v\":\"大陆\"},{\"n\":\"港台\",\"v\":\"港台\"},{\"n\":\"日韩\",\"v\":\"日韩\"},{\"n\":\"欧美\",\"v\":\"欧美\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"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\":\"战争片\"}]},{\"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\"}]},{\"key\":\"lang\",\"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\":\"其它\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"2\":[{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"大陆\",\"v\":\"大陆\"},{\"n\":\"港台\",\"v\":\"港台\"},{\"n\":\"日韩\",\"v\":\"日韩\"},{\"n\":\"欧美\",\"v\":\"欧美\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"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\":\"剧情\"},{\"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\"}]},{\"key\":\"lang\",\"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\":\"其它\"}]},{\"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\":\"其它\"}]},{\"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\":\"其它\"}]},{\"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\"}]},{\"key\":\"lang\",\"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\":\"其它\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"3\":[{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"大陆\",\"v\":\"大陆\"},{\"n\":\"港台\",\"v\":\"港台\"},{\"n\":\"日韩\",\"v\":\"日韩\"},{\"n\":\"欧美\",\"v\":\"欧美\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"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\":\"其它\"}]},{\"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\"}]},{\"key\":\"lang\",\"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\":\"其它\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"21\":[{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"n\":\"全部\",\"v\":\"\"},{\"n\":\"大陆\",\"v\":\"大陆\"},{\"n\":\"港台\",\"v\":\"港台\"},{\"n\":\"日韩\",\"v\":\"日韩\"},{\"n\":\"欧美\",\"v\":\"欧美\"},{\"n\":\"其它\",\"v\":\"其它\"}]},{\"key\":\"class\",\"name\":\"分类\",\"value\":[{\"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\"}]},{\"key\":\"lang\",\"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\":\"其它\"}]},{\"key\":\"by\",\"name\":\"排序\",\"value\":[{\"n\":\"时间\",\"v\":\"time\"},{\"n\":\"人气\",\"v\":\"hits\"},{\"n\":\"评分\",\"v\":\"score\"}]}],\"20\":[{\"key\":\"area\",\"name\":\"地区\",\"value\":[{\"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\"}]},{\"key\":\"lang\",\"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\":\"其它\"}]},{\"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("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("综艺") || + 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(1); + Elements list = homeList.select("div.myui-vodlist__box>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 url = siteUrl + "/index.php/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(".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("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 + "/index.php/vod/detail/id/" + 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) + "/sid/" + matcher.group(2) + "/nid/" + 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 + "/index.php/vod/play/id/" + 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 ""; + } + + + 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("Referer", siteUrl); + return headers; + } + + @Override + public String searchContent(String key, boolean quick) { + try { + String url = "https://www.google.com/search?q=site%3A" + siteHost + "+" + URLEncoder.encode(key); + Document doc = Jsoup.parse(OkHttpUtil.string(url, Headers())); + JSONObject result = new JSONObject(); + JSONArray videos = new JSONArray(); + Elements sourceList = doc.select("div.yuRUbf a"); + for (int i = 0; i < sourceList.size(); i++) { + Element sourcess = sourceList.get(i); + String sourceName = sourcess.select("h3").text(); + String list1 = sourcess.attr("href"); + Matcher matcher = regexVid.matcher(list1); + if (sourceName.contains(key) && matcher.find()) { + Document ddrklink = Jsoup.parse(OkHttpUtil.string(list1, getHeaders(list1))); + JSONObject v = new JSONObject(); + String group = matcher.group(1); + String cover = ddrklink.selectFirst("a.myui-vodlist__thumb img").attr("data-original"); + String title = ddrklink.selectFirst("div.myui-content__detail h1.title").text(); + Elements span_text_muted = ddrklink.select("div.myui-content__detail span.text-muted"); + for (int j = 0; j < span_text_muted.size(); j++) { + Element text = span_text_muted.get(j); + String info = text.text(); + if (info.equals("更新:")) { + String remark = text.nextElementSibling().text(); + v.put("vod_name", title); + 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 ""; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/Xxys.java b/app/src/main/java/com/github/catvod/spider/Xxys.java new file mode 100644 index 0000000..e4af42c --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Xxys.java @@ -0,0 +1,77 @@ +package com.github.catvod.spider; + +import android.content.Context; + + +import com.github.catvod.utils.Misc; +import com.github.catvod.utils.okhttp.OkHttpUtil; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; + +import java.util.regex.Pattern; + +public class Xxys extends AppYsV2 { + + @Override + protected JSONObject getFinalVideo(String flag, ArrayList parseUrls, String url) throws JSONException { + String htmlPlayUrl = ""; + for (String parseUrl : parseUrls) { + if (parseUrl.isEmpty() || parseUrl.equals("null")) + continue; + String playUrl = parseUrl + url; + String content = desc(OkHttpUtil.string(playUrl, null), (byte) 4); + try { + HashMap hashMap = new HashMap(); + OkHttpUtil.stringNoRedirect(playUrl, null, hashMap); + String d = OkHttpUtil.getRedirectLocation(hashMap); + JSONObject result = new JSONObject(); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", d); + return result; + } catch (JSONException e) { + e.printStackTrace(); + } + JSONObject tryJson = null; + try { + tryJson = Misc.jsonParse(url, content); + } catch (Throwable th) { + + } + if (tryJson != null && tryJson.has("url") && tryJson.has("header")) { + tryJson.put("header", tryJson.getJSONObject("header").toString()); + return tryJson; + } + if (content.contains(" list) { + try { + Pattern pattern = aliyun; + if (pattern.matcher(list.get(0)).find()) { + return pushAgent.detailContent(list); + } + Matcher matcher = pattern.matcher(OkHttpUtil.string("https://zhaoziyuan.me/" + list.get(0), null)); + if (!matcher.find()) { + return ""; + } + list.set(0, matcher.group(1)); + return pushAgent.detailContent(list); + } catch (Exception e) { + SpiderDebug.log(e); + } + return ""; + } + + public void init(Context context, String str) { + super.init(context, str); + pushAgent = new PushAgent(); + pushAgent.init(context, str); + } + + 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 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.62 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; + } + + private Pattern regexVid = Pattern.compile("(\\S+)"); + + public String searchContent(String key, boolean quick) { + try { + String url = "https://zhaoziyuan.me/so?filename=" + URLEncoder.encode(key); + Document docs = Jsoup.parse(OkHttpUtil.string(url, null)); + JSONObject result = new JSONObject(); + JSONArray videos = new JSONArray(); + Elements list = docs.select("div.li_con div.news_text"); + for (int i = 0; i < list.size(); i++) { + Element doc = list.get(i); + String sourceName = doc.select("div.news_text a h3").text(); + if (sourceName.contains(key)) { + String list1 = doc.select("div.news_text a").attr("href"); + Matcher matcher = regexVid.matcher(list1); + if (matcher.find()) { + JSONObject v = new JSONObject(); + String group = matcher.group(1); + String cover = "https://inews.gtimg.com/newsapp_bt/0/13263837859/1000"; + String remark = doc.select("div.news_text a p").text(); + + v.put("vod_name", sourceName); + 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 ""; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/Zxzj.java b/app/src/main/java/com/github/catvod/spider/Zxzj.java new file mode 100644 index 0000000..c75fb37 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Zxzj.java @@ -0,0 +1,486 @@ +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; + +public class Zxzj extends Spider { + private static final String siteUrl = "https://zxzj.vip/"; + /** + * 播放源配置 + */ + private JSONObject playerConfig; + /** + * 筛选配置 + */ + private JSONObject filterConfig; + private Pattern regexCategory = Pattern.compile("/list/(\\d+).html"); + private Pattern regexVid = Pattern.compile("/detail/(\\d+).html"); + private Pattern regexPlay = Pattern.compile("/video/(\\d+)-(\\d+)-(\\d+).html"); + private Pattern regexPage = Pattern.compile("/vodshow/(\\S+).html"); + + protected String ext = null; + + @Override + public void init(Context context) { + super.init(context); + try { + playerConfig = new JSONObject("{\"dpp\":{\"sh\":\"DP播放\",\"pu\":\"https://jx.zxzj.vip/dplayer.php?url=\",\"sn\":1,\"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\":\"情色\"}]},{\"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\":\"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\":\"其他\"}]},{\"key\":\"4\",\"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\"}]}],\"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\":\"其他\"}]},{\"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\":\"其他\"}]},{\"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\"}]}],\"6\":[{\"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\":\"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\"}]}],\"5\":[{\"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\":\"其他\"}]},{\"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\"}]}]}"); + } catch (JSONException e) { + SpiderDebug.log(e); + } + } + + + 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("Referer", siteUrl); + return headers; + } + + /** + * 爬虫headers + * + * @param url + * @return + */ + protected HashMap getHeaders(String url) { + HashMap headers = new HashMap<>(); + headers.put("method", "GET"); + 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.stui-header__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("日剧") || + 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.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); + String title = vod.select("a").attr("title"); + String cover = vod.select("a").attr("data-original"); + String remark = vod.select("a .pic-text").text(); + Matcher matcher = regexVid.matcher(vod.select("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 + "vodshow/" + 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.stui-page__item 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()) { + //System.out.println("哈哈"+matcher.group(1)); + page = Integer.parseInt(matcher.group(1).split("-")[8]); + } else { + page = 0; + } + } + if (name.equals("尾页")) { + Matcher matcher = regexPage.matcher(a.attr("href")); + if (matcher.find()) { + //System.out.println("尾页" + matcher.group(1)); + pageCount = Integer.parseInt(matcher.group(1).split("-")[8]); + } 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.select("a").attr("title"); + String cover = vod.select("a").attr("data-original"); + String remark = vod.select("a .pic-text").text(); + Matcher matcher = regexVid.matcher(vod.select("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 + "/detail/" + ids.get(0) + ".html"; + Document doc = Jsoup.parse(OkHttpUtil.string(url, getHeaders(url))); + JSONObject result = new JSONObject(); + JSONObject vodList = new JSONObject(); + + // 取基本数据 + String cover = doc.select("div.stui-content__thumb a img").attr("data-original"); + String title = doc.select("div.stui-content__detail h1").text(); + String category = "", area = "", year = "", remark = "", director = "", actor = "", desc = ""; + Elements data = doc.select("p.data"); + Pattern cate = Pattern.compile("类型:(\\S+)"); + category = doReplaceRegex(cate, data.get(0).text()); + Pattern areas = Pattern.compile("地区:(\\S+)"); + area = doReplaceRegex(areas, data.get(0).text()); + Pattern years = Pattern.compile("年份:(\\S+)"); + year = doReplaceRegex(years, data.get(0).text()); + Pattern rms = Pattern.compile("更新:(\\S+)"); + remark = doReplaceRegex(rms, data.get(3).text()); + Pattern acs = Pattern.compile("主演:(\\S+)"); + actor = doReplaceRegex(acs, data.get(1).text()); + Pattern dis = Pattern.compile("导演:(\\S+)"); + director = doReplaceRegex(dis, data.get(2).text()); + + desc = doc.selectFirst("span.detail-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-vodlist__head h3"); + Elements sourceList = doc.select("ul.stui-content__playlist"); + + 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://zxzj.vip"); + 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 + "/video/" + 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 = pCfg.getString("pu") + player.getString("url"); + Document docs = Jsoup.parse(OkHttpUtil.string(videoUrl, getHeaders(videoUrl))); + Pattern pattern = Pattern.compile("(?<=urls\\s=\\s').*?(?=')"); + Elements allScripts = docs.select("body script"); + for (int j = 0; j < allScripts.size(); j++) { + String scContents = allScripts.get(j).html().trim(); + Matcher matcher = pattern.matcher(scContents); + if (matcher.find()) { + String players = matcher.group(0); + result.put("parse", 0); + result.put("playUrl", ""); + result.put("url", players); + result.put("header", headers.toString()); + } + 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 { + String url = siteUrl + "/vodsearch/-------------.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.stui-vodlist__box"); + for (int i = 0; i < list.size(); i++) { + Element vod = list.get(i); + String title = vod.select("a").attr("title"); + if (title.contains(key)) { + String cover = vod.select("a").attr("data-original"); + Matcher matcher = regexVid.matcher(vod.select("a").attr("href")); + if (!matcher.find()) + continue; + String id = matcher.group(1); + JSONObject v = new JSONObject(); + String remark = vod.select("a span.pic-text").text(); + 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; + } +} diff --git a/app/src/main/java/com/github/catvod/utils/AES.java b/app/src/main/java/com/github/catvod/utils/AES.java new file mode 100644 index 0000000..d20028b --- /dev/null +++ b/app/src/main/java/com/github/catvod/utils/AES.java @@ -0,0 +1,114 @@ +package com.github.catvod.utils; + +import android.util.Base64; + +import com.github.catvod.crawler.SpiderDebug; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.security.spec.AlgorithmParameterSpec; + +import javax.crypto.Cipher; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DESKeySpec; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +public class AES { + + public static String CBC(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(Base64.decode(src.getBytes(), 0))); + } catch (Exception exception) { + SpiderDebug.log(exception); + } + return null; + } + + + public static Cipher GetCipher(int opmode, String key) { + try { + DESKeySpec dks = new DESKeySpec(key.getBytes()); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + Key secretkey = keyFactory.generateSecret(dks); + Cipher cipher = Cipher.getInstance("DES/ECB/PKCS7Padding"); + cipher.init(opmode, secretkey); + return cipher; + } catch (Exception exception) { + SpiderDebug.log(exception); + return null; + } + } + + + + public static String decode(String data, String key) throws Exception { + if (data == null || data.isEmpty()){ + return null; + } + try { + byte[] b = hex2byte(data); + Cipher cipher = GetCipher(Cipher.DECRYPT_MODE, key); + if (cipher != null){ + return new String(cipher.doFinal(b), "UTF-8"); + } else { + return null; + } + } catch (Exception exception) { + SpiderDebug.log(exception); + return data; + } + } + + public static 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; + } + + public static String encrypt(String data, String key) { + try { + byte[] data2 = data.getBytes("UTF-8"); + SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec); + byte[] result = cipher.doFinal(data2); + return bytesToHexStr(result); + } catch (Exception exception) { + SpiderDebug.log(exception); + } + return null; + } + + /** + * byte数组转16进制字符串 + * + * @param bytes byte数组 + * @return hex字符串 + */ + public static 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(); + } + +} diff --git a/app/src/main/java/com/github/catvod/utils/CBC.java b/app/src/main/java/com/github/catvod/utils/CBC.java new file mode 100644 index 0000000..afde9d0 --- /dev/null +++ b/app/src/main/java/com/github/catvod/utils/CBC.java @@ -0,0 +1,21 @@ +package com.github.catvod.utils; + +import com.github.catvod.crawler.SpiderDebug; +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +public class CBC { + public static byte[] CBC(byte[] data, byte[] key, byte[] iv) { + try { + IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); + SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); + cipher.init(2, secretKeySpec, ivParameterSpec); + return cipher.doFinal(data); + } catch (Exception e) { + SpiderDebug.log(e); + return null; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/utils/Misc.java b/app/src/main/java/com/github/catvod/utils/Misc.java new file mode 100644 index 0000000..8923af8 --- /dev/null +++ b/app/src/main/java/com/github/catvod/utils/Misc.java @@ -0,0 +1,155 @@ +package com.github.catvod.utils; + +import android.net.Uri; + +import com.github.catvod.crawler.SpiderDebug; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.regex.Pattern; + +public class Misc { + public static boolean isVip(String url) { + // 适配2.0.6的调用应用内解析列表的支持, 需要配合直连分析一起使用,参考cjt影视和极品直连 + try { + boolean isVip = false; + String host = Uri.parse(url).getHost(); + String[] vipWebsites = new String[]{"iqiyi.com", "v.qq.com", "youku.com", "le.com", "tudou.com", "mgtv.com", "sohu.com", "acfun.cn", "bilibili.com", "baofeng.com", "pptv.com"}; + for (int b = 0; b < vipWebsites.length; b++) { + if (host.contains(vipWebsites[b])) { + if ("iqiyi.com".equals(vipWebsites[b])) { + //爱奇艺需要特殊处理 + if (url.contains("iqiyi.com/a_") || url.contains("iqiyi.com/w_") || url.contains("iqiyi.com/v_")) { + isVip = true; + break; + } + } else { + isVip = true; + break; + } + } + } + return isVip; + } catch (Exception e) { + } + return false; + } + + private static final Pattern snifferMatch = Pattern.compile("http((?!http).){26,}?\\.(m3u8|mp4)\\?.*|http((?!http).){26,}\\.(m3u8|mp4)|http((?!http).){26,}?/m3u8\\?pt=m3u8.*|http((?!http).)*?default\\.ixigua\\.com/.*|http((?!http).)*?cdn-tos[^\\?]*|http((?!http).)*?/obj/tos[^\\?]*|http.*?/player/m3u8play\\.php\\?url=.*|http.*?/player/.*?[pP]lay\\.php\\?url=.*|http.*?/playlist/m3u8/\\?vid=.*|http.*?\\.php\\?type=m3u8&.*|http.*?/download.aspx\\?.*|http.*?/api/up_api.php\\?.*|https.*?\\.66yk\\.cn.*|http((?!http).)*?netease\\.com/file/.*"); + + public static boolean isVideoFormat(String url) { + if (snifferMatch.matcher(url).find()) { + if (url.contains("cdn-tos") && url.contains(".js")) { + return false; + } + return true; + } + return false; + } + + public static String fixUrl(String base, String src) { + try { + if (src.startsWith("//")) { + Uri parse = Uri.parse(base); + src = parse.getScheme() + ":" + src; + } else if (!src.contains("://")) { + Uri parse = Uri.parse(base); + src = parse.getScheme() + "://" + parse.getHost() + src; + } + } catch (Exception e) { + SpiderDebug.log(e); + } + return src; + } + + public static boolean isBlackVodUrl(String input, String url) { + if (url.contains("973973.xyz") || url.contains(".fit:")) + return true; + return false; + } + + public static final String UaWinChrome = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36"; + + public static JSONObject fixJsonVodHeader(JSONObject headers, String input, String url) throws JSONException { + if (headers == null) + headers = new JSONObject(); + if (input.contains("www.mgtv.com")) { + headers.put("Referer", " "); + headers.put("User-Agent", " Mozilla/5.0"); + } else if (url.contains("titan.mgtv")) { + headers.put("Referer", " "); + headers.put("User-Agent", " Mozilla/5.0"); + } else if (input.contains("bilibili")) { + headers.put("Referer", " https://www.bilibili.com/"); + headers.put("User-Agent", " " + Misc.UaWinChrome); + } + return headers; + } + + public static JSONObject jsonParse(String input, String json) throws JSONException { + JSONObject jsonPlayData = new JSONObject(json); + String url; + if (jsonPlayData.has("data")) { + url = jsonPlayData.getJSONObject("data").getString("url"); + } else { + url = jsonPlayData.getString("url"); + } + if (url.startsWith("//")) { + url = "https:" + url; + } + if (!url.startsWith("http")) { + return null; + } + if (url.equals(input)) { + if (isVip(url) || !isVideoFormat(url)) { + return null; + } + } + if (Misc.isBlackVodUrl(input, url)) { + return null; + } + JSONObject headers = new JSONObject(); + String ua = jsonPlayData.optString("user-agent", ""); + if (ua.trim().length() > 0) { + headers.put("User-Agent", " " + ua); + } + String referer = jsonPlayData.optString("referer", ""); + if (referer.trim().length() > 0) { + headers.put("Referer", " " + referer); + } + + headers = Misc.fixJsonVodHeader(headers, input, url); + JSONObject taskResult = new JSONObject(); + taskResult.put("header", headers); + taskResult.put("url", url); + return taskResult; + } + + + public static Charset CharsetUTF8 = Charset.forName("UTF-8"); + public static Charset CharsetIOS8859 = Charset.forName("iso-8859-1"); + + public static String MD5(String src, Charset charset) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] bytes = md.digest(src.getBytes(charset)); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < bytes.length; i++) { + int v = bytes[i] & 0xFF; + String hv = Integer.toHexString(v); + if (hv.length() < 2) { + sb.append(0); + } + sb.append(hv); + } + return sb.toString().toLowerCase(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return ""; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/utils/SSLSocketFactoryCompat.java b/app/src/main/java/com/github/catvod/utils/SSLSocketFactoryCompat.java new file mode 100644 index 0000000..81104e4 --- /dev/null +++ b/app/src/main/java/com/github/catvod/utils/SSLSocketFactoryCompat.java @@ -0,0 +1,167 @@ +package com.github.catvod.utils; + +import android.os.Build; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.security.GeneralSecurityException; +import java.security.cert.CertificateException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509TrustManager; + +public class SSLSocketFactoryCompat extends SSLSocketFactory { + private SSLSocketFactory defaultFactory; + // Android 5.0+ (API level21) provides reasonable default settings + // but it still allows SSLv3 + // https://developer.android.com/about/versions/android-5.0-changes.html#ssl + static String protocols[] = null, cipherSuites[] = null; + + static { + try { + SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); + if (socket != null) { + /* set reasonable protocol versions */ + // - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0) + // - remove all SSL versions (especially SSLv3) because they're insecure now + List protocols = new LinkedList<>(); + for (String protocol : socket.getSupportedProtocols()) + if (!protocol.toUpperCase().contains("SSL")) + protocols.add(protocol); + SSLSocketFactoryCompat.protocols = protocols.toArray(new String[protocols.size()]); + /* set up reasonable cipher suites */ + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + // choose known secure cipher suites + List allowedCiphers = Arrays.asList( + // TLS 1.2 + "TLS_RSA_WITH_AES_256_GCM_SHA384", + "TLS_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256", + // maximum interoperability + "TLS_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA", + // additionally + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"); + List availableCiphers = Arrays.asList(socket.getSupportedCipherSuites()); + // take all allowed ciphers that are available and put them into preferredCiphers + HashSet preferredCiphers = new HashSet<>(allowedCiphers); + preferredCiphers.retainAll(availableCiphers); + /* For maximum security, preferredCiphers should *replace* enabled ciphers (thus disabling + * ciphers which are enabled by default, but have become unsecure), but I guess for + * the security level of DAVdroid and maximum compatibility, disabling of insecure + * ciphers should be a server-side task */ + // add preferred ciphers to enabled ciphers + HashSet enabledCiphers = preferredCiphers; + enabledCiphers.addAll(new HashSet<>(Arrays.asList(socket.getEnabledCipherSuites()))); + SSLSocketFactoryCompat.cipherSuites = enabledCiphers.toArray(new String[enabledCiphers.size()]); + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public SSLSocketFactoryCompat(X509TrustManager tm) { + try { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, (tm != null) ? new X509TrustManager[]{tm} : null, null); + defaultFactory = sslContext.getSocketFactory(); + } catch (GeneralSecurityException e) { + throw new AssertionError(); // The system has no TLS. Just give up. + } + } + + private void upgradeTLS(SSLSocket ssl) { + // Android 5.0+ (API level21) provides reasonable default settings + // but it still allows SSLv3 + // https://developer.android.com/about/versions/android-5.0-changes.html#ssl + if (protocols != null) { + ssl.setEnabledProtocols(protocols); + } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && cipherSuites != null) { + ssl.setEnabledCipherSuites(cipherSuites); + } + } + + @Override + public String[] getDefaultCipherSuites() { + return cipherSuites; + } + + @Override + public String[] getSupportedCipherSuites() { + return cipherSuites; + } + + @Override + public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { + Socket ssl = defaultFactory.createSocket(s, host, port, autoClose); + if (ssl instanceof SSLSocket) + upgradeTLS((SSLSocket) ssl); + return ssl; + } + + @Override + public Socket createSocket(String host, int port) throws IOException, UnknownHostException { + Socket ssl = defaultFactory.createSocket(host, port); + if (ssl instanceof SSLSocket) + upgradeTLS((SSLSocket) ssl); + return ssl; + } + + @Override + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { + Socket ssl = defaultFactory.createSocket(host, port, localHost, localPort); + if (ssl instanceof SSLSocket) + upgradeTLS((SSLSocket) ssl); + return ssl; + } + + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + Socket ssl = defaultFactory.createSocket(host, port); + if (ssl instanceof SSLSocket) + upgradeTLS((SSLSocket) ssl); + return ssl; + } + + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + Socket ssl = defaultFactory.createSocket(address, port, localAddress, localPort); + if (ssl instanceof SSLSocket) + upgradeTLS((SSLSocket) ssl); + return ssl; + } + + //定义一个信任所有证书的TrustManager + public static final X509TrustManager trustAllCert = new X509TrustManager() { + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return new java.security.cert.X509Certificate[]{}; + } + }; +} diff --git a/app/src/main/java/com/github/catvod/utils/SpiderOKClient.java b/app/src/main/java/com/github/catvod/utils/SpiderOKClient.java new file mode 100644 index 0000000..5fba1e9 --- /dev/null +++ b/app/src/main/java/com/github/catvod/utils/SpiderOKClient.java @@ -0,0 +1,36 @@ +package com.github.catvod.utils; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import okhttp3.OkHttpClient; + +public class SpiderOKClient { + private static OkHttpClient noRedirectClient = null; + + public static OkHttpClient noRedirectClient() { + if (noRedirectClient == null) { + OkHttpClient.Builder builder = new OkHttpClient.Builder() + .readTimeout(15, TimeUnit.SECONDS) + .writeTimeout(15, TimeUnit.SECONDS) + .connectTimeout(15, TimeUnit.SECONDS) + .followRedirects(false) + .followSslRedirects(false) + .retryOnConnectionFailure(true) + .sslSocketFactory(new SSLSocketFactoryCompat(SSLSocketFactoryCompat.trustAllCert), SSLSocketFactoryCompat.trustAllCert); + noRedirectClient = builder.build(); + } + return noRedirectClient; + } + + public static String getRedirectLocation(Map> headers) { + if (headers == null) + return null; + if (headers.containsKey("location")) + return headers.get("location").get(0); + if (headers.containsKey("Location")) + return headers.get("Location").get(0); + return null; + } +} diff --git a/app/src/main/java/com/github/catvod/utils/gZip.java b/app/src/main/java/com/github/catvod/utils/gZip.java new file mode 100644 index 0000000..e8f14ea --- /dev/null +++ b/app/src/main/java/com/github/catvod/utils/gZip.java @@ -0,0 +1,22 @@ +package com.github.catvod.utils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.zip.GZIPInputStream; + + +public class gZip { + public static String KS(byte[] bArr) throws IOException { + GZIPInputStream gZIPInputStream = new GZIPInputStream(new ByteArrayInputStream(bArr)); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + byte[] bArr2 = new byte[1024]; + while (true) { + int read = gZIPInputStream.read(bArr2); + if (read == -1) { + return byteArrayOutputStream.toString("UTF-8"); + } + byteArrayOutputStream.write(bArr2, 0, read); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/utils/okhttp/OKCallBack.java b/app/src/main/java/com/github/catvod/utils/okhttp/OKCallBack.java new file mode 100644 index 0000000..9bd5b7c --- /dev/null +++ b/app/src/main/java/com/github/catvod/utils/okhttp/OKCallBack.java @@ -0,0 +1,60 @@ +package com.github.catvod.utils.okhttp; + +import java.io.IOException; + +import okhttp3.Call; +import okhttp3.Response; + + +public abstract class OKCallBack { + + private T result = null; + + public T getResult() { + return result; + } + + protected void setResult(T val) { + result = val; + } + + protected void onError(final Call call, final Exception e) { + onFailure(call, e); + } + + protected void onSuccess(Call call, Response response) { + T obj = onParseResponse(call, response); + setResult(obj); + onResponse(obj); + } + + protected abstract T onParseResponse(Call call, Response response); + + protected abstract void onFailure(Call call, Exception e); + + protected abstract void onResponse(T response); + + public static abstract class OKCallBackDefault extends OKCallBack { + @Override + public Response onParseResponse(Call call, Response response) { + return response; + } + } + + public static abstract class OKCallBackString extends OKCallBack { + @Override + public void onError(Call call, Exception e) { + setResult(""); + super.onError(call, e); + } + + @Override + public String onParseResponse(Call call, Response response) { + try { + return response.body().string(); + } catch (IOException e) { + return ""; + } + } + } +} diff --git a/app/src/main/java/com/github/catvod/utils/okhttp/OKRequest.java b/app/src/main/java/com/github/catvod/utils/okhttp/OKRequest.java new file mode 100644 index 0000000..c24d5ba --- /dev/null +++ b/app/src/main/java/com/github/catvod/utils/okhttp/OKRequest.java @@ -0,0 +1,132 @@ +package com.github.catvod.utils.okhttp; + +import android.text.TextUtils; + +import java.io.IOException; +import java.util.Map; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.FormBody; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.RequestBody; +import okhttp3.Response; + +class OKRequest { + private final String mMethodType; + private String mUrl; + private Object mTag = null; + private final Map mParamsMap; + private final String mJsonStr; + private final Map mHeaderMap; + private final OKCallBack mCallBack; + private okhttp3.Request mOkHttpRequest; + private okhttp3.Request.Builder mRequestBuilder; + + + OKRequest(String methodType, String url, Map paramsMap, Map headerMap, OKCallBack callBack) { + this(methodType, url, null, paramsMap, headerMap, callBack); + } + + OKRequest(String methodType, String url, String jsonStr, Map headerMap, OKCallBack callBack) { + this(methodType, url, jsonStr, null, headerMap, callBack); + } + + private OKRequest(String methodType, String url, String jsonStr, Map paramsMap, Map headerMap, OKCallBack callBack) { + mMethodType = methodType; + mUrl = url; + mJsonStr = jsonStr; + mParamsMap = paramsMap; + mHeaderMap = headerMap; + mCallBack = callBack; + getInstance(); + } + + public void setTag(Object tag) { + mTag = tag; + } + + private void getInstance() { + mRequestBuilder = new okhttp3.Request.Builder(); + switch (mMethodType) { + case OkHttpUtil.METHOD_GET: + setGetParams(); + break; + case OkHttpUtil.METHOD_POST: + mRequestBuilder.post(getRequestBody()); + break; + } + mRequestBuilder.url(mUrl); + if (mTag != null) + mRequestBuilder.tag(mTag); + if (mHeaderMap != null) { + setHeader(); + } + mOkHttpRequest = mRequestBuilder.build(); + } + + private RequestBody getRequestBody() { + if (!TextUtils.isEmpty(mJsonStr)) { + MediaType JSON = MediaType.parse("application/json; charset=utf-8"); + return RequestBody.create(JSON, mJsonStr); + } + FormBody.Builder formBody = new FormBody.Builder(); + if (mParamsMap != null) { + for (String key : mParamsMap.keySet()) { + formBody.add(key, mParamsMap.get(key)); + } + } + return formBody.build(); + } + + private void setGetParams() { + if (mParamsMap != null) { + mUrl = mUrl + "?"; + for (String key : mParamsMap.keySet()) { + mUrl = mUrl + key + "=" + mParamsMap.get(key) + "&"; + } + mUrl = mUrl.substring(0, mUrl.length() - 1); + } + } + + private void setHeader() { + if (mHeaderMap != null) { + for (String key : mHeaderMap.keySet()) { + mRequestBuilder.addHeader(key, mHeaderMap.get(key)); + } + } + } + + void execute(OkHttpClient client) { + Call call = client.newCall(mOkHttpRequest); + try { + Response response = call.execute(); + if (mCallBack != null) { + mCallBack.onSuccess(call, response); + } + } catch (IOException e) { + if (mCallBack != null) { + mCallBack.onError(call, e); + } + } + } + + void call(OkHttpClient client) { + client.newCall(mOkHttpRequest).enqueue(new Callback() { + @Override + public void onFailure(final Call call, final IOException e) { + if (mCallBack != null) { + mCallBack.onError(call, e); + } + } + + @Override + public void onResponse(final Call call, final Response response) throws IOException { + if (mCallBack != null) { + mCallBack.onSuccess(call, response); + } + } + }); + } +} diff --git a/app/src/main/java/com/github/catvod/utils/okhttp/OkHttpUtil.java b/app/src/main/java/com/github/catvod/utils/okhttp/OkHttpUtil.java new file mode 100644 index 0000000..e161c40 --- /dev/null +++ b/app/src/main/java/com/github/catvod/utils/okhttp/OkHttpUtil.java @@ -0,0 +1,200 @@ +package com.github.catvod.utils.okhttp; + +import com.github.catvod.crawler.SpiderDebug; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import okhttp3.Call; +import okhttp3.OkHttpClient; +import okhttp3.Response; + +public class OkHttpUtil { + + public static final String METHOD_GET = "GET"; + public static final String METHOD_POST = "POST"; + + private static final int DEFAULT_TIMEOUT = 15; + + private static final Object lockO = new Object(); + + private static OkHttpClient defaultClient = null; + + /** + * 不自动重定向 + */ + private static OkHttpClient noRedirectClient = null; + + public static OkHttpClient defaultClient() { + synchronized (lockO) { + if (defaultClient == null) { + OkHttpClient.Builder builder = new OkHttpClient.Builder() + .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) + .retryOnConnectionFailure(true) + .sslSocketFactory(new SSLSocketFactoryCompat(SSLSocketFactoryCompat.trustAllCert), SSLSocketFactoryCompat.trustAllCert); + defaultClient = builder.build(); + } + return defaultClient; + } + } + + public static OkHttpClient noRedirectClient() { + synchronized (lockO) { + if (noRedirectClient == null) { + OkHttpClient.Builder builder = new OkHttpClient.Builder() + .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) + .followRedirects(false) + .followSslRedirects(false) + .retryOnConnectionFailure(true) + .sslSocketFactory(new SSLSocketFactoryCompat(SSLSocketFactoryCompat.trustAllCert), SSLSocketFactoryCompat.trustAllCert); + noRedirectClient = builder.build(); + } + return noRedirectClient; + } + } + + public static String string(OkHttpClient client, String url, String tag, Map paramsMap, Map headerMap, Map> respHeaderMap) { + OKCallBack stringCallback = new OKCallBack() { + @Override + public String onParseResponse(Call call, Response response) { + try { + if (respHeaderMap != null) { + respHeaderMap.clear(); + respHeaderMap.putAll(response.headers().toMultimap()); + } + return response.body().string(); + } catch (IOException e) { + return ""; + } + } + + @Override + public void onFailure(Call call, Exception e) { + setResult(""); + SpiderDebug.log(e); + } + + @Override + public void onResponse(String response) { + } + }; + OKRequest req = new OKRequest(METHOD_GET, url, paramsMap, headerMap, stringCallback); + req.setTag(tag); + req.execute(client); + return stringCallback.getResult(); + } + + public static String stringNoRedirect(String url, Map headerMap, Map> respHeaderMap) { + return string(noRedirectClient(), url, null, null, headerMap, respHeaderMap); + } + + public static String string(String url, Map headerMap, Map> respHeaderMap) { + return string(defaultClient(), url, null, null, headerMap, respHeaderMap); + } + + public static String string(String url, Map headerMap) { + return string(defaultClient(), url, null, null, headerMap, null); + } + + public static String string(String url, String tag, Map headerMap) { + return string(defaultClient(), url, tag, null, headerMap, null); + } + + public static void get(OkHttpClient client, String url, OKCallBack callBack) { + get(client, url, null, null, callBack); + } + + public static void get(OkHttpClient client, String url, Map paramsMap, OKCallBack callBack) { + get(client, url, paramsMap, null, callBack); + } + + public static void get(OkHttpClient client, String url, Map paramsMap, Map headerMap, OKCallBack callBack) { + new OKRequest(METHOD_GET, url, paramsMap, headerMap, callBack).execute(client); + } + + public static void post(OkHttpClient client, String url, OKCallBack callBack) { + post(client, url, null, callBack); + } + + public static void post(OkHttpClient client, String url, Map paramsMap, OKCallBack callBack) { + post(client, url, paramsMap, null, callBack); + } + + public static void post(OkHttpClient client, String url, Map paramsMap, Map headerMap, OKCallBack callBack) { + new OKRequest(METHOD_POST, url, paramsMap, headerMap, callBack).execute(client); + } + + public static void post(OkHttpClient client, String url, String tag, Map paramsMap, Map headerMap, OKCallBack callBack) { + OKRequest req = new OKRequest(METHOD_POST, url, paramsMap, headerMap, callBack); + req.setTag(tag); + req.execute(client); + } + + public static void postJson(OkHttpClient client, String url, String jsonStr, OKCallBack callBack) { + postJson(client, url, jsonStr, null, callBack); + } + + public static void postJson(OkHttpClient client, String url, String jsonStr, Map headerMap, OKCallBack callBack) { + new OKRequest(METHOD_POST, url, jsonStr, headerMap, callBack).execute(client); + } + + /** + * 根据Tag取消请求 + */ + public static void cancel(OkHttpClient client, Object tag) { + if (client == null || tag == null) return; + for (Call call : client.dispatcher().queuedCalls()) { + if (tag.equals(call.request().tag())) { + call.cancel(); + } + } + for (Call call : client.dispatcher().runningCalls()) { + if (tag.equals(call.request().tag())) { + call.cancel(); + } + } + } + + public static void cancel(Object tag) { + cancel(defaultClient(), tag); + } + + public static void cancelAll() { + cancelAll(defaultClient()); + } + + /** + * 取消所有请求请求 + */ + public static void cancelAll(OkHttpClient client) { + if (client == null) return; + for (Call call : client.dispatcher().queuedCalls()) { + call.cancel(); + } + for (Call call : client.dispatcher().runningCalls()) { + call.cancel(); + } + } + + /** + * 获取重定向地址 + * + * @param headers + * @return + */ + public static String getRedirectLocation(Map> headers) { + if (headers == null) + return null; + if (headers.containsKey("location")) + return headers.get("location").get(0); + if (headers.containsKey("Location")) + return headers.get("Location").get(0); + return null; + } +} diff --git a/app/src/main/java/com/github/catvod/utils/okhttp/SSLSocketFactoryCompat.java b/app/src/main/java/com/github/catvod/utils/okhttp/SSLSocketFactoryCompat.java new file mode 100644 index 0000000..f0395e0 --- /dev/null +++ b/app/src/main/java/com/github/catvod/utils/okhttp/SSLSocketFactoryCompat.java @@ -0,0 +1,167 @@ +package com.github.catvod.utils.okhttp; + +import android.os.Build; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.security.GeneralSecurityException; +import java.security.cert.CertificateException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509TrustManager; + +public class SSLSocketFactoryCompat extends SSLSocketFactory { + private final SSLSocketFactory defaultFactory; + // Android 5.0+ (API level21) provides reasonable default settings + // but it still allows SSLv3 + // https://developer.android.com/about/versions/android-5.0-changes.html#ssl + static String[] protocols = null; + static String[] cipherSuites = null; + + static { + try { + SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); + if (socket != null) { + /* set reasonable protocol versions */ + // - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0) + // - remove all SSL versions (especially SSLv3) because they're insecure now + List protocols = new LinkedList<>(); + for (String protocol : socket.getSupportedProtocols()) + if (!protocol.toUpperCase().contains("SSL")) + protocols.add(protocol); + SSLSocketFactoryCompat.protocols = protocols.toArray(new String[protocols.size()]); + /* set up reasonable cipher suites */ + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + // choose known secure cipher suites + List allowedCiphers = Arrays.asList( + // TLS 1.2 + "TLS_RSA_WITH_AES_256_GCM_SHA384", + "TLS_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256", + // maximum interoperability + "TLS_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA", + // additionally + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"); + List availableCiphers = Arrays.asList(socket.getSupportedCipherSuites()); + // take all allowed ciphers that are available and put them into preferredCiphers + HashSet preferredCiphers = new HashSet<>(allowedCiphers); + preferredCiphers.retainAll(availableCiphers); + /* For maximum security, preferredCiphers should *replace* enabled ciphers (thus disabling + * ciphers which are enabled by default, but have become unsecure), but I guess for + * the security level of DAVdroid and maximum compatibility, disabling of insecure + * ciphers should be a server-side task */ + // add preferred ciphers to enabled ciphers + HashSet enabledCiphers = preferredCiphers; + enabledCiphers.addAll(new HashSet<>(Arrays.asList(socket.getEnabledCipherSuites()))); + SSLSocketFactoryCompat.cipherSuites = enabledCiphers.toArray(new String[enabledCiphers.size()]); + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public SSLSocketFactoryCompat(X509TrustManager tm) { + try { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, (tm != null) ? new X509TrustManager[]{tm} : null, null); + defaultFactory = sslContext.getSocketFactory(); + } catch (GeneralSecurityException e) { + throw new AssertionError(); // The system has no TLS. Just give up. + } + } + + private void upgradeTLS(SSLSocket ssl) { + // Android 5.0+ (API level21) provides reasonable default settings + // but it still allows SSLv3 + // https://developer.android.com/about/versions/android-5.0-changes.html#ssl + if (protocols != null) { + ssl.setEnabledProtocols(protocols); + } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && cipherSuites != null) { + ssl.setEnabledCipherSuites(cipherSuites); + } + } + + @Override + public String[] getDefaultCipherSuites() { + return cipherSuites; + } + + @Override + public String[] getSupportedCipherSuites() { + return cipherSuites; + } + + @Override + public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { + Socket ssl = defaultFactory.createSocket(s, host, port, autoClose); + if (ssl instanceof SSLSocket) + upgradeTLS((SSLSocket) ssl); + return ssl; + } + + @Override + public Socket createSocket(String host, int port) throws IOException { + Socket ssl = defaultFactory.createSocket(host, port); + if (ssl instanceof SSLSocket) + upgradeTLS((SSLSocket) ssl); + return ssl; + } + + @Override + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { + Socket ssl = defaultFactory.createSocket(host, port, localHost, localPort); + if (ssl instanceof SSLSocket) + upgradeTLS((SSLSocket) ssl); + return ssl; + } + + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + Socket ssl = defaultFactory.createSocket(host, port); + if (ssl instanceof SSLSocket) + upgradeTLS((SSLSocket) ssl); + return ssl; + } + + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + Socket ssl = defaultFactory.createSocket(address, port, localAddress, localPort); + if (ssl instanceof SSLSocket) + upgradeTLS((SSLSocket) ssl); + return ssl; + } + + //定义一个信任所有证书的TrustManager + public static final X509TrustManager trustAllCert = new X509TrustManager() { + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return new java.security.cert.X509Certificate[]{}; + } + }; +} diff --git a/app/src/main/java/com/github/catvod/xpath/XPathRule.java b/app/src/main/java/com/github/catvod/xpath/XPathRule.java new file mode 100644 index 0000000..7238fdc --- /dev/null +++ b/app/src/main/java/com/github/catvod/xpath/XPathRule.java @@ -0,0 +1,687 @@ +package com.github.catvod.xpath; + +import com.github.catvod.crawler.SpiderDebug; + +import org.json.JSONObject; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +public class XPathRule { + /** + * user-agent + */ + private String ua; + /** + * 获取分类和首页推荐的Url + */ + private String homeUrl; + /** + * 分类节点 xpath + */ + private String cateNode; + /** + * 分类节点名 xpath + */ + private String cateName; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern cateNameR; + /** + * 分类节点id xpath + */ + private String cateId; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern cateIdR; + /** + * 手动指定 分类 如果有则不从homeUrl中获取分类 + */ + private LinkedHashMap cateManual = new LinkedHashMap<>(); + + /** + * 筛选 + */ + private JSONObject filter; + + /** + * 更新推荐视频节点 xpath + */ + private String homeVodNode; + /** + * 更新推荐视频名称 xpath + */ + private String homeVodName; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern homeVodNameR; + /** + * 更新推荐视频id xpath + */ + private String homeVodId; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern homeVodIdR; + /** + * 更新推荐视频图片 xpath + */ + private String homeVodImg; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern homeVodImgR; + /** + * 更新推荐视频简介 xpath + */ + private String homeVodMark; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern homeVodMarkR; + /** + * 分类页地址 + */ + private String cateUrl; + /** + * 分类叶视频节点 xpath + */ + private String cateVodNode; + /** + * 分类叶视频名称 xpath + */ + private String cateVodName; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern cateVodNameR; + /** + * 分类叶视频视频id xpath + */ + private String cateVodId; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern cateVodIdR; + /** + * 分类叶视频视频图片 xpath + */ + private String cateVodImg; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern cateVodImgR; + /** + * 分类叶视频视频简介 xpath + */ + private String cateVodMark; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern cateVodMarkR; + + /** + * 详情页面 + */ + private String dtUrl; + /** + * 详情节点 xpath + */ + private String dtNode; + /** + * 详情 视频名 xpath + */ + private String dtName; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern dtNameR; + /** + * 详情视频图片 xpath + */ + private String dtImg; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern dtImgR; + /** + * 详情视频分类 xpath + */ + private String dtCate; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern dtCateR; + /** + * 详情视频年份 xpath + */ + private String dtYear; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern dtYearR; + /** + * 详情视频地区 xpath + */ + private String dtArea; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern dtAreaR; + /** + * 详情视频简介 xpath + */ + private String dtMark; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern dtMarkR; + /** + * 详情演员 xpath + */ + private String dtActor; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern dtActorR; + /** + * 详情导演 xpath + */ + private String dtDirector; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern dtDirectorR; + /** + * 详情 说明 长 xpath + */ + private String dtDesc; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern dtDescR; + + /** + * 详情播放来源节点 + */ + private String dtFromNode; + /** + * 详情播放来源名称 xpath + */ + private String dtFromName; + /** + * 详情 + */ + private Pattern dtFromNameR; + /** + * 详情播放地址列表节点 xpath + */ + private String dtUrlNode; + /** + * 详情播放地址节点 xpath + */ + private String dtUrlSubNode; + /** + * 详情播放地址id xpath + */ + private String dtUrlId; + /** + * 详情 + */ + private Pattern dtUrlIdR; + /** + * 详情播放地址名称 xpath + */ + private String dtUrlName; + /** + * 详情 + */ + private Pattern dtUrlNameR; + /** + * 播放页面url + */ + private String playUrl; + /** + * 播放解析调用ua + */ + private String playUa; + + /** + * 搜索页地址 + */ + private String searchUrl; + + /** + * 搜索页视频节点 xpath + */ + private String scVodNode; + /** + * 搜索页视频名称 xpath + */ + private String scVodName; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern scVodNameR; + /** + * 搜索页视频id xpath + */ + private String scVodId; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern scVodIdR; + /** + * 搜索页视频图片 xpath + */ + private String scVodImg; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern scVodImgR; + /** + * 搜索页视频简介 xpath + */ + private String scVodMark; + /** + * 正则对取到的数据进行二次处理 + */ + private Pattern scVodMarkR; + + private static Pattern getPattern(JSONObject json, String key) { + String v = json.optString(key).trim(); + if (v.isEmpty()) + return null; + else { + try { + return Pattern.compile(v); + } catch (Exception e) { + SpiderDebug.log(e); + } + } + return null; + } + + 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; + } + + public static XPathRule fromJson(String json) { + try { + JSONObject jsonObj = new JSONObject(json); + XPathRule rule = new XPathRule(); + rule.ua = jsonObj.optString("ua"); + rule.homeUrl = jsonObj.optString("homeUrl").trim(); + rule.cateNode = jsonObj.optString("cateNode").trim(); + rule.cateName = jsonObj.optString("cateName").trim(); + rule.cateNameR = getPattern(jsonObj, "cateNameR"); + rule.cateId = jsonObj.optString("cateId").trim(); + rule.cateIdR = getPattern(jsonObj, "cateIdR"); + JSONObject navs = jsonObj.optJSONObject("cateManual"); + if (navs != null) { + Iterator keys = navs.keys(); + while (keys.hasNext()) { + String name = keys.next(); + rule.cateManual.put(name.trim(), navs.getString(name).trim()); + } + } + rule.filter = jsonObj.optJSONObject("filter"); + rule.homeVodNode = jsonObj.optString("homeVodNode").trim(); + rule.homeVodName = jsonObj.optString("homeVodName").trim(); + rule.homeVodNameR = getPattern(jsonObj, "homeVodNameR"); + rule.homeVodId = jsonObj.optString("homeVodId").trim(); + rule.homeVodIdR = getPattern(jsonObj, "homeVodIdR"); + rule.homeVodImg = jsonObj.optString("homeVodImg").trim(); + rule.homeVodImgR = getPattern(jsonObj, "homeVodImgR"); + rule.homeVodMark = jsonObj.optString("homeVodMark").trim(); + rule.homeVodMarkR = getPattern(jsonObj, "homeVodMarkR"); + rule.cateUrl = jsonObj.optString("cateUrl").trim(); + rule.cateVodNode = jsonObj.optString("cateVodNode").trim(); + rule.cateVodName = jsonObj.optString("cateVodName").trim(); + rule.cateVodNameR = getPattern(jsonObj, "cateVodNameR"); + rule.cateVodId = jsonObj.optString("cateVodId").trim(); + rule.cateVodIdR = getPattern(jsonObj, "cateVodIdR"); + rule.cateVodImg = jsonObj.optString("cateVodImg").trim(); + rule.cateVodImgR = getPattern(jsonObj, "cateVodImgR"); + rule.cateVodMark = jsonObj.optString("cateVodMark").trim(); + rule.cateVodMarkR = getPattern(jsonObj, "cateVodMarkR"); + rule.dtUrl = jsonObj.optString("dtUrl"); + rule.dtNode = jsonObj.optString("dtNode"); + rule.dtName = jsonObj.optString("dtName"); + rule.dtNameR = getPattern(jsonObj, "dtNameR"); + rule.dtImg = jsonObj.optString("dtImg"); + rule.dtImgR = getPattern(jsonObj, "dtImgR"); + rule.dtCate = jsonObj.optString("dtCate"); + rule.dtCateR = getPattern(jsonObj, "dtCateR"); + rule.dtYear = jsonObj.optString("dtYear"); + rule.dtYearR = getPattern(jsonObj, "dtYearR"); + rule.dtArea = jsonObj.optString("dtArea"); + rule.dtAreaR = getPattern(jsonObj, "dtAreaR"); + rule.dtMark = jsonObj.optString("dtMark"); + rule.dtMarkR = getPattern(jsonObj, "dtMarkR"); + rule.dtActor = jsonObj.optString("dtActor"); + rule.dtActorR = getPattern(jsonObj, "dtActorR"); + rule.dtDirector = jsonObj.optString("dtDirector"); + rule.dtDirectorR = getPattern(jsonObj, "dtDirectorR"); + rule.dtDesc = jsonObj.optString("dtDesc"); + rule.dtDescR = getPattern(jsonObj, "dtDescR"); + rule.dtFromNode = jsonObj.optString("dtFromNode"); + rule.dtFromName = jsonObj.optString("dtFromName"); + rule.dtFromNameR = getPattern(jsonObj, "dtFromNameR"); + rule.dtUrlNode = jsonObj.optString("dtUrlNode"); + rule.dtUrlSubNode = jsonObj.optString("dtUrlSubNode"); + rule.dtUrlId = jsonObj.optString("dtUrlId"); + rule.dtUrlIdR = getPattern(jsonObj, "dtUrlIdR"); + rule.dtUrlName = jsonObj.optString("dtUrlName"); + rule.dtUrlNameR = getPattern(jsonObj, "dtUrlNameR"); + rule.playUrl = jsonObj.optString("playUrl"); + rule.playUa = jsonObj.optString("playUa"); + rule.searchUrl = jsonObj.optString("searchUrl"); + rule.scVodNode = jsonObj.optString("scVodNode").trim(); + rule.scVodName = jsonObj.optString("scVodName").trim(); + rule.scVodNameR = getPattern(jsonObj, "scVodNameR"); + rule.scVodId = jsonObj.optString("scVodId").trim(); + rule.scVodIdR = getPattern(jsonObj, "scVodIdR"); + rule.scVodImg = jsonObj.optString("scVodImg").trim(); + rule.scVodImgR = getPattern(jsonObj, "scVodImgR"); + rule.scVodMark = jsonObj.optString("scVodMark").trim(); + rule.scVodMarkR = getPattern(jsonObj, "scVodMarkR"); + return rule; + } catch (Exception e) { + SpiderDebug.log(e); + } + return null; + } + + public String getUa() { + return ua; + } + + public String getHomeUrl() { + return homeUrl; + } + + public String getCateNode() { + return cateNode; + } + + public String getCateName() { + return cateName; + } + + public String getCateNameR(String src) { + return doReplaceRegex(cateNameR, src); + } + + public String getCateId() { + return cateId; + } + + public String getCateIdR(String src) { + return doReplaceRegex(cateIdR, src); + } + + public LinkedHashMap getCateManual() { + return cateManual; + } + + public JSONObject getFilter() { + return filter; + } + + public String getHomeVodNode() { + return homeVodNode; + } + + public String getHomeVodName() { + return homeVodName; + } + + public String getHomeVodNameR(String src) { + return doReplaceRegex(homeVodNameR, src); + } + + public String getHomeVodId() { + return homeVodId; + } + + public String getHomeVodIdR(String src) { + return doReplaceRegex(homeVodIdR, src); + } + + public String getHomeVodImg() { + return homeVodImg; + } + + public String getHomeVodImgR(String src) { + return doReplaceRegex(homeVodImgR, src); + } + + public String getHomeVodMark() { + return homeVodMark; + } + + public String getHomeVodMarkR(String src) { + return doReplaceRegex(homeVodMarkR, src); + } + + public String getCateUrl() { + return cateUrl; + } + + public String getCateVodNode() { + return cateVodNode; + } + + public String getCateVodName() { + return cateVodName; + } + + public String getCateVodNameR(String src) { + return doReplaceRegex(cateVodNameR, src); + } + + public String getCateVodId() { + return cateVodId; + } + + public String getCateVodIdR(String src) { + return doReplaceRegex(cateVodIdR, src); + } + + public String getCateVodImg() { + return cateVodImg; + } + + public String getCateVodImgR(String src) { + return doReplaceRegex(cateVodImgR, src); + } + + public String getCateVodMark() { + return cateVodMark; + } + + public String getCateVodMarkR(String src) { + return doReplaceRegex(cateVodNameR, src); + } + + public String getDetailUrl() { + return dtUrl; + } + + public String getDetailNode() { + return dtNode; + } + + public String getDetailName() { + return dtName; + } + + public String getDetailNameR(String src) { + return doReplaceRegex(dtNameR, src); + } + + public String getDetailImg() { + return dtImg; + } + + public String getDetailImgR(String src) { + return doReplaceRegex(dtImgR, src); + } + + public String getDetailCate() { + return dtCate; + } + + public String getDetailCateR(String src) { + return doReplaceRegex(dtCateR, src); + } + + public String getDetailYear() { + return dtYear; + } + + public String getDetailYearR(String src) { + return doReplaceRegex(dtYearR, src); + } + + public String getDetailArea() { + return dtArea; + } + + public String getDetailAreaR(String src) { + return doReplaceRegex(dtAreaR, src); + } + + public String getDetailMark() { + return dtMark; + } + + public String getDetailMarkR(String src) { + return doReplaceRegex(dtMarkR, src); + } + + public String getDetailActor() { + return dtActor; + } + + public String getDetailActorR(String src) { + return doReplaceRegex(dtActorR, src); + } + + public String getDetailDirector() { + return dtDirector; + } + + public String getDetailDirectorR(String src) { + return doReplaceRegex(dtDirectorR, src); + } + + public String getDetailDesc() { + return dtDesc; + } + + public String getDetailDescR(String src) { + return doReplaceRegex(dtDescR, src); + } + + public String getDetailFromNode() { + return dtFromNode; + } + + public String getDetailFromName() { + return dtFromName; + } + + public String getDetailFromNameR(String src) { + return doReplaceRegex(dtFromNameR, src); + } + + public String getDetailUrlNode() { + return dtUrlNode; + } + + public String getDetailUrlSubNode() { + return dtUrlSubNode; + } + + public String getDetailUrlId() { + return dtUrlId; + } + + public String getDetailUrlIdR(String src) { + return doReplaceRegex(dtUrlIdR, src); + } + + public String getDetailUrlName() { + return dtUrlName; + } + + public String getDetailUrlNameR(String src) { + return doReplaceRegex(dtUrlNameR, src); + } + + public String getPlayUrl() { + return playUrl; + } + + public String getPlayUa() { + return playUa; + } + + public String getSearchUrl() { + return searchUrl; + } + + public String getSearchVodNode() { + return scVodNode; + } + + public String getSearchVodName() { + return scVodName; + } + + public String getSearchVodNameR(String src) { + return doReplaceRegex(scVodNameR, src); + } + + public String getSearchVodId() { + return scVodId; + } + + public String getSearchVodIdR(String src) { + return doReplaceRegex(scVodIdR, src); + } + + public String getSearchVodImg() { + return scVodImg; + } + + public String getSearchVodImgR(String src) { + return doReplaceRegex(scVodImgR, src); + } + + public String getSearchVodMark() { + return scVodMark; + } + + public String getSearchVodMarkR(String src) { + return doReplaceRegex(scVodMarkR, src); + } +} diff --git a/app/src/main/java/com/github/catvod/xpath/p.json b/app/src/main/java/com/github/catvod/xpath/p.json new file mode 100644 index 0000000..68ce241 --- /dev/null +++ b/app/src/main/java/com/github/catvod/xpath/p.json @@ -0,0 +1,1326 @@ +{ + "player": { + "dpp": { + "sh": "DP播放", + "pu": "https://pic.zxzjtv.com/dplayer.php?url=", + "sn": 1, + "or": 999 + } + }, + "filter": { + "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": "情色" + } + ] + }, + { + "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": "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": "其他" + } + ] + }, + { + "key": "4", + "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" + } + ] + } + ], + "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": "其他" + } + ] + }, + { + "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": "其他" + } + ] + }, + { + "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" + } + ] + } + ], + "6": [ + { + "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": "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" + } + ] + } + ], + "5": [ + { + "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": "其他" + } + ] + }, + { + "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" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/xpath/test.json b/app/src/main/java/com/github/catvod/xpath/test.json new file mode 100644 index 0000000..a6d46e4 --- /dev/null +++ b/app/src/main/java/com/github/catvod/xpath/test.json @@ -0,0 +1,791 @@ +{ + "siteUrl": "https://www.smdyy.cc", + "regexCategory": "/list/(\\d+).html", + "regexVid": "/kan/(\\d+).html", + "regexPlay": "/play/(\\d+)-(\\d+)-(\\d+).html", + "regexPage": "/show/(\\S+).html", + "player": { + "duoduozy": { + "show": "高清线路", + "or": 999, + "ps": "0", + "parse": "https://player.6080kan.cc/player/play.php?url=" + }, + "sohu": { + "show": "优选7", + "or": 999, + "ps": "0", + "parse": "https://player.6080kan.cc/player/play.php?url=" + }, + "qq": { + "show": "优选3", + "or": 999, + "ps": "0", + "parse": "https://player.6080kan.cc/player/play.php?url=" + }, + "bilibili": { + "show": "bilibili", + "or": 999, + "ps": "0", + "parse": "https://player.6080kan.cc/player/play.php?url=" + }, + "youku": { + "show": "优选1", + "or": 999, + "ps": "0", + "parse": "https://player.6080kan.cc/player/play.php?url=" + }, + "qiyi": { + "show": "优选2", + "or": 999, + "ps": "0", + "parse": "https://player.6080kan.cc/player/play.php?url=" + }, + "letv": { + "show": "优选6", + "or": 999, + "ps": "0", + "parse": "https://player.6080kan.cc/player/play.php?url=" + }, + "xigua": { + "show": "西瓜视频", + "or": 999, + "ps": "0", + "parse": "https://player.6080kan.cc/player/play.php?url=" + }, + "mgtv": { + "show": "优选4", + "or": 999, + "ps": "0", + "parse": "https://player.6080kan.cc/player/play.php?url=" + }, + "tkm3u8": { + "show": "备用", + "or": 999, + "ps": "0", + "parse": "https://player.6080kan.cc/player/play.php?url=" + }, + "pptv": { + "show": "优选5", + "or": 999, + "ps": "0", + "parse": "https://player.6080kan.cc/player/play.php?url=" + } + }, + "filter": { + "1": [ + { + "key": "tid", + "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": "20" + }, + { + "n": "惊悚片", + "v": "21" + }, + { + "n": "冒险片", + "v": "22" + }, + { + "n": "悬疑片", + "v": "23" + }, + { + "n": "武侠片", + "v": "24" + }, + { + "n": "奇幻片", + "v": "25" + }, + { + "n": "纪录片", + "v": "26" + }, + { + "n": "动画片", + "v": "27" + } + ] + }, + { + "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": "" + } + ] + } + ], + "2": [ + { + "key": "tid", + "name": "类型", + "value": [ + { + "n": "全部", + "v": "2" + }, + { + "n": "国产剧", + "v": "13" + }, + { + "n": "港台剧", + "v": "14" + }, + { + "n": "日韩剧", + "v": "15" + }, + { + "n": "欧美剧", + "v": "16" + }, + { + "n": "泰国剧", + "v": "28" + } + ] + }, + { + "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": "其他" + } + ] + }, + { + "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": "" + } + ] + } + ], + "3": [ + { + "key": "3", + "name": "剧情", + "value": [ + { + "n": "全部", + "v": "3" + }, + { + "n": "情感", + "v": "情感" + }, + { + "n": "科幻", + "v": "科幻" + }, + { + "n": "热血", + "v": "热血" + }, + { + "n": "推理", + "v": "推理" + }, + { + "n": "搞笑", + "v": "搞笑" + }, + { + "n": "冒险", + "v": "冒险" + }, + { + "n": "萝莉", + "v": "萝莉" + }, + { + "n": "校园", + "v": "校园" + }, + { + "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": "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": "" + } + ] + } + ] + } +} + + + + diff --git a/app/src/main/res/drawable-hdpi/app_icon.png b/app/src/main/res/drawable-hdpi/app_icon.png new file mode 100644 index 0000000..81491fc Binary files /dev/null and b/app/src/main/res/drawable-hdpi/app_icon.png differ diff --git a/app/src/main/res/drawable-xhdpi/app_icon.png b/app/src/main/res/drawable-xhdpi/app_icon.png new file mode 100644 index 0000000..edbfc76 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/app_icon.png differ diff --git a/app/src/main/res/drawable-xxhdpi/app_icon.png b/app/src/main/res/drawable-xxhdpi/app_icon.png new file mode 100644 index 0000000..0cec2e2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/app_icon.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/app_icon.png b/app/src/main/res/drawable-xxxhdpi/app_icon.png new file mode 100644 index 0000000..00e83b9 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/app_icon.png differ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..10cabcc --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + CatVodSpider + \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..a700f4a --- /dev/null +++ b/build.gradle @@ -0,0 +1,48 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + ext { + appVersionCode = 1 + appVersionName = "1.0.0" + + miniSdkVersion = 16 + compileSdkVersion = 30 + targetSdkVersion = 26 + + jsoup_version = "1.14.1" + jsoupxpath_version = "2.5.0" + okhttp_version = "3.12.13" + rxhttp_version = "2.6.5" + } + + repositories { + mavenCentral() + google() + jcenter() + maven { url 'https://maven.aliyun.com/repository/google' } + maven { url 'https://maven.aliyun.com/repository/central' } + maven { url 'https://maven.aliyun.com/repository/public' } + maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } + maven { url 'https://jitpack.io' } + } + dependencies { + classpath 'com.android.tools.build:gradle:7.2.1' + classpath "gradle.plugin.ru.cleverpumpkin.proguard-dictionaries-generator:plugin:1.0.8" + } +} + +allprojects { + repositories { + mavenCentral() + google() + jcenter() + maven { url 'https://maven.aliyun.com/repository/google' } + maven { url 'https://maven.aliyun.com/repository/central' } + maven { url 'https://maven.aliyun.com/repository/public' } + maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } + maven { url 'https://jitpack.io' } + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} \ No newline at end of file diff --git a/buildAndGenJar.bat b/buildAndGenJar.bat new file mode 100644 index 0000000..57db0a8 --- /dev/null +++ b/buildAndGenJar.bat @@ -0,0 +1,7 @@ +@echo off + +call "%~dp0\gradlew" assembleRelease --no-daemon + +call "%~dp0\jar\genJar.bat" ec + +pause diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..6826e61 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,17 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..f6b961f Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..2575a8c --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Sep 21 09:53:05 CST 2021 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/jar/3rd/apktool_2.4.1.jar b/jar/3rd/apktool_2.4.1.jar new file mode 100644 index 0000000..28ce1e5 Binary files /dev/null and b/jar/3rd/apktool_2.4.1.jar differ diff --git a/jar/3rd/baksmali-2.5.2.jar b/jar/3rd/baksmali-2.5.2.jar new file mode 100644 index 0000000..b548bfc Binary files /dev/null and b/jar/3rd/baksmali-2.5.2.jar differ diff --git a/jar/3rd/dex.jar b/jar/3rd/dex.jar new file mode 100644 index 0000000..46c5f98 Binary files /dev/null and b/jar/3rd/dex.jar differ diff --git a/jar/3rd/dx-1.16.jar b/jar/3rd/dx-1.16.jar new file mode 100644 index 0000000..6e468ce Binary files /dev/null and b/jar/3rd/dx-1.16.jar differ diff --git a/jar/3rd/oss.jar b/jar/3rd/oss.jar new file mode 100644 index 0000000..2949336 Binary files /dev/null and b/jar/3rd/oss.jar differ diff --git a/jar/README.md b/jar/README.md new file mode 100644 index 0000000..712dd9b --- /dev/null +++ b/jar/README.md @@ -0,0 +1,143 @@ +## 共享包 + +### 这里的jar包由群友玩家共享的爬虫代码生成,不定期更新jar包和配置 + +### **注意:由于防火墙的问题,你可能无法直接使用这里的jar包,请自己想办法解决** + +```json + +"spider": "https://github.com/catvod/CatVodTVSpider/blob/master/jar/custom_spider.jar?raw=true", + +国内镜像 + +"spider": "https://litecucumber.coding.net/p/cat/d/config/git/raw/master/custom_spider.txt", + +...... +"sites": [ +...... + { + "key": "csp_Aidi", + "name": "爱迪", + "type": 3, + "api": "csp_Aidi", + "searchable": 1, + "quickSearch": 0, + "filterable": 1 + }, + { + "key": "csp_Enlienli", + "name": "嗯哩嗯哩", + "type": 3, + "api": "csp_Enlienli", + "searchable": 1, + "quickSearch": 0, + "filterable": 1 + }, + { + "key": "csp_Auete", + "name": "Auete", + "type": 3, + "api": "csp_Auete", + "searchable": 1, + "quickSearch": 0, + "filterable": 1 + }, + { + "key": "csp_Cokemv", + "name": "Cokemv", + "type": 3, + "api": "csp_Cokemv", + "searchable": 1, + "quickSearch": 0, + "filterable": 1 + }, + { + "key": "csp_Buka", + "name": "真不卡(测试)", + "type": 3, + "api": "csp_Buka", + "searchable": 0, + "quickSearch": 0, + "filterable": 1 + }, + { + "key": "csp_Ysgc", + "name": "影视工厂", + "type": 3, + "api": "csp_Ysgc", + "searchable": 1, + "quickSearch": 0, + "filterable": 1 + }, + { + "key": "csp_N0ys", + "name": "90影视", + "type": 3, + "api": "csp_N0ys", + "searchable": 1, + "quickSearch": 1, + "filterable": 0 + }, + { + "key": "csp_Nekk", + "name": "9E看看", + "type": 3, + "api": "csp_Nekk", + "searchable": 1, + "quickSearch": 0, + "filterable": 1 + }, + { + "key": "csp_Imaple", + "name": "枫林网(爬虫)", + "type": 3, + "api": "csp_Imaple", + "searchable": 1, + "quickSearch": 0, + "filterable": 1 + }, + { + "key": "csp_Jumi", + "name": "剧迷(爬虫)", + "type": 3, + "api": "csp_Jumi", + "searchable": 1, + "quickSearch": 0, + "filterable": 1 + }, + { + "key": "csp_Nfx", + "name": "NFXHD(爬虫)", + "type": 3, + "api": "csp_Nfx", + "searchable": 1, + "quickSearch": 0, + "filterable": 1 + }, + { + "key": "csp_YydsAli1", + "name": "YYDS阿里(爬虫)", + "type": 3, + "api": "csp_YydsAli1", + "searchable": 1, + "quickSearch": 0, + "filterable": 0 + } +...... +], +...... +"parses": [ +...... + { + "name": "Json并发", + "type": 2, + "url": "Parallel" + }, + { + "name": "Json轮询", + "type": 2, + "url": "Sequence" + } +...... +] +``` diff --git a/jar/custom_spider.jar b/jar/custom_spider.jar new file mode 100644 index 0000000..daae304 Binary files /dev/null and b/jar/custom_spider.jar differ diff --git a/jar/custom_spider.jar.md5 b/jar/custom_spider.jar.md5 new file mode 100644 index 0000000..ffca320 --- /dev/null +++ b/jar/custom_spider.jar.md5 @@ -0,0 +1 @@ +d63fe3db21b48e04884c2d5303907bd1 diff --git a/jar/genJar.bat b/jar/genJar.bat new file mode 100644 index 0000000..fe0588b --- /dev/null +++ b/jar/genJar.bat @@ -0,0 +1,33 @@ +@echo off + +del "%~dp0\custom_spider.jar" + +rd /s/q "%~dp0\Smali_classes" + +java -jar "%~dp0\3rd\baksmali-2.5.2.jar" d "%~dp0\..\app\build\intermediates\dex\release\minifyReleaseWithR8\classes.dex" -o "%~dp0\Smali_classes" + +rd /s/q "%~dp0\spider.jar\smali\com\github\catvod\spider" +rd /s/q "%~dp0\spider.jar\smali\com\github\catvod\parser" + +if not exist "%~dp0\spider.jar\smali\com\github\catvod\" md "%~dp0\spider.jar\smali\com\github\catvod\" + +if "%1" == "ec" ( + java -Dfile.encoding=utf-8 -jar "%~dp0\3rd\oss.jar" "%~dp0\Smali_classes" +) + +move "%~dp0\Smali_classes\com\github\catvod\spider" "%~dp0\spider.jar\smali\com\github\catvod\" +move "%~dp0\Smali_classes\com\github\catvod\parser" "%~dp0\spider.jar\smali\com\github\catvod\" + +rd /s/q "%~dp0\Smali_classes" + +java -jar "%~dp0\3rd\apktool_2.4.1.jar" b "%~dp0\spider.jar" -c + +move "%~dp0\spider.jar\dist\dex.jar" "%~dp0\custom_spider.jar" + +certUtil -hashfile "%~dp0\custom_spider.jar" MD5 | find /i /v "md5" | find /i /v "certutil" > "%~dp0\custom_spider.jar.md5" + +rd /s/q "%~dp0\spider.jar\smali\com\github\catvod\spider" +rd /s/q "%~dp0\spider.jar\smali\com\github\catvod\parser" + +rd /s/q "%~dp0\spider.jar\build" +rd /s/q "%~dp0\spider.jar\dist" diff --git a/jar/spider.jar/apktool.yml b/jar/spider.jar/apktool.yml new file mode 100644 index 0000000..975be9f --- /dev/null +++ b/jar/spider.jar/apktool.yml @@ -0,0 +1,13 @@ +!!brut.androlib.meta.MetaInfo +apkFileName: dex.jar +compressionType: false +doNotCompress: null +isFrameworkApk: false +packageInfo: null +sdkInfo: null +sharedLibrary: false +sparseResources: false +unknownFiles: +usesFramework: null +version: 2.4.1_0303 +versionInfo: null diff --git a/jar/spider.jar/original/META-INF/MANIFEST.MF b/jar/spider.jar/original/META-INF/MANIFEST.MF new file mode 100644 index 0000000..2b41730 --- /dev/null +++ b/jar/spider.jar/original/META-INF/MANIFEST.MF @@ -0,0 +1,4 @@ +Manifest-Version: 1.0 +Dex-Location: classes.dex +Created-By: dx 1.11 + diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..eea76c7 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = "CatVodSpider" +include ':app'