Update zip

This commit is contained in:
GitHub Actions Bot
2026-03-21 18:27:22 +08:00
parent 1210be41f7
commit 06e814560a
6 changed files with 1626 additions and 1583 deletions
+352 -285
View File
@@ -48,6 +48,18 @@
"url": "http://v.rbotv.cn"
}
},
{
"key": "三秋影视",
"name": "三秋|APP",
"type": 3,
"api": "csp_App3Q"
},
{
"key": "坚果影视",
"name": "坚果|APP",
"type": 3,
"api": "csp_AppJg"
},
{
"key": "韩圈",
"name": "韩圈|APP",
@@ -66,64 +78,138 @@
"ext": "https://www.nntv.in/api.php/v1.vod"
},
{
"key": "花柳",
"name": "花柳APP",
"key": "闪影",
"name": "闪影APP",
"type": 3,
"api": "csp_AppYsV2",
"searchable": 1,
"quickSearch": 1,
"filterable": 1,
"ext": "http://38.47.213.61:41271/mogai_api.php/v1.vod"
},
{
"key": "恋鱼",
"name": "恋鱼|APP",
"type": 3,
"api": "csp_AppFox",
"searchable": 1,
"changeable": 1,
"api": "csp_AppFox",
"ext": {
"host": "http://nico.oiio.fun",
"host": "http://103.117.137.33:2443",
"ver": 2
}
},
{
"key": "麒麟",
"name": "麒麟APP",
"key": "云播",
"name": "云播APP",
"type": 3,
"api": "csp_AppFox",
"searchable": 1,
"changeable": 1,
"api": "csp_AppFox",
"ext": {
"host": "https://qh.70qh.top",
"ver": 2
"host": "http://app.hktvyb.cc"
}
},
{
"key": "搜搜",
"name": "搜搜APP",
"key": "火猫",
"name": "火猫APP",
"type": 3,
"api": "csp_AppFox",
"searchable": 1,
"changeable": 1,
"ext": "https://www.zjcvod.com"
},
{
"key": "火花",
"name": "火花|APP",
"type": 3,
"api": "csp_AppFox",
"searchable": 1,
"changeable": 1,
"ext": {
"host": "http://huohua.itcxo.cn"
"host": "https://cunchu8.obs.cn-north-4.myhuaweicloud.com/fox.json"
}
},
{
"key": "顾我",
"name": "顾我APP",
"key": "云朵",
"name": "云朵APP",
"type": 3,
"api": "csp_AppGet",
"searchable": 1,
"changeable": 1,
"ext": {
"url": "https://yd4kcms.yd4k.top",
"dataKey": "Tpmm9FD99lJ8Dexa",
"dataIv": "Tpmm9FD99lJ8Dexa"
}
},
{
"key": "爱影",
"name": "爱影|APP",
"type": 3,
"api": "csp_AppQi",
"searchable": 1,
"changeable": 1,
"ext": {
"site": "https://daen-1256234123.cos.ap-shanghai.myqcloud.com/MuQi/pgqj.json",
"site": "https://aysappto.oss-cn-chengdu.aliyuncs.com/q20.txt",
"dataKey": "ada211sdfsff3261",
"dataIv": "ada211sdfsff3261",
"init": "initV122",
"search": "mineInfo",
"ua": "okhttp/3.10.0"
}
},
{
"key": "星河",
"name": "星河|APP",
"type": 3,
"api": "csp_AppQi",
"searchable": 1,
"changeable": 1,
"ext": {
"site": "https://daen-1256234123.cos.ap-shanghai.myqcloud.com/MuQi/mqxhqj.txt",
"dataKey": "kj37zs29q22jk96t",
"dataIv": "kj37zs29q22jk96t",
"init": "initV122",
"ua": "okhttp/3.10.0"
}
},
{
"key": "金牌",
"name": "金牌|APP",
"type": 3,
"api": "csp_AppQi",
"searchable": 1,
"changeable": 1,
"ext": {
"url": "https://qj3.ggtvb.cc",
"dataKey": "eecbio48dsq13kkk",
"dataIv": "eecbio48dsq13kkk",
"search": "searchList4",
"init": "initV122",
"ua": "okhttp/3.10.0"
}
},
{
"key": "奇奇",
"name": "奇奇|APP",
"type": 3,
"api": "csp_AppQi",
"searchable": 1,
"changeable": 1,
"ext": {
"url": "http://110.42.67.221:8009",
"dataKey": "123456789abcdefg",
"dataIv": "123456789abcdefg",
"init": "initV122",
"ua": "okhttp/3.10.0"
}
},
{
"key": "老鹰",
"name": "老鹰|APP",
"type": 3,
"api": "csp_AppQi",
"searchable": 1,
"changeable": 1,
"ext": {
"site": "https://maotouyinghubei.oss-cn-wuhan-lr.aliyuncs.com/maotouyinghb.txt",
"dataKey": "zxPtEUDGVllIUhDB",
"dataIv": "zxPtEUDGVllIUhDB",
"ua": "okhttp/3.10.0"
}
},
{
"key": "爱盈",
"name": "爱盈|APP",
@@ -140,52 +226,35 @@
}
},
{
"key": "金牌",
"name": "金牌APP",
"key": "花猪",
"name": "花猪APP",
"type": 3,
"api": "csp_AppQi",
"searchable": 1,
"changeable": 1,
"ext": {
"site": "https://dtqj.ggtvb.cc/dtjp.txt",
"dataKey": "eecbio48dsq131ee",
"dataIv": "eecbio48dsq131ee",
"search": "searchList4",
"site": "https://tiantangyoulu.oss-cn-beijing.aliyuncs.com/wenxintishi.txt",
"dataKey": "h2t8fjo964j2sl6a",
"dataIv": "h2t8fjo964j2sl6a",
"ua": "okhttp/3.10.0"
}
},
{
"key": "橘子",
"name": "橘子|APP",
"type": 3,
"api": "csp_AppQi",
"searchable": 1,
"changeable": 1,
"ext": {
"site": "https://juziapp-1319209748.cos.ap-chengdu.myqcloud.com/juzi.txt",
"dataKey": "jasaFBcdV3zrUDf2",
"dataIv": "jasaFBcdV3zrUDf2",
"version": "305",
"init": "initV122",
"ua": "okhttp/3.10.0"
}
},
{
"key": "小猪",
"name": "小猪|APP",
"type": 3,
"api": "csp_AppQi",
"searchable": 1,
"changeable": 1,
"ext": {
"site": "https://tiantangwulu.oss-cn-shanghai.aliyuncs.com/zhuzhuxia.txt",
"dataKey": "j8sr6d93yp49db3p",
"dataIv": "j8sr6d93yp49db3p",
"init": "initV122",
"ua": "okhttp/3.10.0"
}
},
{
"key": "鲸鱼",
"name": "鲸鱼|APP",
"type": 3,
"api": "csp_AppQi",
"searchable": 1,
"changeable": 1,
"ext": {
"site": "https://jingyu4k-1312635929.cos.ap-nanjing.myqcloud.com/juyu3.json",
"dataKey": "AAdgrdghjfgsABC1",
"dataIv": "AAdgrdghjfgsABC1",
"init": "initV122",
"ua": "okhttp/3.10.0"
}
},
{
"key": "优兔",
"name": "优兔|APP",
@@ -196,173 +265,109 @@
"ext": {
"site": "https://uututv-1319209748.cos.ap-shanghai.myqcloud.com/uutuv4.txt",
"dataKey": "UrWKPnmQWJA8AQzd",
"dataIv": "UrWKPnmQWJA8AQzd"
"dataIv": "UrWKPnmQWJA8AQzd",
"ua": "okhttp/3.10.0"
}
},
{
"key": "小鸟",
"name": "小鸟APP",
"key": "蓝鹰",
"name": "蓝鹰APP",
"type": 3,
"api": "csp_AppQi",
"searchable": 1,
"changeable": 1,
"ext": {
"site": "https://lanyinghz.oss-cn-hangzhou.aliyuncs.com/lanyingxmy.txt",
"dataKey": "ca94b06ca359d80e",
"dataIv": "ca94b06ca359d80e",
"init": "initV120",
"ua": "okhttp/3.10.0"
}
},
{
"key": "小羊",
"name": "小羊|APP",
"type": 3,
"api": "csp_AppQi",
"ext": {
"url": "https://qjappcms410.xy4k.com",
"dataKey": "mC6kG4mI1uM8tS4o",
"dataIv": "mC6kG4mI1uM8tS4o"
}
},
{
"key": "不错",
"name": "不错|APP",
"type": 3,
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"url": "http://154.222.26.58:7788",
"dataKey": "guodan2004031600",
"dataIv": "guodan2004031600",
"token": "fd035ffa03d62775add295bfbb7d99c131e0bb49bb9451309b0ffc4df1631146"
"url": "https://zbc4kmcs.zbc4k.app",
"dataKey": "vE4kR7cF6jS6jH7a",
"dataIv": "vE4kR7cF6jS6jH7a"
}
},
{
"key": "方源",
"name": "方源APP",
"key": "星空",
"name": "星空APP",
"type": 3,
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"site": "https://fyys9.fytd.top/1.txt",
"dataKey": "0ef6fc92a64b4e74",
"dataIv": "0ef6fc92a64b4e74"
"url": "http://xkos1.xkgzs.xyz",
"dataKey": "77jkcdvdodfcdkjk",
"dataIv": "77jkcdvdodfcdkjk"
}
},
{
"key": "七月",
"name": "七月APP",
"key": "火狐",
"name": "火狐APP",
"type": 3,
"api": "csp_AppGet",
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"site": "https://99.jl8.top/1.txt",
"dataKey": "xnybssspqtwotuwj",
"dataIv": "xnybssspqtwotuwj"
"url": "http://huohu.yihn.cc",
"dataKey": "huohushipingetap",
"dataIv": "huohushipingetap"
}
},
{
"key": "芬奇",
"name": "芬奇APP",
"key": "秒看",
"name": "秒看APP",
"type": 3,
"api": "csp_AppGet",
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"site": "https://wsapi.dafenqi.mom/yuming.txt",
"dataKey": "bH5mI8iK0tK7aQ5x",
"dataIv": "bH5mI8iK0tK7aQ5x"
"site": "https://mk1080.top/get.txt",
"dataKey": "c60d88b2eep53za8",
"dataIv": "c60d88b2eep53za8",
"token": "4181e508e7a17657d6a6246e70b1b13553e5ae9d8d287dc47000fb2df638dffa"
}
},
{
"key": "缘梦",
"name": "缘梦APP",
"key": "仓鼠",
"name": "仓鼠APP",
"type": 3,
"api": "csp_AppGet",
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"url": "http://165.99.42.137:5432",
"dataKey": "1234567890987654",
"dataIv": "1234567890987654"
}
},
{
"key": "王子",
"name": "王子|APP",
"type": 3,
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"url": "https://app.95112475.xyz",
"dataKey": "5a9w6x58dsq6z3a6",
"dataIv": "5a9w6x58dsq6z3a6"
}
},
{
"key": "小猫",
"name": "小猫|APP",
"type": 3,
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"site": "http://xywlkj.oss-cn-beijing.aliyuncs.com/wp-content/uploads/2024/12/1.txt",
"dataKey": "xmyxmyxywlkjxywl",
"dataIv": "xmyxmyxywlkjxywl"
}
},
{
"key": "小白",
"name": "小白|APP",
"type": 3,
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"url": "https://uutu.efjhl.cn",
"dataKey": "uXVVRRuaPnjEfsX5",
"dataIv": "uXVVRRuaPnjEfsX5"
}
},
{
"key": "气球",
"name": "气球|APP",
"type": 3,
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"url": "https://vv.229d.cn",
"dataKey": "8888888888888888",
"dataIv": "8888888888888888"
}
},
{
"key": "白鸽",
"name": "白鸽|APP",
"type": 3,
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"url": "https://cy.baige.asia",
"dataKey": "599D0FE5178642FD",
"dataIv": "599D0FE5178642FD"
}
},
{
"key": "魔方",
"name": "魔方|APP",
"type": 3,
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"url": "http://www.613mf4k12.top",
"dataKey": "1234567887654321",
"dataIv": "1234567887654321"
}
},
{
"key": "瑞奇",
"name": "瑞奇|APP",
"type": 3,
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"url": "http://rqxk.gdata.fun",
"dataKey": "yangruiqiYsapp00",
"dataIv": "yangruiqiYsapp00"
"url": "https://cs450appcms.cs4k.top",
"dataKey": "cD7wZ7iY6qN3sU1z",
"dataIv": "cD7wZ7iY6qN3sU1z"
}
},
{
"key": "茉莉",
"name": "茉莉|APP",
"type": 3,
"api": "csp_AppGet",
"searchable": 1,
"changeable": 1,
"api": "csp_AppGet",
"ext": {
"site": "https://gitee.com/wmmoliill/wimg/raw/master/img/bk/9.txt",
"dataKey": "88689667dce61725",
@@ -370,12 +375,51 @@
}
},
{
"key": "驿站",
"name": "驿站丨APP",
"key": "段友",
"name": "段友|APP",
"type": 3,
"api": "csp_AppGet",
"searchable": 1,
"changeable": 1,
"ext": {
"url": "https://shangjihuoke.com",
"dataKey": "8E2DC386FD452D05",
"dataIv": "8E2DC386FD452D05"
}
},
{
"key": "黑猫",
"name": "黑猫|APP",
"type": 3,
"api": "csp_AppGet",
"searchable": 1,
"changeable": 1,
"ext": {
"url": "http://app1-0-0.87333.cc",
"dataKey": "VwsHxkCViDXEExWa",
"dataIv": "VwsHxkCViDXEExWa"
}
},
{
"key": "灵虎",
"name": "灵虎|APP",
"type": 3,
"api": "csp_AppGet",
"searchable": 1,
"changeable": 1,
"ext": {
"site": "https://bind.315999.xyz/89.txt",
"dataKey": "#getapp@TMD@2025",
"dataIv": "#getapp@TMD@2025"
}
},
{
"key": "驿站",
"name": "驿站|APP",
"type": 3,
"api": "csp_AppGet",
"searchable": 1,
"changeable": 1,
"ext": {
"site": "https://dyyztvappapigoodgx.68.gy:12689/ciwk28vu38io8/apiurl.txt",
"dataKey": "dyyztvapiappyyds",
@@ -383,51 +427,29 @@
}
},
{
"key": "蝴蝶",
"name": "蝴蝶APP",
"key": "七壹",
"name": "七壹APP",
"type": 3,
"api": "csp_AppNox",
"api": "csp_AppGet",
"searchable": 1,
"changeable": 1,
"ext": {
"url": "http://111.170.7.114:8081",
"header": {
"content-type": "application/json",
"x-app-signature": "1B:20:A2:57:B9:EB:EB:4E:09:0E:B3:5C:11:62:9E:B6:76:51:98:5A:31:68:05:58:E2:BF:E7:62:75:86:BA:51",
"x-app-package": "com.muyuesg.app",
"x-app-version-code": "7",
"x-app-version-name": "0.0.7"
}
"url": "https://qiyiys.cc",
"dataKey": "45452893929B40D9",
"dataIv": "45452893929B40D9"
}
},
{
"key": "片喵",
"name": "片喵APP",
"key": "瑞奇",
"name": "瑞奇APP",
"type": 3,
"api": "csp_AppNox",
"api": "csp_AppGet",
"searchable": 1,
"changeable": 1,
"ext": {
"url": "https://svip.2video.cc",
"header": {
"content-type": "application/json",
"x-app-signature": "70:DF:B1:2A:AE:C3:E3:73:6E:23:0F:67:B9:3B:C5:63:2D:EA:2A:2C:9E:9D:52:82:1D:3F:3C:3C:B9:10:9E:EE",
"x-app-package": "com.ds.wlss",
"x-app-version-code": "56",
"x-app-version-name": "1.2.6"
}
}
},
{
"key": "豆丁",
"name": "豆丁|APP",
"type": 3,
"api": "csp_AppNox",
"ext": {
"url": "http://172.247.44.102:9924",
"header": {
"content-type": "application/json",
"x-app-signature": "99:CA:F0:76:5A:92:1F:00:1A:60:96:2C:BB:AC:01:51:A6:4E:C6:28:EB:67:F5:82:9C:2C:78:66:91:C3:60:56",
"x-app-package": "com.ddsp.app",
"x-app-version-code": "2",
"x-app-version-name": "3.0.9"
}
"url": "http://rqxk.gdata.fun",
"dataKey": "yangruiqiYsapp00",
"dataIv": "yangruiqiYsapp00"
}
},
{
@@ -493,9 +515,11 @@
"changeable": 1,
"ext": {
"site": [
"https://www.wogg.one",
"https://wogg.xxooo.cf",
"https://woggpan.888484.xyz",
"https://wogg.333232.xyz",
"https://woggpan.888484.xyz"
"http://woggpan.xxooo.cf",
"https://www.wogg.one"
]
},
"timeout": 60
@@ -628,10 +652,11 @@
"changeable": 1,
"ext": {
"site": [
"https://xhww.net",
"https://erxiaofn.site",
"https://erxiaofn.click",
"https://www.xhww.net"
"https://www.2xiaopan.top",
"https://2xiaopan.top",
"https://www.erxiaozhan.top",
"https://www.2xiaozhan.top",
"https://wexwp.cc"
]
},
"timeout": 60
@@ -707,9 +732,8 @@
"type": 3,
"api": "csp_PanWebShareCloudLJ",
"searchable": 1,
"quickSearch": 1,
"filterable": 1,
"changeable": 1,
"quickSearch": 0,
"filterable": 0,
"style": {
"type": "list",
"ratio": 1.433
@@ -730,9 +754,8 @@
"type": 3,
"api": "csp_PanWebShareCloudHM",
"searchable": 1,
"quickSearch": 1,
"filterable": 1,
"changeable": 1,
"quickSearch": 0,
"filterable": 0,
"style": {
"type": "list",
"ratio": 1.433
@@ -752,9 +775,8 @@
"type": 3,
"api": "csp_PanWebShareCloudKF",
"searchable": 1,
"quickSearch": 1,
"filterable": 1,
"changeable": 1,
"quickSearch": 0,
"filterable": 0,
"style": {
"type": "list",
"ratio": 1.433
@@ -773,9 +795,8 @@
"type": 3,
"api": "csp_PanWebShareCloudPT",
"searchable": 1,
"quickSearch": 1,
"filterable": 1,
"changeable": 1,
"quickSearch": 0,
"filterable": 0,
"style": {
"type": "list"
},
@@ -787,9 +808,8 @@
"type": 3,
"api": "csp_PanWebShareCloud123",
"searchable": 1,
"quickSearch": 1,
"filterable": 1,
"changeable": 1,
"quickSearch": 0,
"filterable": 0,
"style": {
"type": "list",
"ratio": 1.433
@@ -807,6 +827,9 @@
"name": "人人|4K",
"type": 3,
"api": "csp_RenRen",
"searchable": 1,
"quickSearch": 0,
"filterable": 0,
"timeout": 60
},
{
@@ -814,6 +837,9 @@
"name": "即刻|4K",
"type": 3,
"api": "csp_Jike",
"searchable": 1,
"quickSearch": 0,
"filterable": 0,
"style": {
"type": "list"
},
@@ -824,6 +850,9 @@
"name": "双星|4K",
"type": 3,
"api": "csp_ShuangXing",
"searchable": 1,
"quickSearch": 0,
"filterable": 0,
"style": {
"type": "list"
},
@@ -837,7 +866,8 @@
"searchable": 1,
"changeable": 1,
"quickSearch": 1,
"filterable": 1
"filterable": 1,
"genre": "shortdrama"
},
{
"key": "锦鲤短剧",
@@ -847,7 +877,8 @@
"searchable": 1,
"changeable": 1,
"quickSearch": 1,
"filterable": 1
"filterable": 1,
"genre": "shortdrama"
},
{
"key": "星阁短剧",
@@ -857,7 +888,19 @@
"searchable": 1,
"changeable": 1,
"quickSearch": 1,
"filterable": 1
"filterable": 1,
"genre": "shortdrama"
},
{
"key": "碎片短剧",
"name": "碎片|短剧",
"type": 3,
"api": "csp_SuipianDJ",
"searchable": 1,
"changeable": 1,
"quickSearch": 1,
"filterable": 1,
"genre": "shortdrama"
},
{
"key": "星芽短剧",
@@ -867,7 +910,8 @@
"searchable": 1,
"changeable": 1,
"quickSearch": 1,
"filterable": 1
"filterable": 1,
"genre": "shortdrama"
},
{
"key": "剧王短剧",
@@ -877,7 +921,8 @@
"searchable": 1,
"changeable": 1,
"quickSearch": 1,
"filterable": 1
"filterable": 1,
"genre": "shortdrama"
},
{
"key": "厂长影视",
@@ -903,12 +948,6 @@
"api": "csp_Tvyb",
"ext": "http://www.tvyb03.com"
},
{
"key": "苹果影视",
"name": "苹果|影视",
"type": 3,
"api": "csp_LiteApple"
},
{
"key": "饺子影视",
"name": "饺子|影视",
@@ -972,6 +1011,17 @@
"api": "csp_XBPQ",
"ext": "./XBPQ/永乐影视.json"
},
{
"key": "星辰影视",
"name": "星辰|影视",
"type": 3,
"api": "csp_XBPQ",
"ext": {
"分类url": "https://www.sdconglin.com/show/{cateId}-{area}-{by}-{class}-{lang}-{letter}---{catePg}---{year}.html",
"分类": "电视剧$2#短剧$36#电影$1#综艺$3#动漫$4",
"简介": "display: none;\">&&<"
}
},
{
"key": "剧圈影视",
"name": "剧圈|影视",
@@ -1032,18 +1082,6 @@
"parsesKey": "aassddwwxxllsx1x"
}
},
{
"key": "卡卡动漫",
"name": "卡卡|动漫",
"type": 3,
"searchable": 1,
"api": "csp_AppGet",
"ext": {
"url": "http://154.201.90.53:8002",
"dataKey": "123456789abcdefg",
"dataIv": "123456789abcdefg"
}
},
{
"key": "丫丫动漫",
"name": "丫丫|动漫",
@@ -1056,18 +1094,6 @@
"dataIv": "qkxnwkfjwpcnwycl"
}
},
{
"key": "冬日动漫",
"name": "冬日丨动漫",
"type": 3,
"searchable": 1,
"api": "csp_AppGet",
"ext": {
"url": "http://www.drdm.fun",
"dataKey": "qE2nD0rL1lH4uP9r",
"dataIv": "qE2nD0rL1lH4uP9r"
}
},
{
"key": "方舟动漫",
"name": "方舟丨动漫",
@@ -1075,7 +1101,7 @@
"searchable": 1,
"api": "csp_AppGet",
"ext": {
"url": "https://www.cyfz.vip",
"url": "https://www.cyfz.top",
"dataKey": "e72cdfd629e8895d",
"dataIv": "e72cdfd629e8895d"
}
@@ -1300,8 +1326,7 @@
"style": {
"type": "list",
"ratio": 1.433
},
"ext": "./json/quarkShare.json"
}
},
{
"key": "UC云盘",
@@ -1314,8 +1339,7 @@
"style": {
"type": "list",
"ratio": 1.433
},
"ext": "./json/ucShare.json"
}
},
{
"key": "百度云盘",
@@ -1355,6 +1379,9 @@
"name": "百酷|搜索",
"type": 3,
"api": "csp_Baiku",
"searchable": 1,
"quickSearch": 0,
"filterable": 0,
"timeout": 60
},
{
@@ -1362,6 +1389,9 @@
"name": "米搜|搜索",
"type": 3,
"api": "csp_MiSou",
"searchable": 1,
"quickSearch": 0,
"filterable": 0,
"timeout": 60
},
{
@@ -1369,6 +1399,9 @@
"name": "酷乐|搜索",
"type": 3,
"api": "csp_KuLe",
"searchable": 1,
"quickSearch": 0,
"filterable": 0,
"timeout": 60
},
{
@@ -1376,6 +1409,9 @@
"name": "鬼鬼|搜索",
"type": 3,
"api": "csp_GuiGui",
"searchable": 1,
"quickSearch": 0,
"filterable": 0,
"timeout": 60
},
{
@@ -1383,6 +1419,9 @@
"name": "混合|搜索",
"type": 3,
"api": "csp_HunHePan",
"searchable": 1,
"quickSearch": 0,
"filterable": 0,
"timeout": 60
},
{
@@ -1390,6 +1429,9 @@
"name": "兄弟|搜索",
"type": 3,
"api": "csp_XiongDiPan",
"searchable": 1,
"quickSearch": 0,
"filterable": 0,
"timeout": 60
},
{
@@ -1397,6 +1439,9 @@
"name": "天翼|搜索",
"type": 3,
"api": "csp_TianYiSo",
"searchable": 1,
"quickSearch": 0,
"filterable": 0,
"timeout": 60
},
{
@@ -1404,6 +1449,9 @@
"name": "趣盘|搜索",
"type": 3,
"api": "csp_QuPanSo",
"searchable": 1,
"quickSearch": 0,
"filterable": 0,
"timeout": 60
},
{
@@ -1429,6 +1477,15 @@
"type": "list"
}
},
{
"key": "919体育",
"name": "919|体育",
"type": 3,
"api": "csp_919Tiyu",
"style": {
"type": "list"
}
},
{
"key": "爱听音乐",
"name": "爱听|音乐",
@@ -1705,7 +1762,17 @@
"url": "https://jx.xmflv.com/?url=",
"ext": {
"header": {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.57"
"user-agent": "Mozilla/5.0 (Linux; Android 13; V2049A Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36"
}
}
},
{
"name": "云解",
"type": 0,
"url": "https://yparse.ik9.cc/index.php?url=",
"ext": {
"header": {
"user-agent": "Mozilla/5.0 (Linux; Android 13; V2049A Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36"
}
}
},
@@ -1715,7 +1782,7 @@
"url": "https://jx.xymp4.cc/?url=",
"ext": {
"header": {
"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.3124.68"
"user-agent": "Mozilla/5.0 (Linux; Android 13; V2049A Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36"
}
}
},
+443 -943
View File
@@ -2,7 +2,6 @@ var rule = {
title: '奇珍异兽[官]',
host: 'https://www.iqiyi.com',
homeUrl: '',
// detailUrl:'https://pcw-api.iqiyi.com/albums/album/avlistinfo?aid=fyid&size=2000&page=1',
detailUrl: 'https://pcw-api.iqiyi.com/video/video/videoinfowithuser/fyid?agent_type=1&authcookie=&subkey=fyid&subscribe=1',
searchUrl: 'https://search.video.iqiyi.com/o?if=html5&key=**&pageNum=fypage&pos=1&pageSize=24&site=iqiyi',
searchable: 2,
@@ -25,76 +24,57 @@ var rule = {
'n': '新上线',
'v': 4
}]
}, {
'key': 'year',
'name': '全部年份',
'value': [{
'n': '全部',
'v': ''
}, {
"n": "2026",
"v": 2026
}, {
"n": "2025",
"v": 2025
}, {
"n": "2024",
"v": 2024
}, {
'n': '2023',
'v': 2023
}, {
'n': '2022',
'v': 2022
}, {
'n': '2021',
'v': 2021
}, {
'n': '2020',
'v': 2020
}, {
'n': '2019',
'v': 2019
}, {
'n': '2018',
'v': 2018
}, {
'n': '2017',
'v': 2017
}, {
'n': '2016-2011',
'v': '2011_2016'
}, {
'n': '2010-2000',
'v': '2000_2010'
}, {
'n': '90年代',
'v': '1990_1999'
}, {
'n': '80年代',
'v': '1980_1989'
}, {
'n': '更早',
'v': '1964_1979'
}]
}, {
'key': 'is_purchase',
'name': '全部资费',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '免费',
'v': 0
}, {
'n': '会员',
'v': 1
}, {
'n': '付费',
'v': 2
}]
}, {
'key': 'three_category_id',
'name': '类型',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '喜剧',
'v': 8
}, {
'n': '爱情',
'v': 6
}, {
'n': '动作',
'v': 11
}, {
'n': '悬疑',
'v': 289
}, {
'n': '科幻',
'v': 9
}, {
'n': '恐怖',
'v': 10
}, {
'n': '犯罪',
'v': 291
}, {
'n': '战争',
'v': 7
}, {
'n': '动画',
'v': 12
}, {
'n': '奇幻',
'v': 1284
}, {
'n': '枪战',
'v': 131
}, {
'n': '惊悚',
'v': 128
}, {
'n': '青春',
'v': 130
}, {
'n': '家庭',
'v': 27356
}]
}, {
'key': 'region',
'name': '地区',
'value': [{
'n': '全部',
@@ -128,75 +108,72 @@ var rule = {
'v': 5
}]
}, {
'key': '18001',
'name': '类型',
'key': 'year',
'name': '全部年份',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '喜剧',
'v': 8
"n": "2026",
"v": 2026
}, {
'n': '爱情',
'v': 6
"n": "2025",
"v": 2025
}, {
'n': '动作',
'v': 11
"n": "2024",
"v": 2024
}, {
'n': '枪战',
'v': 131
'n': '2023',
'v': 2023
}, {
'n': '犯罪',
'v': 291
'n': '2022',
'v': 2022
}, {
'n': '惊悚',
'v': 128
'n': '2021',
'v': 2021
}, {
'n': '恐怖',
'v': 10
'n': '2020',
'v': 2020
}, {
'n': '悬疑',
'v': 289
'n': '2019',
'v': 2019
}, {
'n': '动画',
'v': 12
'n': '2018',
'v': 2018
}, {
'n': '家庭',
'v': 27356
'n': '2017',
'v': 2017
}, {
'n': '奇幻',
'v': 1284
'n': '2016-2011',
'v': '2011_2016'
}, {
'n': '魔幻',
'v': 129
'n': '2010-2000',
'v': '2000_2010'
}, {
'n': '科幻',
'v': 9
'n': '90年代',
'v': '1990_1999'
}, {
'n': '战争',
'v': 7
'n': '80年代',
'v': '1980_1989'
}, {
'n': '青春',
'v': 130
'n': '更早',
'v': '1964_1979'
}]
}, {
'key': '27396',
'name': '规格',
'key': 'is_purchase',
'name': '全部资费',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '巨制',
'v': 27397
'n': '免费',
'v': 0
}, {
'n': '院线',
'v': 27815
'n': '会员',
'v': 1
}, {
'n': '独播',
'v': 30149
}, {
'n': '网络电影',
'v': 27401
'n': '付费',
'v': 2
}]
}],
'2': [{
@@ -215,6 +192,92 @@ var rule = {
'n': '新上线',
'v': 4
}]
}, {
'key': 'three_category_id',
'name': '类型',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '古装',
'v': 24
}, {
'n': '言情',
'v': 20
}, {
'n': '都市',
'v': 24064
}, {
'n': '悬疑',
'v': 32
}, {
'n': '武侠',
'v': 23
}, {
'n': '家庭',
'v': 1654
}, {
'n': '喜剧',
'v': 135
}, {
'n': '战争',
'v': 27916
}, {
'n': '军旅',
'v': 1655
}, {
'n': '谍战',
'v': 290
}, {
'n': '偶像',
'v': 30
}, {
'n': '青春',
'v': 1653
}, {
'n': '罪案',
'v': 149
}, {
'n': '历史',
'v': 21
}, {
'n': '年代',
'v': 27
}, {
'n': '科幻',
'v': 34
}, {
'n': '奇幻',
'v': 27881
}, {
'n': '剧情',
'v': 24063
}, {
'n': '农村',
'v': 29
}, {
'n': '宫廷',
'v': 139
}, {
'n': '商战',
'v': 140
}]
}, {
'key': 'region',
'name': '地区',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '内地',
'v': 15
}, {
'n': '中国台湾',
'v': 1117
}, {
'n': '美国',
'v': 18
}]
}, {
'key': 'year',
'name': '全部年份',
@@ -283,125 +346,6 @@ var rule = {
'n': '付费',
'v': 2
}]
}, {
'key': 'three_category_id',
'name': '地区',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '内地',
'v': 15
}, {
'n': '港剧',
'v': 16
}, {
'n': '韩剧',
'v': 17
}, {
'n': '美剧',
'v': 18
}, {
'n': '日剧',
'v': 309
}, {
'n': '泰剧',
'v': 1114
}, {
'n': '台湾地区',
'v': 1117
}, {
'n': '英剧',
'v': 28916
}, {
'n': '其它',
'v': 19
}]
}, {
'key': '18003',
'name': '类型',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '自制',
'v': 11992
}, {
'n': '古装',
'v': 24
}, {
'n': '言情',
'v': 20
}, {
'n': '武侠',
'v': 23
}, {
'n': '偶像',
'v': 30
}, {
'n': '家庭',
'v': 1654
}, {
'n': '青春',
'v': 1653
}, {
'n': '都市',
'v': 24064
}, {
'n': '喜剧',
'v': 135
}, {
'n': '战争',
'v': 27916
}, {
'n': '军旅',
'v': 1655
}, {
'n': '谍战',
'v': 290
}, {
'n': '悬疑',
'v': 32
}, {
'n': '罪案',
'v': 149
}, {
'n': '穿越',
'v': 148
}, {
'n': '宫廷',
'v': 139
}, {
'n': '历史',
'v': 21
}, {
'n': '神话',
'v': 145
}, {
'n': '科幻',
'v': 34
}, {
'n': '年代',
'v': 27
}, {
'n': '农村',
'v': 29
}, {
'n': '商战',
'v': 140
}, {
'n': '剧情',
'v': 24063
}, {
'n': '奇幻',
'v': 27881
}, {
'n': '网剧',
'v': 24065
}, {
'n': '竖短片',
'v': 32839
}]
}],
'3': [{
'key': 'mode',
@@ -419,6 +363,50 @@ var rule = {
'n': '新上线',
'v': 4
}]
}, {
'key': 'three_category_id',
'name': '类型',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '人文',
'v': 70
}, {
'n': '历史',
'v': 74
}, {
'n': '军事',
'v': 72
}, {
'n': '自然',
'v': 33933
}, {
'n': '探险',
'v': 73
}, {
'n': '社会',
'v': 71
}, {
'n': '美食',
'v': 33908
}, {
'n': '科技',
'v': 28119
}]
}, {
'key': 'region',
'name': '地区',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '国内',
'v': 20323
}, {
'n': '国外',
'v': 20324
}]
}, {
'key': 'year',
'name': '全部年份',
@@ -487,152 +475,6 @@ var rule = {
'n': '付费',
'v': 2
}]
}, {
'key': 'three_category_id',
'name': '地区',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '国内',
'v': 20323
}, {
'n': '国外',
'v': 20324
}]
}, {
'key': '18004',
'name': '类型',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '人文',
'v': 70
}, {
'n': '美食',
'v': 33908
}, {
'n': '医疗',
'v': 33924
}, {
'n': '自然',
'v': 33933
}, {
'n': '萌宠',
'v': 33945
}, {
'n': '财经',
'v': 33953
}, {
'n': '罪案',
'v': 33960
}, {
'n': '竞技',
'v': 33967
}, {
'n': '灾难',
'v': 33974
}, {
'n': '军事',
'v': 72
}, {
'n': '历史',
'v': 74
}, {
'n': '探险',
'v': 73
}, {
'n': '社会',
'v': 71
}, {
'n': '科技',
'v': 28119
}, {
'n': '旅游',
'v': 310
}]
}, {
'key': '28467',
'name': '出品方',
'value': [{
'n': '全部',
'v': ''
}, {
'n': 'BBC',
'v': 28468
}, {
'n': '美国历史频道',
'v': 28470
}, {
'n': '探索频道',
'v': 28471
}, {
'n': '央视记录',
'v': 28472
}, {
'n': '北京纪实频道',
'v': 28473
}, {
'n': '上海纪实频道',
'v': 28474
}, {
'n': '朗思文化',
'v': 28476
}, {
'n': 'CNEX',
'v': 28477
}, {
'n': '五星传奇',
'v': 28478
}, {
'n': 'IMG',
'v': 28479
}, {
'n': 'NHK',
'v': 28480
}, {
'n': '爱奇艺出品',
'v': 31283
}, {
'n': 'Netflix',
'v': 31286
}]
}, {
'key': '29076',
'name': '片种',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '纪录电影',
'v': 29077
}, {
'n': '系列纪录片',
'v': 29078
}, {
'n': '网络纪录片',
'v': 29082
}, {
'n': '纪实栏目',
'v': 29083
}]
}, {
'key': '31294',
'name': '时长',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '微纪录',
'v': 29079
}, {
'n': '长纪录',
'v': 29080
}, {
'n': '短纪录',
'v': 29081
}]
}],
'4': [{
'key': 'mode',
@@ -650,6 +492,50 @@ var rule = {
'n': '新上线',
'v': 4
}]
}, {
'key': 'three_category_id',
'name': '类型',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '热血',
'v': 30232
}, {
'n': '搞笑',
'v': 30230
}, {
'n': '恋爱',
'v': 30243
}, {
'n': '冒险',
'v': 30267
}, {
'n': '校园',
'v': 30249
}, {
'n': '科幻',
'v': 30245
}]
}, {
'key': 'region',
'name': '地区',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '中国大陆',
'v': 37
}, {
'n': '日本',
'v': 38
}, {
'n': '欧美',
'v': 39
}, {
'n': '其它',
'v': 40
}]
}, {
'key': 'year',
'name': '全部年份',
@@ -698,9 +584,6 @@ var rule = {
}, {
'n': '80年代',
'v': '1980_1989'
}, {
'n': '更早',
'v': '1964_1979'
}]
}, {
'key': 'is_purchase',
@@ -718,154 +601,6 @@ var rule = {
'n': '付费',
'v': 2
}]
}, {
'key': 'three_category_id',
'name': '地区',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '中国大陆',
'v': 37
}, {
'n': '日本',
'v': 38
}, {
'n': '韩国',
'v': 1106
}, {
'n': '欧美',
'v': 30218
}, {
'n': '其它',
'v': 40
}]
}, {
'key': '30219',
'name': '版本',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '动画',
'v': 30220
}, {
'n': '特摄',
'v': 30223
}, {
'n': '布袋戏',
'v': 30224
}, {
'n': '特别篇',
'v': 32782
}, {
'n': '动态漫画',
'v': 32783
}, {
'n': '动画电影',
'v': 32784
}, {
'n': '竖版视频',
'v': 32785
}, {
'n': '轻动画',
'v': 33482
}, {
'n': '短剧',
'v': 33483
}]
}, {
'key': '30225',
'name': '风格',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '搞笑',
'v': 30230
}, {
'n': '热血',
'v': 30232
}, {
'n': '催泪',
'v': 30233
}, {
'n': '治愈',
'v': 30234
}, {
'n': '励志',
'v': 30237
}, {
'n': '机战',
'v': 30241
}, {
'n': '恋爱',
'v': 30243
}, {
'n': '科幻',
'v': 30245
}, {
'n': '奇幻',
'v': 30247
}, {
'n': '推理',
'v': 30248
}, {
'n': '校园',
'v': 30249
}, {
'n': '日常',
'v': 30252
}, {
'n': '历史',
'v': 30254
}, {
'n': '美食',
'v': 30255
}, {
'n': '职场',
'v': 30256
}, {
'n': '偶像',
'v': 30258
}, {
'n': '泡面',
'v': 30265
}, {
'n': '冒险',
'v': 30267
}, {
'n': '竞技',
'v': 30268
}, {
'n': '合家欢',
'v': 30270
}, {
'n': '武侠',
'v': 32792
}, {
'n': '玄幻',
'v': 32793
}]
}, {
'key': '32795',
'name': '新类型',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '轻小说改编',
'v': 32796
}, {
'n': '漫画改编',
'v': 32797
}, {
'n': '游戏改编',
'v': 32798
}, {
'n': '原创',
'v': 32799
}]
}],
'6': [{
'key': 'mode',
@@ -883,139 +618,21 @@ var rule = {
'n': '新上线',
'v': 4
}]
}, {
'key': 'year',
'name': '全部年份',
'value': [{
'n': '全部',
'v': ''
}, {
"n": "2026",
"v": 2026
}, {
"n": "2025",
"v": 2025
}, {
"n": "2024",
"v": 2024
}, {
'n': '2023',
'v': 2023
}, {
'n': '2022',
'v': 2022
}, {
'n': '2021',
'v': 2021
}, {
'n': '2020',
'v': 2020
}, {
'n': '2019',
'v': 2019
}, {
'n': '2018',
'v': 2018
}, {
'n': '2017',
'v': 2017
}, {
'n': '2016-2011',
'v': '2011_2016'
}, {
'n': '2010-2000',
'v': '2000_2010'
}, {
'n': '90年代',
'v': '1990_1999'
}, {
'n': '80年代',
'v': '1980_1989'
}, {
'n': '更早',
'v': '1964_1979'
}]
}, {
'key': 'is_purchase',
'name': '全部资费',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '免费',
'v': 0
}, {
'n': '会员',
'v': 1
}, {
'n': '付费',
'v': 2
}]
}, {
'key': 'three_category_id',
'name': '地区',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '内地',
'v': 151
}, {
'n': '港台',
'v': 152
}, {
'n': '韩国',
'v': 33306
}, {
'n': '欧美',
'v': 154
}, {
'n': '其它',
'v': 1113
}]
}, {
'key': '18014',
'name': '类型',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '播报',
'v': 155
}, {
'n': '访谈',
'v': 156
}, {
'n': '游戏',
'v': 158
}, {
'n': '晚会',
'v': 292
}, {
'n': '曲艺',
'v': 293
'n': '真人秀',
'v': 2224
}, {
'n': '脱口秀',
'v': 2118
}, {
'n': '真人秀',
'v': 2224
}, {
'n': '竞技',
'v': 30278
}, {
'n': '爱奇艺出品',
'v': 30279
}, {
'n': '竞演',
'v': 33860
}]
}, {
'key': '33162',
'name': '题材',
'value': [{
'n': '全部',
'v': ''
'n': '晚会',
'v': 292
}, {
'n': '音乐',
'v': 33163
@@ -1023,266 +640,18 @@ var rule = {
'n': '舞蹈',
'v': 33172
}, {
'n': '文化',
'v': 33173
}, {
'n': '美食',
'v': 33182
}, {
'n': '伦理',
'v': 33184
}, {
'n': '相亲',
'v': 33193
}, {
'n': '纪实',
'v': 33195
}, {
'n': '生活',
'v': 33196
}, {
'n': '亲子',
'v': 33197
}, {
'n': '少儿',
'v': 33198
}, {
'n': '财经',
'v': 33199
}, {
'n': '健康',
'v': 33200
}, {
'n': '时尚',
'v': 33203
}, {
'n': '旅游',
'v': 33205
}, {
'n': '教育',
'v': 33206
}, {
'n': '其它',
'v': 33220
}, {
'n': '爱情',
'v': 33316
}, {
'n': '搞笑',
'v': 33317
}, {
'n': '益智',
'v': 33318
}, {
'n': '职场',
'v': 33319
}, {
'n': '语言',
'v': 33530
}, {
'n': '辩论',
'v': 33531
}, {
'n': '演讲',
'v': 33843
}]
}],
'5': [{
'key': 'mode',
'name': '综合排序',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '热播榜',
'v': 11
}, {
'n': '好评榜',
'v': 8
}, {
'n': '新上线',
'v': 4
'n': '竞技',
'v': 30278
}]
}, {
'key': 'year',
'name': '全部年份',
'value': [{
'n': '全部',
'v': ''
}, {
"n": "2026",
"v": 2026
}, {
"n": "2025",
"v": 2025
}, {
"n": "2024",
"v": 2024
}, {
'n': '2023',
'v': 2023
}, {
'n': '2022',
'v': 2022
}, {
'n': '2021',
'v': 2021
}, {
'n': '2020',
'v': 2020
}, {
'n': '2019',
'v': 2019
}, {
'n': '2018',
'v': 2018
}, {
'n': '2017',
'v': 2017
}, {
'n': '2016-2011',
'v': '2011_2016'
}, {
'n': '2010-2000',
'v': '2000_2010'
}, {
'n': '90年代',
'v': '1990_1999'
}, {
'n': '80年代',
'v': '1980_1989'
}, {
'n': '更早',
'v': '1964_1979'
}]
}, {
'key': 'is_purchase',
'name': '全部资费',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '免费',
'v': 0
}, {
'n': '会员',
'v': 1
}, {
'n': '付费',
'v': 2
}]
}, {
'key': 'three_category_id',
'key': 'region',
'name': '地区',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '内地',
'v': 221
}, {
'n': '港台',
'v': 220
}, {
'n': '欧美',
'v': 219
}, {
'n': '日韩',
'v': 218
}, {
'n': '拉美',
'v': 217
}, {
'n': '亚洲地区',
'v': 216
}, {
'n': '非洲',
'v': 215
}]
}, {
'key': '18009',
'name': '语种',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '普通话',
'v': 91
}, {
'n': '粤语',
'v': 92
}, {
'n': '闽南语',
'v': 93
}, {
'n': '英语',
'v': 94
}, {
'n': '日语',
'v': 95
}, {
'n': '韩语',
'v': 96
}, {
'n': '其它',
'v': 97
}]
}, {
'key': '23554',
'name': '音乐类型',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '单曲MV',
'v': 23556
}, {
'n': '单曲现场',
'v': 23557
}, {
'n': '演唱会',
'v': 23558
}, {
'n': '新闻',
'v': 23559
}, {
'n': '访谈',
'v': 23560
}, {
'n': '音乐记录',
'v': 23561
}, {
'n': '音乐周边',
'v': 23562
}, {
'n': '音乐节目',
'v': 23563
}, {
'n': '影视原声',
'v': 23564
}, {
'n': '音乐短片',
'v': 23565
}, {
'n': '其他',
'v': 23566
}]
}],
'16': [{
'key': 'mode',
'name': '综合排序',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '热播榜',
'v': 11
}, {
'n': '好评榜',
'v': 8
}, {
'n': '新上线',
'v': 4
'v': 151
}]
}, {
'key': 'year',
@@ -1332,9 +701,6 @@ var rule = {
}, {
'n': '80年代',
'v': '1980_1989'
}, {
'n': '更早',
'v': '1964_1979'
}]
}, {
'key': 'is_purchase',
@@ -1352,46 +718,192 @@ var rule = {
'n': '付费',
'v': 2
}]
}, {
'key': '18061',
'name': '类型',
}],
'35': [{
'key': 'mode',
'name': '综合排序',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '喜剧',
'v': 1296
'n': '热播榜',
'v': 11
}, {
'n': '爱情',
'v': 1297
'n': '好评榜',
'v': 8
}, {
'n': '动作',
'v': 1298
'n': '新上线',
'v': 4
}]
}, {
'key': 'year',
'name': '全部年份',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '奇幻',
'v': 1299
"n": "2026",
"v": 2026
}, {
'n': '惊悚',
'v': 1300
"n": "2025",
"v": 2025
}, {
'n': '悬疑',
'v': 1301
"n": "2024",
"v": 2024
}, {
'n': '青春',
'v': 1302
'n': '2023',
'v': 2023
}, {
'n': '2022',
'v': 2022
}]
}, {
'key': 'is_purchase',
'name': '全部资费',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '免费',
'v': 0
}, {
'n': '会员',
'v': 1
}, {
'n': '付费',
'v': 2
}]
}],
'15': [{
'key': 'mode',
'name': '综合排序',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '热播榜',
'v': 11
}, {
'n': '好评榜',
'v': 8
}, {
'n': '新上线',
'v': 4
}]
}, {
'key': 'is_purchase',
'name': '全部资费',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '免费',
'v': 0
}, {
'n': '会员',
'v': 1
}, {
'n': '付费',
'v': 2
}]
}],
'37': [{
'key': 'mode',
'name': '综合排序',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '热播榜',
'v': 11
}, {
'n': '好评榜',
'v': 8
}, {
'n': '新上线',
'v': 4
}]
}, {
'key': 'year',
'name': '全部年份',
'value': [{
'n': '全部',
'v': ''
}, {
"n": "2026",
"v": 2026
}, {
"n": "2025",
"v": 2025
}, {
"n": "2024",
"v": 2024
}, {
'n': '2023',
'v': 2023
}, {
'n': '2022',
'v': 2022
}]
}, {
'key': 'is_purchase',
'name': '全部资费',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '免费',
'v': 0
}, {
'n': '会员',
'v': 1
}, {
'n': '付费',
'v': 2
}]
}],
'31': [{
'key': 'mode',
'name': '综合排序',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '热播榜',
'v': 11
}, {
'n': '好评榜',
'v': 8
}, {
'n': '新上线',
'v': 4
}]
}, {
'key': 'is_purchase',
'name': '全部资费',
'value': [{
'n': '全部',
'v': ''
}, {
'n': '免费',
'v': 0
}, {
'n': '会员',
'v': 1
}, {
'n': '付费',
'v': 2
}]
}]
},
// url:'https://pcw-api.iqiyi.com/search/recommend/list?channel_id=fyclass&data_type=1&is_purchase=&mode=24&page_id=fypage&ret_num=48&three_category_id=',
url: 'https://pcw-api.iqiyi.com/search/recommend/list?channel_id=fyclass&data_type=1&page_id=fypage&ret_num=48',
filter_url: 'is_purchase={{fl.is_purchase}}&mode={{fl.mode}}&three_category_id={{fl.three_category_id}}&market_release_date_level={{fl.year}}',
// url:'https://pcw-api.iqiyi.com/search/video/videolists?channel_id=fyclass&pageNum=fypage&pageSize=24&data_type=1&site=iqiyi',
url: 'https://pcw-api.iqiyi.com/search/recommend/list?channel_id=fyclass&data_type=1&page_id=fypage&ret_num=24',
filter_url: 'is_purchase={{fl.is_purchase}}&mode={{fl.mode}}&three_category_id={{fl.three_category_id}}&market_release_date_level={{fl.year}}&region={{fl.region}}',
headers: {
'User-Agent': 'MOBILE_UA'
},
timeout: 5000,
class_name: '电影&电视剧&纪录片&动漫&综艺&音乐&网络电影',
class_url: '1&2&3&4&6&5&16',
class_name: '电视剧&短剧&电影&综艺&少儿&动漫&漫剧&纪录片&知识',
class_url: '2&35&1&6&15&4&37&3&31',
limit: 20,
play_parse: true,
lazy: $js.toString(() => {
@@ -1430,20 +942,8 @@ var rule = {
};
}
}),
// play_parse:true,
// 手动调用解析请求json的url,此lazy不方便
// lazy:'js:input="https://cache.json.icu/home/api?type=ys&uid=292796&key=fnoryABDEFJNPQV269&url="+input.split("?")[0];log(input);let html=JSON.parse(request(input));log(html);input=html.url||input',
// 推荐:'.list_item;img&&alt;img&&src;a&&Text;a&&data-float',
// 一级:'json:.data.list;.name;.imageUrl;.latestOrder;.albumId',
推荐: '',
// 推荐:'js:let d=[];fetch_params.headers["user-agent"]=PC_UA;pdfh=jsp.pdfh;pdfa=jsp.pdfa;pd=jsp.pd;let html=fetch(HOST,fetch_params);let lists=pdfa(html,".qy-mod-li");lists.forEach(function(it){try{let title=pdfh(it,"p.sub&&title");let desc=pdfh(it,".qy-mod-label&&Text");let pic_url=pd(it,"img&&src");d.push({title:title,desc:desc,img:pic_url})}catch(e){}});res=setResult(d);',
: 'js:let d=[];if(MY_CATE==="16"){input=input.replace("channel_id=16","channel_id=1").split("three_category_id")[0];input+="three_category_id=27401"}else if(MY_CATE==="5"){input=input.replace("data_type=1","data_type=2")}let html=request(input);let json=JSON.parse(html);if(json.code==="A00003"){fetch_params.headers["user-agent"]=PC_UA;json=JSON.parse(fetch(input,fetch_params))}json.data.list.forEach(function(data){if(data.channelId===1){desc=data.hasOwnProperty("score")?data.score+"分\\t":""}else if(data.channelId===2||data.channelId===4){if(data.latestOrder===data.videoCount){desc=(data.hasOwnProperty("score")?data.score+"分\\t":"")+data.latestOrder+"集全"}else{if(data.videoCount){desc=(data.hasOwnProperty("score")?data.score+"分\\t":"")+data.latestOrder+"/"+data.videoCount+"集"}else{desc="更新至 "+data.latestOrder+"集"}}}else if(data.channelId===6){desc=data.period+"期"}else if(data.channelId===5){desc=data.focus}else{if(data.latestOrder){desc="更新至 第"+data.latestOrder+"期"}else if(data.period){desc=data.period}else{desc=data.focus}}url=MY_CATE+"$"+data.albumId;d.push({url:url,title:data.name,desc:desc,pic_url:data.imageUrl.replace(".jpg","_390_520.jpg?caplist=jpg,webp")})});setResult(d);',
// 一级:'js:let d=[];if(MY_CATE==="16"){input=input.replace("channel_id=16","channel_id=1").split("three_category_id")[0];input+="three_category_id=27401"}else if(MY_CATE==="5"){input=input.replace("data_type=1","data_type=2")}let html=fetch(input,fetch_params);let json=JSON.parse(html);if(json.code==="A00003"){fetch_params.headers["user-agent"]=PC_UA;json=JSON.parse(fetch(input,fetch_params))}json.data.list.forEach(function(data){if(data.channelId===1){desc=data.hasOwnProperty("score")?data.score+"分\\t":""}else if(data.channelId===2||data.channelId===4){if(data.latestOrder===data.videoCount){desc=(data.hasOwnProperty("score")?data.score+"分\\t":"")+data.latestOrder+"集全"}else{if(data.videoCount){desc=(data.hasOwnProperty("score")?data.score+"分\\t":"")+data.latestOrder+"/"+data.videoCount+"集"}else{desc="更新至 "+data.latestOrder+"集"}}}else if(data.channelId===6){desc=data.period+"期"}else if(data.channelId===5){desc=data.focus}else{if(data.latestOrder){desc="更新至 第"+data.latestOrder+"期"}else if(data.period){desc=data.period}else{desc=data.focus}}url=MY_CATE+"$"+data.albumId;d.push({url:url,title:data.name,desc:desc,pic_url:data.imageUrl.replace(".jpg","_390_520.jpg?caplist=jpg,webp")})});setResult(d);',
// 一级:'json:.data.list;.name;.imageUrl;.playUrl;.latestOrder',
// 二级:{is_json:1,"title":"data.title;data.moviecategory[0]+data.moviecategory[1]","img":"data.cdncover","desc":"data.area[0];data.director[0]","content":"data.description","tabs":"data.playlink_sites;data.playlinksdetail.#idv.quality","lists":"data.playlinksdetail.#idv.default_url"},
// 二级:{is_json:1,"title":"data.name+data.subtitle;data.latestOrder","img":"data.imageUrl","desc":"data.categories;data.areas","content":"data.description","tabs":"data.name","lists":"data.playlinksdetail.#idv.default_url"},
二级: '',
二级: 'js:let d=[];let html=request(input);let json=JSON.parse(html).data;VOD={vod_id:"",vod_url:input,vod_name:"",type_name:"",vod_actor:"",vod_year:"",vod_director:"",vod_area:"",vod_content:"",vod_remarks:"",vod_pic:""};VOD.vod_name=json.name;try{if(json.latestOrder){VOD.vod_remarks="类型: "+(json.categories[0].name||"")+"\\t"+(json.categories[1].name||"")+"\\t"+(json.categories[2].name||"")+"\\t"+"评分:"+(json.score||"")+"\\n更新至:第"+json.latestOrder+"集(期)/共"+json.videoCount+"集(期)"}else{VOD.vod_remarks="类型: "+(json.categories[0].name||"")+"\\t"+(json.categories[1].name||"")+"\\t"+(json.categories[2].name||"")+"\\t"+"评分:"+(json.score||"")+json.period}}catch(e){VOD.vod_remarks=json.subtitle}VOD.vod_area=(json.focus||"")+"\\n资费:"+(json.payMark===1?"VIP":"免费")+"\\n地区:"+(json.areas||"");let vsize="579_772";try{vsize=json.imageSize[12]}catch(e){}VOD.vod_pic=json.imageUrl.replace(".jpg","_"+vsize+".jpg?caplist=jpg,webp");VOD.type_name=json.categories.map(function(it){return it.name}).join(",");if(json.people.main_charactor){let vod_actors=[];json.people.main_charactor.forEach(function(it){vod_actors.push(it.name)});VOD.vod_actor=vod_actors.join(",")}VOD.vod_content=json.description;let playlists=[];if(json.channelId===1||json.channelId===5){playlists=[{playUrl:json.playUrl,imageUrl:json.imageUrl,shortTitle:json.shortTitle,focus:json.focus,period:json.period}]}else{if(json.channelId===6){let qs=json.period.split("-")[0];let listUrl="https://pcw-api.iqiyi.com/album/source/svlistinfo?cid=6&sourceid="+json.albumId+"&timelist="+qs;let playData=JSON.parse(request(listUrl)).data[qs];playData.forEach(function(it){playlists.push({playUrl:it.playUrl,imageUrl:it.imageUrl,shortTitle:it.shortTitle,focus:it.focus,period:it.period})})}else{let listUrl="https://pcw-api.iqiyi.com/albums/album/avlistinfo?aid="+json.albumId+"&size=200&page=1";let data=JSON.parse(request(listUrl)).data;let total=data.total;playlists=data.epsodelist;if(total>200){for(let i=2;i<total/200+1;i++){let listUrl="https://pcw-api.iqiyi.com/albums/album/avlistinfo?aid="+json.albumId+"&size=200&page="+i;let data=JSON.parse(request(listUrl)).data;playlists=playlists.concat(data.epsodelist)}}}}playlists.forEach(function(it){d.push({title:it.shortTitle||"第"+it.order+"集",desc:it.subtitle||it.focus||it.period,img:it.imageUrl.replace(".jpg","_480_270.jpg?caplist=jpg,webp"),url:it.playUrl})});VOD.vod_play_from="qiyi";VOD.vod_play_url=d.map(function(it){return it.title+"$"+it.url}).join("#");',
// 二级:'js:let d=[];let html=request(input);let json=JSON.parse(html).data;vod={vod_id:"",vod_url:input,vod_name:"",type_name:"",vod_actor:"",vod_year:"",vod_director:"",vod_area:"",vod_content:"",vod_remarks:"",vod_pic:""};vod.vod_name=json.name;try{if(json.latestOrder){vod.vod_remarks="类型: "+(json.categories[0].name||"")+"\\t"+(json.categories[1].name||"")+"\\t"+(json.categories[2].name||"")+"\\t"+"评分:"+(json.score||"")+"\\n更新至:第"+json.latestOrder+"集(期)/共"+json.videoCount+"集(期)"}else{vod.vod_remarks="类型: "+(json.categories[0].name||"")+"\\t"+(json.categories[1].name||"")+"\\t"+(json.categories[2].name||"")+"\\t"+"评分:"+(json.score||"")+json.period}}catch(e){vod.vod_remarks=json.subtitle}vod.vod_area=(json.focus||"")+"\\n资费:"+(json.payMark===1?"VIP":"免费")+"\\n地区:"+(json.areas||"");let vsize="579_772";try{vsize=json.imageSize[12]}catch(e){}vod.vod_pic=json.imageUrl.replace(".jpg","_"+vsize+".jpg?caplist=jpg,webp");vod.type_name=json.categories.map(function(it){return it.name}).join(",");if(json.people.main_charactor){vod_actors=[];json.people.main_charactor.forEach(function(it){vod_actors.push(it.name)});vod.vod_actor=vod_actors.join(",")}vod.vod_content=json.description;let playlists=[];if(json.channelId===1||json.channelId===5){playlists=[{playUrl:json.playUrl,imageUrl:json.imageUrl,shortTitle:json.shortTitle,focus:json.focus,period:json.period}]}else{if(json.channelId===6){let qs=json.period.split("-")[0];let listUrl="https://pcw-api.iqiyi.com/album/source/svlistinfo?cid=6&sourceid="+json.albumId+"&timelist="+qs;let playData=JSON.parse(request(listUrl)).data[qs];playData.forEach(function(it){playlists.push({playUrl:it.playUrl,imageUrl:it.imageUrl,shortTitle:it.shortTitle,focus:it.focus,period:it.period})})}else{let listUrl="https://pcw-api.iqiyi.com/albums/album/avlistinfo?aid="+json.albumId+"&size=200&page=1";let data=JSON.parse(request(listUrl)).data;let total=data.total;playlists=data.epsodelist;if(total>200){for(let i=2;i<total/200+1;i++){let listUrl="https://pcw-api.iqiyi.com/albums/album/avlistinfo?aid="+json.albumId+"&size=200&page="+i;let data=JSON.parse(request(listUrl)).data;playlists=playlists.concat(data.epsodelist)}}}}playlists.forEach(function(it){d.push({title:it.shortTitle||"第"+it.order+"集",desc:it.subtitle||it.focus||it.period,img:it.imageUrl.replace(".jpg","_480_270.jpg?caplist=jpg,webp"),url:it.playUrl})});vod.vod_play_from="qiyi";vod.vod_play_url=d.map(function(it){return it.title+"$"+it.url}).join("#");',
一级: 'js:let d=[];var rm=input.match(/&region=([^&]+)/);if(rm&&rm[1]){input=input.replace(/three_category_id=[^&]*/,"three_category_id="+rm[1])}input=input.replace(/&region=[^&]*/g,"");if(MY_CATE==="1"||MY_CATE==="4"){input=input.replace("search/recommend/list","search/video/videolists").replace("page_id=","pageNum=").replace("ret_num=24","pageSize=24")}let html=request(input);let json=JSON.parse(html);if(json.code==="A00003"){fetch_params.headers["user-agent"]=PC_UA;json=JSON.parse(fetch(input,fetch_params))}json.data.list.forEach(function(data){var vid=data.albumId||data.tvId;if(data.channelId===1){desc=data.score?data.score+"分\\t":"";if(data.duration)desc+=data.duration}else if(data.channelId===2||data.channelId===4||data.channelId===35||data.channelId===15||data.channelId===37){if(data.latestOrder===data.videoCount){desc=(data.score?data.score+"分\\t":"")+data.latestOrder+"集全"}else{if(data.videoCount){desc=(data.score?data.score+"分\\t":"")+data.latestOrder+"/"+data.videoCount+"集"}else if(data.latestOrder){desc="更新至 "+data.latestOrder+"集"}else{desc=data.focus||""}}}else if(data.channelId===6){desc=data.period+"期"}else{if(data.latestOrder){desc="更新至 第"+data.latestOrder+"期"}else if(data.period){desc=data.period}else{desc=data.focus||""}}url=MY_CATE+"$"+vid;d.push({url:url,title:data.name,desc:desc,pic_url:data.imageUrl.replace(".jpg","_390_520.jpg?caplist=jpg,webp")})});setResult(d);',
: 'js:let d=[];let html=request(input);let json=JSON.parse(html).data;VOD={vod_id:"",vod_url:input,vod_name:"",type_name:"",vod_actor:"",vod_year:"",vod_director:"",vod_area:"",vod_content:"",vod_remarks:"",vod_pic:""};VOD.vod_name=json.name;try{if(json.latestOrder){VOD.vod_remarks="类型: "+(json.categories[0].name||"")+"\\t"+(json.categories[1].name||"")+"\\t"+(json.categories[2].name||"")+"\\t"+"评分:"+(json.score||"")+"\\n更新至:第"+json.latestOrder+"集(期)/共"+json.videoCount+"集(期)"}else{VOD.vod_remarks="类型: "+(json.categories[0].name||"")+"\\t"+(json.categories[1].name||"")+"\\t"+(json.categories[2].name||"")+"\\t"+"评分:"+(json.score||"")+json.period}}catch(e){VOD.vod_remarks=json.subtitle}VOD.vod_area=(json.focus||"")+"\\n资费:"+(json.payMark===1?"VIP":"免费")+"\\n地区:"+(json.areas||"");let vsize="579_772";try{vsize=json.imageSize[12]}catch(e){}VOD.vod_pic=json.imageUrl.replace(".jpg","_"+vsize+".jpg?caplist=jpg,webp");VOD.type_name=json.categories.map(function(it){return it.name}).join(",");if(json.people.main_charactor){let vod_actors=[];json.people.main_charactor.forEach(function(it){vod_actors.push(it.name)});VOD.vod_actor=vod_actors.join(",")}VOD.vod_content=json.description;let playlists=[];if(json.channelId===1){playlists=[{playUrl:json.playUrl,imageUrl:json.imageUrl,shortTitle:json.shortTitle,focus:json.focus,period:json.period}]}else{if(json.channelId===6){let qs=json.period.split("-")[0];let listUrl="https://pcw-api.iqiyi.com/album/source/svlistinfo?cid=6&sourceid="+json.albumId+"&timelist="+qs;let playData=JSON.parse(request(listUrl)).data[qs];playData.forEach(function(it){playlists.push({playUrl:it.playUrl,imageUrl:it.imageUrl,shortTitle:it.shortTitle,focus:it.focus,period:it.period})})}else{let listUrl="https://pcw-api.iqiyi.com/albums/album/avlistinfo?aid="+json.albumId+"&size=200&page=1";let data=JSON.parse(request(listUrl)).data;let total=data.total;playlists=data.epsodelist;if(total>200){for(let i=2;i<total/200+1;i++){let listUrl="https://pcw-api.iqiyi.com/albums/album/avlistinfo?aid="+json.albumId+"&size=200&page="+i;let data=JSON.parse(request(listUrl)).data;playlists=playlists.concat(data.epsodelist)}}}}playlists.forEach(function(it){d.push({title:it.shortTitle||"第"+it.order+"集",desc:it.subtitle||it.focus||it.period,img:it.imageUrl.replace(".jpg","_480_270.jpg?caplist=jpg,webp"),url:it.playUrl})});VOD.vod_play_from="qiyi";VOD.vod_play_url=d.map(function(it){return it.title+"$"+it.url}).join("#");',
搜索: 'json:.data.docinfos;.albumDocInfo.albumTitle;.albumDocInfo.albumVImage;.albumDocInfo.channel;.albumDocInfo.albumId;.albumDocInfo.tvFocus',
}
}
-8
View File
@@ -33,10 +33,6 @@
"shareId": "ZHNChQfiPfk",
"folder": "root"
},
{
"shareId": "e27BPgDwxeA",
"folder": "root"
},
{
"shareId": "XUH7r6BZuML",
"folder": "root"
@@ -54,10 +50,6 @@
"shareId": "8Fg4TNsd2A2",
"folder": "root"
},
{
"shareId": "ar8Kg9azw1S",
"folder": "root"
},
{
"shareId": "GMYSz3AHFaA",
"folder": "root"
-9
View File
@@ -34,14 +34,5 @@
"folder": "950f5ca7d5e54d528c0dae1fddec5c78"
}
]
},
{
"name": "音乐",
"folders": [
{
"shareId": "369e30038dae4",
"folder": "1b8a55dc18a54fb7aea8ed2b6fd6ad53"
}
]
}
]
+831 -338
View File
@@ -1,9 +1,16 @@
# -*- coding: utf-8 -*-
# by @嗷呜
# by @星河
# 修复版本 - 参考最新三合一.js重构虎牙、斗鱼、B站直播逻辑
# 修复:虎牙清晰度选择,确保ratio参数正确传递码率值
# 修复:斗鱼切换分辨率只能播放1秒的问题(每次重新获取安全密钥和签名)
# 修复:B站使用特殊UA和WBI签名绕过-352风控 [^90^][^30^]
import json
import re
import sys
import time
import hashlib
import random
import urllib.parse
from base64 import b64decode, b64encode
from urllib.parse import parse_qs
import requests
@@ -16,19 +23,13 @@ from concurrent.futures import ThreadPoolExecutor
class Spider(Spider):
def init(self, extend=""):
tid = 'douyin'
headers = self.gethr(0, tid)
response = requests.head(self.hosts[tid], headers=headers)
ttwid = response.cookies.get('ttwid')
headers.update({
'authority': self.hosts[tid].split('//')[-1],
'cookie': f'ttwid={ttwid}' if ttwid else ''
})
self.dyheaders = headers
# 初始化B站WBI密钥
self.bili_wbi_keys = None
self.bili_wbi_expire = 0
pass
def getName(self):
pass
return "直播"
def isVideoFormat(self, url):
pass
@@ -41,6 +42,7 @@ class Spider(Spider):
headers = [
{
# 特殊UA绕过B站风控 [^90^]
"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 Edg/126.0.0.0"
},
{
@@ -51,8 +53,7 @@ class Spider(Spider):
excepturl = 'https://www.baidu.com'
hosts = {
"huya": ["https://www.huya.com","https://mp.huya.com"],
"douyin": "https://live.douyin.com",
"huya": ["https://www.huya.com", "https://mp.huya.com"],
"douyu": "https://www.douyu.com",
"wangyi": "https://cc.163.com",
"bili": ["https://api.live.bilibili.com", "https://api.bilibili.com"]
@@ -60,7 +61,6 @@ class Spider(Spider):
referers = {
"huya": "https://live.cdn.huya.com",
"douyin": "https://live.douyin.com",
"douyu": "https://m.douyu.com",
"bili": "https://live.bilibili.com"
}
@@ -74,12 +74,8 @@ class Spider(Spider):
"bili": {
'Accept': '*/*',
'Icy-MetaData': '1',
'referer': referers['bili'],
'user-agent': headers[0]['User-Agent']
},
'douyin': {
'User-Agent': 'libmpv',
'Icy-MetaData': '1'
'referer': 'https://live.bilibili.com',
'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'
},
'huya': {
'User-Agent': 'ExoPlayer',
@@ -92,42 +88,109 @@ class Spider(Spider):
}
}
def process_bili(self):
# WBI签名相关常量 [^30^]
MIXIN_KEY_ENC_TAB = [
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52
]
def _get_bili_wbi_keys(self):
"""获取B站WBI密钥 [^30^]"""
try:
self.blfdata = self.fetch(
f'{self.hosts["bili"][0]}/room/v1/Area/getList?need_entrance=1&parent_id=0',
headers=self.gethr(0, 'bili')
# 检查缓存
if self.bili_wbi_keys and time.time() < self.bili_wbi_expire:
return self.bili_wbi_keys
# 从导航接口获取 - 使用特殊UA [^90^]
resp = self.fetch(
'https://api.bilibili.com/x/web-interface/nav',
headers={
'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',
'Referer': 'https://www.bilibili.com/'
}
).json()
return ('bili', [{'key': 'cate', 'name': '分类',
'value': [{'n': i['name'], 'v': str(i['id'])}
for i in self.blfdata['data']]}])
if resp.get('code') != 0:
return None
img_url = resp['data']['wbi_img']['img_url']
sub_url = resp['data']['wbi_img']['sub_url']
# 提取文件名作为key
img_key = img_url.rsplit('/', 1)[1].split('.')[0]
sub_key = sub_url.rsplit('/', 1)[1].split('.')[0]
self.bili_wbi_keys = (img_key, sub_key)
self.bili_wbi_expire = time.time() + 86400 # 24小时过期
return self.bili_wbi_keys
except Exception as e:
print(f"获取B站WBI密钥失败: {e}")
return None
def _get_mixin_key(self, orig: str):
"""生成mixin_key [^30^]"""
return ''.join([orig[i] for i in self.MIXIN_KEY_ENC_TAB])[:32]
def _enc_wbi(self, params: dict):
"""WBI签名 [^30^]"""
keys = self._get_bili_wbi_keys()
if not keys:
return params
img_key, sub_key = keys
mixin_key = self._get_mixin_key(img_key + sub_key)
# 添加时间戳
params['wts'] = round(time.time())
# 排序参数
params = dict(sorted(params.items()))
# 过滤特殊字符
params = {
k: ''.join(filter(lambda c: c not in "!'()*", str(v)))
for k, v in params.items()
}
# 计算签名
query = urllib.parse.urlencode(params)
w_rid = hashlib.md5((query + mixin_key).encode()).hexdigest()
params['w_rid'] = w_rid
return params
def process_bili(self):
"""获取B站分类列表 - 使用WBI签名 [^30^]"""
try:
# 尝试获取分类列表 - 使用特殊UA和WBI签名
params = {'need_entrance': 1, 'parent_id': 0}
signed_params = self._enc_wbi(params)
data = self.fetch(
f'{self.hosts["bili"][0]}/room/v1/Area/getList',
params=signed_params,
headers=self.headers[0]
).json()
if data.get('code') == 0 and data.get('data'):
# 保存分类数据供后续使用
self.bili_areas = data['data']
return ('bili', [{'key': 'cate', 'name': '分类',
'value': [{'n': i['name'], 'v': str(i['id'])}
for i in data['data']]}])
return 'bili', None
except Exception as e:
print(f"bili处理错误: {e}")
return 'bili', None
def process_douyin(self):
try:
data = self.getpq(self.hosts['douyin'], headers=self.dyheaders)('script')
for i in data.items():
if 'categoryData' in i.text():
content = i.text()
start = content.find('{')
end = content.rfind('}') + 1
if start != -1 and end != -1:
json_str = content[start:end]
json_str = json_str.replace('\\"', '"')
try:
self.dyifdata = json.loads(json_str)
return ('douyin', [{'key': 'cate', 'name': '分类',
'value': [{'n': i['partition']['title'],
'v': f"{i['partition']['id_str']}@@{i['partition']['title']}"}
for i in self.dyifdata['categoryData']]}])
except json.JSONDecodeError as e:
print(f"douyin解析错误: {e}")
return 'douyin', None
except Exception as e:
print(f"douyin请求或处理错误: {e}")
return 'douyin', None
# 使用默认分类
return 'bili', [{'key': 'cate', 'name': '分类',
'value': [{'n': '网游', 'v': '2'}, {'n': '手游', 'v': '3'},
{'n': '单机', 'v': '6'}, {'n': '娱乐', 'v': '1'},
{'n': '电台', 'v': '5'}, {'n': '虚拟主播', 'v': '9'},
{'n': '生活', 'v': '10'}, {'n': '知识', 'v': '11'},
{'n': '赛事', 'v': '13'}]}]
def process_douyu(self):
try:
@@ -146,9 +209,9 @@ class Spider(Spider):
result = {}
cateManual = {
"虎牙": "huya",
"抖音": "douyin",
"斗鱼": "douyu",
"网易": "wangyi"
"网易": "wangyi",
"B站": "bili"
}
classes = []
filters = {
@@ -157,10 +220,9 @@ class Spider(Spider):
{'n': '娱乐', 'v': '8'}, {'n': '手游', 'v': '3'}]}]
}
with ThreadPoolExecutor(max_workers=3) as executor:
with ThreadPoolExecutor(max_workers=2) as executor:
futures = {
executor.submit(self.process_bili): 'bili',
executor.submit(self.process_douyin): 'douyin',
executor.submit(self.process_douyu): 'douyu'
}
@@ -195,8 +257,6 @@ class Spider(Spider):
vdata, pagecount = self.biliContent(tid, pg, filter, extend, vdata)
elif 'huya' in tid:
vdata, pagecount = self.huyaContent(tid, pg, filter, extend, vdata)
elif 'douyin' in tid:
vdata, pagecount = self.douyinContent(tid, pg, filter, extend, vdata)
elif 'douyu' in tid:
vdata, pagecount = self.douyuContent(tid, pg, filter, extend, vdata)
result['list'] = vdata
@@ -223,39 +283,102 @@ class Spider(Spider):
return vdata, 9999
def biliContent(self, tid, pg, filter, extend, vdata):
if extend.get('cate') and pg == '1' and 'click' not in tid:
for i in self.blfdata['data']:
if str(i['id']) == extend['cate']:
for j in i['list']:
v = self.buildvod(
vod_id=f"click_{tid}@@{i['id']}@@{j['id']}",
vod_name=j.get('name'),
vod_pic=j.get('pic'),
vod_tag=1,
style={"type": "oval", "ratio": 1}
)
vdata.append(v)
return vdata, 1
else:
path = f'/xlive/web-interface/v1/second/getListByArea?platform=web&sort=online&page_size=30&page={pg}'
"""B站分类内容 - 使用WBI签名绕过风控 [^30^][^90^]"""
try:
# 分类列表 - 显示子分类
if extend.get('cate') and pg == '1' and 'click' not in tid:
# 从已保存的分类数据中找到对应分类的子分类
if hasattr(self, 'bili_areas'):
for area in self.bili_areas:
if str(area['id']) == extend['cate']:
for sub_area in area.get('list', []):
v = self.buildvod(
vod_id=f"click_{tid}@@{extend['cate']}@@{sub_area['id']}",
vod_name=sub_area.get('name'),
vod_pic=sub_area.get('pic'),
vod_tag=1,
style={"type": "oval", "ratio": 1}
)
vdata.append(v)
return vdata, 1
# 如果没有找到子分类,直接返回空,让用户进入房间列表
return vdata, 1
# 房间列表 - 使用getList接口并添加WBI签名 [^30^]
if 'click' in tid:
# 子分类房间
ids = tid.split('_')[1].split('@@')
tid = ids[0]
path = f'/xlive/web-interface/v1/second/getList?platform=web&parent_area_id={ids[1]}&area_id={ids[-1]}&sort_type=&page={pg}'
data = self.fetch(f'{self.hosts[tid][0]}{path}', headers=self.gethr(0, tid)).json()
for i in data['data']['list']:
if i.get('roomid'):
data = self.buildvod(
f"{tid}@@{i['roomid']}",
i.get('title'),
i.get('cover'),
i.get('watched_show', {}).get('text_large'),
0,
i.get('uname'),
style={"type": "rect", "ratio": 1.33}
)
vdata.append(data)
return vdata, 9999
parent_area_id = ids[1]
area_id = ids[2]
else:
# 默认使用分类ID作为parent_area_idarea_id为0表示该分类下所有
parent_area_id = extend.get('cate', '2') # 默认网游
area_id = 0
# 构建请求参数并添加WBI签名 [^30^]
params = {
'parent_area_id': parent_area_id,
'area_id': area_id,
'page': pg,
'platform': 'web',
'sort_type': 'online' # 按热度排序
}
signed_params = self._enc_wbi(params)
# 调用getList接口
api_url = f'{self.hosts[tid][0]}/xlive/web-interface/v1/second/getList'
data = self.fetch(api_url, params=signed_params, headers=self.headers[0]).json()
# 如果WBI签名失败,尝试不带签名
if data.get('code') == -352:
print("WBI签名失败,尝试无签名请求...")
params = {
'parent_area_id': parent_area_id,
'area_id': area_id,
'page': pg,
'platform': 'web',
'sort_type': 'online'
}
data = self.fetch(api_url, params=params, headers=self.headers[0]).json()
if data.get('code') == 0:
room_list = data.get('data', {}).get('list', [])
for room in room_list:
if room.get('roomid'):
# 处理在线人数显示
online = room.get('online', 0)
if online > 10000:
online_str = f"{online / 10000:.1f}"
else:
online_str = str(online)
v = self.buildvod(
f"{tid}@@{room['roomid']}",
room.get('title', '未知标题'),
room.get('cover') or room.get('system_cover'),
f"{online_str}",
0,
room.get('uname', ''),
style={"type": "rect", "ratio": 1.33}
)
vdata.append(v)
# 检查是否有更多数据
has_more = data.get('data', {}).get('has_more', 0)
if not has_more:
pagecount = int(pg)
else:
pagecount = 9999
else:
print(f"B站API返回错误: {data.get('message', '未知错误')} (code: {data.get('code')})")
pagecount = 1
return vdata, pagecount
except Exception as e:
print(f"B站内容获取错误: {e}")
return vdata, 1
def huyaContent(self, tid, pg, filter, extend, vdata):
if extend.get('cate') and pg == '1' and 'click' not in tid:
@@ -295,44 +418,6 @@ class Spider(Spider):
vdata.append(v)
return vdata, 9999
def douyinContent(self, tid, pg, filter, extend, vdata):
if extend.get('cate') and pg == '1' and 'click' not in tid:
ids = extend.get('cate').split('@@')
for i in self.dyifdata['categoryData']:
c = i['partition']
if c['id_str'] == ids[0] and c['title'] == ids[1]:
vlist = i['sub_partition'].copy()
vlist.insert(0, {'partition': c})
for j in vlist:
j = j['partition']
v = self.buildvod(
vod_id=f"click_{tid}@@{j['id_str']}@@{j['type']}",
vod_name=j.get('title'),
vod_pic='https://p3-pc-weboff.byteimg.com/tos-cn-i-9r5gewecjs/pwa_v3/512x512-1.png',
vod_tag=1,
style={"type": "oval", "ratio": 1}
)
vdata.append(v)
return vdata, 1
else:
path = f'/webcast/web/partition/detail/room/?aid=6383&app_name=douyin_web&live_id=1&device_platform=web&count=15&offset={(int(pg) - 1) * 15}&partition=720&partition_type=1'
if 'click' in tid:
ids = tid.split('_')[1].split('@@')
tid = ids[0]
path = f'/webcast/web/partition/detail/room/?aid=6383&app_name=douyin_web&live_id=1&device_platform=web&count=15&offset={(int(pg) - 1) * 15}&partition={ids[1]}&partition_type={ids[-1]}&req_from=2'
data = self.fetch(f'{self.hosts[tid]}{path}', headers=self.dyheaders).json()
for i in data['data']['data']:
v = self.buildvod(
vod_id=f"{tid}@@{i['web_rid']}",
vod_name=i['room'].get('title'),
vod_pic=i['room']['cover'].get('url_list')[0],
vod_year=i.get('user_count_str'),
vod_remarks=i['room']['owner'].get('nickname'),
style={"type": "rect", "ratio": 1.33}
)
vdata.append(v)
return vdata, 9999
def douyuContent(self, tid, pg, filter, extend, vdata):
if extend.get('cate') and pg == '1' and 'click' not in tid:
for i in self.dyufdata['data']['cate2Info']:
@@ -375,8 +460,6 @@ class Spider(Spider):
vod = self.biliDetail(ids)
elif ids[0] == 'huya':
vod = self.huyaDetail(ids)
elif ids[0] == 'douyin':
vod = self.douyinDetail(ids)
elif ids[0] == 'douyu':
vod = self.douyuDetail(ids)
return {'list': [vod]}
@@ -425,186 +508,550 @@ class Spider(Spider):
return self.handle_exception(e)
def biliDetail(self, ids):
"""
B站直播详情 - 使用playUrl接口获取多清晰度
"""
try:
vdata = self.fetch(
f'{self.hosts[ids[0]][0]}/xlive/web-room/v1/index/getInfoByRoom?room_id={ids[1]}&wts={int(time.time())}',
headers=self.gethr(0, ids[0])).json()
v = vdata['data']['room_info']
room_id = ids[1]
# 获取房间信息
info_res = self.fetch(
f'{self.hosts["bili"][0]}/room/v1/Room/get_info?room_id={room_id}',
headers=self.headers[0]
).json()
if info_res.get('code') != 0:
return self.handle_exception(Exception("获取房间信息失败"))
room_info = info_res['data']
title = room_info.get('title', 'B站直播')
vod = self.buildvod(
vod_name=v.get('title'),
type_name=v.get('parent_area_name') + '/' + v.get('area_name'),
vod_remarks=v.get('tags'),
vod_play_from=v.get('title'),
vod_name=title,
type_name=f"{room_info.get('parent_area_name', '')}/{room_info.get('area_name', '')}",
vod_director=room_info.get('uname', ''),
vod_remarks=f"在线{room_info.get('online', 0)}"
)
data = self.fetch(
f'{self.hosts[ids[0]][0]}/xlive/web-room/v2/index/getRoomPlayInfo?room_id={ids[1]}&protocol=0%2C1&format=0%2C1%2C2&codec=0%2C1&platform=web',
headers=self.gethr(0, ids[0])).json()
vdnams = data['data']['playurl_info']['playurl']['g_qn_desc']
all_accept_qns = []
streams = data['data']['playurl_info']['playurl']['stream']
for stream in streams:
for format_item in stream['format']:
for codec in format_item['codec']:
if 'accept_qn' in codec:
all_accept_qns.append(codec['accept_qn'])
max_accept_qn = max(all_accept_qns, key=len) if all_accept_qns else []
quality_map = {
item['qn']: item['desc']
for item in vdnams
}
quality_names = [f"{quality_map.get(qn)}${ids[0]}@@{ids[1]}@@{qn}" for qn in max_accept_qn]
vod['vod_play_url'] = "#".join(quality_names)
# 获取播放地址信息
play_res = self.fetch(
f'{self.hosts["bili"][0]}/room/v1/Room/playUrl?cid={room_id}&qn=10000&platform=web',
headers={
**self.headers[0],
'Referer': 'https://live.bilibili.com/',
'Origin': 'https://live.bilibili.com'
}
).json()
if play_res.get('code') != 0:
return self.handle_exception(Exception("获取播放地址失败"))
play_data = play_res['data']
accept_quality = play_data.get('accept_quality', ['10000', '400', '250', '150'])
quality_desc = {item['qn']: item['desc'] for item in play_data.get('quality_description', [])}
# 构建清晰度列表
qualities = []
for qn in sorted([int(q) for q in accept_quality], reverse=True):
desc = quality_desc.get(qn, f'清晰度{qn}')
qualities.append(f"{desc}$bili@@{room_id}@@{qn}")
vod['vod_play_from'] = 'B站直播'
vod['vod_play_url'] = '#'.join(qualities)
return vod
except Exception as e:
print(f"B站详情错误: {e}")
return self.handle_exception(e)
def huyaDetail(self, ids):
"""
虎牙播放详情 - 参考最新三合一.js重构
支持多线路多清晰度选择
核心算法:通过房间信息API获取uid、streamName和rateArray,为每个清晰度生成签名URL
清晰度说明:
- 蓝光8M/6M/4M/10M = 8000/6000/4000/10000 kbps = 1080P+
- 蓝光 = 3000 kbps = 1080P
- 超清 = 2000 kbps = 1080P (官方标准)
- 高清 = 1200 kbps = 720P
- 标清/流畅 = 500-800 kbps = 480P/540P
"""
try:
vdata = self.fetch(f'{self.hosts[ids[0]][1]}/cache.php?m=Live&do=profileRoom&roomid={ids[1]}',
headers=self.headers[0]).json()
v = vdata['data']['liveData']
room_id = ids[1]
# 1. 获取房间信息
api_url = f'{self.hosts[ids[0]][1]}/cache.php?m=Live&do=profileRoom&roomid={room_id}'
res = self.fetch(api_url, headers=self.headers[0])
if res.status_code != 200:
return self.handle_exception(Exception(f"API请求失败: {res.status_code}"))
data = res.json()
if not data or not data.get('data'):
return self.handle_exception(Exception("房间数据为空"))
room_data = data['data']
# 2. 提取关键信息
uid = room_data.get('profileInfo', {}).get('uid')
stream_info = room_data.get('stream', {})
live_data = room_data.get('liveData', {})
if not uid:
return self.handle_exception(Exception("缺少uid"))
# 3. 获取streamName和码率信息
base_stream_list = stream_info.get('baseSteamInfoList', [])
if not base_stream_list:
return self.handle_exception(Exception("无直播流信息"))
# 获取第一个CDN的streamName作为基准
base_stream = base_stream_list[0]
stream_name = base_stream.get('sStreamName')
if not stream_name:
return self.handle_exception(Exception("无法获取streamName"))
# 4. 构建VOD对象
vod = self.buildvod(
vod_name=v.get('introduction'),
type_name=v.get('gameFullName'),
vod_director=v.get('nick'),
vod_remarks=v.get('contentIntro'),
vod_name=live_data.get('introduction', '虎牙直播'),
type_name=live_data.get('gameFullName', ''),
vod_director=live_data.get('nick', ''),
vod_remarks=live_data.get('contentIntro', ''),
)
data = dict(reversed(list(vdata['data']['stream'].items())))
names = []
plist = []
for stream_type, stream_data in data.items():
if isinstance(stream_data, dict) and 'multiLine' in stream_data and 'rateArray' in stream_data:
names.append(f"线路{len(names) + 1}")
qualities = sorted(
stream_data['rateArray'],
key=lambda x: (x['iBitRate'], x['sDisplayName']),
reverse=True
# 5. 获取所有CDN线路
cdn_list = []
for stream in base_stream_list:
cdn_type = stream.get('sCdnType', 'AL')
flv_url = stream.get('sFlvUrl', '')
hls_url = stream.get('sHlsUrl', '')
stream_name_cdn = stream.get('sStreamName', stream_name)
if flv_url:
cdn_list.append({
'cdn': cdn_type,
'flv_base': flv_url,
'hls_base': hls_url,
'stream_name': stream_name_cdn,
'priority': stream.get('iWebPriorityRate', 0)
})
# 按优先级排序
cdn_list.sort(key=lambda x: x['priority'], reverse=True)
# 6. 获取清晰度列表 (rateArray)
rate_array = stream_info.get('rateArray', [])
# 如果没有rateArray,尝试从vMultiStreamInfo获取
if not rate_array and 'vMultiStreamInfo' in room_data:
rate_array = room_data['vMultiStreamInfo']
# 如果仍然没有,使用默认清晰度(按虎牙官方标准)
if not rate_array:
rate_array = [
{'sDisplayName': '蓝光4M', 'iBitRate': 4000},
{'sDisplayName': '蓝光', 'iBitRate': 3000},
{'sDisplayName': '超清', 'iBitRate': 2000}, # 2000kbps = 1080P
{'sDisplayName': '高清', 'iBitRate': 1200}, # 1200kbps = 720P
{'sDisplayName': '流畅', 'iBitRate': 500}
]
# 过滤和排序清晰度
# 虎牙的rateArray中,iBitRate就是码率值,sDisplayName是显示名称
# 需要确保:超清=2000kbps(1080P),高清=1200kbps(720P)
filtered_rates = []
seen_bitrates = set()
for rate in rate_array:
bit_rate = rate.get('iBitRate', 0)
name = rate.get('sDisplayName', '')
# 跳过重复的码率
if bit_rate in seen_bitrates:
continue
# 修正清晰度名称,确保符合虎牙标准
# 2000kbps应该是超清(1080P),不是高清
if bit_rate == 2000 and ('高清' in name or '720' in name):
name = '超清' # 强制修正为超清
elif bit_rate == 1200 and ('标清' in name or '480' in name):
name = '高清' # 1200kbps对应高清
elif bit_rate == 2000 and name == '原画':
name = '超清' # 修正原画为超清
seen_bitrates.add(bit_rate)
filtered_rates.append({
'sDisplayName': name,
'iBitRate': bit_rate
})
# 按码率从高到低排序
sorted_rates = sorted(filtered_rates, key=lambda x: x['iBitRate'], reverse=True)
# 7. 为每个CDN生成各清晰度的播放URL
play_lines = []
line_names = []
for cdn_idx, cdn in enumerate(cdn_list[:3]): # 最多取3个CDN
cdn_name = cdn['cdn']
line_names.append(f"线路{cdn_idx + 1}({cdn_name})")
qualities = []
for rate in sorted_rates:
quality_name = rate['sDisplayName']
bit_rate = rate['iBitRate']
# 生成该清晰度的URL
quality_url = self._generate_huya_play_url(
cdn, uid, stream_name, bit_rate
)
cdn_urls = []
for cdn in stream_data['multiLine']:
quality_urls = []
for quality in qualities:
quality_name = quality['sDisplayName']
bit_rate = quality['iBitRate']
base_url = cdn['url']
if bit_rate > 0:
if '.m3u8' in base_url:
new_url = base_url.replace(
'ratio=2000',
f'ratio={bit_rate}'
)
else:
new_url = base_url.replace(
'imgplus.flv',
f'imgplus_{bit_rate}.flv'
)
else:
new_url = base_url
quality_urls.extend([quality_name, new_url])
encoded_urls = self.e64(json.dumps(quality_urls))
cdn_urls.append(f"{cdn['cdnType']}${ids[0]}@@{encoded_urls}")
if cdn_urls:
plist.append('#'.join(cdn_urls))
vod['vod_play_from'] = "$$$".join(names)
vod['vod_play_url'] = "$$$".join(plist)
qualities.extend([quality_name, quality_url])
# 编码该线路的所有清晰度
encoded_qualities = self.e64(json.dumps(qualities))
play_lines.append(f"{live_data.get('introduction', '直播')}${ids[0]}@@{encoded_qualities}")
# 8. 构建播放数据
vod['vod_play_from'] = "$$$".join(line_names)
vod['vod_play_url'] = "$$$".join(play_lines)
return vod
except Exception as e:
return self.handle_exception(e)
def douyinDetail(self, ids):
url = f'{self.hosts[ids[0]]}/webcast/room/web/enter/?aid=6383&app_name=douyin_web&live_id=1&device_platform=web&enter_from=web_live&web_rid={ids[1]}&room_id_str=&enter_source=&Room-Enter-User-Login-Ab=0&is_need_double_stream=false&cookie_enabled=true&screen_width=1980&screen_height=1080&browser_language=zh-CN&browser_platform=Win32&browser_name=Edge&browser_version=125.0.0.0'
data = self.fetch(url, headers=self.dyheaders).json()
try:
vdata = data['data']['data'][0]
vod = self.buildvod(
vod_name=vdata['title'],
vod_remarks=vdata['user_count_str'],
)
resolution_data = vdata['stream_url']['live_core_sdk_data']['pull_data']['options']['qualities']
stream_json = vdata['stream_url']['live_core_sdk_data']['pull_data']['stream_data']
stream_json = json.loads(stream_json)
available_types = []
if any(sdk_key in stream_json['data'] and 'main' in stream_json['data'][sdk_key] for sdk_key in
stream_json['data']):
available_types.append('main')
if any(sdk_key in stream_json['data'] and 'backup' in stream_json['data'][sdk_key] for sdk_key in
stream_json['data']):
available_types.append('backup')
plist = []
for line_type in available_types:
format_arrays = {'flv': [], 'hls': [], 'lls': []}
qualities = sorted(resolution_data, key=lambda x: x['level'], reverse=True)
for quality in qualities:
sdk_key = quality['sdk_key']
if sdk_key in stream_json['data'] and line_type in stream_json['data'][sdk_key]:
stream_info = stream_json['data'][sdk_key][line_type]
if stream_info.get('flv'):
format_arrays['flv'].extend([quality['name'], stream_info['flv']])
if stream_info.get('hls'):
format_arrays['hls'].extend([quality['name'], stream_info['hls']])
if stream_info.get('lls'):
format_arrays['lls'].extend([quality['name'], stream_info['lls']])
format_urls = []
for format_name, url_array in format_arrays.items():
if url_array:
encoded_urls = self.e64(json.dumps(url_array))
format_urls.append(f"{format_name}${ids[0]}@@{encoded_urls}")
if format_urls:
plist.append('#'.join(format_urls))
names = ['线路1', '线路2'][:len(plist)]
vod['vod_play_from'] = "$$$".join(names)
vod['vod_play_url'] = "$$$".join(plist)
return vod
except Exception as e:
return self.handle_exception(e)
def _generate_huya_play_url(self, cdn, uid, stream_name, bit_rate):
"""
生成虎牙播放URL,参考最新三合一.js算法
关键:ratio参数必须正确设置为iBitRate值(如2000、4000等)
"""
# 基础URL构建
flv_base = cdn['flv_base']
stream = cdn['stream_name']
# 生成时间戳和签名参数
timestamp = int(time.time())
seqid = f"{uid}{timestamp}"
ss = hashlib.md5(f"{seqid}|huya_adr|102".encode()).hexdigest()
ws_time = hex(timestamp + 21600)[2:] # 16进制,有效期6小时
# 计算wsSecret
ws_secret = hashlib.md5(
f"DWq8BcJ3h6DJt6TY_{uid}_{stream_name}_{ss}_{ws_time}".encode()
).hexdigest()
# 构建基础URL
base_url = f"{flv_base}/{stream}.flv"
# 关键修复:ratio参数直接使用iBitRate值
# 超清=2000,高清=1200,蓝光=3000/4000/6000/8000
if bit_rate > 0:
ratio_param = f"ratio={bit_rate}"
else:
# 原画/0码率时,使用默认2000或从URL推断
ratio_param = "ratio=2000"
# 构建完整URL
play_url = (
f"{base_url}?{ratio_param}&wsSecret={ws_secret}&wsTime={ws_time}"
f"&ctype=huya_adr&seqid={seqid}&uid={uid}"
f"&fs=bgct&ver=1&t=102"
)
return play_url
def douyuDetail(self, ids):
headers = self.gethr(0, zr=f'{self.hosts[ids[0]]}/{ids[1]}')
"""
斗鱼播放详情 - 参考最新三合一.js重构
核心算法:设备ID生成 -> 获取加密密钥 -> 计算签名 -> 获取播放地址
修复:切换分辨率只能播放1秒的问题
方案:存储房间号和码率信息,在playerContent中实时获取对应码率的URL
"""
try:
data = self.fetch(f'{self.hosts[ids[0]]}/betard/{ids[1]}', headers=headers).json()
vname = data['room']['room_name']
channel = ids[1]
headers = self.gethr(0, zr=f'{self.hosts[ids[0]]}/{channel}')
# 1. 初始化会话和设备ID (参考JS中的initialize和setupDeviceId)
session = {}
# 请求首页获取Cookie
try:
home_res = self.fetch(f'{self.hosts[ids[0]]}/{channel}', headers=headers)
if home_res.headers.get('Set-Cookie'):
cookie_str = home_res.headers.get('Set-Cookie')
# 解析dy_did
did_match = re.search(r'dy_did=([a-f0-9]{32})', cookie_str)
if did_match:
device_id = did_match.group(1)
else:
device_id = self._generate_random_hex(32)
else:
device_id = self._generate_random_hex(32)
except:
device_id = self._generate_random_hex(32)
session['dy_did'] = device_id
session['mantine-color-scheme-value'] = 'light'
# 2. 获取房间基本信息
betard_res = self.fetch(f'{self.hosts[ids[0]]}/betard/{channel}', headers=headers).json()
if not betard_res or not betard_res.get('room'):
return self.handle_exception(Exception("获取房间信息失败"))
room_info = betard_res['room']
vname = room_info.get('room_name', '斗鱼直播')
vod = self.buildvod(
vod_name=vname,
vod_remarks=data['room'].get('second_lvl_name'),
vod_director=data['room'].get('nickname'),
vod_remarks=room_info.get('second_lvl_name', ''),
vod_director=room_info.get('nickname', ''),
)
vdata = self.fetch(f'{self.hosts[ids[0]]}/swf_api/homeH5Enc?rids={ids[1]}', headers=headers).json()
json_body = vdata['data']
json_body = {"html": self.douyu_text(json_body[f'room{ids[1]}']), "rid": ids[1]}
sign = self.post('http://alive.nsapps.cn/api/AllLive/DouyuSign', json=json_body, headers=self.headers[1]).json()['data']
body = f'{sign}&cdn=&rate=-1&ver=Douyu_223061205&iar=1&ive=1&hevc=0&fa=0'
body=self.params_to_json(body)
nubdata = self.post(f'{self.hosts[ids[0]]}/lapi/live/getH5Play/{ids[1]}', data=body, headers=headers).json()
plist = []
names = []
for i,x in enumerate(nubdata['data']['cdnsWithName']):
names.append(f'线路{i+1}')
d = {'sign': sign, 'cdn': x['cdn'], 'id': ids[1]}
plist.append(
f'{vname}${ids[0]}@@{self.e64(json.dumps(d))}@@{self.e64(json.dumps(nubdata["data"]["multirates"]))}')
vod['vod_play_from'] = "$$$".join(names)
vod['vod_play_url'] = "$$$".join(plist)
# 3. 获取安全密钥 (参考JS中的getSecurityKey)
sec_url = f"{self.hosts[ids[0]]}/wgapi/livenc/liveweb/websec/getEncryption?did={device_id}"
sec_res = self.fetch(sec_url, headers=headers).json()
if not sec_res or sec_res.get('error') != 0:
return self.handle_exception(Exception("获取加密密钥失败"))
security_data = sec_res['data']
secret_key = security_data.get('key')
random_str = security_data.get('rand_str')
enc_time = security_data.get('enc_time', 1)
enc_data = security_data.get('enc_data')
# 4. 计算签名 (参考JS中的computeSignature)
current_time = int(time.time())
# 迭代计算MD5
current = random_str
for _ in range(enc_time):
current = hashlib.md5(f"{current}{secret_key}".encode()).hexdigest()
signature = hashlib.md5(f"{current}{secret_key}{channel}{current_time}".encode()).hexdigest()
# 5. 请求播放地址 (参考JS中的requestStreamData)
play_payload = {
'enc_data': enc_data,
'tt': str(current_time),
'did': device_id,
'auth': signature,
'cdn': '',
'rate': '',
'hevc': '0',
'fa': '0',
'ive': '0'
}
play_api = f"{self.hosts[ids[0]]}/lapi/live/getH5PlayV1/{channel}"
# 构建请求头带Cookie
play_headers = headers.copy()
cookie_str = '; '.join([f"{k}={v}" for k, v in session.items()])
play_headers['Cookie'] = cookie_str
play_headers['Content-Type'] = 'application/x-www-form-urlencoded'
play_res = requests.post(play_api, data=play_payload, headers=play_headers, timeout=10).json()
if not play_res or play_res.get('error') != 0:
# 尝试旧版API
play_res = self._try_legacy_douyu_api(channel, device_id, signature, current_time, play_headers)
if not play_res:
return self.handle_exception(Exception("获取播放地址失败"))
stream_info = play_res.get('data', {})
# 6. 检查并更新设备ID (参考JS中的checkAndUpdateDeviceId)
rtmp_live = stream_info.get('rtmp_live', '')
if rtmp_live:
did_match = re.search(r'did=([a-f0-9]{32})', rtmp_live)
if did_match and did_match.group(1) != device_id:
device_id = did_match.group(1)
session['dy_did'] = device_id
# 重新请求
play_payload['did'] = device_id
play_res = requests.post(play_api, data=play_payload, headers=play_headers, timeout=10).json()
if play_res and play_res.get('error') == 0:
stream_info = play_res.get('data', {})
# 7. 提取播放URL和多码率信息
stream_url = None
if stream_info.get('rtmp_url') and stream_info.get('rtmp_live'):
stream_url = f"{stream_info['rtmp_url']}/{stream_info['rtmp_live']}"
elif stream_info.get('hls_url'):
stream_url = stream_info['hls_url']
if not stream_url:
return self.handle_exception(Exception("无法获取播放地址"))
# 8. 构建多码率选项
multirates = stream_info.get('multirates', [])
# 关键修复:存储房间号和码率信息,而不是直接存储URL
# 这样在切换清晰度时可以重新获取对应码率的签名URL
qualities = []
if multirates:
# 按码率排序
sorted_rates = sorted(multirates, key=lambda x: x.get('bit', 0), reverse=True)
for rate in sorted_rates:
bit_rate = rate.get('rate', -1)
name = rate.get('name', f"{bit_rate}P")
# 存储格式:码率值,用于playerContent中重新获取URL
# 使用特殊标记#来区分这是码率值而不是URL
qualities.extend([name, f"#{bit_rate}"])
else:
# 只有原画
qualities = ['原画', '#-1']
# 同时存储房间号和设备信息,用于重新获取URL
# 格式:房间号|设备ID|签名信息(base64编码)
session_info = {
'channel': channel,
'device_id': device_id,
'secret_key': secret_key,
'random_str': random_str,
'enc_time': enc_time,
'enc_data': enc_data
}
encoded_session = self.e64(json.dumps(session_info))
# 9. 构建播放数据
# vod_play_url格式:房间名$平台@@base64(清晰度列表)@@base64(会话信息)
encoded_qualities = self.e64(json.dumps(qualities))
vod['vod_play_from'] = '斗鱼直播'
vod['vod_play_url'] = f"{vname}${ids[0]}@@{encoded_qualities}@@{encoded_session}"
return vod
except Exception as e:
return self.handle_exception(e)
def _generate_random_hex(self, length):
"""生成随机十六进制字符串"""
hex_chars = '0123456789abcdef'
return ''.join(random.choice(hex_chars) for _ in range(length))
def douyu_text(self, text):
function_positions = [m.start() for m in re.finditer('function', text)]
total_functions = len(function_positions)
if total_functions % 2 == 0:
target_index = total_functions // 2 + 1
else:
target_index = (total_functions - 1) // 2 + 1
if total_functions >= target_index:
cut_position = function_positions[target_index - 1]
ctext = text[4:cut_position]
return re.sub(r'eval\(strc\)\([\w\d,]+\)', 'strc', ctext)
return text
def _try_legacy_douyu_api(self, channel, device_id, signature, timestamp, headers):
"""尝试使用旧版API获取播放地址"""
try:
legacy_payload = {
'did': device_id,
'tt': str(timestamp),
'sign': signature,
'cdn': '',
'rate': '-1',
'ver': 'Douyu_223061205',
'iar': '1',
'ive': '1',
'hevc': '0',
'fa': '0'
}
legacy_api = f"https://www.douyu.com/lapi/live/getH5Play/{channel}"
res = requests.post(legacy_api, data=legacy_payload, headers=headers, timeout=10)
return res.json() if res.status_code == 200 else None
except:
return None
def _get_douyu_play_url(self, channel, device_id, secret_key, random_str, enc_time, enc_data, rate):
"""
获取斗鱼指定码率的播放URL(带签名)
用于切换清晰度时重新获取URL
"""
try:
current_time = int(time.time())
# 重新计算签名
current = random_str
for _ in range(enc_time):
current = hashlib.md5(f"{current}{secret_key}".encode()).hexdigest()
signature = hashlib.md5(f"{current}{secret_key}{channel}{current_time}".encode()).hexdigest()
# 构建请求
play_payload = {
'enc_data': enc_data,
'tt': str(current_time),
'did': device_id,
'auth': signature,
'cdn': '',
'rate': str(rate) if rate > 0 else '',
'hevc': '0',
'fa': '0',
'ive': '0'
}
play_api = f"https://www.douyu.com/lapi/live/getH5PlayV1/{channel}"
headers = {
'User-Agent': self.headers[0]['User-Agent'],
'Referer': f'https://www.douyu.com/{channel}',
'Origin': 'https://www.douyu.com',
'Cookie': f'dy_did={device_id}; mantine-color-scheme-value=light',
'Content-Type': 'application/x-www-form-urlencoded'
}
play_res = requests.post(play_api, data=play_payload, headers=headers, timeout=10).json()
if not play_res or play_res.get('error') != 0:
# 尝试旧版API
return self._get_douyu_play_url_legacy(channel, device_id, signature, current_time, rate)
stream_info = play_res.get('data', {})
# 检查设备ID是否匹配
if stream_info.get('rtmp_live'):
did_match = re.search(r'did=([a-f0-9]{32})', stream_info['rtmp_live'])
if did_match and did_match.group(1) != device_id:
# 设备ID不匹配,使用新设备ID重新获取
return self._get_douyu_play_url(channel, did_match.group(1), secret_key, random_str, enc_time, enc_data, rate)
if stream_info.get('rtmp_url') and stream_info.get('rtmp_live'):
return f"{stream_info['rtmp_url']}/{stream_info['rtmp_live']}"
elif stream_info.get('hls_url'):
return stream_info['hls_url']
return None
except Exception as e:
print(f"获取斗鱼播放URL失败: {e}")
return None
def _get_douyu_play_url_legacy(self, channel, device_id, signature, timestamp, rate):
"""使用旧版API获取斗鱼播放URL"""
try:
legacy_payload = {
'did': device_id,
'tt': str(timestamp),
'sign': signature,
'cdn': '',
'rate': str(rate) if rate > 0 else '-1',
'ver': 'Douyu_223061205',
'iar': '1',
'ive': '1',
'hevc': '0',
'fa': '0'
}
legacy_api = f"https://www.douyu.com/lapi/live/getH5Play/{channel}"
headers = {
'User-Agent': self.headers[0]['User-Agent'],
'Referer': f'https://www.douyu.com/{channel}',
'Cookie': f'dy_did={device_id}',
'Content-Type': 'application/x-www-form-urlencoded'
}
res = requests.post(legacy_api, data=legacy_payload, headers=headers, timeout=10)
if res.status_code == 200:
data = res.json()
if data.get('error') == 0:
stream_info = data.get('data', {})
if stream_info.get('rtmp_url') and stream_info.get('rtmp_live'):
return f"{stream_info['rtmp_url']}/{stream_info['rtmp_live']}"
return None
except:
return None
def searchContent(self, key, quick, pg="1"):
pass
@@ -613,12 +1060,12 @@ class Spider(Spider):
try:
ids = id.split('@@')
p = 1
if ids[0] in ['wangyi', 'douyin','huya']:
if ids[0] in ['wangyi']:
p, url = 0, json.loads(self.d64(ids[1]))
elif ids[0] == 'bili':
p, url = self.biliplay(ids)
elif ids[0] == 'huya':
p, url = 0, json.loads(self.d64(ids[1]))
p, url = self.huyaplay(ids)
elif ids[0] == 'douyu':
p, url = self.douyuplay(ids)
return {'parse': p, 'url': url, 'header': self.playheaders[ids[0]]}
@@ -626,69 +1073,116 @@ class Spider(Spider):
return {'parse': 1, 'url': self.excepturl, 'header': self.headers[0]}
def biliplay(self, ids):
"""
B站播放解析 - 使用playUrl接口获取指定清晰度直播流
ids: [平台, 房间号, 清晰度qn]
支持多线路返回
"""
try:
data = self.fetch(
f'{self.hosts[ids[0]][0]}/xlive/web-room/v2/index/getRoomPlayInfo?room_id={ids[1]}&protocol=0,1&format=0,2&codec=0&platform=web&qn={ids[2]}',
headers=self.gethr(0, ids[0])).json()
room_id = ids[1]
qn = ids[2] if len(ids) > 2 else '10000'
# 使用playUrl接口获取直播流
play_url = f'{self.hosts["bili"][0]}/room/v1/Room/playUrl?cid={room_id}&qn={qn}&platform=web'
data = self.fetch(play_url, headers={
**self.headers[0],
'Referer': 'https://live.bilibili.com/',
'Origin': 'https://live.bilibili.com'
}).json()
if data.get('code') != 0:
return 1, self.excepturl
play_data = data['data']
durl_list = play_data.get('durl', [])
if not durl_list:
return 1, self.excepturl
# 构建多线路结果 [线路1, URL1, 线路2, URL2, ...]
urls = []
line_index = 1
for stream in data['data']['playurl_info']['playurl']['stream']:
for format_item in stream['format']:
for codec in format_item['codec']:
for url_info in codec['url_info']:
full_url = f"{url_info['host']}/{codec['base_url'].lstrip('/')}{url_info['extra']}"
urls.extend([f"线路{line_index}", full_url])
line_index += 1
for idx, item in enumerate(durl_list, 1):
url = item.get('url')
if url:
urls.extend([f'线路{idx}', url])
# 如果只有一条线路,直接返回URL
if len(urls) == 2:
return 0, urls[1] # 直接返回URL字符串
return 0, urls
except Exception as e:
print(f"B站播放错误: {e}")
return 1, self.excepturl
def huyaplay(self, ids):
"""
虎牙播放解析 - 返回所有清晰度选项供用户选择
ids[1] 格式: base64编码的 [清晰度名称1, URL1, 清晰度名称2, URL2, ...]
"""
try:
# ids[1] 是编码后的播放地址列表 [名称1, URL1, 名称2, URL2, ...]
decoded = json.loads(self.d64(ids[1]))
# decoded 是一个列表,奇数索引是名称,偶数索引是URL
return 0, decoded
except Exception as e:
print(f"虎牙播放解析错误: {e}")
return 1, self.excepturl
def douyuplay(self, ids):
"""
斗鱼播放解析 - 实时获取对应码率的播放URL
ids格式: [平台, base64(清晰度列表), base64(会话信息)]
清晰度列表: [名称1, #码率1, 名称2, #码率2, ...]
#表示这是码率值,需要重新获取URL
"""
try:
sdata = json.loads(self.d64(ids[1]))
headers = self.gethr(0, zr=f'{self.hosts[ids[0]]}/{sdata["id"]}')
ldata = json.loads(self.d64(ids[2]))
result_obj = {}
with ThreadPoolExecutor(max_workers=len(ldata)) as executor:
futures = [
executor.submit(
self.douyufp,
sdata,
quality,
headers,
self.hosts[ids[0]],
result_obj
) for quality in ldata
]
for future in futures:
future.result()
if len(ids) < 3:
# 兼容旧格式
decoded = json.loads(self.d64(ids[1]))
return 0, decoded
# 解析清晰度列表和会话信息
qualities = json.loads(self.d64(ids[1]))
session_info = json.loads(self.d64(ids[2]))
channel = session_info['channel']
device_id = session_info['device_id']
secret_key = session_info['secret_key']
random_str = session_info['random_str']
enc_time = session_info['enc_time']
enc_data = session_info['enc_data']
# 为每个清晰度实时获取播放URL
result = []
for bit in sorted(result_obj.keys(), reverse=True):
result.extend(result_obj[bit])
if result:
return 0, result
return 1, self.excepturl
for i in range(0, len(qualities), 2):
name = qualities[i]
rate_marker = qualities[i + 1]
# 解析码率值(去掉#前缀)
if rate_marker.startswith('#'):
rate = int(rate_marker[1:])
else:
rate = -1
# 实时获取对应码率的URL
play_url = self._get_douyu_play_url(
channel, device_id, secret_key, random_str,
enc_time, enc_data, rate
)
if play_url:
result.extend([name, play_url])
if not result:
return 1, self.excepturl
return 0, result
except Exception as e:
print(f"斗鱼播放解析错误: {e}")
return 1, self.excepturl
def douyufp(self, sdata, quality, headers, host, result_obj):
try:
body = f'{sdata["sign"]}&cdn={sdata["cdn"]}&rate={quality["rate"]}'
body=self.params_to_json(body)
data = self.post(f'{host}/lapi/live/getH5Play/{sdata["id"]}',
data=body, headers=headers).json()
if data.get('data'):
play_url = data['data']['rtmp_url'] + '/' + data['data']['rtmp_live']
bit = quality.get('bit', 0)
if bit not in result_obj:
result_obj[bit] = []
result_obj[bit].extend([quality['name'], play_url])
except Exception as e:
print(f"Error fetching {quality['name']}: {str(e)}")
def localProxy(self, param):
pass
@@ -763,5 +1257,4 @@ class Spider(Spider):
def handle_exception(self, e):
print(f"报错: {str(e)}")
return {'vod_play_from': '哎呀翻车啦', 'vod_play_url': f'翻车啦${self.excepturl}'}
return {'vod_play_from': '哎呀翻车啦', 'vod_play_url': f'翻车啦${self.excepturl}'}
Binary file not shown.