├── README.md
├── back
├── hanXC.json
├── lib
├── 0408.jar
├── TVB云播.js
├── custom_spider.jar
├── drpy2.min.js
├── nmys.json
├── spider.jar
├── svip.jar
├── 可可影视.json
├── 河马短剧.json
├── 河马短剧.py
├── 甜圈短剧.py
├── 素白白.json
├── 红果短剧.py
├── 金牌影视.js
├── 金牌影视2.js
├── 骚火影视.json
└── 骚火电影.js
├── live.txt
├── shenghanku.json
└── zyhan.json
/README.md:
--------------------------------------------------------------------------------
1 | # TVBox
2 |
--------------------------------------------------------------------------------
/back:
--------------------------------------------------------------------------------
1 | //{"key":"天翼资源","name":"天翼资源","type":1,"api":"https://www.911ysw.top/tianyi.php/provide/vod/","playUrl":"","searchable":1,"quickSearch":1 , "categories": ["国产剧", "综艺","动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片","惊悚片","犯罪片","悬疑片","惊悚片", "港台剧", "日韩剧","泰国剧", "欧美剧" ] },
2 | //{"key":"星辰","name":"星辰影院","type": 3,"api": "csp_XBPQ","ext": {"作者": "心动","站名": "星辰","主页url": "https://yyrj.site","搜索模式": "1","搜索url":"/index.php/vod/search/wd/{wd}.html","线路数组":"
","线路标题":"
&&[不包含:飞刀资源]","分类url": "/index.php/vod/show/area/{area}/id/{cateId}/page/{catePg}/year/{year}.html","分类": "电影&电视剧&综艺&动漫&短剧","分类值": "1&2&3&4&5"}},
3 | {"key": "hipy_js_8号影院","name": "8号影院","type": 3,"api": "https://yubox.xyz/drpy_libs/drpy2.min.js","searchable": 1,"quickSearch": 1,"filterable": 1,"order_num": 9,"ext": "https://yubox.xyz/drpy_js/8号影院.js"},
4 |
5 | //{"key": "花姐影院","name": "花姐影院","type": 3,"api": "csp_XBPQ","searchable": 1,"quickSearch": 1,"filterable": 1,"ext": {"数组": "
","搜索url": "https://www.huajie2.com/search.php?searchword={wd}",
6 | "分类url":"https://www.huajie2.com/search.php?searchtype=5&area={area}&class={class}&by={by}&year={year}&tid={cateId}&yuyan={lang}&page={catePg}","分类": "国产剧&电视剧&电影&综艺&动漫","分类值": "13&2&1&3&4&40"},"jar":"https://gitlab.com/xmbjm/omg/-/raw/main/jar/xyqxbpq.jar"},
7 |
8 | //{"key":"cj_非凡量子","name":"非凡量子","type":1,"api":"https://xysjtv.yy365.vip/api.php/provide/vod/?ac=list","playurl": "https://tvmvip.com/lz2.php?url=","searchable":1,"quickSearch":1,"filterable":1,"changeable":1},
9 |
10 |
11 | //{"key":"csp_U酷","name":"U酷资源","type":1,"api":"https://api.ukuapi.com/api.php/provide/vod/","playUrl":"","searchable":1,"quickSearch":1, "categories":["国产剧","短剧", "综艺", "动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片","韩剧","港澳剧", "台湾剧", "日剧","泰剧","欧美剧", "日韩综艺", "港台综艺", "欧美综艺", "日韩动漫", "欧美动漫"] },
12 | //{"key":"zy_云解析","name":"步步资源", "type":1, "api":"https://api.yparse.com/api/json","playurl":"https://yparse.ik9.cc/index.php?url=", "searchable": 1, "quickSearch": 1, "filterable": 1, "categories": ["短剧","国产剧","微电影","韩国剧","日本剧","泰国剧", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "纪录片","动画片", "香港剧", "台湾剧","欧美剧", "海外剧" ] },
13 | //https://www.yparse.com/help
14 | //{"key":"zy_天空影视", "name": "天空资源", "type": 1, "api": "https://m3u8.tiankongapi.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "categories":["短剧","国产剧", "综艺", "大陆综艺", "国产动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "动画片","奇幻片","灾难片","韩国剧", "台湾剧", "泰国剧", "日韩综艺", "港台综艺", "欧美综艺", "日本动漫", "欧美动漫" ,"其他片" ] },
15 | //{"key":"zy_天空资源1", "name": "天空资源", "type": 1, "api": "http://api.tiankongapi.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "categories": ["短剧", "国产剧", "大陆综艺","国产动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "纪录片", "悬疑片", "犯罪片", "动画片", "奇幻片", "香港剧", "台湾剧", "美国剧", "韩国剧", "日本剧","日韩综艺", "港台综艺", "欧美综艺", "国产动漫", "日韩动漫", "欧美动漫", "其他剧" ] },
16 |
17 | //{"key":"zy_无尽", "name": "无尽资源","type": 1, "api": "https://api.wujinapi.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "categories":["国产剧", "综艺", "大陆综艺", "动漫","国产动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "动画片","奇幻片","灾难片","韩国剧","香港剧", "台湾剧", "日本剧","泰国剧","美国剧", "日韩综艺", "港台综艺", "欧美综艺", "日韩动漫", "欧美动漫" ]},
18 | //{"key":"zy_樱花资源", "name": "樱花资源", "type": 1, "api": "https://m3u8.apiyhzy.com/api.php/provide/vod/?ac=list", "searchable": 1, "quickSearch": 1,"categories": [ "国产剧","大陆综艺","动作片","喜剧片","爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "纪录片", "悬疑片", "犯罪片", "动画片", "奇幻片", "香港剧", "台湾剧", "美国剧", "韩国剧", "日本剧","日韩综艺", "港台综艺", "欧美综艺", "国产动漫", "日韩动漫", "欧美动漫" ]},
19 | ////樱花影视https://www.yhh888.cn/zxtype/23.html
20 |
21 | //{"key":"速播资源","name":"速播资源","type":1,"api":"https://subocaiji.com/api.php/provide/vod/","playUrl":"","searchable":1,"quickSearch":1 , "categories": ["大陆剧", "综艺","动漫","中国动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片","动漫电影","港澳剧","台湾剧","韩剧", "日剧", "美剧","泰剧", "伦理片","日本动漫"] },
22 |
23 | //{"key":"zy_飞速1","name":"飞速资源", "type": 1, "api": "https://www.feisuzy.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "categories": ["国产剧", "短剧", "大陆综艺","国产动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "纪录片", "动画片","香港剧", "台湾剧", "欧美剧", "韩国剧", "日本剧","泰国剧","日韩综艺", "港台综艺", "欧美综艺", "日韩动漫", "欧美动漫", "其他片" ] },
24 | //{"key":"zy_飞速2", "name": "飞速资源", "type": 1, "api": "https://www.feisuzyapi.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "categories": [ "国产剧","短剧", "大陆综艺","国产动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "纪录片", "动画片","香港剧", "台湾剧", "欧美剧", "韩国剧", "日本剧","泰国剧","日韩综艺", "港台综艺", "欧美综艺", "日韩动漫", "欧美动漫", "其他片" ] },
25 | //飞速资源:http://feisuzy.cc/,飞速 feisuzy.com、(fszy1-10).com、feisuzy.cc(总有一条可以打开)
26 |
27 | //{"key":"zy_金鹰","name": "金鹰资源", "type": 1, "api":"https://jyzyapi.com/provide/vod/from/jinyingyun/at/json","playurl": "https://hd.iapijy.com/play?url=", "searchable": 1, "quickSearch": 1, "categories": ["内地剧","短剧", "综艺","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "纪录片", "香港剧", "台湾剧", "美国剧", "韩剧", "日剧"] },
28 | //域名: jinyingzy.com jinyingzy.net 备用域名: jyzy1.com jyzy2.com jyzy3.com m3u8 解析接口: https://hd.iapijy.com/play?url=
29 |
30 | //{"key":"zy_淘片","name":"淘片资源","type": 1,"api": "https://taopianapi.com/cjapi/mc/vod/json.html","searchable": 1,"quickSearch": 1,"filterable": 1,"categories":["电视剧/国产剧","综艺/大陆综艺","动漫/国产动漫","电视剧/韩国剧","综艺/日韩综艺","动漫/日本动漫","电影/动作片","电影/科幻片", "电影/奇幻片", "电影/喜剧片", "电影/爱情片", "电影/惊悚片", "电影/恐怖片","电影/纪录片","剧情片","电影/动画片","电影/冒险片","电影/战争片"]},
31 | //https://taopianapi.com/cjapi/sda/vod/json/iframe.html,https://taopianapi.com/
32 |
33 | //{"key":"虎牙资源","name":"虎牙资源","type":1,"api":"https://www.huyaapi.com/api.php/provide/vod/","playUrl":"","searchable":1,"quickSearch":1, "categories": ["短剧","内地剧","综艺","中国动漫","动画片","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片","记录片", "香港剧","韩剧","日剧","马泰剧","台湾剧", "日本动漫","欧美剧" ] },
34 |
35 | //{"key":"csp_xBPQ_爱看影院","name":"️爱看影院","type":3,"api":"csp_XBPQ","searchable":1,"quickSearch":1,"filterable":1,"ext":{"分类url":"https://www.3wyy.com/vodshow/{cateId}-{area}-time-{class}-{lang}----{catePg}---{year}.html;;lr","分类":"电影$1#连续剧$2#综艺$3#动漫$4"}},
36 | //{"key": "索尼资源","name": "索尼资源","type": 1,"api": "https://suoniapi.com/api.php/provide/vod/from/snm3u8/","categories": ["爽文短剧","国产剧","大陆综艺","国产动漫","动画片","动作片","喜剧片","爱情片","科幻片","恐怖片","剧情片","战争片","欧美剧","韩剧","日剧","港剧","台剧","泰剧","海外剧","纪录片","日韩综艺","港台综艺","欧美综艺","日韩动漫","欧美动漫","港台动漫","海外动漫","演唱会","体育赛事","篮球","足球","预告片","斯诺克","影视解说"],"searchable": 1,"quickSearch": 1},
37 | //{"key":"爱坤资源","name":"爱坤影视","type":1,"api":"https://ikunzyapi.com/api.php/provide/vod/","playUrl":"","searchable":1,"quickSearch":1, "categories": ["爽文短剧","国产剧","大陆综艺","国产动漫","日韩综艺","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片","惊悚片","家庭片","古装片","犯罪片","悬疑片", "香港剧","韩国剧","日本剧","泰剧","欧美剧" ] },
38 | //https://ikunzyapi.com/
39 | //{"key":"zy_红牛","name":"红牛资源","type":1,"api": "https://www.hongniuzy2.com/api.php/provide/vod/","searchable": 1, "quickSearch": 1, "filterable": 1, "categories": [ "国产剧", "综艺","大陆综艺", "动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "纪录片", "港澳剧", "台湾剧","日剧", "韩剧", "泰剧", "欧美剧", "欧美电影"]},
40 | //{"key": "csp_非凡资源","name": "非凡资源","type": 1,"api": "http://cj.ffzyapi.com/api.php/provide/vod/","playurl": "https://tvmvip.com/lz2.php?url=","searchable": 1,"quickSearch": 1,"filterable": 1,"categories": ["国产剧","大陆综艺", "国产动漫","动作片","喜剧片","科幻片","恐怖片","爱情片","剧情片","战争片","记录片","欧美剧","香港剧","韩国剧","台湾剧","日本剧","海外剧","泰国剧","日韩动漫","欧美动漫","港台动漫","海外动漫","港台综艺","日韩综艺","欧美综艺"]},
41 | //非凡资源备用网址:ffzy1.tv ffzy2.tv ffzy3.tv ffzy4.tv ffzy5.tv
42 | //{"key":"zy_百度","name":"百度资源","type": 1,"api": "https://api.apibdzy.com/api.php/provide/vod/?ac=list","searchable": 1,"quickSearch": 1,"filterable": 1,"playerType": 2,"categories": ["大陆剧","大陆综艺","国产动漫","动作片","喜剧片","科幻片","恐怖片","爱情片","剧情片","战争片","纪录片","动画电影","欧美剧","犯罪片","港澳剧","韩剧","泰剧","台湾剧","日剧","海外剧","其他片","悬疑片","奇幻片","动画片","体育赛事","日韩动漫","欧美动漫","港台动漫","海外动漫","港台综艺","日韩综艺","欧美综艺"]},
43 |
44 | //{"key":"csp_AppYsV2_555","name":"555影视","type":3,"api":"csp_AppYsV2","searchable":1,"quickSearch":1,"filterable":1,"ext":"https://5flixs.net/api.php/app/"},
45 | //555电影发布页:https://www.555dyy.top/ 笔盒18:https://beabox.xyz/;最新地址发布页beabox.tv,https://bihek.vip/,无法访问可发送邮件至beabox@email.com
46 |
47 | //{"key":"csp_Kuaikan","name":"快看影视","type":3,"api":"csp_Kuaikan","searchable":1,"quickSearch":1,"filterable":1",playerType":2,"changeable":1,"jar":"https://mirror.ghproxy.com/raw.githubusercontent.com/hanhan8127/TVBox/main/shenghan.jar"},
48 |
49 | //{"key":"zy_光速", "name":"光速资源", "type": 1, "api": "https://api.guangsuapi.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "categories": ["短剧", "大陆剧", "综艺","动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "纪录片","港澳剧", "台湾剧", "欧美剧", "韩剧", "日剧","泰剧" ] },
50 |
51 | //{"key":"影图资源","name":"影图资源","type":1,"api":"https://cj.vodimg.top/api.php/provide/vod/","searchable":1,"quickSearch":1, "categories": ["电影","连续剧","国产剧", "综艺","动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "港台剧", "日韩剧", "欧美剧" ]},
52 | //{"key":"csp_暴风","name":"暴风资源","type": 1,"api": "https://bfzyapi.com/api.php/provide/vod/","searchable": 1,"quickSearch": 1,"filterable": 1,"playerType": 2,"categories":["国产剧","大陆综艺","国产动漫","日韩动漫","动作片","喜剧片","科幻片","恐怖片","爱情片","剧情片","战争片","纪录片","欧美剧","犯罪片","香港剧","韩国剧","台湾剧","日本剧","海外剧","其他片","悬疑片","奇幻片","动画片","日韩动漫","欧美动漫","港台动漫","海外动漫","港台综艺","日韩综艺","欧美综艺"]},
53 |
54 | //{"key":"奇虎资源", "name":"奇虎资源", "type": 1, "api": "https://caiji.qhzyapi.com/api.php/provide/vod/?ac=list", "searchable": 1, "quickSearch": 1,"categories": ["短剧","国产剧","大陆综艺","国产动漫","韩国剧","动画片","剧情片","战争片","动作片","科幻片","记录片","爱情片","喜剧片","灾难片","日本动漫","欧美动漫","日本剧","泰国剧","台湾剧","香港剧","欧美剧","日韩综艺","港台综艺","欧美综艺"]},
55 | //虎资源站:qihuzy.com,备用网址:qihuzy1.com至qihuzy9.com
56 |
57 | //{"key":"快云资源","name":"快云资源","type": 1,"api": "https://kuaiyun-api.com/api.php/provide/vod","searchable": 1,"quickSearch": 1,"filterable": 1,"changeable": 1,"categories": ["国产剧","国产综艺","国产动漫","日本动漫","动作片","爱情片","科幻片","恐怖片","奇幻片","战争片","喜剧片","动画电影","犯罪片","纪录片","欧美剧","港台剧","泰剧","港台综艺","日韩综艺","欧美综艺","韩国综艺","欧美动漫","日本剧","电影解说","奇幻片","灾难片","悬疑片","海外剧"]},
58 |
59 | //{"key":"zy_八戒", "name":"八戒资源", "type": 1, "api": "http://cj.bajiecaiji.com/inc/apijson_vod.php","searchable": 1, "quickSearch": 1, "categories": ["国产剧", "大陆综艺","国产动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "纪录片", "香港剧", "台湾剧", "韩国剧", "日本剧","泰国剧", "欧美剧", "日韩综艺", "港台综艺", "欧美综艺", "日韩动漫", "欧美动漫", "港台动漫" ] },
60 | //http://cj.bajiecaiji.com/inc/api.php
61 |
62 | //{"key":"zy_快车资源","name":"快车资源", "type": 1, "api": "https://caiji.kczyapi.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "categories": [ "国产剧", "大陆综艺","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片", "香港剧", "台湾剧", "欧美剧", "韩国剧", "日本剧","日韩综艺", "港台综艺", "欧美综艺", "国产动漫", "日韩动漫", "欧美动漫" ] },
63 |
64 | //{"key":"csp_SP360","name":"360影视","type":3,"playerType":2,"api":"csp_SP360","searchable":1,"quickSearch":1,"filterable":1,"changeable":0},
65 | //{"key": "hipy_js_360影视[官]","name": "360影视","type": 3,"api": "https://yubox.xyz/drpy_libs/drpy2.min.js","searchable": 1,"quickSearch": 1,"filterable": 1,"order_num": 0,"ext": "https://yubox.xyz/drpy_js/360影视[官].js"},
66 | //{"key": "苹果","name":"小苹果","type":3,"api":"csp_LiteApple","searchable":1,"quickSearch":1,"filterable":1,"changeable":1,"playerType":1},
67 |
68 | //{"key":"vidhub","name":"影视视库","type":3,"api":"csp_WebVidHub","searchable":1,"quickSearch":0,"filterable":0,"ext":"https://vidhub1.cc"},
69 |
70 | //{"key":"小镇","name":"电影小镇","type":3,"api":"csp_XBPQ","searchable":1,"quickSearch":1,"filterable":1,"ext":{"主页url":"http://dyxz.tv","数组":"&&
","图片":"data-original=\"&&\"","标题":"title=\"&&\"","链接":"href=\"&&\"","副标题":"&&","搜索url":"http://dyxz.tv/search.php;post;searchword={wd}","搜索模式":"1","搜索数组":"","搜索图片":"data-original=\"&&\"","搜索标题":"title=\"&&\"","搜索链接":"href=\"&&\"","搜索副标题":"&&","搜索后缀":"/view/","线路数组":"","线路标题":">&&<","播放数组":"","影片年代":"年份:&&","影片地区":"地区:&&","导演":"导演:&&","主演":"主演:&&","简介":"更新:&&","播放列表":"","播放标题":">&&<","播放链接":"href=\"&&\"","免嗅":"0","分类url":"http://dyxz.tv/list/{cateId}_{catePg}.html","分类":"电影$1#电视剧$2#动漫$3#综艺$4"}},
71 | //{"key": "Xinsj","name": "新视觉","type": 3,"api": "csp_Xinsj", "timeout": 15, "searchable": 1,"quickSearch": 1,"changeable": 1,"ext": "https://www.hdmyy.com/"},
72 | //https://www.kan80.app/,https://www.hdmyy.com/,https://www.80yy3.com/
73 |
74 | //{"key": "zxzj","name": "在线之家","type": 3,"api": "csp_Zxzj","searchable": 1,"quickSearch": 1,"changeable": 1,"ext": "https://www.zxzj.pro/"},
75 | //https://www.zxzj.site/
76 |
77 | //{"key": "海兔影院","name":"海兔影院","type":3,"api":"csp_XBPQ","jar":"https://gitlab.com/xmbjm/omg/-/raw/main/jar/xyqxbpq.jar","ext": {"分类url":"https://www.haituu.tv/vodshow/{cateId}-{area}-{by}-{class}-----{catePg}---{year}.html","分类": "电视剧$2#电影$1#综艺$3#动漫$4"}},
78 | //www.haituu.tv;www.haitu.vip;www.haitu.xyz
79 |
80 | //{"key":"csp_xBPQ_影视工厂","name":"️影视工厂","type":3,"api":"csp_XBPQ","searchable":1,"quickSearch":1,"filterable":1,"changeable":1,"ext":{"分类url":"https://www.ysgc.fun/vodshow/{cateId}-{area}-time-{class}-{lang}----{catePg}---{year}.html;;lr","分类":"电影$1#连续剧$2#综艺$3#动漫$4"}},
81 |
82 | //{"key":"zy_最大资源","name":"最大资源","type":1,"api":"https://zuidazy.co/api.php/provide/vod/","playurl":"https://jx.zuidplay.com/m3u8Player/?url=","searchable": 1, "quickSearch": 1, "categories": ["国产剧","港剧","美剧","动作片","喜剧片","爱情片","科幻片","恐怖片","剧情片","战争片","纪录片","悬疑片","犯罪片"]},
83 | //资源站域名:zuidazy.me,zuidazy.co,zuida.xyz;zuidazy.me,zuidazy.co,zuida.xyz;https://api.zuidapi.com/api.php/provide/vod/from/zuidam3u8/at/xml/
84 |
85 | //{"key":"cj_鸡肋视频","name":"鸡肋视频","type":0,"api":"http://playersll.gaoxin155.com.cn/api.php/provide/vod/at/xml/","searchable":1,"quickSearch":1,"filterable":1,"changeable":1,"categories":[]},
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/hanXC.json:
--------------------------------------------------------------------------------
1 | //以下全部出自网络和大佬资源,如有冒犯请联系删除。[所有内容仅供学习使用,请勿用于违法用途]
2 |
3 | {
4 |
5 | "spider":"./lib/spider.jar",
6 | //https://try.gogs.io/NB666/api/raw/main/config.bin
7 | //http://my.djian.top/yutih2025/uuyug2025/raw/branch/maing/svip.json
8 | "lives": [{"name": "live","type": 0,
9 | //https://raw.bgithub.xyz/wcb1969/iptv/refs/heads/main/TV2025
10 | "url": "./live.txt","playerType":2,
11 | //"url": "https://raw.bgithub.xyz/xiongjian83/TvBox/refs/heads/main/live.txt","playerType":2,
12 |
13 | "epg":"http://epg.112114.xyz/?ch={name}&date={date}",
14 | "logo": "https://live.fanmingming.com/tv/{name}.png"
15 | }],
16 |
17 | "sites":[
18 |
19 | {"key":"豆豆","name":"胜寒提醒您:请勿相信视频中广告!在设置里面开启自动换源,体验更佳!","type":3,"api":"csp_Douban","indexs":1,"searchable":0,"quickSearch":0,"filterable":0},
20 |
21 | {"key":"xiaozhen","name":"小镇影视","type":3,"api":"csp_XBPQ","searchable":1,"quickSearch":1,"filterable":1,
22 | "ext":{"线路数组":"","线路标题":">&&<","分类url":"http://dyxz.tv/list/{cateId}_{catePg}.html","分类":"电影$1#电视剧$2#动漫$3#综艺$4"}},
23 | {"key": "雨见视频","name": "雨见蓝光","type": 3,"api": "csp_XBPQ","searchable": 1,"quickSearch": 1,"filterable": 1,
24 | "ext": {"影片类型": "类型:&&
","简介": "简介:&&
","分类url": "http://yjsp.mxys8.com/index.php/vod/show/area/{area}/by/{by}/class/{class}/id/{cateId}/page/{catePg}/year/{year}.html","分类": "国产剧$13#电影$1#连续剧$2#动漫$4#综艺$3#纪录片$27"}},
25 | //米 http://yj.appss.cc
26 | {"key": "csp_Gz360","name":"瓜子影视","type": 3,"quickSearch": 1,"api": "csp_Gz360"},
27 | {"key":"baibai","name":"素白影视","type":3,"quickSearch":1,"api":"csp_SuBaiBai","ext":"https://www.subaibai.com"},
28 | //https://subaibai.vip/
29 |
30 | //{"key":"尘落影视","name":"尘落影视","type": 3,"api": "csp_Wetv","searchable": 1,"quickSearch": 1,"ext": "https://v.wetv.wang"},
31 | {"key":"csp_红狐狸影视","name":"狐狸影视","type":3,"api":"csp_XBPQ","ext":{"分类url":"https://honghuli.com/show/{cateId}-{area}-------{catePg}---{year}.html","分类":"电影$1#电视剧$2#综艺$3#动漫$4"}},
32 |
33 | {"key":"drpy_js_金牌1","name":"金牌影视","type":3,"api":"./lib/drpy2.min.js","ext":"./lib/金牌影视.js"},
34 | {"key":"drpy_js_金牌","name":"金牌秒播","type":3,"api":"./lib/drpy2.min.js","ext":"./lib/金牌影视2.js"},
35 | //https://www.cfkj86.com/ http://www.yuhelover.com/ https://www.ghw9zwp5.com https://chuang999.com/ https://helloux9w23vc.com/ www.y5yy.com https://www.hkybqufgh.com/ http://www.guanyugekj.com/
36 | //https://gitee.com/senno/tvbox/raw/master/api.json; https://m.sunnafh.com/ https://www.gs4x7nq4.com/ https://ndhfiohk.com/ https://jieys.com/ https://www.vv3nwjk.com/ https://www.jpyy2.com/
37 | //https://www.sizhengxt.com,https://www.sizhengxt.com,https://www.tjrongze.com,https://www.jiabaide.cn
38 |
39 |
40 | {"key": "dianyiPQ","name": "电影先生","type": 3,"api": "csp_XBPQ","searchable": 1,"filterable": 1,"quickSearch": 1,
41 | "ext": {"分类url": "https://xn--44qz85a01qpc.com/pianku-{cateId}-{class}-{by}-{area}-{lang}----{catePg}---{year}.html","分类": "电视剧$dianshiju#电影$dianying#综艺$zongyi#动漫$dongman",
42 | "影片年代": "&&
","影片类型": "module-info-tag\">&&立即播放","搜索url": "https://xn--44qz85a01qpc.com/search--------------.html?wd={wd}",
43 | "简介": "style=\"line-height: 20px;\"&&","线路数组": "data-dropdown-value=&&[不包含:QI节点#QT节点#KU节点]","线路标题": "&&[排序:TK>HD>XS>YI>DI>]"}},
44 |
45 | {"key":"厂长","name":"厂长影视","type":3,"playerType":"2","api":"csp_Czsapp","searchable":1,"quickSearch":1,"filterable":1,"ext": "https://www.czzymovie.com/"},
46 |
47 | {"key":"可可影视","name":"可可影视","type":3,"api":"csp_XBPQ","searchable":1,"quickSearch":1,"filterable":1,"ext":"./lib/可可影视.json"},
48 | {"key":"火火影视","name":"火火影视","type":3,"api":"csp_SaoHuo","playerType":2,"ext":"https://shdy5.us"},
49 |
50 | {"key":"Wwys","name":"农民影视","type":3,"quickSearch":1,"api":"csp_Wwys","ext":"https://www.wwgz.cn"},
51 |
52 | {"key":"Lkdy","name":"来看影视","type": 3,"quickSearch": 1,"api": "csp_Lkdy"},
53 | //{"key":"浪酷影视","name":"浪酷影视","type": 3,"api": "csp_AppRJ","searchable": 1,"quickSearch": 1,"filterable": 0,"ext": {"url": "http://v.lkuys.cn"}},
54 | //{"key":"天天影视","name":"天天影视","type": 3,"api": "csp_AppRJ","searchable": 1,"quickSearch": 1,"filterable": 0,"ext": {"url": "http://tt.ysdqjs.cn"}},
55 | //{"key":"热播影视","name":"热播影视","type": 3,"api": "csp_AppRJ","searchable": 1,"quickSearch": 1,"filterable": 0,"ext": {"url": "http://v.rbotv.cn"}},
56 |
57 | //{"key": "lkvod","name":"爱看影视","type": 3,"api": "csp_XBPQ","ext":{"分类url":"https://lkvod.me/show/{cateId}-----------.html","分类": "国产剧$13#电视剧$2#日韩剧$15#电影$1#动漫$4#综艺$3"}},
58 | {"key":"bestpipe","name":"百思影视","type":3,"api":"csp_XBPQ","ext":{"分类url":"https://www.bestpipe.cn/vodshow/{cateId}-{area}-------{catePg}---.html","分类":"电影$20#剧集$21#短剧$24#综艺$23#动漫$22"}},
59 |
60 | //{"key": "全集","name": "全集影视","type": 3,"api": "csp_XBPQ","ext": {"分类url": "https://www.qjwtv.com/qjw/area/{area}/{cateId}/page/{catePg}/year/{year}.html","分类":"国产剧$gcj#短剧$dj#电影$dianying#电视剧$dianshiju#动漫$dongmna#综艺$zongyi#纪录片$jilupian"}},
61 | {"key": "耐看观影","name": "耐看观影","type": 3,"api": "csp_XBPQ",
62 | "ext": {"分类url":"https://www.nkvod.com/show/{cateId}-----------.html","分类": "电视剧$2#电影$1#动漫$4#综艺$3"}},
63 |
64 | {"key":"iysdq","name":"影院大全","type":3,"api":"csp_XBPQ",
65 | "ext":{"分类url":"https://www.iysdq.cc/vodshow/{cateId}-{area}-------{catePg}---.html","分类":"电影$1#电视剧$2#综艺$3#动漫$4#短剧$5"}},
66 | //https://www.iysdq.net/ https://www.iysdq.com https://www.iysdq.cc https://www.iysdq.cc/vodshow/1-%E5%A4%A7%E9%99%86-------2---.html
67 | {"key": "QD4K","name": "起点影视","type": 3,"api": "csp_AppYsV2","searchable": 1,"quickSearch": 1,"filterable": 1,"ext": "http://172.83.156.150:1010/api.php/app/"},
68 | // https://try.gogs.io/NB666/api/raw/main/config.bin
69 | {"key": "木耳","name": "木耳影院","type": 1,"api": "https://json02.heimuer.xyz/api.php/provide/vod","searchable": 1,"filterable": 1,"changeable": 1,"timeout":15,
70 | "categories": ["国产剧","国产综艺","国产动漫","韩剧","日本动漫","剧情片","动作片","冒险片","喜剧片","奇幻片","恐怖片","悬疑片","惊悚片","灾难片","爱情片","犯罪片","科幻片","歌舞片","战争片","经典片", "动画电影","网络电影","港剧","日剧","泰剧","台剧","欧美剧","新马剧","其他剧","港台综艺","韩国综艺","日本综艺","欧美综艺","新马泰综艺","其他综艺","古装短剧","虐恋短剧","逆袭短剧","神豪短剧","重生短剧","复仇短剧","穿越短剧","甜宠短剧","强者短剧","欧美动漫","韩国动漫","港台动漫"]},
71 |
72 | {"key": "小白","name": "小白影视","type": 3,"api": "csp_XBPQ",
73 | "ext": {"分类url": "https://www.xbaiys.com/xbys/area/{area}/{cateId}/page/{catePg}/year/{year}.html","分类":"国产剧$gcj#热门短剧$rmdj#电影$dianying#电视剧$dianshiju#动漫$dongmna#综艺$zongyi#纪录片$jilupian"}},
74 | {"key": "最全","name": "最全影视","type": 3,"api": "csp_XBPQ",
75 | "ext": {"分类url": "https://www.zqystv.com/zqys/area/{area}/{cateId}/page/{catePg}/year/{year}.html","分类":"国产剧$gcj#热门短剧$rmdj#电影$dianying#电视剧$dianshiju#动漫$dongmna#综艺$zongyi#纪录片$jilupian"}},
76 | //https://www.jileitv.com/ https://www.zpcxb.com https://www.ysmdhk.com/
77 |
78 | {"key": "狐狸君","name": "狐君4K","type": 3,"api": "csp_XBPQ","changeable": 1,"searchable": 1,"quickSearch": 1,"filterable": 1,
79 | "ext": {"搜索模式": "1","搜索url": "https://www.foxjun.com/s/?q={wd}","搜索数组": "class=\"media\">&&/div>", "搜索图片": "src=\"&&\"","搜索标题": "《&&》",
80 | "搜索副标题": "》&&\"","搜索链接": "href=\"&&\"","标题": "《&&》","副标题": "》&&\"","影片年代": "上映日期:&&","影片类型": "类型:&&","主演": "主演:&&","简介": "简介:&&",
81 | "播放数组": "&&","播放列表": "[包含:magnet]","播放标题": ">&&<","播放链接": "href=\"&&\"","分类url": "https://www.foxjun.com/channel/{cateId}.html?apage1={catepg}",
82 | "分类": "国产剧$guochanju#电影$dianying#动画$donghua#美欧剧$meiouju#日韩剧$rihanju"}},
83 |
84 | {"key":"csp_AppXY","name":"上头短剧","type":3,"quickSearch":1,"api":"csp_AppXY"},
85 | {"key": "星芽短剧","name": "星芽短剧","type": 3,"api": "csp_AppXY","searchable": 1,"quickSearch": 0,"filterable": 0},
86 | {"key": "红果短剧","name": "红果短剧","type": 3,"api": "./lib/红果短剧.py","searchable": 1,"changeable": 1,"quickSearch": 1,"filterable": 1,"playerType": 2},
87 | {"key": "甜圈短剧","name": "甜圈短剧","type": 3,"api": "./lib/甜圈短剧.py","searchable": 1,"changeable": 1,"quickSearch": 1,"filterable": 1,"playerType": 2},
88 | {"key": "河马短剧","name": "河马短剧","type": 3,"api": "./lib/河马短剧.py","searchable": 1,"changeable": 1,"quickSearch": 1,"filterable": 1,"playerType": 2},
89 |
90 | {"key":"星芽短剧2","name":"星芽短剧","type":3,"api":"https://weixine.net/js/lib/drpy2.min.js","ext": "https://weixine.net/js/xingya.js"},
91 | {"key": "HG影视","name": "HG影视","type": 3,"api": "csp_AppYsV2","searchable": 1,"quickSearch": 1,"filterable": 1,"ext": "https://cs.hgyx.vip/api2/api.php/app/"},
92 | //https://cs.hgyx.vip/
93 | {"key": "csp_非凡资源","name": "非凡影院","type": 1,"api": "http://ffzy.tv/api.php/provide/vod/","searchable": 1,"quickSearch": 1,"filterable": 1,
94 | "categories": ["短剧","国产剧","大陆综艺", "国产动漫","韩国剧","动作片","喜剧片","科幻片","恐怖片","爱情片","剧情片","战争片","记录片","欧美剧","香港剧","台湾剧","日本剧","海外剧","泰国剧","日韩动漫","欧美动漫","港台动漫","海外动漫","港台综艺","日韩综艺","欧美综艺"]},
95 | //非凡资源备用网址:ffzy1.tv ffzy2.tv ffzy3.tv ffzy4.tv ffzy5.tv http://ffzy.tv/api.php/provide/vod/
96 |
97 | {"key":"极速资源","name":"极速影院","type": 1,"api": "https://jszyapi.com/api.php/provide/vod/at/json","searchable": 1,"quickSearch": 1,"filterable": 1,
98 | "categories": ["短剧","内地剧","大陆综艺","中国动漫","动作片","喜剧片","爱情片","科幻片","恐怖片","剧情片","战争片","动画片","记录片","台湾剧","日剧","韩剧","马泰剧","港台综艺","日韩综艺","欧美综艺","日韩动漫","欧美动漫","港台动漫","海外动漫"]},
99 | //https://jszyapi.com/ www.jisuzy.com www.jisuzy.tv www.jisuziyuan.com www.jszy666.com https://jisjiexi.com/play/?url=
100 |
101 | {"key":"天翼资源","name":"天翼影视","type":1,"api":"https://www.911ysw.top/tianyi.php/provide/vod/","playUrl":"","searchable":1,"quickSearch":1 ,
102 | "categories": ["国产剧","综艺","动漫","动作片", "喜剧片", "爱情片", "科幻片", "恐怖片", "剧情片", "战争片","惊悚片","犯罪片","悬疑片","惊悚片","港台剧","日韩剧","泰国剧", "欧美剧"]},
103 |
104 | {"key": "csp_hanhan","name": "请勿相信影片广告!","type": 1,"playerType": 2,"api": "","searchable": 1,"quickSearch": 1,"filterable": 1}
105 |
106 | ],
107 |
108 | "parses":[
109 |
110 | {"name":"Json聚合","type":3,"url":"Demo"},
111 | {"name":"线0","type":0,"url":"https://bd.jx.cn/?url="},
112 | {"name":"线1","type": 1,"url": "https://www.pangujiexi.com/pangu/?url=","ext": {"flag": ["qq","腾讯","qiyi","爱奇艺","奇艺","youku","优酷","sohu","搜狐","letv","乐视","mgtv","芒果","tnmb","seven","bilibili","1905","NetFilx"]}},
113 | {"name":"线2","url": "https://jx.xmflv.cc/?url=","type": 0,"ext": {"flag": ["qiyi","imgo","爱奇艺","奇艺","qq","qq 预告及花絮","腾讯","youku","优酷","pptv","PPTV","letv","乐视","leshi","mgtv","芒果","sohu","xigua","fun","风行"]}},
114 | {"name":"线3","url":"https://www.playm3u8.cn/jiexi.php?url=","type":0,"ext":{"flag":["qiyi","imgo","爱奇艺","奇艺","qq","腾讯","youku","优酷","pptv","PPTV","letv","乐视","leshi","bilibili","哔哩哔哩","哔哩","mgtv","芒果","sohu","xigua","fun","风行"],"header":{"User-Agent":"Mozilla/5.0"}},"header":{"User-Agent":"Mozilla/5.0"}},
115 | {"name":"线4","type":0,"url":"https://www.8090g.cn/?url="},
116 | {"name":"线5","type":1,"url":"https://www.pouyun.com/?url="},
117 | {"name":"线6","type":1,"url":"https://jx.m3u8.tv/jiexi/?url="},
118 | {"name":"线7","type":1,"url":"https://jx.2s0.cn/player/?url="},
119 | {"name":"线8","type":0,"url":"https://www.yemu.xyz/?url="},
120 | {"name":"线9","type":1,"url":"https://www.ckplayer.vip/jiexi/?url="},
121 | {"name":"线10","type":1,"url":"https://www.pangujiexi.com/pangu/?url="},
122 | {"name":"线11","type":0,"url":"https://jx.yparse.com/index.php?url=","ext":{"header":{"user-agent":"Mozilla/5.0(Linux;Android13;V2049ABuild/TP1A.220624.014;wv)AppleWebKit/537.36(KHTML,likeGecko)Version/4.0Chrome/116.0.0.0MobileSafari/537.36"}}},
123 |
124 | {"name":"胜寒欢迎您","type":0,"url":""}
125 | ],
126 |
127 |
128 | "flags":["youku","优酷","优 酷","优酷视频", "qq","腾讯","腾 讯","腾讯视频", "iqiyi", "qiyi","奇艺","爱奇艺","爱 奇 艺", "m1905", "xigua", "letv","leshi","乐视","乐 视", "sohu","搜狐","搜 狐","搜狐视频", "tudou","mgtv","芒果","imgo","芒果TV","芒 果 T V", "bilibili","哔 哩","哔 哩 哔 哩","SPA","YuMi-vip","pptv","PPTV","ltnb","rx","SLYS4k","tucheng","BYGA","luanzi","dxzy","QEYSS","aliyun","AliS","122","chuangying","CL4K","xfyun","wuduzy","wasu","renrenmi","ppayun","haiwaikan","cool","dbm3u8","xmm","funshion","ruyi1080","ruyib1080"],
129 | "doh":[{"name":"Google","url":"https://dns.google/dns-query","ips":["8.8.4.4","8.8.8.8"]},
130 | {"name":"Cloudflare","url":"https://cloudflare-dns.com/dns-query","ips":["1.1.1.1","1.0.0.1","2606:4700:4700::1111","2606:4700:4700::1001"]},
131 | {"name":"AdGuard","url":"https://dns.adguard.com/dns-query","ips":["94.140.14.140","94.140.14.141"]},
132 | {"name":"DNSWatch","url":"https://resolver2.dns.watch/dns-query","ips":["84.200.69.80","84.200.70.40"]},
133 | {"name":"Quad9","url":"https://dns.quad9.net/dns-quer","ips":["9.9.9.9","149.112.112.112"]}],
134 | "rules":[
135 | {"name":"kk","hosts":["kuaikan"],"regex":["5","20.123","20.167","#EXT-X-DISCONTINUITY\\r*\\n*((?!#EXT-X-DISCONTINUITY)[\\s\\S])*?#EXT-X-KEY:METHOD((?!#EXT-X-DISCONTINUITY)[\\s\\S])*?#EXT-X-DISCONTINUITY"]},
136 | {"name":"yqk","hosts":["yqk"],"regex":["18.4","15.1666","#EXT-X-DISCONTINUITY\\r*\\n*((?!#EXT-X-DISCONTINUITY)[\\s\\S])*?#EXT-X-CUE-OUT((?!#EXT-X-DISCONTINUITY)[\\s\\S])*?#EXT-X-CUE-IN"]},
137 | {"name":"sn","hosts":["suonizy"],"regex":["#EXTINF.*?\\s+.*?original.*?\\.ts\\s+","15.1666","15.2666","16.3333","15.266667"]},
138 | {"name":"bf","hosts":["bfzy"],"regex":["#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:3,[\\s\\S]*?#EXT-X-DISCONTINUITY"]},
139 | {"name":"xx","hosts":["aws.ulivetv.net"],"regex":["#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:8,[\\s\\S]*?#EXT-X-DISCONTINUITY"]},
140 | {"name":"lz","hosts":["vip.lz","hd.lz","v.cdnlz","yzzy1.play"],"regex":["18.5333","19.52","18.6666"]},
141 | {"name":"ff","hosts":["vip.ffzy","hd.ffzy","ffzy"],"regex":["25.0666","25.08","20.52","25.1","25.1999"]},
142 | {"name":"hs","hosts":["huoshan.com"],"regex":["item_id="]},
143 | {"name":"dy","hosts":["douyin.com"],"regex":["is_play_url="]},
144 | {"name":"nm","hosts":["toutiaovod.com"],"regex":["video/tos/cn"]},
145 | {"name":"cl","hosts":["magnet"],"regex":["最 新","直 播","更 新"]}
146 | ]
147 | }
148 |
--------------------------------------------------------------------------------
/lib/0408.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hanhan8127/TVBox/e3e2d3df1d42c6aacbafc4d033fde1eeaa0ce341/lib/0408.jar
--------------------------------------------------------------------------------
/lib/TVB云播.js:
--------------------------------------------------------------------------------
1 | var rule = {
2 | title: 'TVB云播',
3 | //模板:'mxpro',
4 | host: 'http://www.tvyun07.com',
5 | url: 'vod/show/id/fyfilter.html',
6 | filterable: 1,//是否启用分类筛选,
7 | filter_url: '{{fl.cateId}}{{fl.area}}{{fl.by}}{{fl.class}}{{fl.lang}}{{fl.letter}}/page/fypage{{fl.year}}',
8 | class_name: '电影&电视剧&综艺&动漫&日韩剧&国产剧&欧美剧&港台剧',
9 | class_url: '1&2&3&4&16&13&15&14',
10 | filter: {
11 | "1": [{ "key": "cateId", "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" }] }, { "key": "class", "name": "剧情", "value": [{ "n": "全部", "v": "" }, { "n": "喜剧", "v": "/class/喜剧" }, { "n": "爱情", "v": "/class/爱情" }, { "n": "恐怖", "v": "/class/恐怖" }, { "n": "动作", "v": "/class/动作" }, { "n": "科幻", "v": "/class/科幻" }, { "n": "剧情", "v": "/class/剧情" }, { "n": "战争", "v": "/class/战争" }, { "n": "警匪", "v": "/class/警匪" }, { "n": "犯罪", "v": "/class/犯罪" }, { "n": "动画", "v": "/class/动画" }, { "n": "奇幻", "v": "/class/奇幻" }, { "n": "武侠", "v": "/class/武侠" }, { "n": "冒险", "v": "/class/冒险" }, { "n": "枪战", "v": "/class/枪战" }, { "n": "悬疑", "v": "/class/悬疑" }, { "n": "惊悚", "v": "/class/惊悚" }, { "n": "经典", "v": "/class/经典" }, { "n": "青春", "v": "/class/青春" }, { "n": "文艺", "v": "/class/文艺" }, { "n": "微电影", "v": "/class/微电影" }, { "n": "古装", "v": "/class/古装" }, { "n": "历史", "v": "/class/历史" }, { "n": "运动", "v": "/class/运动" }, { "n": "农村", "v": "/class/农村" }, { "n": "儿童", "v": "/class/儿童" }, { "n": "网络电影", "v": "/class/网络电影" }] }, { "key": "area", "name": "地区", "value": [{ "n": "全部", "v": "" }, { "n": "大陆", "v": "/area/大陆" }, { "n": "香港", "v": "/area/香港" }, { "n": "台湾", "v": "/area/台湾" }, { "n": "美国", "v": "/area/美国" }, { "n": "法国", "v": "/area/法国" }, { "n": "英国", "v": "/area/英国" }, { "n": "日本", "v": "/area/日本" }, { "n": "韩国", "v": "/area/韩国" }, { "n": "德国", "v": "/area/德国" }, { "n": "泰国", "v": "/area/泰国" }, { "n": "印度", "v": "/area/印度" }, { "n": "意大利", "v": "/area/意大利" }, { "n": "西班牙", "v": "/area/西班牙" }, { "n": "加拿大", "v": "/area/加拿大" }, { "n": "其他", "v": "/area/其他" }] }, { "key": "lang", "name": "语言", "value": [{ "n": "全部", "v": "" }, { "n": "国语", "v": "/lang/国语" }, { "n": "英语", "v": "/lang/英语" }, { "n": "粤语", "v": "/lang/粤语" }, { "n": "韩语", "v": "/lang/韩语" }, { "n": "日语", "v": "/lang/日语" }, { "n": "法语", "v": "/lang/法语" }, { "n": "德语", "v": "/lang/德语" }, { "n": "其它", "v": "/lang/其它" }] }, { "key": "year", "name": "年份", "value": [{ "n": "全部", "v": "" }, { "n": "2025", "v": "/year/2025" },{ "n": "2024", "v": "/year/2024" }, { "n": "2023", "v": "/year/2023" }, { "n": "2022", "v": "/year/2022" }, { "n": "2021", "v": "/year/2021" }, { "n": "2020", "v": "/year/2020" }, { "n": "2019", "v": "/year/2019" }, { "n": "2018", "v": "/year/2018" }, { "n": "2017", "v": "/year/2017" }, { "n": "2016", "v": "/year/2016" }, { "n": "2015", "v": "/year/2015" }, { "n": "2014", "v": "/year/2014" }, { "n": "2013", "v": "/year/2013" }, { "n": "2012", "v": "/year/2012" }, { "n": "2011", "v": "/year/2011" }, { "n": "2010", "v": "/year/2010" }, { "n": "2009", "v": "/year/2009" }, { "n": "2008", "v": "/year/2008" }, { "n": "2007", "v": "/year/2007" }, { "n": "2006", "v": "/year/2006" }, { "n": "2005", "v": "/year/2005" }, { "n": "2004", "v": "/year/2004" }] }, { "key": "by", "name": "排序", "value": [{ "n": "全部", "v": "" }, { "n": "时间", "v": "/by/time" }, { "n": "人气", "v": "/by/hits" }, { "n": "评分", "v": "/by/score" }] }],
12 | "2": [{ "key": "cateId", "name": "类型", "value": [{ "n": "全部", "v": "2" }, { "n": "国产剧", "v": "13" }, { "n": "港台剧", "v": "14" }, { "n": "日韩剧", "v": "15" }, { "n": "欧美剧", "v": "16" }] }, { "key": "class", "name": "剧情", "value": [{ "n": "全部", "v": "" }, { "n": "古装", "v": "/class/古装" }, { "n": "青春", "v": "/class/青春" }, { "n": "偶像", "v": "/class/偶像" }, { "n": "喜剧", "v": "/class/喜剧" }, { "n": "家庭", "v": "/class/家庭" }, { "n": "犯罪", "v": "/class/犯罪" }, { "n": "动作", "v": "/class/动作" }, { "n": "奇幻", "v": "/class/奇幻" }, { "n": "剧情", "v": "/class/剧情" }, { "n": "历史", "v": "/class/历史" }, { "n": "经典", "v": "/class/经典" }, { "n": "乡村", "v": "/class/乡村" }, { "n": "情景", "v": "/class/情景" }, { "n": "商战", "v": "/class/商战" }, { "n": "网剧", "v": "/class/网剧" }, { "n": "其他", "v": "/class/其他" }] }, { "key": "area", "name": "地区", "value": [{ "n": "全部", "v": "" }, { "n": "内地", "v": "/area/内地" }, { "n": "韩国", "v": "/area/韩国" }, { "n": "香港", "v": "/area/香港" }, { "n": "台湾", "v": "/area/台湾" }, { "n": "日本", "v": "/area/日本" }, { "n": "美国", "v": "/area/美国" }, { "n": "泰国", "v": "/area/泰国" }, { "n": "英国", "v": "/area/英国" }, { "n": "新加坡", "v": "/area/新加坡" }, { "n": "其他", "v": "/area/其他" }] }, { "key": "year", "name": "年份", "value": [{ "n": "全部", "v": "" }, { "n": "2025", "v": "/year/2025" },{ "n": "2024", "v": "/year/2024" }, { "n": "2023", "v": "/year/2023" }, { "n": "2022", "v": "/year/2022" }, { "n": "2021", "v": "/year/2021" }, { "n": "2020", "v": "/year/2020" }, { "n": "2019", "v": "/year/2019" }, { "n": "2018", "v": "/year/2018" }, { "n": "2017", "v": "/year/2017" }, { "n": "2016", "v": "/year/2016" }, { "n": "2015", "v": "/year/2015" }, { "n": "2014", "v": "/year/2014" }, { "n": "2013", "v": "/year/2013" }, { "n": "2012", "v": "/year/2012" }, { "n": "2011", "v": "/year/2011" }, { "n": "2010", "v": "/year/2010" }, { "n": "2009", "v": "/year/2009" }, { "n": "2008", "v": "/year/2008" }, { "n": "2007", "v": "/year/2007" }, { "n": "2006", "v": "/year/2006" }, { "n": "2005", "v": "/year/2005" }, { "n": "2004", "v": "/year/2004" }] }, { "key": "lang", "name": "语言", "value": [{ "n": "全部", "v": "" }, { "n": "国语", "v": "/lang/国语" }, { "n": "英语", "v": "/lang/英语" }, { "n": "粤语", "v": "/lang/粤语" }, { "n": "韩语", "v": "/lang/韩语" }, { "n": "日语", "v": "/lang/日语" }, { "n": "其它", "v": "/lang/其它" }] }, { "key": "by", "name": "排序", "value": [{ "n": "全部", "v": "" }, { "n": "时间", "v": "/by/time" }, { "n": "人气", "v": "/by/hits" }, { "n": "评分", "v": "/by/score" }] }],
13 | "3": [{ "key": "class", "name": "剧情", "value": [{ "n": "全部", "v": "" }, { "n": "选秀", "v": "/class/选秀" }, { "n": "情感", "v": "/class/情感" }, { "n": "访谈", "v": "/class/访谈" }, { "n": "播报", "v": "/class/播报" }, { "n": "旅游", "v": "/class/旅游" }, { "n": "音乐", "v": "/class/音乐" }, { "n": "美食", "v": "/class/美食" }, { "n": "纪实", "v": "/class/纪实" }, { "n": "曲艺", "v": "/class/曲艺" }, { "n": "生活", "v": "/class/生活" }, { "n": "游戏互动", "v": "/class/游戏互动" }, { "n": "财经", "v": "/class/财经" }, { "n": "求职", "v": "/class/求职" }] }, { "key": "area", "name": "地区", "value": [{ "n": "全部", "v": "" }, { "n": "内地", "v": "/area/内地" }, { "n": "港台", "v": "/area/港台" }, { "n": "日韩", "v": "/area/日韩" }, { "n": "欧美", "v": "/area/欧美" }] }, { "key": "lang", "name": "语言", "value": [{ "n": "全部", "v": "" }, { "n": "国语", "v": "/lang/国语" }, { "n": "英语", "v": "/lang/英语" }, { "n": "粤语", "v": "/lang/粤语" }, { "n": "韩语", "v": "/lang/韩语" }, { "n": "日语", "v": "/lang/日语" }, { "n": "其它", "v": "/lang/其它" }] }, { "key": "year", "name": "年份", "value": [{ "n": "全部", "v": "" }, { "n": "2025", "v": "/year/2025" },{ "n": "2024", "v": "/year/2024" }, { "n": "2023", "v": "/year/2023" }, { "n": "2022", "v": "/year/2022" }, { "n": "2021", "v": "/year/2021" }, { "n": "2020", "v": "/year/2020" }, { "n": "2019", "v": "/year/2019" }, { "n": "2018", "v": "/year/2018" }, { "n": "2017", "v": "/year/2017" }, { "n": "2016", "v": "/year/2016" }, { "n": "2015", "v": "/year/2015" }, { "n": "2014", "v": "/year/2014" }, { "n": "2013", "v": "/year/2013" }, { "n": "2012", "v": "/year/2012" }, { "n": "2011", "v": "/year/2011" }, { "n": "2010", "v": "/year/2010" }, { "n": "2009", "v": "/year/2009" }, { "n": "2008", "v": "/year/2008" }, { "n": "2007", "v": "/year/2007" }, { "n": "2006", "v": "/year/2006" }, { "n": "2005", "v": "/year/2005" }, { "n": "2004", "v": "/year/2004" }] }, { "key": "by", "name": "排序", "value": [{ "n": "全部", "v": "" }, { "n": "时间", "v": "/by/time" }, { "n": "人气", "v": "/by/hits" }, { "n": "评分", "v": "/by/score" }] }],
14 | "4": [{ "key": "class", "name": "剧情", "value": [{ "n": "全部", "v": "" }, { "n": "情感", "v": "/class/情感" }, { "n": "科幻", "v": "/class/科幻" }, { "n": "热血", "v": "/class/热血" }, { "n": "推理", "v": "/class/推理" }, { "n": "搞笑", "v": "/class/搞笑" }, { "n": "冒险", "v": "/class/冒险" }, { "n": "萝莉", "v": "/class/萝莉" }, { "n": "校园", "v": "/class/校园" }, { "n": "动作", "v": "/class/动作" }, { "n": "机战", "v": "/class/机战" }, { "n": "运动", "v": "/class/运动" }, { "n": "战争", "v": "/class/战争" }, { "n": "少年", "v": "/class/少年" }, { "n": "少女", "v": "/class/少女" }, { "n": "社会", "v": "/class/社会" }, { "n": "原创", "v": "/class/原创" }, { "n": "亲子", "v": "/class/亲子" }, { "n": "益智", "v": "/class/益智" }, { "n": "励志", "v": "/class/励志" }, { "n": "其它", "v": "/class/其他" }] }, { "key": "area", "name": "地区", "value": [{ "n": "全部", "v": "" }, { "n": "国产", "v": "/area/国产" }, { "n": "日本", "v": "/area/日本" }, { "n": "欧美", "v": "/area/欧美" }, { "n": "其他", "v": "/area/其他" }] }, { "key": "lang", "name": "语言", "value": [{ "n": "全部", "v": "" }, { "n": "国语", "v": "/lang/国语" }, { "n": "英语", "v": "/lang/英语" }, { "n": "粤语", "v": "/lang/粤语" }, { "n": "韩语", "v": "/lang/韩语" }, { "n": "日语", "v": "/lang/日语" }, { "n": "其它", "v": "/lang/其它" }] }, { "key": "year", "name": "年份", "value": [{ "n": "全部", "v": "" }, { "n": "2025", "v": "/year/2025" },{ "n": "2024", "v": "/year/2024" }, { "n": "2023", "v": "/year/2023" }, { "n": "2022", "v": "/year/2022" }, { "n": "2021", "v": "/year/2021" }, { "n": "2020", "v": "/year/2020" }, { "n": "2019", "v": "/year/2019" }, { "n": "2018", "v": "/year/2018" }, { "n": "2017", "v": "/year/2017" }, { "n": "2016", "v": "/year/2016" }, { "n": "2015", "v": "/year/2015" }, { "n": "2014", "v": "/year/2014" }, { "n": "2013", "v": "/year/2013" }, { "n": "2012", "v": "/year/2012" }, { "n": "2011", "v": "/year/2011" }, { "n": "2010", "v": "/year/2010" }, { "n": "2009", "v": "/year/2009" }, { "n": "2008", "v": "/year/2008" }, { "n": "2007", "v": "/year/2007" }, { "n": "2006", "v": "/year/2006" }, { "n": "2005", "v": "/year/2005" }, { "n": "2004", "v": "/year/2004" }] }, { "key": "by", "name": "排序", "value": [{ "n": "全部", "v": "" }, { "n": "时间", "v": "/by/time" }, { "n": "人气", "v": "/by/hits" }, { "n": "评分", "v": "/by/score" }] }]
15 | },
16 | filter_def: {
17 | 1: { cateId: '1' },
18 | 2: { cateId: '2' },
19 | 3: { cateId: '3' },
20 | 4: { cateId: '4' },
21 | 13: { cateId: '13' },
22 | 14: { cateId: '14' },
23 | 15: { cateId: '15' },
24 | 16: { cateId: '16' }
25 | },
26 | searchUrl: '/vod/search.html?wd=**&submit=',
27 | searchable: 2,//是否启用全局搜索,
28 | quickSearch: 0,//是否启用快速搜索,
29 | filterable: 0,//是否启用分类筛选,
30 | play_parse: true,
31 | lazy: '',
32 | limit: 6,
33 | // 推荐:'ul.myui-vodlist;ul li;*;*;*;*',
34 | 推荐: 'ul.myui-vodlist;li;*;*;*;*',
35 | // 推荐:'ul.myui-vodlist;ul&&li;*;*;*;*', // 此写法本地js无效
36 | double: true, // 推荐内容是否双层定位
37 | 一级: '.myui-vodlist__box;a&&title;.lazyload&&data-original;.tag&&Text;a&&href',
38 | 二级: {
39 | "title": "h1&&Text;.data:eq(0) a:eq(0)&&Text",
40 | "img": ".lazyload&&data-original",
41 | "desc": ";.data:eq(0) a:eq(2)&&Text;.data:eq(0) a:eq(1)&&Text;.data:eq(2)&&Text;.data:eq(3)&&Text",
42 | "content": ".text-collapse span&&Text",
43 | "tabs": ".myui-panel__head h3",
44 | "lists": ".myui-content__list:eq(#id) li"
45 | },
46 | 搜索: 'ul.myui-vodlist__media li;*;*;*;*',
47 | }
48 |
--------------------------------------------------------------------------------
/lib/custom_spider.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hanhan8127/TVBox/e3e2d3df1d42c6aacbafc4d033fde1eeaa0ce341/lib/custom_spider.jar
--------------------------------------------------------------------------------
/lib/drpy2.min.js:
--------------------------------------------------------------------------------
1 | import cheerio from "assets://js/lib/cheerio.min.js"; import "assets://js/lib/crypto-js.js"; import "./jsencrypt.js"; import 模板 from "../js/模板.js"; import { gbkTool } from "./gbk.js"; function init_test() { console.log("init_test_start"); console.log("当前版本号:" + VERSION); console.log(RKEY); console.log(JSON.stringify(rule)); console.log("init_test_end") } function pre() { if (typeof rule.预处理 === "string" && rule.预处理 && rule.预处理.trim()) { let code = rule.预处理.trim(); console.log("执行预处理代码:" + code); if (code.startsWith("js:")) { code = code.replace("js:", "") } try { eval(code) } catch (e) { console.log("预处理执行失败:" + e.message) } } } let rule = {}; let vercode = typeof pdfl === "function" ? "drpy2.1" : "drpy2"; const VERSION = vercode + " 3.9.49beta40 202400426"; const MOBILE_UA = "Mozilla/5.0 (Linux; Android 11; M2007J3SC Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045714 Mobile Safari/537.36"; const PC_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36"; const UA = "Mozilla/5.0"; const UC_UA = "Mozilla/5.0 (Linux; U; Android 9; zh-CN; MI 9 Build/PKQ1.181121.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.5.5.1035 Mobile Safari/537.36"; const IOS_UA = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"; const RULE_CK = "cookie"; const CATE_EXCLUDE = "首页|留言|APP|下载|资讯|新闻|动态"; const TAB_EXCLUDE = "猜你|喜欢|下载|剧情|热播"; const OCR_RETRY = 3; const OCR_API = "http://drpy.nokia.press:8028/ocr/drpy/text"; if (typeof MY_URL === "undefined") { var MY_URL } var HOST; var RKEY; var fetch; var print; var log; var rule_fetch_params; var fetch_params; var oheaders; var _pdfh; var _pdfa; var _pd; const DOM_CHECK_ATTR = /(url|src|href|-original|-src|-play|-url|style)$/; const SPECIAL_URL = /^(ftp|magnet|thunder|ws):/; const NOADD_INDEX = /:eq|:lt|:gt|:first|:last|^body$|^#/; const URLJOIN_ATTR = /(url|src|href|-original|-src|-play|-url|style)$/; const SELECT_REGEX = /:eq|:lt|:gt|#/g; const SELECT_REGEX_A = /:eq|:lt|:gt/g; if (typeof Object.assign != "function") { Object.assign = function () { let target = arguments[0]; for (let i = 1; i < arguments.length; i++) { let source = arguments[i]; for (let key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key] } } } return target } } if (!String.prototype.includes) { String.prototype.includes = function (search, start) { if (typeof start !== "number") { start = 0 } if (start + search.length > this.length) { return false } else { return this.indexOf(search, start) !== -1 } } } if (!Array.prototype.includes) { Object.defineProperty(Array.prototype, "includes", { value: function (searchElement, fromIndex) { if (this == null) { throw new TypeError('"this" is null or not defined') } var o = Object(this); var len = o.length >>> 0; if (len === 0) { return false } var n = fromIndex | 0; var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); while (k < len) { if (o[k] === searchElement) { return true } k++ } return false } }) } if (typeof String.prototype.startsWith != "function") { String.prototype.startsWith = function (prefix) { return this.slice(0, prefix.length) === prefix } } if (typeof String.prototype.endsWith != "function") { String.prototype.endsWith = function (suffix) { return this.indexOf(suffix, this.length - suffix.length) !== -1 } } Object.prototype.myValues = function (obj) { if (obj == null) { throw new TypeError("Cannot convert undefined or null to object") } var res = []; for (var k in obj) { if (obj.hasOwnProperty(k)) { res.push(obj[k]) } } return res }; if (typeof Object.prototype.values != "function") { Object.prototype.values = function (obj) { if (obj == null) { throw new TypeError("Cannot convert undefined or null to object") } var res = []; for (var k in obj) { if (obj.hasOwnProperty(k)) { res.push(obj[k]) } } return res } } if (typeof Array.prototype.join != "function") { Array.prototype.join = function (emoji) { emoji = emoji || ""; let self = this; let str = ""; let i = 0; if (!Array.isArray(self)) { throw String(self) + "is not Array" } if (self.length === 0) { return "" } if (self.length === 1) { return String(self[0]) } i = 1; str = this[0]; for (; i < self.length; i++) { str += String(emoji) + String(self[i]) } return str } } if (typeof Array.prototype.toReversed != "function") { Array.prototype.toReversed = function () { const clonedList = this.slice(); const reversedList = clonedList.reverse(); return reversedList } } String.prototype.rstrip = function (chars) { let regex = new RegExp(chars + "$"); return this.replace(regex, "") }; Array.prototype.append = Array.prototype.push; String.prototype.strip = String.prototype.trim; function 是否正版(vipUrl) { let flag = new RegExp("qq.com|iqiyi.com|youku.com|mgtv.com|bilibili.com|sohu.com|ixigua.com|pptv.com|miguvideo.com|le.com|1905.com|fun.tv"); return flag.test(vipUrl) } function urlDeal(vipUrl) { if (!vipUrl) { return "" } if (!是否正版(vipUrl)) { return vipUrl } if (!/miguvideo/.test(vipUrl)) { vipUrl = vipUrl.split("#")[0].split("?")[0] } return vipUrl } function setResult(d) { if (!Array.isArray(d)) { return [] } VODS = []; d.forEach(function (it) { let obj = { vod_id: it.url || "", vod_name: it.title || "", vod_remarks: it.desc || "", vod_content: it.content || "", vod_pic: it.pic_url || it.img || "" }; let keys = Object.keys(it); if (keys.includes("tname")) { obj.type_name = it.tname || "" } if (keys.includes("tid")) { obj.type_id = it.tid || "" } if (keys.includes("year")) { obj.vod_year = it.year || "" } if (keys.includes("actor")) { obj.vod_actor = it.actor || "" } if (keys.includes("director")) { obj.vod_director = it.director || "" } if (keys.includes("area")) { obj.vod_area = it.area || "" } VODS.push(obj) }); return VODS } function setResult2(res) { VODS = res.list || []; return VODS } function setHomeResult(res) { if (!res || typeof res !== "object") { return [] } return setResult(res.list) } function rc(js) { if (js === "maomi_aes.js") { var a = CryptoJS.enc.Utf8.parse("625222f9149e961d"); var t = CryptoJS.enc.Utf8.parse("5efdtf6060e2o330"); return { De: function (word) { word = CryptoJS.enc.Hex.parse(word); return CryptoJS.AES.decrypt(CryptoJS.enc.Base64.stringify(word), a, { iv: t, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }).toString(CryptoJS.enc.Utf8) }, En: function (word) { var Encrypted = CryptoJS.AES.encrypt(word, a, { iv: t, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); return Encrypted.ciphertext.toString() } } } return {} } function maoss(jxurl, ref, key) { fetch_params = JSON.parse(JSON.stringify(rule_fetch_params)); eval(getCryptoJS()); try { var getVideoInfo = function (text) { return CryptoJS.AES.decrypt(text, key, { iv: iv, padding: CryptoJS.pad.Pkcs7 }).toString(CryptoJS.enc.Utf8) }; var token_key = key == undefined ? "dvyYRQlnPRCMdQSe" : key; if (ref) { var html = request(jxurl, { headers: { Referer: ref } }) } else { var html = request(jxurl) } if (html.indexOf("&btwaf=") != -1) { html = request(jxurl + "&btwaf" + html.match(/&btwaf(.*?)"/)[1], { headers: { Referer: ref } }) } var token_iv = html.split('_token = "')[1].split('"')[0]; var key = CryptoJS.enc.Utf8.parse(token_key); var iv = CryptoJS.enc.Utf8.parse(token_iv); eval(html.match(/var config = {[\s\S]*?}/)[0] + ""); if (!config.url.startsWith("http")) { config.url = CryptoJS.AES.decrypt(config.url, key, { iv: iv, padding: CryptoJS.pad.Pkcs7 }).toString(CryptoJS.enc.Utf8) } return config.url } catch (e) { return "" } } function urlencode(str) { str = (str + "").toString(); return encodeURIComponent(str).replace(/!/g, "%21").replace(/'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/\*/g, "%2A").replace(/%20/g, "+") } function base64Encode(text) { return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(text)) } function base64Decode(text) { return CryptoJS.enc.Utf8.stringify(CryptoJS.enc.Base64.parse(text)) } function md5(text) { return CryptoJS.MD5(text).toString() } function encodeStr(input, encoding) { encoding = encoding || "gbk"; if (encoding.startsWith("gb")) { const strTool = gbkTool(); input = strTool.encode(input) } return input } function decodeStr(input, encoding) { encoding = encoding || "gbk"; if (encoding.startsWith("gb")) { const strTool = gbkTool(); input = strTool.decode(input) } return input } function getCryptoJS() { return 'console.log("CryptoJS已装载");' } const RSA = { decode: function (data, key, option) { option = option || {}; if (typeof JSEncrypt === "function") { let chunkSize = option.chunkSize || 117; let privateKey = this.getPrivateKey(key); const decryptor = new JSEncrypt; decryptor.setPrivateKey(privateKey); let uncrypted = ""; uncrypted = decryptor.decryptUnicodeLong(data); return uncrypted } else { return false } }, encode: function (data, key, option) { option = option || {}; if (typeof JSEncrypt === "function") { let chunkSize = option.chunkSize || 117; let publicKey = this.getPublicKey(key); const encryptor = new JSEncrypt; encryptor.setPublicKey(publicKey); let encrypted = ""; encrypted = encryptor.encryptUnicodeLong(data); return encrypted } else { return false } }, fixKey(key, prefix, endfix) { if (!key.includes(prefix)) { key = prefix + key } if (!key.includes(endfix)) { key += endfix } return key }, getPrivateKey(key) { let prefix = "-----BEGIN RSA PRIVATE KEY-----"; let endfix = "-----END RSA PRIVATE KEY-----"; return this.fixKey(key, prefix, endfix) }, getPublicKey(key) { let prefix = "-----BEGIN PUBLIC KEY-----"; let endfix = "-----END PUBLIC KEY-----"; return this.fixKey(key, prefix, endfix) } }; function getProxyUrl() { if (typeof getProxy === "function") { return getProxy(true) } else { return "http://127.0.0.1:9978/proxy?do=js" } } function fixAdM3u8(m3u8_text, m3u8_url, ad_remove) { if (!m3u8_text && !m3u8_url || !m3u8_text && m3u8_url && !m3u8_url.startsWith("http")) { return "" } if (!m3u8_text) { log("m3u8_url:" + m3u8_url); m3u8_text = request(m3u8_url) } log("len(m3u8_text):" + m3u8_text.length); if (!ad_remove) { return m3u8_text } if (ad_remove.startsWith("reg:")) { ad_remove = ad_remove.slice(4) } else if (ad_remove.startsWith("js:")) { ad_remove = ad_remove.slice(3) } let m3u8_start = m3u8_text.slice(0, m3u8_text.indexOf("#EXTINF")).trim(); let m3u8_body = m3u8_text.slice(m3u8_text.indexOf("#EXTINF"), m3u8_text.indexOf("#EXT-X-ENDLIST")).trim(); let m3u8_end = m3u8_text.slice(m3u8_text.indexOf("#EXT-X-ENDLIST")).trim(); let murls = []; let m3_body_list = m3u8_body.split("\n"); let m3_len = m3_body_list.length; let i = 0; while (i < m3_len) { let mi = m3_body_list[i]; let mi_1 = m3_body_list[i + 1]; if (mi.startsWith("#EXTINF")) { murls.push([mi, mi_1].join("&")); i += 2 } else if (mi.startsWith("#EXT-X-DISCONTINUITY")) { let mi_2 = m3_body_list[i + 2]; murls.push([mi, mi_1, mi_2].join("&")); i += 3 } else { break } } let new_m3u8_body = []; for (let murl of murls) { if (ad_remove && new RegExp(ad_remove).test(murl)) { } else { let murl_list = murl.split("&"); if (!murl_list[murl_list.length - 1].startsWith("http") && m3u8_url.startsWith("http")) { murl_list[murl_list.length - 1] = urljoin(m3u8_url, murl_list[murl_list.length - 1]) } murl_list.forEach(it => { new_m3u8_body.push(it) }) } } new_m3u8_body = new_m3u8_body.join("\n").trim(); m3u8_text = [m3u8_start, new_m3u8_body, m3u8_end].join("\n").trim(); return m3u8_text } function fixAdM3u8Ai(m3u8_url) { let ts = (new Date).getTime(); function b(s1, s2) { let i = 0; while (i < s1.length) { if (s1[i] !== s2[i]) { break } i++ } return i } function reverseString(str) { return str.split("").reverse().join("") } let m3u8 = request(m3u8_url); m3u8 = m3u8.trim().split("\n").map(it => it.startsWith("#") ? it : urljoin(m3u8_url, it)).join("\n"); let last_url = m3u8.split("\n").slice(-1)[0]; if (last_url.includes(".m3u8") && last_url !== m3u8_url) { m3u8_url = last_url; m3u8 = request(m3u8_url) } let s = m3u8.trim().split("\n").filter(it => it.trim()).join("\n"); let ss = s.split("\n"); let firststr = ss.find(x => !x.startsWith("#")); let maxl = 0; let firststrlen = firststr.length; let ml = Math.round(ss.length / 2).toString().length; let laststr = ss.toReversed().find(x => { if (!x.startsWith("#")) { let k = b(reverseString(firststr), reverseString(x)); maxl = b(firststr, x); if (firststrlen - maxl <= ml + k) { return true } } return false }); log("最后一条切片:" + laststr); let ad_urls = []; for (let i = 0; i < ss.length; i++) { let s = ss[i]; if (!s.startsWith("#")) { if (b(firststr, s) < maxl) { ad_urls.push(s); ss.splice(i - 1, 2); i = i - 2 } else { ss[i] = urljoin(m3u8_url, s) } } else { ss[i] = s.replace(/URI=\"(.*)\"/, 'URI="' + urljoin(m3u8_url, "$1") + '"') } } log("处理的m3u8地址:" + m3u8_url); log("----广告地址----"); log(ad_urls); m3u8 = ss.join("\n"); log("处理耗时:" + ((new Date).getTime() - ts).toString()); return m3u8 } function forceOrder(lists, key, option) { let start = Math.floor(lists.length / 2); let end = Math.min(lists.length - 1, start + 1); if (start >= end) { return lists } let first = lists[start]; let second = lists[end]; if (key) { try { first = first[key]; second = second[key] } catch (e) { } } if (option && typeof option === "function") { try { first = option(first); second = option(second) } catch (e) { } } first += ""; second += ""; if (first.match(/(\d+)/) && second.match(/(\d+)/)) { let num1 = Number(first.match(/(\d+)/)[1]); let num2 = Number(second.match(/(\d+)/)[1]); if (num1 > num2) { lists.reverse() } } return lists } let VODS = []; let VOD = {}; let TABS = []; let LISTS = []; globalThis.encodeUrl = urlencode; globalThis.urlencode = urlencode; function urljoin(fromPath, nowPath) { fromPath = fromPath || ""; nowPath = nowPath || ""; return joinUrl(fromPath, nowPath) } var urljoin2 = urljoin; const defaultParser = { pdfh: pdfh, pdfa: pdfa, pd: pd }; function pdfh2(html, parse) { let html2 = html; try { if (typeof html !== "string") { html2 = html.rr(html.ele).toString() } } catch (e) { print("html对象转文本发生了错误:" + e.message) } let result = defaultParser.pdfh(html2, parse); let option = parse.includes("&&") ? parse.split("&&").slice(-1)[0] : parse.split(" ").slice(-1)[0]; if (/style/.test(option.toLowerCase()) && /url\(/.test(result)) { try { result = result.match(/url\((.*?)\)/)[1]; result = result.replace(/^['|"](.*)['|"]$/, "$1") } catch (e) { } } return result } function pdfa2(html, parse) { let html2 = html; try { if (typeof html !== "string") { html2 = html.rr(html.ele).toString() } } catch (e) { print("html对象转文本发生了错误:" + e.message) } return defaultParser.pdfa(html2, parse) } function pd2(html, parse, uri) { let ret = pdfh2(html, parse); if (typeof uri === "undefined" || !uri) { uri = "" } if (DOM_CHECK_ATTR.test(parse) && !SPECIAL_URL.test(ret)) { if (/http/.test(ret)) { ret = ret.slice(ret.indexOf("http")) } else { ret = urljoin(MY_URL, ret) } } return ret } const parseTags = { jsp: { pdfh: pdfh2, pdfa: pdfa2, pd: pd2 }, json: { pdfh(html, parse) { if (!parse || !parse.trim()) { return "" } if (typeof html === "string") { html = JSON.parse(html) } parse = parse.trim(); if (!parse.startsWith("$.")) { parse = "$." + parse } parse = parse.split("||"); for (let ps of parse) { let ret = cheerio.jp(ps, html); if (Array.isArray(ret)) { ret = ret[0] || "" } else { ret = ret || "" } if (ret && typeof ret !== "string") { ret = ret.toString() } if (ret) { return ret } } return "" }, pdfa(html, parse) { if (!parse || !parse.trim()) { return "" } if (typeof html === "string") { html = JSON.parse(html) } parse = parse.trim(); if (!parse.startsWith("$.")) { parse = "$." + parse } let ret = cheerio.jp(parse, html); if (Array.isArray(ret) && Array.isArray(ret[0]) && ret.length === 1) { return ret[0] || [] } return ret || [] }, pd(html, parse) { let ret = parseTags.json.pdfh(html, parse); if (ret) { return urljoin(MY_URL, ret) } return ret } }, jq: { pdfh(html, parse) { if (!html || !parse || !parse.trim()) { return "" } parse = parse.trim(); let result = defaultParser.pdfh(html, parse); return result }, pdfa(html, parse) { if (!html || !parse || !parse.trim()) { return [] } parse = parse.trim(); let result = defaultParser.pdfa(html, parse); print(`pdfa解析${parse}=>${result.length}`); return result }, pd(html, parse, base_url) { if (!html || !parse || !parse.trim()) { return "" } parse = parse.trim(); base_url = base_url || MY_URL; return defaultParser.pd(html, parse, base_url) } }, getParse(p0) { if (p0.startsWith("jsp:")) { return this.jsp } else if (p0.startsWith("json:")) { return this.json } else if (p0.startsWith("jq:")) { return this.jq } else { return this.jq } } }; const stringify = JSON.stringify; const jsp = parseTags.jsp; const jq = parseTags.jq; function readFile(filePath) { filePath = filePath || "./uri.min.js"; var fd = os.open(filePath); var buffer = new ArrayBuffer(1024); var len = os.read(fd, buffer, 0, 1024); console.log(len); let text = String.fromCharCode.apply(null, new Uint8Array(buffer)); console.log(text); return text } function dealJson(html) { try { html = html.trim(); if (!(html.startsWith("{") && html.endsWith("}") || html.startsWith("[") && html.endsWith("]"))) { html = "{" + html.match(/.*?\{(.*)\}/m)[1] + "}" } } catch (e) { } try { html = JSON.parse(html) } catch (e) { } return html } var OcrApi = { api: OCR_API, classification: function (img) { let code = ""; try { log("通过drpy_ocr验证码接口过验证..."); let html = request(OCR_API, { data: { img: img }, headers: { "User-Agent": PC_UA }, method: "POST" }, true); code = html || "" } catch (e) { log(`OCR识别验证码发生错误:${e.message}`) } return code } }; function verifyCode(url) { let cnt = 0; let host = getHome(url); let cookie = ""; while (cnt < OCR_RETRY) { try { let yzm_url = `${host}/index.php/verify/index.html`; console.log(`验证码链接:${yzm_url}`); let hhtml = request(yzm_url, { withHeaders: true, toBase64: true }, true); let json = JSON.parse(hhtml); if (!cookie) { let setCk = Object.keys(json).find(it => it.toLowerCase() === "set-cookie"); cookie = setCk ? json[setCk].split(";")[0] : "" } console.log("cookie:" + cookie); let img = json.body; let code = OcrApi.classification(img); console.log(`第${cnt + 1}次验证码识别结果:${code}`); let submit_url = `${host}/index.php/ajax/verify_check?type=search&verify=${code}`; console.log(submit_url); let html = request(submit_url, { headers: { Cookie: cookie, "User-Agent": MOBILE_UA }, method: "POST" }); html = JSON.parse(html); if (html.msg === "ok") { console.log(`第${cnt + 1}次验证码提交成功`); return cookie } else if (html.msg !== "ok" && cnt + 1 >= OCR_RETRY) { cookie = "" } } catch (e) { console.log(`第${cnt + 1}次验证码提交失败:${e.message}`); if (cnt + 1 >= OCR_RETRY) { cookie = "" } } cnt += 1 } return cookie } function setItem(k, v) { local.set(RKEY, k, v); console.log(`规则${RKEY}设置${k} => ${v}`) } function getItem(k, v) { return local.get(RKEY, k) || v } function clearItem(k) { local.delete(RKEY, k) } function getHome(url) { if (!url) { return "" } let tmp = url.split("//"); url = tmp[0] + "//" + tmp[1].split("/")[0]; try { url = decodeURIComponent(url) } catch (e) { } return url } function buildUrl(url, obj) { obj = obj || {}; if (url.indexOf("?") < 0) { url += "?" } let param_list = []; let keys = Object.keys(obj); keys.forEach(it => { param_list.push(it + "=" + obj[it]) }); let prs = param_list.join("&"); if (keys.length > 0 && !url.endsWith("?")) { url += "&" } url += prs; return url } function require(url) { eval(request(url)) } function request(url, obj, ocr_flag) { ocr_flag = ocr_flag || false; if (typeof obj === "undefined" || !obj || obj === {}) { if (!fetch_params || !fetch_params.headers) { let headers = { "User-Agent": MOBILE_UA }; if (rule.headers) { Object.assign(headers, rule.headers) } if (!fetch_params) { fetch_params = {} } fetch_params.headers = headers } if (!fetch_params.headers.Referer) { fetch_params.headers.Referer = getHome(url) } obj = fetch_params } else { let headers = obj.headers || {}; let keys = Object.keys(headers).map(it => it.toLowerCase()); if (!keys.includes("user-agent")) { headers["User-Agent"] = MOBILE_UA } if (!keys.includes("referer")) { headers["Referer"] = getHome(url) } obj.headers = headers } if (rule.encoding && rule.encoding !== "utf-8" && !ocr_flag) { if (!obj.headers.hasOwnProperty("Content-Type") && !obj.headers.hasOwnProperty("content-type")) { obj.headers["Content-Type"] = "text/html; charset=" + rule.encoding } } if (typeof obj.body != "undefined" && obj.body && typeof obj.body === "string") { if (!obj.headers.hasOwnProperty("Content-Type") && !obj.headers.hasOwnProperty("content-type")) { obj.headers["Content-Type"] = "application/x-www-form-urlencoded; charset=" + rule.encoding } } else if (typeof obj.body != "undefined" && obj.body && typeof obj.body === "object") { obj.data = obj.body; delete obj.body } if (!url) { return obj.withHeaders ? "{}" : "" } if (obj.toBase64) { obj.buffer = 2; delete obj.toBase64 } if (obj.redirect === false) { obj.redirect = 0 } console.log(JSON.stringify(obj.headers)); console.log("request:" + url + `|method:${obj.method || "GET"}|body:${obj.body || ""}`); let res = req(url, obj); let html = res.content || ""; if (obj.withHeaders) { let htmlWithHeaders = res.headers; htmlWithHeaders.body = html; return JSON.stringify(htmlWithHeaders) } else { return html } } function post(url, obj) { obj.method = "POST"; return request(url, obj) } fetch = request; print = function (data) { data = data || ""; if (typeof data == "object" && Object.keys(data).length > 0) { try { data = JSON.stringify(data); console.log(data) } catch (e) { console.log(typeof data + ":" + data.length); return } } else if (typeof data == "object" && Object.keys(data).length < 1) { console.log("null object") } else { console.log(data) } }; log = print; function checkHtml(html, url, obj) { if (/\?btwaf=/.test(html)) { let btwaf = html.match(/btwaf(.*?)"/)[1]; url = url.split("#")[0] + "?btwaf" + btwaf; print("宝塔验证访问链接:" + url); html = request(url, obj) } return html } function getCode(url, obj) { let html = request(url, obj); html = checkHtml(html, url, obj); return html } function getHtml(url) { let obj = {}; if (rule.headers) { obj.headers = rule.headers } let cookie = getItem(RULE_CK, ""); if (cookie) { if (obj.headers && !Object.keys(obj.headers).map(it => it.toLowerCase()).includes("cookie")) { log("历史无cookie,新增过验证后的cookie"); obj.headers["Cookie"] = cookie } else if (obj.headers && obj.headers.cookie && obj.headers.cookie !== cookie) { obj.headers["Cookie"] = cookie; log("历史有小写过期的cookie,更新过验证后的cookie") } else if (obj.headers && obj.headers.Cookie && obj.headers.Cookie !== cookie) { obj.headers["Cookie"] = cookie; log("历史有大写过期的cookie,更新过验证后的cookie") } else if (!obj.headers) { obj.headers = { Cookie: cookie }; log("历史无headers,更新过验证后的含cookie的headers") } } let html = getCode(url, obj); return html } function homeParse(homeObj) { fetch_params = JSON.parse(JSON.stringify(rule_fetch_params)); let classes = []; if (homeObj.class_name && homeObj.class_url) { let names = homeObj.class_name.split("&"); let urls = homeObj.class_url.split("&"); let cnt = Math.min(names.length, urls.length); for (let i = 0; i < cnt; i++) { classes.push({ type_id: urls[i], type_name: names[i] }) } } if (homeObj.class_parse) { if (homeObj.class_parse.startsWith("js:")) { var input = homeObj.MY_URL; try { eval(homeObj.class_parse.replace("js:", "")); if (Array.isArray(input)) { classes = input } } catch (e) { log("通过js动态获取分类发生了错误:" + e.message) } } else { let p = homeObj.class_parse.split(";"); let p0 = p[0]; let _ps = parseTags.getParse(p0); let is_json = p0.startsWith("json:"); _pdfa = _ps.pdfa; _pdfh = _ps.pdfh; _pd = _ps.pd; MY_URL = rule.url; if (is_json) { try { let cms_cate_url = homeObj.MY_URL.replace("ac=detail", "ac=list"); let html = getHtml(cms_cate_url); if (html) { if (cms_cate_url === homeObj.MY_URL) { homeHtmlCache = html } let list = _pdfa(html, p0.replace("json:", "")); if (list && list.length > 0) { classes = list } } } catch (e) { console.log(e.message) } } else if (p.length >= 3 && !is_json) { try { let html = getHtml(homeObj.MY_URL); if (html) { homeHtmlCache = html; let list = _pdfa(html, p0); if (list && list.length > 0) { list.forEach((it, idex) => { try { let name = _pdfh(it, p[1]); if (homeObj.cate_exclude && new RegExp(homeObj.cate_exclude).test(name)) { return } let url = _pd(it, p[2]); if (p.length > 3 && p[3]) { let exp = new RegExp(p[3]); url = url.match(exp)[1] } classes.push({ type_id: url.trim(), type_name: name.trim() }) } catch (e) { console.log(`分类列表定位第${idex}个元素正常报错:${e.message}`) } }) } } } catch (e) { console.log(e.message) } } } } classes = classes.filter(it => !homeObj.cate_exclude || !new RegExp(homeObj.cate_exclude).test(it.type_name)); let resp = { class: classes }; if (homeObj.filter) { resp.filters = homeObj.filter } console.log(JSON.stringify(resp)); return JSON.stringify(resp) } function getPP(p, pn, pp, ppn) { try { let ps = p[pn] === "*" && pp.length > ppn ? pp[ppn] : p[pn]; return ps } catch (e) { return "" } } function homeVodParse(homeVodObj) { fetch_params = JSON.parse(JSON.stringify(rule_fetch_params)); let d = []; MY_URL = homeVodObj.homeUrl; console.log(MY_URL); let t1 = (new Date).getTime(); let p = homeVodObj.推荐; print("p:" + p); if (p === "*" && rule.一级) { p = rule.一级; homeVodObj.double = false } if (!p || typeof p !== "string") { return "{}" } p = p.trim(); let pp = rule.一级.split(";"); if (p.startsWith("js:")) { const TYPE = "home"; var input = MY_URL; HOST = rule.host; eval(p.replace("js:", "")); d = VODS } else { p = p.split(";"); if (!homeVodObj.double && p.length < 5) { return "{}" } else if (homeVodObj.double && p.length < 6) { return "{}" } let p0 = getPP(p, 0, pp, 0); let _ps = parseTags.getParse(p0); _pdfa = _ps.pdfa; _pdfh = _ps.pdfh; _pd = _ps.pd; let is_json = p0.startsWith("json:"); p0 = p0.replace(/^(jsp:|json:|jq:)/, ""); let html = homeHtmlCache || getHtml(MY_URL); homeHtmlCache = undefined; if (is_json) { html = dealJson(html) } try { console.log("double:" + homeVodObj.double); if (homeVodObj.double) { let items = _pdfa(html, p0); let p1 = getPP(p, 1, pp, 0); let p2 = getPP(p, 2, pp, 1); let p3 = getPP(p, 3, pp, 2); let p4 = getPP(p, 4, pp, 3); let p5 = getPP(p, 5, pp, 4); let p6 = getPP(p, 6, pp, 5); for (let item of items) { let items2 = _pdfa(item, p1); for (let item2 of items2) { try { let title = _pdfh(item2, p2); let img = ""; try { img = _pd(item2, p3) } catch (e) { } let desc = ""; try { desc = _pdfh(item2, p4) } catch (e) { } let links = []; for (let _p5 of p5.split("+")) { let link = !homeVodObj.detailUrl ? _pd(item2, _p5, MY_URL) : _pdfh(item2, _p5); links.push(link) } let content; if (p.length > 6 && p[6]) { content = _pdfh(item2, p6) } else { content = "" } let vid = links.join("$"); if (rule.二级 === "*") { vid = vid + "@@" + title + "@@" + img } let vod = { vod_name: title, vod_pic: img, vod_remarks: desc, vod_content: content, vod_id: vid }; d.push(vod) } catch (e) { console.log("首页列表双层定位处理发生错误:" + e.message) } } } } else { let items = _pdfa(html, p0); let p1 = getPP(p, 1, pp, 1); let p2 = getPP(p, 2, pp, 2); let p3 = getPP(p, 3, pp, 3); let p4 = getPP(p, 4, pp, 4); let p5 = getPP(p, 5, pp, 5); for (let item of items) { try { let title = _pdfh(item, p1); let img = ""; try { img = _pd(item, p2, MY_URL) } catch (e) { } let desc = ""; try { desc = _pdfh(item, p3) } catch (e) { } let links = []; for (let _p5 of p4.split("+")) { let link = !homeVodObj.detailUrl ? _pd(item, _p5, MY_URL) : _pdfh(item, _p5); links.push(link) } let content; if (p.length > 5 && p[5]) { content = _pdfh(item, p5) } else { content = "" } let vid = links.join("$"); if (rule.二级 === "*") { vid = vid + "@@" + title + "@@" + img } let vod = { vod_name: title, vod_pic: img, vod_remarks: desc, vod_content: content, vod_id: vid }; d.push(vod) } catch (e) { console.log("首页列表单层定位处理发生错误:" + e.message) } } } } catch (e) { } } let t2 = (new Date).getTime(); console.log("加载首页推荐耗时:" + (t2 - t1) + "毫秒"); if (rule.图片替换 && rule.图片替换.includes("=>")) { let replace_from = rule.图片替换.split("=>")[0]; let replace_to = rule.图片替换.split("=>")[1]; d.forEach(it => { if (it.vod_pic && it.vod_pic.startsWith("http")) { it.vod_pic = it.vod_pic.replace(replace_from, replace_to) } }) } if (rule.图片来源) { d.forEach(it => { if (it.vod_pic && it.vod_pic.startsWith("http")) { it.vod_pic = it.vod_pic + rule.图片来源 } }) } if (d.length > 0) { print(d.slice(0, 2)) } return JSON.stringify({ list: d }) } function categoryParse(cateObj) { fetch_params = JSON.parse(JSON.stringify(rule_fetch_params)); let p = cateObj.一级; if (!p || typeof p !== "string") { return "{}" } let d = []; let url = cateObj.url.replaceAll("fyclass", cateObj.tid); if (cateObj.pg === 1 && url.includes("[") && url.includes("]")) { url = url.split("[")[1].split("]")[0] } else if (cateObj.pg > 1 && url.includes("[") && url.includes("]")) { url = url.split("[")[0] } if (rule.filter_url) { if (!/fyfilter/.test(url)) { if (!url.endsWith("&") && !rule.filter_url.startsWith("&")) { url += "&" } url += rule.filter_url } else { url = url.replace("fyfilter", rule.filter_url) } let fl = cateObj.filter ? cateObj.extend : {}; if (rule.filter_def && typeof rule.filter_def === "object") { try { if (Object.keys(rule.filter_def).length > 0 && rule.filter_def.hasOwnProperty(cateObj.tid)) { let self_fl_def = rule.filter_def[cateObj.tid]; if (self_fl_def && typeof self_fl_def === "object") { let fl_def = JSON.parse(JSON.stringify(self_fl_def)); fl = Object.assign(fl_def, fl) } } } catch (e) { print("合并不同分类对应的默认筛选出错:" + e.message) } } let new_url; new_url = cheerio.jinja2(url, { fl: fl }); url = new_url } if (/fypage/.test(url)) { if (url.includes("(") && url.includes(")")) { let url_rep = url.match(/.*?\((.*)\)/)[1]; let cnt_page = url_rep.replaceAll("fypage", cateObj.pg); let cnt_pg = eval(cnt_page); url = url.replaceAll(url_rep, cnt_pg).replaceAll("(", "").replaceAll(")", "") } else { url = url.replaceAll("fypage", cateObj.pg) } } MY_URL = url; console.log(MY_URL); p = p.trim(); const MY_CATE = cateObj.tid; if (p.startsWith("js:")) { var MY_FL = cateObj.extend; const TYPE = "cate"; var input = MY_URL; const MY_PAGE = cateObj.pg; var desc = ""; eval(p.trim().replace("js:", "")); d = VODS } else { p = p.split(";"); if (p.length < 5) { return "{}" } let _ps = parseTags.getParse(p[0]); _pdfa = _ps.pdfa; _pdfh = _ps.pdfh; _pd = _ps.pd; let is_json = p[0].startsWith("json:"); p[0] = p[0].replace(/^(jsp:|json:|jq:)/, ""); try { let html = getHtml(MY_URL); if (html) { if (is_json) { html = dealJson(html) } let list = _pdfa(html, p[0]); list.forEach(it => { let links = p[4].split("+").map(p4 => { return !rule.detailUrl ? _pd(it, p4, MY_URL) : _pdfh(it, p4) }); let link = links.join("$"); let vod_id = rule.detailUrl ? MY_CATE + "$" + link : link; let vod_name = _pdfh(it, p[1]).replace(/\n|\t/g, "").trim(); let vod_pic = _pd(it, p[2], MY_URL); if (rule.二级 === "*") { vod_id = vod_id + "@@" + vod_name + "@@" + vod_pic } d.push({ vod_id: vod_id, vod_name: vod_name, vod_pic: vod_pic, vod_remarks: _pdfh(it, p[3]).replace(/\n|\t/g, "").trim() }) }) } } catch (e) { console.log(e.message) } } if (rule.图片替换 && rule.图片替换.includes("=>")) { let replace_from = rule.图片替换.split("=>")[0]; let replace_to = rule.图片替换.split("=>")[1]; d.forEach(it => { if (it.vod_pic && it.vod_pic.startsWith("http")) { it.vod_pic = it.vod_pic.replace(replace_from, replace_to) } }) } if (rule.图片来源) { d.forEach(it => { if (it.vod_pic && it.vod_pic.startsWith("http")) { it.vod_pic = it.vod_pic + rule.图片来源 } }) } if (d.length > 0) { print(d.slice(0, 2)) } let pagecount = 0; if (rule.pagecount && typeof rule.pagecount === "object" && rule.pagecount.hasOwnProperty(MY_CATE)) { print(`MY_CATE:${MY_CATE},pagecount:${JSON.stringify(rule.pagecount)}`); pagecount = parseInt(rule.pagecount[MY_CATE]) } let nodata = { list: [{ vod_name: "无数据,防无限请求", vod_id: "no_data", vod_remarks: "不要点,会崩的", vod_pic: "https://ghproxy.net/https://raw.githubusercontent.com/hjdhnx/dr_py/main/404.jpg" }], total: 1, pagecount: 1, page: 1, limit: 1 }; let vod = d.length < 1 ? JSON.stringify(nodata) : JSON.stringify({ page: parseInt(cateObj.pg), pagecount: pagecount || 999, limit: 20, total: 999, list: d }); return vod } function searchParse(searchObj) { fetch_params = JSON.parse(JSON.stringify(rule_fetch_params)); let d = []; if (!searchObj.searchUrl) { return "{}" } let p = searchObj.搜索 === "*" && rule.一级 ? rule.一级 : searchObj.搜索; if (!p || typeof p !== "string") { return "{}" } p = p.trim(); let pp = rule.一级.split(";"); let url = searchObj.searchUrl.replaceAll("**", searchObj.wd); if (searchObj.pg === 1 && url.includes("[") && url.includes("]") && !url.includes("#")) { url = url.split("[")[1].split("]")[0] } else if (searchObj.pg > 1 && url.includes("[") && url.includes("]") && !url.includes("#")) { url = url.split("[")[0] } if (/fypage/.test(url)) { if (url.includes("(") && url.includes(")")) { let url_rep = url.match(/.*?\((.*)\)/)[1]; let cnt_page = url_rep.replaceAll("fypage", searchObj.pg); let cnt_pg = eval(cnt_page); url = url.replaceAll(url_rep, cnt_pg).replaceAll("(", "").replaceAll(")", "") } else { url = url.replaceAll("fypage", searchObj.pg) } } MY_URL = url; console.log(MY_URL); if (p.startsWith("js:")) { const TYPE = "search"; const MY_PAGE = searchObj.pg; const KEY = searchObj.wd; var input = MY_URL; var detailUrl = rule.detailUrl || ""; eval(p.trim().replace("js:", "")); d = VODS } else { p = p.split(";"); if (p.length < 5) { return "{}" } let p0 = getPP(p, 0, pp, 0); let _ps = parseTags.getParse(p0); _pdfa = _ps.pdfa; _pdfh = _ps.pdfh; _pd = _ps.pd; let is_json = p0.startsWith("json:"); p0 = p0.replace(/^(jsp:|json:|jq:)/, ""); try { let req_method = MY_URL.split(";").length > 1 ? MY_URL.split(";")[1].toLowerCase() : "get"; let html; if (req_method === "post") { let rurls = MY_URL.split(";")[0].split("#"); let rurl = rurls[0]; let params = rurls.length > 1 ? rurls[1] : ""; print(`post=》rurl:${rurl},params:${params}`); let _fetch_params = JSON.parse(JSON.stringify(rule_fetch_params)); let postData = { body: params }; Object.assign(_fetch_params, postData); html = post(rurl, _fetch_params) } else if (req_method === "postjson") { let rurls = MY_URL.split(";")[0].split("#"); let rurl = rurls[0]; let params = rurls.length > 1 ? rurls[1] : ""; print(`postjson-》rurl:${rurl},params:${params}`); try { params = JSON.parse(params) } catch (e) { params = "{}" } let _fetch_params = JSON.parse(JSON.stringify(rule_fetch_params)); let postData = { body: params }; Object.assign(_fetch_params, postData); html = post(rurl, _fetch_params) } else { html = getHtml(MY_URL) } if (html) { if (/系统安全验证|输入验证码/.test(html)) { let cookie = verifyCode(MY_URL); if (cookie) { console.log(`本次成功过验证,cookie:${cookie}`); setItem(RULE_CK, cookie) } else { console.log(`本次自动过搜索验证失败,cookie:${cookie}`) } html = getHtml(MY_URL) } if (!html.includes(searchObj.wd)) { console.log("搜索结果源码未包含关键字,疑似搜索失败,正为您打印结果源码"); console.log(html) } if (is_json) { html = dealJson(html) } let list = _pdfa(html, p0); let p1 = getPP(p, 1, pp, 1); let p2 = getPP(p, 2, pp, 2); let p3 = getPP(p, 3, pp, 3); let p4 = getPP(p, 4, pp, 4); let p5 = getPP(p, 5, pp, 5); list.forEach(it => { let links = p4.split("+").map(_p4 => { return !rule.detailUrl ? _pd(it, _p4, MY_URL) : _pdfh(it, _p4) }); let link = links.join("$"); let content; if (p.length > 5 && p[5]) { content = _pdfh(it, p5) } else { content = "" } let vod_id = link; let vod_name = _pdfh(it, p1).replace(/\n|\t/g, "").trim(); let vod_pic = _pd(it, p2, MY_URL); if (rule.二级 === "*") { vod_id = vod_id + "@@" + vod_name + "@@" + vod_pic } let ob = { vod_id: vod_id, vod_name: vod_name, vod_pic: vod_pic, vod_remarks: _pdfh(it, p3).replace(/\n|\t/g, "").trim(), vod_content: content.replace(/\n|\t/g, "").trim() }; d.push(ob) }) } } catch (e) { print("搜索发生错误:" + e.message); return "{}" } } if (rule.图片替换 && rule.图片替换.includes("=>")) { let replace_from = rule.图片替换.split("=>")[0]; let replace_to = rule.图片替换.split("=>")[1]; d.forEach(it => { if (it.vod_pic && it.vod_pic.startsWith("http")) { it.vod_pic = it.vod_pic.replace(replace_from, replace_to) } }) } if (rule.图片来源) { d.forEach(it => { if (it.vod_pic && it.vod_pic.startsWith("http")) { it.vod_pic = it.vod_pic + rule.图片来源 } }) } return JSON.stringify({ page: parseInt(searchObj.pg), pagecount: 10, limit: 20, total: 100, list: d }) } function detailParse(detailObj) { let t1 = (new Date).getTime(); fetch_params = JSON.parse(JSON.stringify(rule_fetch_params)); let orId = detailObj.orId; let vod_name = "片名"; let vod_pic = ""; let vod_id = orId; if (rule.二级 === "*") { let extra = orId.split("@@"); vod_name = extra.length > 1 ? extra[1] : vod_name; vod_pic = extra.length > 2 ? extra[2] : vod_pic } let vod = { vod_id: vod_id, vod_name: vod_name, vod_pic: vod_pic, type_name: "类型", vod_year: "年份", vod_area: "地区", vod_remarks: "更新信息", vod_actor: "主演", vod_director: "导演", vod_content: "简介" }; let p = detailObj.二级; let url = detailObj.url; let detailUrl = detailObj.detailUrl; let fyclass = detailObj.fyclass; let tab_exclude = detailObj.tab_exclude; let html = detailObj.html || ""; MY_URL = url; if (detailObj.二级访问前) { try { print(`尝试在二级访问前执行代码:${detailObj.二级访问前}`); eval(detailObj.二级访问前.trim().replace("js:", "")) } catch (e) { print(`二级访问前执行代码出现错误:${e.message}`) } } if (p === "*") { vod.vod_play_from = "道长在线"; vod.vod_remarks = detailUrl; vod.vod_actor = "没有二级,只有一级链接直接嗅探播放"; vod.vod_content = MY_URL; vod.vod_play_url = "嗅探播放$" + MY_URL.split("@@")[0] } else if (typeof p === "string" && p.trim().startsWith("js:")) { const TYPE = "detail"; var input = MY_URL; var play_url = ""; eval(p.trim().replace("js:", "")); vod = VOD; console.log(JSON.stringify(vod)) } else if (p && typeof p === "object") { let tt1 = (new Date).getTime(); if (!html) { html = getHtml(MY_URL) } print(`二级${MY_URL}仅获取源码耗时:${(new Date).getTime() - tt1}毫秒`); let _ps; if (p.is_json) { print("二级是json"); _ps = parseTags.json; html = dealJson(html) } else if (p.is_jsp) { print("二级是jsp"); _ps = parseTags.jsp } else if (p.is_jq) { print("二级是jq"); _ps = parseTags.jq } else { print("二级默认jq"); _ps = parseTags.jq } let tt2 = (new Date).getTime(); print(`二级${MY_URL}获取并装载源码耗时:${tt2 - tt1}毫秒`); _pdfa = _ps.pdfa; _pdfh = _ps.pdfh; _pd = _ps.pd; if (p.title) { let p1 = p.title.split(";"); vod.vod_name = _pdfh(html, p1[0]).replace(/\n|\t/g, "").trim(); let type_name = p1.length > 1 ? _pdfh(html, p1[1]).replace(/\n|\t/g, "").replace(/ /g, "").trim() : ""; vod.type_name = type_name || vod.type_name } if (p.desc) { try { let p1 = p.desc.split(";"); vod.vod_remarks = _pdfh(html, p1[0]).replace(/\n|\t/g, "").trim(); vod.vod_year = p1.length > 1 ? _pdfh(html, p1[1]).replace(/\n|\t/g, "").trim() : ""; vod.vod_area = p1.length > 2 ? _pdfh(html, p1[2]).replace(/\n|\t/g, "").trim() : ""; vod.vod_actor = p1.length > 3 ? _pdfh(html, p1[3]).replace(/\n|\t/g, "").trim() : ""; vod.vod_director = p1.length > 4 ? _pdfh(html, p1[4]).replace(/\n|\t/g, "").trim() : "" } catch (e) { } } if (p.content) { try { let p1 = p.content.split(";"); vod.vod_content = _pdfh(html, p1[0]).replace(/\n|\t/g, "").trim() } catch (e) { } } if (p.img) { try { let p1 = p.img.split(";"); vod.vod_pic = _pd(html, p1[0], MY_URL) } catch (e) { } } let vod_play_from = "$$$"; let playFrom = []; if (p.重定向 && p.重定向.startsWith("js:")) { print("开始执行重定向代码:" + p.重定向); html = eval(p.重定向.replace("js:", "")) } if (p.tabs) { if (p.tabs.startsWith("js:")) { print("开始执行tabs代码:" + p.tabs); var input = MY_URL; eval(p.tabs.replace("js:", "")); playFrom = TABS } else { let p_tab = p.tabs.split(";")[0]; let vHeader = _pdfa(html, p_tab); console.log(vHeader.length); let tab_text = p.tab_text || "body&&Text"; let new_map = {}; for (let v of vHeader) { let v_title = _pdfh(v, tab_text).trim(); if (!v_title) { v_title = "线路空" } console.log(v_title); if (tab_exclude && new RegExp(tab_exclude).test(v_title)) { continue } if (!new_map.hasOwnProperty(v_title)) { new_map[v_title] = 1 } else { new_map[v_title] += 1 } if (new_map[v_title] > 1) { v_title += Number(new_map[v_title] - 1) } playFrom.push(v_title) } } console.log(JSON.stringify(playFrom)) } else { playFrom = ["道长在线"] } vod.vod_play_from = playFrom.join(vod_play_from); let vod_play_url = "$$$"; let vod_tab_list = []; if (p.lists) { if (p.lists.startsWith("js:")) { print("开始执行lists代码:" + p.lists); try { var input = MY_URL; var play_url = ""; eval(p.lists.replace("js:", "")); for (let i in LISTS) { if (LISTS.hasOwnProperty(i)) { try { LISTS[i] = LISTS[i].map(it => it.split("$").slice(0, 2).join("$")) } catch (e) { print("格式化LISTS发生错误:" + e.message) } } } vod_play_url = LISTS.map(it => it.join("#")).join(vod_play_url) } catch (e) { print("js执行lists: 发生错误:" + e.message) } } else { let list_text = p.list_text || "body&&Text"; let list_url = p.list_url || "a&&href"; let is_tab_js = p.tabs.trim().startsWith("js:"); for (let i = 0; i < playFrom.length; i++) { let tab_name = playFrom[i]; let tab_ext = p.tabs.split(";").length > 1 && !is_tab_js ? p.tabs.split(";")[1] : ""; let p1 = p.lists.replaceAll("#idv", tab_name).replaceAll("#id", i); tab_ext = tab_ext.replaceAll("#idv", tab_name).replaceAll("#id", i); let tabName = tab_ext ? _pdfh(html, tab_ext) : tab_name; console.log(tabName); let new_vod_list = []; let tt1 = (new Date).getTime(); if (typeof pdfl === "function") { new_vod_list = pdfl(html, p1, list_text, list_url, MY_URL) } else { let vodList = []; try { vodList = _pdfa(html, p1); console.log("len(vodList):" + vodList.length) } catch (e) { } for (let i = 0; i < vodList.length; i++) { let it = vodList[i]; new_vod_list.push(_pdfh(it, list_text).trim() + "$" + _pd(it, list_url, MY_URL)) } } if (new_vod_list.length > 0) { new_vod_list = forceOrder(new_vod_list, "", x => x.split("$")[0]); console.log(`drpy影响性能代码共计列表数循环次数:${new_vod_list.length},耗时:${(new Date).getTime() - tt1}毫秒`) } let vlist = new_vod_list.join("#"); vod_tab_list.push(vlist) } vod_play_url = vod_tab_list.join(vod_play_url) } } vod.vod_play_url = vod_play_url } if (rule.图片替换 && rule.图片替换.includes("=>")) { let replace_from = rule.图片替换.split("=>")[0]; let replace_to = rule.图片替换.split("=>")[1]; vod.vod_pic = vod.vod_pic.replace(replace_from, replace_to) } if (rule.图片来源 && vod.vod_pic && vod.vod_pic.startsWith("http")) { vod.vod_pic = vod.vod_pic + rule.图片来源 } if (!vod.vod_id || vod_id.includes("$") && vod.vod_id !== vod_id) { vod.vod_id = vod_id } let t2 = (new Date).getTime(); console.log(`加载二级界面${MY_URL}耗时:${t2 - t1}毫秒`); vod = vodDeal(vod); return JSON.stringify({ list: [vod] }) } function get_tab_index(vod) { let obj = {}; vod.vod_play_from.split("$$$").forEach((it, index) => { obj[it] = index }); return obj } function vodDeal(vod) { let vod_play_from = vod.vod_play_from.split("$$$"); let vod_play_url = vod.vod_play_url.split("$$$"); let tab_removed_list = vod_play_from; let tab_ordered_list = vod_play_from; let tab_renamed_list = vod_play_from; let tab_list = vod_play_from; let play_ordered_list = vod_play_url; if (rule.tab_remove && rule.tab_remove.length > 0 || rule.tab_order && rule.tab_order.length > 0) { let tab_index_dict = get_tab_index(vod); if (rule.tab_remove && rule.tab_remove.length > 0) { tab_removed_list = vod_play_from.filter(it => !rule.tab_remove.includes(it)); tab_list = tab_removed_list } if (rule.tab_order && rule.tab_order.length > 0) { let tab_order = rule.tab_order; tab_ordered_list = tab_removed_list.sort((a, b) => { return (tab_order.indexOf(a) === -1 ? 9999 : tab_order.indexOf(a)) - (tab_order.indexOf(b) === -1 ? 9999 : tab_order.indexOf(b)) }); tab_list = tab_ordered_list } play_ordered_list = tab_list.map(it => vod_play_url[tab_index_dict[it]]) } if (rule.tab_rename && typeof rule.tab_rename === "object" & Object.keys(rule.tab_rename).length > 0) { tab_renamed_list = tab_list.map(it => rule.tab_rename[it] || it); tab_list = tab_renamed_list } vod.vod_play_from = tab_list.join("$$$"); vod.vod_play_url = play_ordered_list.join("$$$"); return vod } function tellIsJx(url) { try { let is_vip = !/\.(m3u8|mp4|m4a)$/.test(url.split("?")[0]) && 是否正版(url); return is_vip ? 1 : 0 } catch (e) { return 1 } } function playParse(playObj) { fetch_params = JSON.parse(JSON.stringify(rule_fetch_params)); MY_URL = playObj.url; var MY_FLAG = playObj.flag; if (!/http/.test(MY_URL)) { try { MY_URL = base64Decode(MY_URL) } catch (e) { } } MY_URL = decodeURIComponent(MY_URL); var input = MY_URL; var flag = MY_FLAG; let common_play = { parse: 1, url: input, flag: flag, jx: tellIsJx(input) }; let lazy_play; if (!rule.play_parse || !rule.lazy) { lazy_play = common_play } else if (rule.play_parse && rule.lazy && typeof rule.lazy === "string") { try { let lazy_code = rule.lazy.replace("js:", "").trim(); print("开始执行js免嗅=>" + lazy_code); eval(lazy_code); lazy_play = typeof input === "object" ? input : { parse: 1, jx: tellIsJx(input), url: input } } catch (e) { print("js免嗅错误:" + e.message); lazy_play = common_play } } else { lazy_play = common_play } if (Array.isArray(rule.play_json) && rule.play_json.length > 0) { let web_url = lazy_play.url; for (let pjson of rule.play_json) { if (pjson.re && (pjson.re === "*" || web_url.match(new RegExp(pjson.re)))) { if (pjson.json && typeof pjson.json === "object") { let base_json = pjson.json; lazy_play = Object.assign(lazy_play, base_json); break } } } } else if (rule.play_json && !Array.isArray(rule.play_json)) { let base_json = { jx: 1, parse: 1 }; lazy_play = Object.assign(lazy_play, base_json) } else if (!rule.play_json) { let base_json = { jx: 0, parse: 1 }; lazy_play = Object.assign(lazy_play, base_json) } console.log(JSON.stringify(lazy_play)); return JSON.stringify(lazy_play) } function proxyParse(proxyObj) { var input = proxyObj.params; if (proxyObj.proxy_rule) { log("准备执行本地代理规则:\n" + proxyObj.proxy_rule); try { eval(proxyObj.proxy_rule); if (input && input !== proxyObj.params && Array.isArray(input) && input.length === 3) { return input } else { return [404, "text/plain", "Not Found"] } } catch (e) { return [500, "text/plain", "代理规则错误:" + e.message] } } else { return [404, "text/plain", "Not Found"] } } function isVideoParse(isVideoObj) { var input = isVideoObj.url; if (!isVideoObj.t) { let re_matcher = new RegExp(isVideoObj.isVideo, "i"); return re_matcher.test(input) } else { try { eval(isVideoObj.isVideo); if (typeof input === "boolean") { return input } else { return false } } catch (e) { log("执行嗅探规则发生错误:" + e.message); return false } } } function init(ext) { console.log("init"); try { let muban = 模板.getMubans(); if (typeof ext == "object") { rule = ext } else if (typeof ext == "string") { if (ext.startsWith("http")) { let js = request(ext, { method: "GET" }); if (js) { eval(js.replace("var rule", "rule")) } } else { eval(ext.replace("var rule", "rule")) } } if (rule.模板 && muban.hasOwnProperty(rule.模板)) { print("继承模板:" + rule.模板); rule = Object.assign(muban[rule.模板], rule) } let rule_cate_excludes = (rule.cate_exclude || "").split("|").filter(it => it.trim()); let rule_tab_excludes = (rule.tab_exclude || "").split("|").filter(it => it.trim()); rule_cate_excludes = rule_cate_excludes.concat(CATE_EXCLUDE.split("|").filter(it => it.trim())); rule_tab_excludes = rule_tab_excludes.concat(TAB_EXCLUDE.split("|").filter(it => it.trim())); rule.cate_exclude = rule_cate_excludes.join("|"); rule.tab_exclude = rule_tab_excludes.join("|"); rule.host = (rule.host || "").rstrip("/"); HOST = rule.host; if (rule.hostJs) { console.log(`检测到hostJs,准备执行...`); try { eval(rule.hostJs); rule.host = HOST.rstrip("/") } catch (e) { console.log(`执行${rule.hostJs}获取host发生错误:` + e.message) } } rule.url = rule.url || ""; rule.double = rule.double || false; rule.homeUrl = rule.homeUrl || ""; rule.detailUrl = rule.detailUrl || ""; rule.searchUrl = rule.searchUrl || ""; rule.homeUrl = rule.host && rule.homeUrl ? urljoin(rule.host, rule.homeUrl) : rule.homeUrl || rule.host; rule.homeUrl = cheerio.jinja2(rule.homeUrl, { rule: rule }); rule.detailUrl = rule.host && rule.detailUrl ? urljoin(rule.host, rule.detailUrl) : rule.detailUrl; rule.二级访问前 = rule.二级访问前 || ""; if (rule.url.includes("[") && rule.url.includes("]")) { let u1 = rule.url.split("[")[0]; let u2 = rule.url.split("[")[1].split("]")[0]; rule.url = rule.host && rule.url ? urljoin(rule.host, u1) + "[" + urljoin(rule.host, u2) + "]" : rule.url } else { rule.url = rule.host && rule.url ? urljoin(rule.host, rule.url) : rule.url } if (rule.searchUrl.includes("[") && rule.searchUrl.includes("]") && !rule.searchUrl.includes("#")) { let u1 = rule.searchUrl.split("[")[0]; let u2 = rule.searchUrl.split("[")[1].split("]")[0]; rule.searchUrl = rule.host && rule.searchUrl ? urljoin(rule.host, u1) + "[" + urljoin(rule.host, u2) + "]" : rule.searchUrl } else { rule.searchUrl = rule.host && rule.searchUrl ? urljoin(rule.host, rule.searchUrl) : rule.searchUrl } rule.timeout = rule.timeout || 5e3; rule.encoding = rule.编码 || rule.encoding || "utf-8"; rule.search_encoding = rule.搜索编码 || rule.search_encoding || ""; rule.图片来源 = rule.图片来源 || ""; rule.图片替换 = rule.图片替换 || ""; rule.play_json = rule.hasOwnProperty("play_json") ? rule.play_json : []; rule.pagecount = rule.hasOwnProperty("pagecount") ? rule.pagecount : {}; rule.proxy_rule = rule.hasOwnProperty("proxy_rule") ? rule.proxy_rule : ""; rule.sniffer = rule.hasOwnProperty("sniffer") ? rule.sniffer : ""; rule.sniffer = !!(rule.sniffer && rule.sniffer !== "0" && rule.sniffer !== "false"); rule.isVideo = rule.hasOwnProperty("isVideo") ? rule.isVideo : ""; rule.tab_remove = rule.hasOwnProperty("tab_remove") ? rule.tab_remove : []; rule.tab_order = rule.hasOwnProperty("tab_order") ? rule.tab_order : []; rule.tab_rename = rule.hasOwnProperty("tab_rename") ? rule.tab_rename : {}; if (rule.headers && typeof rule.headers === "object") { try { let header_keys = Object.keys(rule.headers); for (let k of header_keys) { if (k.toLowerCase() === "user-agent") { let v = rule.headers[k]; console.log(v); if (["MOBILE_UA", "PC_UA", "UC_UA", "IOS_UA", "UA"].includes(v)) { rule.headers[k] = eval(v) } } else if (k.toLowerCase() === "cookie") { let v = rule.headers[k]; if (v && v.startsWith("http")) { console.log(v); try { v = fetch(v); console.log(v); rule.headers[k] = v } catch (e) { console.log(`从${v}获取cookie发生错误:` + e.message) } } } } } catch (e) { console.log("处理headers发生错误:" + e.message) } } rule_fetch_params = { headers: rule.headers || false, timeout: rule.timeout, encoding: rule.encoding }; oheaders = rule.headers || {}; RKEY = typeof key !== "undefined" && key ? key : "drpy_" + (rule.title || rule.host); pre(); init_test() } catch (e) { console.log("init_test发生错误:" + e.message) } } let homeHtmlCache = undefined; function home(filter) { console.log("home"); let homeObj = { filter: rule.filter || false, MY_URL: rule.homeUrl, class_name: rule.class_name || "", class_url: rule.class_url || "", class_parse: rule.class_parse || "", cate_exclude: rule.cate_exclude }; return homeParse(homeObj) } function homeVod(params) { console.log("homeVod"); let homeVodObj = { "推荐": rule.推荐, double: rule.double, homeUrl: rule.homeUrl, detailUrl: rule.detailUrl }; return homeVodParse(homeVodObj) } function category(tid, pg, filter, extend) { let cateObj = { url: rule.url, "一级": rule.一级, tid: tid, pg: parseInt(pg), filter: filter, extend: extend }; return categoryParse(cateObj) } function detail(vod_url) { let orId = vod_url; let fyclass = ""; log("orId:" + orId); if (vod_url.indexOf("$") > -1) { let tmp = vod_url.split("$"); fyclass = tmp[0]; vod_url = tmp[1] } let detailUrl = vod_url.split("@@")[0]; let url; if (!detailUrl.startsWith("http") && !detailUrl.includes("/")) { url = rule.detailUrl.replaceAll("fyid", detailUrl).replaceAll("fyclass", fyclass) } else if (detailUrl.includes("/")) { url = urljoin(rule.homeUrl, detailUrl) } else { url = detailUrl } let detailObj = { orId: orId, url: url, "二级": rule.二级, "二级访问前": rule.二级访问前, detailUrl: detailUrl, fyclass: fyclass, tab_exclude: rule.tab_exclude }; return detailParse(detailObj) } function play(flag, id, flags) { let playObj = { url: id, flag: flag, flags: flags }; return playParse(playObj) } function search(wd, quick, pg) { if (rule.search_encoding) { if (rule.search_encoding.toLowerCase() !== "utf-8") { wd = encodeStr(wd, rule.search_encoding) } } else if (rule.encoding && rule.encoding.toLowerCase() !== "utf-8") { wd = encodeStr(wd, rule.encoding) } let searchObj = { searchUrl: rule.searchUrl, "搜索": rule.搜索, wd: wd, pg: pg || 1, quick: quick }; return searchParse(searchObj) } function proxy(params) { if (rule.proxy_rule && rule.proxy_rule.trim()) { rule.proxy_rule = rule.proxy_rule.trim() } if (rule.proxy_rule.startsWith("js:")) { rule.proxy_rule = rule.proxy_rule.replace("js:", "") } let proxyObj = { params: params, proxy_rule: rule.proxy_rule }; return proxyParse(proxyObj) } function sniffer() { let enable_sniffer = rule.sniffer || false; if (enable_sniffer) { log("开始执行辅助嗅探代理规则...") } return enable_sniffer } function isVideo(url) { let t = 0; let is_video; if (rule.isVideo && rule.isVideo.trim()) { is_video = rule.isVideo.trim() } if (is_video.startsWith("js:")) { is_video = is_video.replace("js:", ""); t = 1 } let isVideoObj = { url: url, isVideo: is_video, t: t }; let result = isVideoParse(isVideoObj); if (result) { log("成功执行辅助嗅探规则并检测到视频地址:\n" + rule.isVideo) } return result } function DRPY() { return { init: init, home: home, homeVod: homeVod, category: category, detail: detail, play: play, search: search, proxy: proxy, sniffer: sniffer, isVideo: isVideo } } export default { init: init, home: home, homeVod: homeVod, category: category, detail: detail, play: play, search: search, proxy: proxy, sniffer: sniffer, isVideo: isVideo, DRPY: DRPY };
--------------------------------------------------------------------------------
/lib/nmys.json:
--------------------------------------------------------------------------------
1 | {
2 | "规则名": "农民影视",
3 | "规则作者": "香雅情",
4 | "请求头参数": "User-Agent$手机#Referer$https://www.wwgz.cn",
5 | "网页编码格式": "UTF-8",
6 | "图片是否需要代理": "0",
7 | "是否开启获取首页数据": "1",
8 | "首页推荐链接": "https://www.wwgz.cn",
9 | "首页列表数组规则": "body&&.globalPicList",
10 | "首页片单列表数组规则": "li:has(img)",
11 | "首页片单是否Jsoup写法": "1",
12 | "首页片单标题": ".sTit&&Text",
13 | "首页片单链接": "a&&href",
14 | "首页片单图片": "img&&data-echo||data-src||src",
15 | "首页片单副标题": ".sBottom&&Text",
16 | "首页片单链接加前缀": "https://www.wwgz.cn",
17 | "首页片单链接加后缀": "",
18 | "分类起始页码": "1",
19 | "分类链接": "https://www.wwgz.cn/vod-list-id-{cateId}-pg-{catePg}-order--by-{by}-class--year-{year}-letter--area-{area}-lang-.html",
20 | "分类名称": "电影&电视剧&综艺&动漫&短剧",
21 | "分类名称替换词": "1&2&3&4&26",
22 | "筛选数据": "ext",
23 | "筛选子分类名称": "动作片&喜剧片&爱情片&科幻片&恐怖片&剧情片&战争片&惊悚片&奇幻片||国产剧&港台泰&日韩剧&欧美剧||空||动漫剧&动漫片",
24 | "筛选子分类替换词": "5&6&7&8&9&10&11&16&17||12&13&14&15||空||18&19",
25 | "筛选地区名称": "大陆&香港&台湾&美国&韩国&日本&泰国&新加坡&马来西亚&印度&英国&法国&加拿大&西班牙&俄罗斯&其它",
26 | "筛选地区替换词": "*",
27 | "分类截取模式": "1",
28 | "分类列表数组规则": ".globalPicList&&li",
29 | "分类片单是否Jsoup写法": "1",
30 | "分类片单标题": ".sTit&&Text",
31 | "分类片单链接": "a&&href",
32 | "分类片单图片": "img&&data-echo||data-src||src",
33 | "分类片单副标题": ".sBottom&&Text",
34 | "分类片单链接加前缀": "https://www.wwgz.cn",
35 | "分类片单链接加后缀": "",
36 | "搜索请求头参数": "User-Agent$手机#Referer$https://www.wwgz.cn",
37 | "search_url": "https://v.nmvod.cn/index.php?m=vod-search;post",
38 | "sea_PtBody": "wd={wd}",
39 | "search_mode": "1",
40 | "sea_arr_rule": "#data_list&&li",
41 | "sea_is_jsoup": "1",
42 | "sea_pic": ".lazyload&&data-src",
43 | "sea_title": ".sTit&&Text",
44 | "sea_url": "a&&href",
45 | "搜索片单副标题": ".sDes,-1&&Text",
46 | "搜索片单链接加前缀": "https://www.wwgz.cn",
47 | "搜索片单链接加后缀": "",
48 | "链接是否直接播放": "0",
49 | "直接播放链接加前缀": "https://live.52sf.ga/huya/",
50 | "直接播放链接加后缀": "#isVideo=true#",
51 | "直接播放直链视频请求头": "authority$ku.peizq.online#Referer$https://play.peizq.online",
52 | "详情是否Jsoup写法": "1",
53 | "类型详情": ".type-title&&Text",
54 | "年代详情": "body&&span:contains(年代:)&&Text!年代:",
55 | "地区详情": "",
56 | "演员详情": "body&&.sDes:contains(主演:)&&Text!主演:",
57 | "简介详情": ".detail-con&&p&&Text!简介:",
58 | "线路列表数组规则": "#leftTabBox&&ul&&li",
59 | "线路标题": "Text[替换:默认=>农民专线]",
60 | "播放列表数组规则": "#leftTabBox&&.numList",
61 | "选集列表数组规则": "li",
62 | "选集标题链接是否Jsoup写法": "1",
63 | "选集标题": "a&&Text",
64 | "选集链接": "a&&href",
65 | "是否反转选集序列": "1",
66 | "选集链接加前缀": "https://www.wwgz.cn",
67 | "选集链接加后缀": "",
68 | "分析MacPlayer": "0",
69 | "是否开启手动嗅探": "1",
70 | "手动嗅探视频链接关键词": ".mp4#.m3u8#item/video#video_mp4#video/tos",
71 | "手动嗅探视频链接过滤词": ".html#=http"
72 | }
--------------------------------------------------------------------------------
/lib/spider.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hanhan8127/TVBox/e3e2d3df1d42c6aacbafc4d033fde1eeaa0ce341/lib/spider.jar
--------------------------------------------------------------------------------
/lib/svip.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hanhan8127/TVBox/e3e2d3df1d42c6aacbafc4d033fde1eeaa0ce341/lib/svip.jar
--------------------------------------------------------------------------------
/lib/可可影视.json:
--------------------------------------------------------------------------------
1 | {
2 | "站名": "可可影视",
3 | "请求头": "User-Agent$MOBILE_UA",
4 | "编码": "UTF-8",
5 | "图片代理": "0",
6 | "主页url": "https://www.kkys04.com/",
7 | //https://www.kkys02.com/ https://www.kkys03.com/ https://www.kkys01.com/
8 | "首页": "120",
9 | "起始页": "1",
10 | "分类url": "/show/{cateId}-{class}-{area}-{lang}-{year}-{by}-{catePg}.html;;mrcd0",
11 | "分类": "电影&剧集&综艺&动漫&短剧",
12 | "分类值": "1&2&4&3&6",
13 | "数组": "默认--||搜索--/detail&&",
14 | "标题": "title\">&&
&&&&&&&&&&&&&&&&&&&&[不包含:4K(高峰不卡)]",
26 | "线路标题": "label\">&&<",
27 | "播放数组": "episode-list&&",
29 | "播放标题": ">&&<",
30 | "播放链接": "href=\"&&\"",
31 | "嗅探词": ".mp4#.m3u8",
32 | "搜索请求头": "User-Agent$MOBILE_UA",
33 | "搜索url": "/search?k={wd}&page={pg}",
34 | "搜索模式": "1",
35 | "筛选": "1",
36 | "剧情": "Netflix&剧情&喜剧&动作&爱情&恐怖&惊悚&犯罪&科幻&悬疑&奇幻&冒险&战争&历史&古装&家庭&传记&武侠&歌舞&短片&动画&儿童&职场||Netflix&剧情&爱情&喜剧&犯罪&悬疑&古装&动作&家庭&惊悚&奇幻&美剧&科幻&历史&战争&韩剧&武侠&言情&恐怖&冒险&都市&职场||纪录&真人秀&记录&脱口秀&剧情&历史&喜剧&传记&相声&节目&歌舞&冒险&运动&Season&犯罪&短片&搞笑&晚会||Netflix&动态漫画&剧情&动画&喜剧&冒险&动作&奇幻&科幻&儿童&搞笑&爱情&家庭&短片&热血&益智&悬疑&经典&校园&Anime&运动&亲子&青春&恋爱&武侠&惊悚||逆袭&甜宠&虐恋&穿越&重生&剧情&科幻&武侠&爱情&动作&战争&冒险&其它",
37 | "剧情值": "*",
38 | "地区": "中国大陆&中国香港&中国台湾&美国&日本&韩国&英国&法国&德国&印度&泰国&丹麦&瑞典&巴西&加拿大&俄罗斯&意大利&比利时&爱尔兰&西班牙&澳大利亚&其他||中国大陆&中国香港&韩国&美国&日本&法国&英国&德国&中国台湾&泰国&印度&其他||中国大陆&中国香港&中国台湾&美国&日本&韩国&其他||日本&中国大陆&中国台湾&美国&中国香港&韩国&英国&法国&德国&印度&泰国&丹麦&瑞典&巴西&加拿大&俄罗斯&意大利&比利时&爱尔兰&西班牙&澳大利亚&其他||空",
39 | "地区值": "*",
40 | "语言": "国语&粤语&英语&日语&韩语&法语||国语&粤语&英语&日语&韩语&法语||国语&粤语&英语&日语&韩语&法语||国语&粤语&英语&日语&韩语&法语||空",
41 | "语言值": "*",
42 | "排序": "综合&最新&最热&评分",
43 | "排序值": "1&2&3&4"
44 | }
45 |
--------------------------------------------------------------------------------
/lib/河马短剧.json:
--------------------------------------------------------------------------------
1 | {
2 | "规则名": "河马短剧",
3 | "规则作者": "香雅情",
4 | "请求头参数": "MOBILE_UA",
5 | "网页编码格式": "UTF-8",
6 | "图片是否需要代理": "否",
7 | "是否开启获取首页数据": "否",
8 | "首页推荐链接": "https://www.kuaikaw.cn",
9 | "首页列表数组规则": "body&&.module-items",
10 | "首页片单列表数组规则": ".module-item:lt(12)",
11 | "首页片单是否Jsoup写法": "1",
12 | "分类起始页码": "1",
13 | "分类链接": "https://www.kuaikaw.cn/browse/{cateId}/{catePg}[firstPage=https://www.kuaikaw.cn/browse/{cateId}]",
14 | "分类名称": "短剧全部",
15 | "分类名称替换词": "0",
16 | //"筛选数据": {},
17 | "筛选数据": "ext",
18 | //{cateId}
19 | "筛选子分类名称": "全部&民国&萌宝&超能&甜宠&豪门恩怨&长生&神医&寻亲&抗战谍战&奇幻&闪婚&职场商战&权谋&高手下山&时空之旅&欢喜冤家&都市&体育&家庭&喜剧&都市修仙&神豪&科幻&致富&奇幻脑洞&强者回归&励志&复仇&马甲&亲情&小人物&无敌&现实&重生&穿越&年代&悬疑&婚姻&家国情仇&虐恋&古装&仙侠&玄幻仙侠&传承觉醒&功夫武打&戏曲歌舞&情感&逆袭&战争",
20 | "筛选子分类替换词": "0&590-839&589&1115&442&462&585&1073&438&1125&1093&1092-1097&715&713&943&840-1101&474&1094&718&717&1129&1128&714-1126&917&1124&475&1130&918&721&476&1076-1100&416-463&1091-1096&719&835-837&472&1074&441-469&439-465&916&716-722&445-470&1127&915&466&444-468&1102&720&473&1095&1098&838&417-464&1099",
21 | //{class}
22 | "筛选类型名称": "",
23 | "筛选类型替换词": "*",
24 | //{area}
25 | "筛选地区名称": "",
26 | "筛选地区替换词": "*",
27 | //{year}
28 | "筛选年份名称": "",
29 | "筛选年份替换词": "*",
30 | //{lang}
31 | "筛选语言名称": "",
32 | "筛选语言替换词": "*",
33 | //{by}
34 | "筛选排序名称": "时间&人气&评分",
35 | "筛选排序替换词": "time&hits&score",
36 | "分类截取模式": "1",
37 | "分类列表数组规则": ".BrowseList_listBox__MyeBa&&.BrowseList_listItem__h7lD4",
38 | "分类片单是否Jsoup写法": "是",
39 | "分类片单标题": "img&&alt",
40 | "分类片单链接": "a&&href",
41 | "分类片单图片": "img&&src",
42 | "分类片单副标题": ".BrowseList_lastChapter__dkL54&&Text",
43 | "分类片单链接加前缀": "https://www.kuaikaw.cn",
44 | "分类片单链接加后缀": "",
45 | "搜索请求头参数": "User-Agent$MOBILE_UA",
46 | "搜索链接": "https://www.kuaikaw.cn/search/{SearchPg}?searchValue={wd}",
47 | "POST请求数据": "",
48 | "搜索截取模式": "1",
49 | "搜索列表数组规则": ".search_searchList__AvbeR&&.MTagBookList_tagBookItem__C_038",
50 | "搜索片单是否Jsoup写法": "是",
51 | "搜索片单图片": "img&&src",
52 | "搜索片单标题": "img&&alt",
53 | "搜索片单链接": "a&&href",
54 | "搜索片单副标题": "",
55 | "搜索片单链接加前缀": "https://www.kuaikaw.cn",
56 | "搜索片单链接加后缀": "",
57 | "链接是否直接播放": "否",
58 | "直接播放链接加前缀": "",
59 | "直接播放链接加后缀": "",
60 | "直接播放直链视频请求头": "",
61 | "详情是否Jsoup写法": "是",
62 | "类型详情": "",
63 | "年代详情": "",
64 | "地区详情": "",
65 | "演员详情": "",
66 | "简介详情": ".introduction_introBox__t4Bbz&&Text",
67 | "线路列表数组规则": "",
68 | "线路标题": "Text",
69 | "播放列表数组规则": "body&&.CatalogList_swiperBox__5kdPs",
70 | "选集列表数组规则": "a:not(:has(img))",
71 | "选集标题链接是否Jsoup写法": "是",
72 | "选集标题": "a&&Text",
73 | "选集链接": "a&&href",
74 | "是否反转选集序列": "否",
75 | "选集链接加前缀": "https://www.kuaikaw.cn",
76 | "选集链接加后缀": "",
77 | "分析MacPlayer": "否",
78 | "是否开启手动嗅探": "否",
79 | "手动嗅探视频链接关键词": ".mp4#.m3u8#.flv#video/tos",
80 | "手动嗅探视频链接过滤词": ".html#=http"
81 | }
82 |
--------------------------------------------------------------------------------
/lib/河马短剧.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import requests
3 | import re
4 | import json
5 | import traceback
6 | import sys
7 |
8 | sys.path.append('../../')
9 | try:
10 | from base.spider import Spider
11 | except ImportError:
12 | # 定义一个基础接口类,用于本地测试
13 | class Spider:
14 | def init(self, extend=""):
15 | pass
16 |
17 | class Spider(Spider):
18 | def __init__(self):
19 | self.siteUrl = "https://www.kuaikaw.cn"
20 | self.nextData = None # 缓存NEXT_DATA数据
21 | self.cateManual = {
22 | "甜宠": "462",
23 | "古装仙侠": "1102",
24 | "现代言情": "1145",
25 | "青春": "1170",
26 | "豪门恩怨": "585",
27 | "逆袭": "417-464",
28 | "重生": "439-465",
29 | "系统": "1159",
30 | "总裁": "1147",
31 | "职场商战": "943"
32 | }
33 |
34 | def getName(self):
35 | # 返回爬虫名称
36 | return "河马短剧"
37 |
38 | def init(self, extend=""):
39 | return
40 |
41 | def fetch(self, url, headers=None):
42 | """统一的网络请求接口"""
43 | if headers is None:
44 | headers = {
45 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0",
46 | "Referer": self.siteUrl,
47 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
48 | "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8"
49 | }
50 |
51 | try:
52 | response = requests.get(url, headers=headers, timeout=10, allow_redirects=True)
53 | response.raise_for_status()
54 | return response
55 | except Exception as e:
56 | print(f"请求异常: {url}, 错误: {str(e)}")
57 | return None
58 |
59 | def isVideoFormat(self, url):
60 | # 检查是否为视频格式
61 | video_formats = ['.mp4', '.mkv', '.avi', '.wmv', '.m3u8', '.flv', '.rmvb']
62 | for format in video_formats:
63 | if format in url.lower():
64 | return True
65 | return False
66 |
67 | def manualVideoCheck(self):
68 | # 不需要手动检查
69 | return False
70 |
71 | def homeContent(self, filter):
72 | """获取首页分类及筛选"""
73 | result = {}
74 | # 分类列表,使用已初始化的cateManual
75 | classes = []
76 | for k in self.cateManual:
77 | classes.append({
78 | 'type_name': k,
79 | 'type_id': self.cateManual[k]
80 | })
81 | result['class'] = classes
82 | # 获取首页推荐视频
83 | try:
84 | result['list'] = self.homeVideoContent()['list']
85 | except:
86 | result['list'] = []
87 |
88 | return result
89 |
90 | def homeVideoContent(self):
91 | """获取首页推荐视频内容"""
92 | videos = []
93 | try:
94 | response = self.fetch(self.siteUrl)
95 | html_content = response.text
96 | # 提取NEXT_DATA JSON数据
97 | next_data_pattern = r''
98 | next_data_match = re.search(next_data_pattern, html_content, re.DOTALL)
99 | if next_data_match:
100 | next_data_json = json.loads(next_data_match.group(1))
101 | page_props = next_data_json.get("props", {}).get("pageProps", {})
102 | # 获取轮播图数据 - 这些通常是推荐内容
103 | if "bannerList" in page_props and isinstance(page_props["bannerList"], list):
104 | banner_list = page_props["bannerList"]
105 | for banner in banner_list:
106 | book_id = banner.get("bookId", "")
107 | book_name = banner.get("bookName", "")
108 | cover_url = banner.get("coverWap", banner.get("wapUrl", ""))
109 | # 获取状态和章节数
110 | status = banner.get("statusDesc", "")
111 | total_chapters = banner.get("totalChapterNum", "")
112 | if book_id and book_name:
113 | videos.append({
114 | "vod_id": f"/drama/{book_id}",
115 | "vod_name": book_name,
116 | "vod_pic": cover_url,
117 | "vod_remarks": f"{status} {total_chapters}集" if total_chapters else status
118 | })
119 |
120 | # SEO分类下的推荐
121 | if "seoColumnVos" in page_props and isinstance(page_props["seoColumnVos"], list):
122 | for column in page_props["seoColumnVos"]:
123 | book_infos = column.get("bookInfos", [])
124 | for book in book_infos:
125 | book_id = book.get("bookId", "")
126 | book_name = book.get("bookName", "")
127 | cover_url = book.get("coverWap", "")
128 | status = book.get("statusDesc", "")
129 | total_chapters = book.get("totalChapterNum", "")
130 |
131 | if book_id and book_name:
132 | videos.append({
133 | "vod_id": f"/drama/{book_id}",
134 | "vod_name": book_name,
135 | "vod_pic": cover_url,
136 | "vod_remarks": f"{status} {total_chapters}集" if total_chapters else status
137 | })
138 |
139 | # # 去重
140 | # seen = set()
141 | # unique_videos = []
142 | # for video in videos:
143 | # if video["vod_id"] not in seen:
144 | # seen.add(video["vod_id"])
145 | # unique_videos.append(video)
146 | # videos = unique_videos
147 |
148 | except Exception as e:
149 | print(f"获取首页推荐内容出错: {e}")
150 |
151 | result = {
152 | "list": videos
153 | }
154 | return result
155 |
156 | def categoryContent(self, tid, pg, filter, extend):
157 | """获取分类内容"""
158 | result = {}
159 | videos = []
160 | url = f"{self.siteUrl}/browse/{tid}/{pg}"
161 | response = self.fetch(url)
162 | html_content = response.text
163 | # 提取NEXT_DATA JSON数据
164 | next_data_pattern = r''
165 | next_data_match = re.search(next_data_pattern, html_content, re.DOTALL)
166 | if next_data_match:
167 | next_data_json = json.loads(next_data_match.group(1))
168 | page_props = next_data_json.get("props", {}).get("pageProps", {})
169 | # 获取总页数和当前页
170 | current_page = page_props.get("page", 1)
171 | total_pages = page_props.get("pages", 1)
172 | # 获取书籍列表
173 | book_list = page_props.get("bookList", [])
174 | # 转换为通用格式
175 | for book in book_list:
176 | book_id = book.get("bookId", "")
177 | book_name = book.get("bookName", "")
178 | cover_url = book.get("coverWap", "")
179 | status_desc = book.get("statusDesc", "")
180 | total_chapters = book.get("totalChapterNum", "")
181 | if book_id and book_name:
182 | videos.append({
183 | "vod_id": f"/drama/{book_id}",
184 | "vod_name": book_name,
185 | "vod_pic": cover_url,
186 | "vod_remarks": f"{status_desc} {total_chapters}集" if total_chapters else status_desc
187 | })
188 | # 构建返回结果
189 | result = {
190 | "list": videos,
191 | "page": int(current_page),
192 | "pagecount": total_pages,
193 | "limit": len(videos),
194 | "total": total_pages * len(videos) if videos else 0
195 | }
196 | return result
197 |
198 | def switch(self, key, pg):
199 | # 搜索功能
200 | search_results = []
201 | # 获取第一页结果,并检查总页数
202 | url = f"{self.siteUrl}/search?searchValue={key}&page={pg}"
203 | response = self.fetch(url)
204 | html_content = response.text
205 | # 提取NEXT_DATA JSON数据
206 | next_data_pattern = r''
207 | next_data_match = re.search(next_data_pattern, html_content, re.DOTALL)
208 | if next_data_match:
209 | next_data_json = json.loads(next_data_match.group(1))
210 | page_props = next_data_json.get("props", {}).get("pageProps", {})
211 | # 获取总页数
212 | total_pages = page_props.get("pages", 1)
213 | # 处理所有页的数据
214 | all_book_list = []
215 | # 添加第一页的书籍列表
216 | book_list = page_props.get("bookList", [])
217 | all_book_list.extend(book_list)
218 | # 如果有多页,获取其他页的数据
219 | if total_pages > 1 : # quick模式只获取第一页
220 | for page in range(2, total_pages + 1):
221 | next_page_url = f"{self.siteUrl}/search?searchValue={key}&page={page}"
222 | next_page_response = self.fetch(next_page_url)
223 | next_page_html = next_page_response.text
224 | next_page_match = re.search(next_data_pattern, next_page_html, re.DOTALL)
225 | if next_page_match:
226 | next_page_json = json.loads(next_page_match.group(1))
227 | next_page_props = next_page_json.get("props", {}).get("pageProps", {})
228 | next_page_books = next_page_props.get("bookList", [])
229 | all_book_list.extend(next_page_books)
230 | # 转换为统一的搜索结果格式
231 | for book in all_book_list:
232 | book_id = book.get("bookId", "")
233 | book_name = book.get("bookName", "")
234 | cover_url = book.get("coverWap", "")
235 | total_chapters = book.get("totalChapterNum", "0")
236 | status_desc = book.get("statusDesc", "")
237 | # 构建视频项
238 | vod = {
239 | "vod_id": f"/drama/{book_id}",
240 | "vod_name": book_name,
241 | "vod_pic": cover_url,
242 | "vod_remarks": f"{status_desc} {total_chapters}集"
243 | }
244 | search_results.append(vod)
245 | result = {
246 | "list": search_results,
247 | "page": pg
248 | }
249 | return result
250 |
251 | def searchContent(self, key, quick, pg=1):
252 | result = self.switch(key, pg=pg)
253 | result['page'] = pg
254 | return result
255 |
256 | def searchContentPage(self, key, quick, pg=1):
257 | return self.searchContent(key, quick, pg)
258 |
259 | def detailContent(self, ids):
260 | # 获取剧集信息
261 | vod_id = ids[0]
262 | episode_id = None
263 | chapter_id = None
264 |
265 | if not vod_id.startswith('/drama/'):
266 | if vod_id.startswith('/episode/'):
267 | episode_info = vod_id.replace('/episode/', '').split('/')
268 | if len(episode_info) >= 2:
269 | episode_id = episode_info[0]
270 | chapter_id = episode_info[1]
271 | vod_id = f'/drama/{episode_id}'
272 | else:
273 | vod_id = '/drama/' + vod_id
274 |
275 | drama_url = self.siteUrl + vod_id
276 | print(f"请求URL: {drama_url}")
277 |
278 | headers = {
279 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0",
280 | "Referer": self.siteUrl,
281 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
282 | "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8"
283 | }
284 |
285 | rsp = self.fetch(drama_url, headers=headers)
286 | if not rsp or rsp.status_code != 200:
287 | print(f"请求失败,状态码: {getattr(rsp, 'status_code', 'N/A')}")
288 | return {}
289 |
290 | html = rsp.text
291 | next_data_match = re.search(r'', html, re.DOTALL)
292 |
293 | if not next_data_match:
294 | print("未找到NEXT_DATA内容")
295 | return {}
296 |
297 | try:
298 | next_data = json.loads(next_data_match.group(1))
299 | page_props = next_data.get("props", {}).get("pageProps", {})
300 | print(f"找到页面属性,包含 {len(page_props.keys())} 个键")
301 |
302 | book_info = page_props.get("bookInfoVo", {})
303 | chapter_list = page_props.get("chapterList", [])
304 |
305 | title = book_info.get("title", "")
306 | sub_title = f"{book_info.get('totalChapterNum', '')}集"
307 |
308 | categories = []
309 | for category in book_info.get("categoryList", []):
310 | categories.append(category.get("name", ""))
311 |
312 | vod_content = book_info.get("introduction", "")
313 |
314 | vod = {
315 | "vod_id": vod_id,
316 | "vod_name": title,
317 | "vod_pic": book_info.get("coverWap", ""),
318 | "type_name": ",".join(categories),
319 | "vod_year": "",
320 | "vod_area": book_info.get("countryName", ""),
321 | "vod_remarks": sub_title,
322 | "vod_actor": ", ".join([p.get("name", "") for p in book_info.get("performerList", [])]),
323 | "vod_director": "",
324 | "vod_content": vod_content
325 | }
326 |
327 | # 处理播放列表
328 | play_url_list = []
329 | episodes = []
330 |
331 | if chapter_list:
332 | print(f"找到 {len(chapter_list)} 个章节")
333 |
334 | # 先检查是否有可以直接使用的MP4链接作为模板
335 | mp4_template = None
336 | first_mp4_chapter_id = None
337 |
338 | # 先搜索第一个章节的MP4链接
339 | # 为提高成功率,尝试直接请求第一个章节的播放页
340 | if chapter_list and len(chapter_list) > 0:
341 | first_chapter = chapter_list[0]
342 | first_chapter_id = first_chapter.get("chapterId", "")
343 | drama_id_clean = vod_id.replace('/drama/', '')
344 |
345 | if first_chapter_id and drama_id_clean:
346 | first_episode_url = f"{self.siteUrl}/episode/{drama_id_clean}/{first_chapter_id}"
347 | print(f"请求第一集播放页: {first_episode_url}")
348 |
349 | first_rsp = self.fetch(first_episode_url, headers=headers)
350 | if first_rsp and first_rsp.status_code == 200:
351 | first_html = first_rsp.text
352 | # 直接从HTML提取MP4链接
353 | mp4_pattern = r'(https?://[^"\']+\.mp4)'
354 | mp4_matches = re.findall(mp4_pattern, first_html)
355 | if mp4_matches:
356 | mp4_template = mp4_matches[0]
357 | first_mp4_chapter_id = first_chapter_id
358 | print(f"找到MP4链接模板: {mp4_template}")
359 | print(f"模板对应的章节ID: {first_mp4_chapter_id}")
360 |
361 | # 如果未找到模板,再检查章节对象中是否有MP4链接
362 | if not mp4_template:
363 | for chapter in chapter_list[:5]: # 只检查前5个章节以提高效率
364 | if "chapterVideoVo" in chapter and chapter["chapterVideoVo"]:
365 | chapter_video = chapter["chapterVideoVo"]
366 | mp4_url = chapter_video.get("mp4", "") or chapter_video.get("mp4720p", "") or chapter_video.get("vodMp4Url", "")
367 | if mp4_url and ".mp4" in mp4_url:
368 | mp4_template = mp4_url
369 | first_mp4_chapter_id = chapter.get("chapterId", "")
370 | print(f"从chapterVideoVo找到MP4链接模板: {mp4_template}")
371 | print(f"模板对应的章节ID: {first_mp4_chapter_id}")
372 | break
373 |
374 | # 遍历所有章节处理播放信息
375 | for chapter in chapter_list:
376 | chapter_id = chapter.get("chapterId", "")
377 | chapter_name = chapter.get("chapterName", "")
378 |
379 | # 1. 如果章节自身有MP4链接,直接使用
380 | if "chapterVideoVo" in chapter and chapter["chapterVideoVo"]:
381 | chapter_video = chapter["chapterVideoVo"]
382 | mp4_url = chapter_video.get("mp4", "") or chapter_video.get("mp4720p", "") or chapter_video.get("vodMp4Url", "")
383 | if mp4_url and ".mp4" in mp4_url:
384 | episodes.append(f"{chapter_name}${mp4_url}")
385 | continue
386 |
387 | # 2. 如果有MP4模板,尝试替换章节ID构建MP4链接
388 | if mp4_template and first_mp4_chapter_id and chapter_id:
389 | # 替换模板中的章节ID部分
390 | if first_mp4_chapter_id in mp4_template:
391 | new_mp4_url = mp4_template.replace(first_mp4_chapter_id, chapter_id)
392 | episodes.append(f"{chapter_name}${new_mp4_url}")
393 | continue
394 |
395 | # 3. 如果上述方法都不可行,回退到使用chapter_id构建中间URL
396 | if chapter_id and chapter_name:
397 | url = f"{vod_id}${chapter_id}${chapter_name}"
398 | episodes.append(f"{chapter_name}${url}")
399 |
400 | if not episodes and vod_id:
401 | # 尝试构造默认的集数
402 | total_chapters = int(book_info.get("totalChapterNum", "0"))
403 | if total_chapters > 0:
404 | print(f"尝试构造 {total_chapters} 个默认集数")
405 |
406 | # 如果知道章节ID的模式,可以构造
407 | if chapter_id and episode_id:
408 | for i in range(1, total_chapters + 1):
409 | chapter_name = f"第{i}集"
410 | url = f"{vod_id}${chapter_id}${chapter_name}"
411 | episodes.append(f"{chapter_name}${url}")
412 | else:
413 | # 使用普通的构造方式
414 | for i in range(1, total_chapters + 1):
415 | chapter_name = f"第{i}集"
416 | url = f"{vod_id}${chapter_name}"
417 | episodes.append(f"{chapter_name}${url}")
418 |
419 | if episodes:
420 | play_url_list.append("#".join(episodes))
421 | vod['vod_play_from'] = '河马剧场'
422 | vod['vod_play_url'] = '$$$'.join(play_url_list)
423 |
424 | result = {
425 | 'list': [vod]
426 | }
427 | return result
428 | except Exception as e:
429 | print(f"解析详情页失败: {str(e)}")
430 | print(traceback.format_exc())
431 | return {}
432 |
433 | def playerContent(self, flag, id, vipFlags):
434 | result = {}
435 | print(f"调用playerContent: flag={flag}, id={id}")
436 |
437 | headers = {
438 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0",
439 | "Referer": self.siteUrl,
440 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
441 | "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8"
442 | }
443 |
444 | # 解析id参数
445 | parts = id.split('$')
446 | drama_id = None
447 | chapter_id = None
448 |
449 | if len(parts) >= 2:
450 | drama_id = parts[0]
451 | chapter_id = parts[1]
452 | chapter_name = parts[2] if len(parts) > 2 else "第一集"
453 | print(f"解析参数: drama_id={drama_id}, chapter_id={chapter_id}")
454 | else:
455 | # 处理旧数据格式
456 | print(f"使用原始URL格式: {id}")
457 | result["parse"] = 0
458 | result["url"] = id
459 | result["header"] = json.dumps(headers)
460 | return result
461 |
462 | # 直接检查chapter_id是否包含http(可能已经是视频链接)
463 | if 'http' in chapter_id and '.mp4' in chapter_id:
464 | print(f"已经是MP4链接: {chapter_id}")
465 | result["parse"] = 0
466 | result["url"] = chapter_id
467 | result["header"] = json.dumps(headers)
468 | return result
469 |
470 | # 构建episode页面URL
471 | drama_id_clean = drama_id.replace('/drama/', '')
472 | episode_url = f"{self.siteUrl}/episode/{drama_id_clean}/{chapter_id}"
473 | print(f"请求episode页面: {episode_url}")
474 |
475 | try:
476 | rsp = self.fetch(episode_url, headers=headers)
477 | if not rsp or rsp.status_code != 200:
478 | print(f"请求失败,状态码: {getattr(rsp, 'status_code', 'N/A')}")
479 | result["parse"] = 0
480 | result["url"] = id
481 | result["header"] = json.dumps(headers)
482 | return result
483 |
484 | html = rsp.text
485 | print(f"获取页面大小: {len(html)} 字节")
486 |
487 | # 尝试从NEXT_DATA提取视频链接
488 | mp4_url = None
489 |
490 | # 方法1: 从NEXT_DATA提取
491 | next_data_match = re.search(r'', html, re.DOTALL)
492 | if next_data_match:
493 | try:
494 | print("找到NEXT_DATA")
495 | next_data = json.loads(next_data_match.group(1))
496 | page_props = next_data.get("props", {}).get("pageProps", {})
497 |
498 | # 从chapterList中查找当前章节
499 | chapter_list = page_props.get("chapterList", [])
500 | print(f"找到章节列表,长度: {len(chapter_list)}")
501 |
502 | for chapter in chapter_list:
503 | if chapter.get("chapterId") == chapter_id:
504 | print(f"找到匹配的章节: {chapter.get('chapterName')}")
505 | chapter_video = chapter.get("chapterVideoVo", {})
506 | mp4_url = chapter_video.get("mp4", "") or chapter_video.get("mp4720p", "") or chapter_video.get("vodMp4Url", "")
507 | if mp4_url:
508 | print(f"从chapterList找到MP4链接: {mp4_url}")
509 | break
510 |
511 | # 如果未找到,尝试从当前章节获取
512 | if not mp4_url:
513 | current_chapter = page_props.get("chapterInfo", {})
514 | if current_chapter:
515 | print("找到当前章节信息")
516 | chapter_video = current_chapter.get("chapterVideoVo", {})
517 | mp4_url = chapter_video.get("mp4", "") or chapter_video.get("mp4720p", "") or chapter_video.get("vodMp4Url", "")
518 | if mp4_url:
519 | print(f"从chapterInfo找到MP4链接: {mp4_url}")
520 | except Exception as e:
521 | print(f"解析NEXT_DATA失败: {str(e)}")
522 | print(traceback.format_exc())
523 |
524 | # 方法2: 直接从HTML中提取MP4链接
525 | if not mp4_url:
526 | mp4_pattern = r'(https?://[^"\']+\.mp4)'
527 | mp4_matches = re.findall(mp4_pattern, html)
528 | if mp4_matches:
529 | # 查找含有chapter_id的链接
530 | matched_mp4 = False
531 | for url in mp4_matches:
532 | if chapter_id in url:
533 | mp4_url = url
534 | matched_mp4 = True
535 | print(f"从HTML直接提取章节MP4链接: {mp4_url}")
536 | break
537 |
538 | # 如果没找到包含chapter_id的链接,使用第一个
539 | if not matched_mp4 and mp4_matches:
540 | mp4_url = mp4_matches[0]
541 | print(f"从HTML直接提取MP4链接: {mp4_url}")
542 |
543 | if mp4_url and ".mp4" in mp4_url:
544 | print(f"最终找到的MP4链接: {mp4_url}")
545 | result["parse"] = 0
546 | result["url"] = mp4_url
547 | result["header"] = json.dumps(headers)
548 | return result
549 | else:
550 | print(f"未找到有效的MP4链接,尝试再次解析页面内容")
551 | # 再尝试一次从HTML中广泛搜索所有可能的MP4链接
552 | all_mp4_pattern = r'(https?://[^"\']+\.mp4)'
553 | all_mp4_matches = re.findall(all_mp4_pattern, html)
554 | if all_mp4_matches:
555 | mp4_url = all_mp4_matches[0]
556 | print(f"从HTML广泛搜索找到MP4链接: {mp4_url}")
557 | result["parse"] = 0
558 | result["url"] = mp4_url
559 | result["header"] = json.dumps(headers)
560 | return result
561 |
562 | print(f"未找到视频链接,返回原episode URL: {episode_url}")
563 | result["parse"] = 0
564 | result["url"] = episode_url
565 | result["header"] = json.dumps(headers)
566 | return result
567 | except Exception as e:
568 | print(f"请求或解析失败: {str(e)}")
569 | print(traceback.format_exc())
570 | result["parse"] = 0
571 | result["url"] = id
572 | result["header"] = json.dumps(headers)
573 | return result
574 |
575 | def localProxy(self, param):
576 | # 本地代理处理,此处简单返回传入的参数
577 | return [200, "video/MP2T", {}, param]
578 |
579 | def destroy(self):
580 | # 资源回收
581 | pass
--------------------------------------------------------------------------------
/lib/甜圈短剧.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # by @嗷呜
3 | import sys
4 | sys.path.append('..')
5 | from base.spider import Spider
6 |
7 |
8 | class Spider(Spider):
9 |
10 | def init(self, extend=""):
11 | pass
12 |
13 | def getName(self):
14 | pass
15 |
16 | def isVideoFormat(self, url):
17 | pass
18 |
19 | def manualVideoCheck(self):
20 | pass
21 |
22 | def destroy(self):
23 | pass
24 |
25 | ahost='https://api.cenguigui.cn'
26 |
27 | headers = {
28 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
29 | 'sec-ch-ua-platform': '"macOS"',
30 | 'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="134", "Google Chrome";v="134"',
31 | 'DNT': '1',
32 | 'sec-ch-ua-mobile': '?0',
33 | 'Sec-Fetch-Site': 'cross-site',
34 | 'Sec-Fetch-Mode': 'no-cors',
35 | 'Sec-Fetch-Dest': 'video',
36 | 'Sec-Fetch-Storage-Access': 'active',
37 | 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
38 | }
39 |
40 | def homeContent(self, filter):
41 | result = {'class': [{'type_id': '推荐榜', 'type_name': '推荐榜'},
42 | {'type_id': '新剧', 'type_name': '新剧'},
43 | {'type_id': '逆袭', 'type_name': '逆袭'},
44 | {'type_id': '霸总', 'type_name': '霸总'},
45 | {'type_id': '现代言情', 'type_name': '现代言情'},
46 | {'type_id': '打脸虐渣', 'type_name': '打脸虐渣'},
47 | {'type_id': '豪门恩怨', 'type_name': '豪门恩怨'},
48 | {'type_id': '神豪', 'type_name': '神豪'},
49 | {'type_id': '马甲', 'type_name': '马甲'},
50 | {'type_id': '都市日常', 'type_name': '都市日常'},
51 | {'type_id': '战神归来', 'type_name': '战神归来'},
52 | {'type_id': '小人物', 'type_name': '小人物'},
53 | {'type_id': '女性成长', 'type_name': '女性成长'},
54 | {'type_id': '大女主', 'type_name': '大女主'},
55 | {'type_id': '穿越', 'type_name': '穿越'},
56 | {'type_id': '都市修仙', 'type_name': '都市修仙'},
57 | {'type_id': '强者回归', 'type_name': '强者回归'},
58 | {'type_id': '亲情', 'type_name': '亲情'},
59 | {'type_id': '古装', 'type_name': '古装'},
60 | {'type_id': '重生', 'type_name': '重生'},
61 | {'type_id': '闪婚', 'type_name': '闪婚'},
62 | {'type_id': '赘婿逆袭', 'type_name': '赘婿逆袭'},
63 | {'type_id': '虐恋', 'type_name': '虐恋'},
64 | {'type_id': '追妻', 'type_name': '追妻'},
65 | {'type_id': '天下无敌', 'type_name': '天下无敌'},
66 | {'type_id': '家庭伦理', 'type_name': '家庭伦理'},
67 | {'type_id': '萌宝', 'type_name': '萌宝'},
68 | {'type_id': '古风权谋', 'type_name': '古风权谋'},
69 | {'type_id': '职场', 'type_name': '职场'},
70 | {'type_id': '奇幻脑洞', 'type_name': '奇幻脑洞'},
71 | {'type_id': '异能', 'type_name': '异能'},
72 | {'type_id': '无敌神医', 'type_name': '无敌神医'},
73 | {'type_id': '古风言情', 'type_name': '古风言情'},
74 | {'type_id': '传承觉醒', 'type_name': '传承觉醒'},
75 | {'type_id': '现言甜宠', 'type_name': '现言甜宠'},
76 | {'type_id': '奇幻爱情', 'type_name': '奇幻爱情'},
77 | {'type_id': '乡村', 'type_name': '乡村'},
78 | {'type_id': '历史古代', 'type_name': '历史古代'},
79 | {'type_id': '王妃', 'type_name': '王妃'},
80 | {'type_id': '高手下山', 'type_name': '高手下山'},
81 | {'type_id': '娱乐圈', 'type_name': '娱乐圈'},
82 | {'type_id': '强强联合', 'type_name': '强强联合'},
83 | {'type_id': '破镜重圆', 'type_name': '破镜重圆'},
84 | {'type_id': '暗恋成真', 'type_name': '暗恋成真'},
85 | {'type_id': '民国', 'type_name': '民国'},
86 | {'type_id': '欢喜冤家', 'type_name': '欢喜冤家'},
87 | {'type_id': '系统', 'type_name': '系统'},
88 | {'type_id': '真假千金', 'type_name': '真假千金'},
89 | {'type_id': '龙王', 'type_name': '龙王'},
90 | {'type_id': '校园', 'type_name': '校园'},
91 | {'type_id': '穿书', 'type_name': '穿书'},
92 | {'type_id': '女帝', 'type_name': '女帝'},
93 | {'type_id': '团宠', 'type_name': '团宠'},
94 | {'type_id': '年代爱情', 'type_name': '年代爱情'},
95 | {'type_id': '玄幻仙侠', 'type_name': '玄幻仙侠'},
96 | {'type_id': '青梅竹马', 'type_name': '青梅竹马'},
97 | {'type_id': '悬疑推理', 'type_name': '悬疑推理'},
98 | {'type_id': '皇后', 'type_name': '皇后'},
99 | {'type_id': '替身', 'type_name': '替身'},
100 | {'type_id': '大叔', 'type_name': '大叔'},
101 | {'type_id': '喜剧', 'type_name': '喜剧'},
102 | {'type_id': '剧情', 'type_name': '剧情'}]}
103 | return result
104 |
105 | def homeVideoContent(self):
106 | pass
107 |
108 | def categoryContent(self, tid, pg, filter, extend):
109 | params = {
110 | 'classname': tid,
111 | 'offset': str((int(pg) - 1)),
112 | }
113 | data = self.fetch(f'{self.ahost}/api/duanju/api.php', params=params, headers=self.headers).json()
114 | videos = []
115 | for k in data['data']:
116 | videos.append({
117 | 'vod_id': k.get('book_id'),
118 | 'vod_name': k.get('title'),
119 | 'vod_pic': k.get('cover'),
120 | 'vod_year': k.get('score'),
121 | 'vod_remarks': f"{k.get('sub_title')}|{k.get('episode_cnt')}"
122 | })
123 | result = {}
124 | result['list'] = videos
125 | result['page'] = pg
126 | result['pagecount'] = 9999
127 | result['limit'] = 90
128 | result['total'] = 999999
129 | return result
130 |
131 | def detailContent(self, ids):
132 | v=self.fetch(f'{self.ahost}/api/duanju/api.php', params={'book_id': ids[0]}, headers=self.headers).json()
133 | vod = {
134 | 'type_name': v.get('category'),
135 | 'vod_year': v.get('time'),
136 | 'vod_remarks': v.get('duration'),
137 | 'vod_content': v.get('desc'),
138 | 'vod_play_from': '嗷呜爱看短剧',
139 | 'vod_play_url': '#'.join([f"{i['title']}${i['video_id']}" for i in v['data']])
140 | }
141 | return {'list':[vod]}
142 |
143 | def searchContent(self, key, quick, pg="1"):
144 | return self.categoryContent(key, pg, True, {})
145 |
146 | def playerContent(self, flag, id, vipFlags):
147 | data=self.fetch(f'{self.ahost}/api/duanju/api.php', params={'video_id': id}, headers=self.headers).json()
148 | return {'parse': 0, 'url': data['data']['url'], 'header': self.headers}
149 |
150 | def localProxy(self, param):
151 | pass
152 |
--------------------------------------------------------------------------------
/lib/素白白.json:
--------------------------------------------------------------------------------
1 | {
2 | "站名": "素白白影视",
3 | "主页url": "https://www.subaibai.com",
4 | "图片代理": "0",
5 | "头部集合": "User-Agent$Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36#authority$www.subaibai.com#Referer$https://www.subaibai.com/#Origin$https://www.subaibai.com/",
6 | "分类": "国产剧&电影&电视剧&热门电影&高分电影&动漫电影&欧美剧&韩剧&动漫剧",
7 | "分类值": "new-movie&tv-drama&hot-month&high-movie&cartoon-movie&american-drama&korean-drama&anime-drama",
8 | "分类url": "https://www.subaibai.com/{cateId}/page/{catePg};;aks2",
9 | "二次截取": "&&
",
10 | "数组": "
&&[替换:data-original=\">>图https://images.weserv.nl/?url=#https://www.subaibaiys.com>>https://www.subaibai.com]",
11 | "图片": "图&&\"",
12 | "副标题": "class=\"jidi\">&&",
13 | "搜索模式": "1",
14 | "搜索url": "https://www.subaibai.com/?s={wd}",
15 | "影片年代": "年份:&&",
16 | "影片地区": "地区:&&",
17 | "影片类型": "类型:&&",
18 | "导演": "导演:&&",
19 | "主演": "主演:&&",
20 | "简介": "yp_context\">&&",
21 | "线路数组": "mi_paly_box\">&&",
22 | "线路标题": "ypxingq_t\">&&
[替换:在线播放>>]",
23 | "播放数组": "&&
[替换:https://www.subaibaiys.com>>https://www.subaibai.com]",
24 | "播放列表": "",
25 | "播放标题": ">&&<",
26 | "播放链接": "href=\"&&\"",
27 | "嗅探词": "wangchuanxin.top#.mp4?#.m3u8#.mp4#.flv#.mp3#.m4a",
28 | "过滤词": "data.m3u8.in#51.la#cnzz.com#baidu.com#bilibili.com",
29 | "播放请求头": "User-Agent$Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36#authority$wangchuanxin.top#Origin$https://www.subaibai.com/"
30 | }
--------------------------------------------------------------------------------
/lib/红果短剧.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # by @嗷呜
3 | import re
4 | import sys
5 | from pyquery import PyQuery as pq
6 | sys.path.append('..')
7 | from base.spider import Spider
8 |
9 | class Spider(Spider):
10 |
11 | def init(self, extend=""):
12 | pass
13 |
14 | def getName(self):
15 | pass
16 |
17 | def isVideoFormat(self, url):
18 | pass
19 |
20 | def manualVideoCheck(self):
21 | pass
22 |
23 | def destroy(self):
24 | pass
25 |
26 | host='https://www.hongguodj.cc'
27 |
28 | headers = {
29 | 'Accept': '*/*',
30 | 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
31 | 'Cache-Control': 'no-cache',
32 | 'Connection': 'keep-alive',
33 | 'DNT': '1',
34 | 'Origin': host,
35 | 'Pragma': 'no-cache',
36 | 'Sec-Fetch-Dest': 'empty',
37 | 'Sec-Fetch-Mode': 'cors',
38 | 'Sec-Fetch-Site': 'cross-site',
39 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
40 | 'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="134", "Google Chrome";v="134"',
41 | 'sec-ch-ua-mobile': '?0',
42 | 'sec-ch-ua-platform': '"macOS"',
43 | }
44 |
45 | def homeContent(self, filter):
46 | result = {}
47 | classes = []
48 | vlist = []
49 | data = pq(self.fetch(self.host, headers=self.headers).text)
50 | for i in list(data('.slip li').items())[1:]:
51 | classes.append({
52 | 'type_name': i.text(),
53 | 'type_id': re.findall(r'\d+', i('a').attr('href'))[0]
54 | })
55 | for i in data('.wrap .rows').items():
56 | vlist.extend(self.getlist(i('li')))
57 | result['class'] = classes
58 | result['list'] = vlist
59 | return result
60 |
61 | def homeVideoContent(self):
62 | pass
63 |
64 | def categoryContent(self, tid, pg, filter, extend):
65 | data=pq(self.fetch(f'{self.host}/type/{tid}-{pg}.html', headers=self.headers).text)
66 | result = {}
67 | result['list'] = self.getlist(data('.list ul li'))
68 | result['page'] = pg
69 | result['pagecount'] = 9999
70 | result['limit'] = 90
71 | result['total'] = 999999
72 | return result
73 |
74 | def detailContent(self, ids):
75 | data=pq(self.fetch(f'{self.host}{ids[0]}', headers=self.headers).text)
76 | v=data('.info')
77 | p=v('p')
78 | vod = {
79 | 'vod_name': v('h1').text(),
80 | 'type_name': p.eq(2).text(),
81 | 'vod_year': p.eq(3).text(),
82 | 'vod_area': p.eq(4).text(),
83 | 'vod_remarks': v('em').text(),
84 | 'vod_actor': p.eq(0).text(),
85 | 'vod_director': p.eq(1).text(),
86 | 'vod_content': data('#desc .text').text(),
87 | 'vod_play_from': '',
88 | 'vod_play_url': ''
89 | }
90 | names = [i.text() for i in data('.title.slip a').items()]
91 | plist=[]
92 | for i in data('.play-list ul').items():
93 | plist.append('#'.join([f'{j("a").text()}${j("a").attr("href")}' for j in i('li').items()]))
94 | vod['vod_play_from'] = '$$$'.join(names)
95 | vod['vod_play_url'] = '$$$'.join(plist)
96 | return {'list': [vod]}
97 |
98 | def searchContent(self, key, quick, pg="1"):
99 | data=pq(self.fetch(f'{self.host}/search/{key}----------{pg}---.html', headers=self.headers).text)
100 | return {'list': self.getlist(data('.show.rows li')),'page':pg}
101 |
102 | def playerContent(self, flag, id, vipFlags):
103 | p=0
104 | uid=f'{self.host}{id}'
105 | data=pq(self.fetch(uid, headers=self.headers).text)
106 | url=data('.video.ratio').attr('data-play')
107 | if not url:
108 | url = uid
109 | p = 1
110 | return {'parse': p, 'url': url, 'header': self.headers}
111 |
112 | def localProxy(self, param):
113 | pass
114 |
115 | def getlist(self,data):
116 | vlist = []
117 | for j in data.items():
118 | vlist.append({
119 | 'vod_id': j('a').attr('href'),
120 | 'vod_name': j('img').attr('alt'),
121 | 'vod_pic': self.host + j('img').attr('data-src'),
122 | 'vod_year': j('.bg').text(),
123 | 'vod_remarks': j('p').text()
124 | })
125 | return vlist
126 |
127 |
128 |
--------------------------------------------------------------------------------
/lib/金牌影视.js:
--------------------------------------------------------------------------------
1 | var rule = {
2 | title: '金牌影院',
3 | host: 'https://m.sunnafh.com',
4 | url: '/api/mw-movie/anonymous/video/list?pageNum=fypage&pageSize=30&sort=1&sortBy=1&type1=fyclass',
5 | searchUrl: '/api/mw-movie/anonymous/video/searchByWordPageable?keyword=**&pageNum=fypage&pageSize=12&type=false',
6 | headers: {
7 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
8 | },
9 | searchable: 2,
10 | quickSearch: 0,
11 | filterable: 0,
12 | class_name: '电影&电视剧&综艺&动漫',
13 | class_url: '1&2&3&4',
14 | limit: 6,
15 | double: false,
16 | play_parse:true,
17 | lazy:`js:
18 | let pid = input.split('/')[5];
19 | let nid = input.split('/')[7];
20 | const t = new Date().getTime();
21 | eval(getCryptoJS);
22 | let signkey = 'clientType=1&id='+pid+'&nid='+nid+'&key=cb808529bae6b6be45ecfab29a4889bc&t='+t;
23 | const key = CryptoJS.SHA1(CryptoJS.MD5(signkey).toString()).toString();
24 | let json_data = JSON.parse(request('https://m.sunnafh.com/api/mw-movie/anonymous/v2/video/episode/url?clientType=1&id='+pid+'&nid='+nid,{headers: {
25 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
26 | 'deviceid': '63ffad23-a598-4f96-85d7-7bf5f3e4a0a2',
27 | 'sign': key,
28 | 't': t
29 | }}));
30 | let link = json_data.data.list[0].url;
31 | if(/\\.(m3u8|mp4)/.test(link)){input={jx:0,parse:0,url:link}}else{input={jx:0,parse:1,url:link}}
32 | `,
33 | 一级: `js:
34 | let d = [];
35 | let url = '';
36 | let t = new Date().getTime();
37 | eval(getCryptoJS);
38 | let signkey = 'pageNum='+MY_PAGE+'&pageSize=30&sort=1&sortBy=1&type1='+MY_CATE+'&key=cb808529bae6b6be45ecfab29a4889bc&t='+t;
39 | let key = CryptoJS.SHA1(CryptoJS.MD5(signkey).toString()).toString();
40 | let list = JSON.parse(request(input,{headers:{
41 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
42 | 'Accept': 'application/json, text/plain, */*',
43 | 'deviceId': '63ffad23-a598-4f96-85d7-7bf5f3e4a0a2',
44 | 'sign': key,
45 | 't': t
46 | }})).data.list;
47 | list.forEach((it)=>{
48 | d.push({
49 | title: it.vodName,
50 | desc:it.vodRemarks,
51 | img:it.vodPic,
52 | url:'http'+it.vodId
53 | })
54 | });
55 | setResult(d);
56 | `,
57 | 二级: `js:
58 | let kid=input.split('http')[1];
59 | let t = new Date().getTime();
60 | eval(getCryptoJS);
61 | let signkey = 'id='+kid+'&key=cb808529bae6b6be45ecfab29a4889bc&t='+t;
62 | let key = CryptoJS.SHA1(CryptoJS.MD5(signkey).toString()).toString();
63 | let kjson = JSON.parse(request('https://m.sunnafh.com/api/mw-movie/anonymous/video/detail?id='+kid,{headers:{
64 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
65 | 'Accept': 'application/json, text/plain, */*',
66 | 'deviceId': '63ffad23-a598-4f96-85d7-7bf5f3e4a0a2',
67 | 'sign': key,
68 | 't': t
69 | }})).data;
70 | let kurls = kjson.episodeList.map(function(it) => {
71 | return it.name + "$" + "https://m.sunnafh.com/vod/play/"+kid+"/sid/"+it.nid
72 | }).join('#');
73 | VOD = {
74 | vod_id: kid,
75 | vod_name: kjson.vodName,
76 | vod_pic: kjson.vodPic,
77 | type_name: kjson.vodClass,
78 | vod_remarks: kjson.vodRemarks,
79 | vod_year: kjson.vodYear,
80 | vod_area: kjson.vodArea,
81 | vod_lang: kjson.vodLang,
82 | vod_director: kjson.vodDirector,
83 | vod_actor: kjson.vodActor,
84 | vod_content: kjson.vodContent,
85 | vod_play_from: '金牌线路',
86 | vod_play_url: kurls
87 | }`,
88 | 搜索: `js:
89 | let t = new Date().getTime();
90 | eval(getCryptoJS);
91 | let pg = MY_PAGE;
92 | let signkey = 'keyword='+KEY+'&pageNum='+pg+'&pageSize=12&type=false&key=cb808529bae6b6be45ecfab29a4889bc&t='+t;
93 | let key = CryptoJS.SHA1(CryptoJS.MD5(signkey).toString()).toString();
94 | let html = JSON.parse(request(input,{headers: {
95 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
96 | 'deviceid': '63ffad23-a598-4f96-85d7-7bf5f3e4a0a2',
97 | 'sign': key,
98 | 't': t
99 | }}));
100 | let data = html.data.list;
101 | let d = [];
102 | data.forEach(it=>{
103 | d.push({
104 | title: it.vodName,
105 | desc:it.vodVersion,
106 | img:it.vodPic,
107 | url:'http'+it.vodId
108 | })
109 | });
110 | setResult(d)
111 | `,
112 | }
--------------------------------------------------------------------------------
/lib/金牌影视2.js:
--------------------------------------------------------------------------------
1 | var rule = {
2 | title: '金牌影院',
3 | host: 'https://www.gs4x7nq4.com/ ',
4 | url: '/api/mw-movie/anonymous/video/list?pageNum=fypage&pageSize=30&sort=1&sortBy=1&type1=fyclass',
5 | searchUrl: '/api/mw-movie/anonymous/video/searchByWordPageable?keyword=**&pageNum=fypage&pageSize=12&type=false',
6 | headers: {
7 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
8 | },
9 | searchable: 2,
10 | quickSearch: 0,
11 | filterable: 0,
12 | class_name: '电影&电视剧&综艺&动漫',
13 | class_url: '1&2&3&4',
14 | limit: 6,
15 | double: false,
16 | play_parse:true,
17 | lazy:`js:
18 | let pid = input.split('/')[5];
19 | let nid = input.split('/')[7];
20 | const t = new Date().getTime();
21 | eval(getCryptoJS);
22 | let signkey = 'clientType=1&id='+pid+'&nid='+nid+'&key=cb808529bae6b6be45ecfab29a4889bc&t='+t;
23 | const key = CryptoJS.SHA1(CryptoJS.MD5(signkey).toString()).toString();
24 | let json_data = JSON.parse(request('https://www.gs4x7nq4.com/api/mw-movie/anonymous/v2/video/episode/url?clientType=1&id='+pid+'&nid='+nid,{headers: {
25 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
26 | 'deviceid': '63ffad23-a598-4f96-85d7-7bf5f3e4a0a2',
27 | 'sign': key,
28 | 't': t
29 | }}));
30 | let link = json_data.data.list[0].url;
31 | if(/\\.(m3u8|mp4)/.test(link)){input={jx:0,parse:0,url:link}}else{input={jx:0,parse:1,url:link}}
32 | `,
33 | 一级: `js:
34 | let d = [];
35 | let url = '';
36 | let t = new Date().getTime();
37 | eval(getCryptoJS);
38 | let signkey = 'pageNum='+MY_PAGE+'&pageSize=30&sort=1&sortBy=1&type1='+MY_CATE+'&key=cb808529bae6b6be45ecfab29a4889bc&t='+t;
39 | let key = CryptoJS.SHA1(CryptoJS.MD5(signkey).toString()).toString();
40 | let list = JSON.parse(request(input,{headers:{
41 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
42 | 'Accept': 'application/json, text/plain, */*',
43 | 'deviceId': '63ffad23-a598-4f96-85d7-7bf5f3e4a0a2',
44 | 'sign': key,
45 | 't': t
46 | }})).data.list;
47 | list.forEach((it)=>{
48 | d.push({
49 | title: it.vodName,
50 | desc:it.vodRemarks,
51 | img:it.vodPic,
52 | url:'http'+it.vodId
53 | })
54 | });
55 | setResult(d);
56 | `,
57 | 二级: `js:
58 | let kid=input.split('http')[1];
59 | let t = new Date().getTime();
60 | eval(getCryptoJS);
61 | let signkey = 'id='+kid+'&key=cb808529bae6b6be45ecfab29a4889bc&t='+t;
62 | let key = CryptoJS.SHA1(CryptoJS.MD5(signkey).toString()).toString();
63 | let kjson = JSON.parse(request('https://www.gs4x7nq4.com/api/mw-movie/anonymous/video/detail?id='+kid,{headers:{
64 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
65 | 'Accept': 'application/json, text/plain, */*',
66 | 'deviceId': '63ffad23-a598-4f96-85d7-7bf5f3e4a0a2',
67 | 'sign': key,
68 | 't': t
69 | }})).data;
70 | let kurls = kjson.episodeList.map(function(it) => {
71 | return it.name + "$" + "https://www.gs4x7nq4.com/vod/play/"+kid+"/sid/"+it.nid
72 | }).join('#');
73 | VOD = {
74 | vod_id: kid,
75 | vod_name: kjson.vodName,
76 | vod_pic: kjson.vodPic,
77 | type_name: kjson.vodClass,
78 | vod_remarks: kjson.vodRemarks,
79 | vod_year: kjson.vodYear,
80 | vod_area: kjson.vodArea,
81 | vod_lang: kjson.vodLang,
82 | vod_director: kjson.vodDirector,
83 | vod_actor: kjson.vodActor,
84 | vod_content: kjson.vodContent,
85 | vod_play_from: '金牌线路',
86 | vod_play_url: kurls
87 | }`,
88 | 搜索: `js:
89 | let t = new Date().getTime();
90 | eval(getCryptoJS);
91 | let pg = MY_PAGE;
92 | let signkey = 'keyword='+KEY+'&pageNum='+pg+'&pageSize=12&type=false&key=cb808529bae6b6be45ecfab29a4889bc&t='+t;
93 | let key = CryptoJS.SHA1(CryptoJS.MD5(signkey).toString()).toString();
94 | let html = JSON.parse(request(input,{headers: {
95 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
96 | 'deviceid': '63ffad23-a598-4f96-85d7-7bf5f3e4a0a2',
97 | 'sign': key,
98 | 't': t
99 | }}));
100 | let data = html.data.list;
101 | let d = [];
102 | data.forEach(it=>{
103 | d.push({
104 | title: it.vodName,
105 | desc:it.vodVersion,
106 | img:it.vodPic,
107 | url:'http'+it.vodId
108 | })
109 | });
110 | setResult(d)
111 | `,
112 | }
--------------------------------------------------------------------------------
/lib/骚火影视.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "作者":"天天开心",
4 |
5 | "站名":"骚火影视",
6 |
7 | "主页url":"https://saohuo.vip/",
8 |
9 | "简介":"+",
10 |
11 | "导演":"
* / 导演:&& /",
12 |
13 | "主演":"主演:&&
",
14 |
15 | "影片地区":"&& / ",
16 |
17 | "影片年代":"
* / && /",
18 |
19 | "影片状态":"v_note\">&&
",
20 |
21 | "搜索url":"/search.php?searchword={wd}",
22 |
23 | "线路二次截取":"",
24 |
25 | "线路数组":"",
26 |
27 | "线路标题":"+>&&<[替换:1号线路>>骚火专线#2线路>>骚火备用]",
28 |
29 | "跳转播放链接":"