Sync all projects
This commit is contained in:
@@ -0,0 +1,493 @@
|
||||
{
|
||||
"spider": "./spider.jar",
|
||||
"wallpaper": "https://www.wexwp.cc/bizhi.php",
|
||||
"logo": "https://wkphoto.bj.bcebos.com/bba1cd11728b47106798119ad3cec3fdfc032335.jpg",
|
||||
"lives": [
|
||||
{
|
||||
"name": "📺 平台直播",
|
||||
"type": 0,
|
||||
"ua": "okhttp/3.15"
|
||||
}
|
||||
],
|
||||
"sites": [
|
||||
{
|
||||
"key": "豆豆",
|
||||
"name": "🎬豆瓣┃精选 仅供测试 端午快乐 备用:https://zzzy.shop/tv/",
|
||||
"type": 3,
|
||||
"quickSearch": 0,
|
||||
"filterable": 1,
|
||||
"changeable": 0,
|
||||
"api": "csp_Douban",
|
||||
"searchable": 0
|
||||
},
|
||||
{
|
||||
"key": "config",
|
||||
"name": "⚙️Cookie┃配置 修了很多 偷窃贩卖后果自负",
|
||||
"type": 3,
|
||||
"api": "csp_Config",
|
||||
"searchable": 0
|
||||
},
|
||||
{
|
||||
"key": "csp_Netfixtv",
|
||||
"name": "🚀🚀臻臻┃网盘4K",
|
||||
"type": 3,
|
||||
"changeable": "0",
|
||||
"quickSearch": 1,
|
||||
"timeout": 15,
|
||||
"api": "csp_Duopan",
|
||||
"filterable": 1,
|
||||
"ext": "Yu2Y3Q8tqDTqZ+GCqfQZz8i/vsP/tl9O+/0ZjpgnBg/PMzRiiQD9UYIf+3JzSYfEA6i1Q5r/3Jfwr7fMDI7U1JLPJcKD28X0a35jjXkBu698XPhaPr6ar7Vp3lQagSF+hIAvVL960RZSmiOOP6YK2w7JUucHzjaUSXH5lSMsdYo8Y1uW9RbJbwW9hG5ZGHehv5wL6oCqNXlsK4wXGISArmjuKZJ6/klD911RhkbFFBK3D3JfSvhJP8XultFMdkz/LXjactGy8H244BePv+8GDk8Ane8xTy9a2k56SltKCaMfOJVc2FlkbPmvh/AdBEAfayuUAQhoLz+04Lll9FhQnbTxevNINFB7xIenO5JrJ+x8MbGpHdUta7XEoSKTtwflUCCUPzJj/RLP1M98+e8+D/6ez1JhJyW2TS1x0UkCYYnPR2RAU7+JI4bzJozX2ZiZ"
|
||||
},
|
||||
{
|
||||
"key": "csp_Netfixtv2",
|
||||
"name": "🚀🛸指南┃网盘4K",
|
||||
"type": 3,
|
||||
"changeable": "0",
|
||||
"quickSearch": 1,
|
||||
"timeout": 15,
|
||||
"api": "csp_Duopan",
|
||||
"filterable": 1,
|
||||
"ext": "N/01JeZBCBEQ0wOXNuAI/o0m0ISTSGY4YIqieW4PO7Bhg/O8J6kFcgo5lFnnTV5oGFu1hcPVkBPZy5wZc9Hoq4PGebzlCMd7ze3mrHsHYuGe8y0dYEU6j9DgBXZrNqamzVl1Td8NV7nj1NFLyU8I4ISTxhQBO+Ue7GT3EeBxt157MxYWRwInJHZlvcH5uxTu+QfY1kGQ23EGHuk4JY/HV/U8n34h+DS5IteV9vf4rcv7LTTwrmpcr6f1iQmzix/5lQh+HrLZqhCBnBHGhNonz6+ZtkunHAlK86i1oWUEvGkUmKlrJJzSXPw/NBFSDBVOB0YBBDVfeDYHlNnTzJti0KyRQbnnkvzz5pXJcAwfNyPSjxxdRWdiaeAAdXZ3jGn5LNm3tYiPrL4qOYRuzido+CRkAf8bv1x9pr7RSd+P00Sj6PeZdNaL8CaQ2kdf6JUsEOhhQB7sWu8XgEUeUq6SC5izJabxXtHL7l1Bcm2zD8WTXfE+/+9PRwTJGInS7f+MktgujF8y50EriqMA0KoMbQ=="
|
||||
},
|
||||
{
|
||||
"key": "csp_Wogg",
|
||||
"name": "🧸玩偶┃网盘4K",
|
||||
"type": 3,
|
||||
"api": "csp_Wogg",
|
||||
"timeout": 15,
|
||||
"changeable": "0",
|
||||
"quickSearch": 1,
|
||||
"filterable": 1,
|
||||
"ext": "mAdMvijsdpLz+xMtYQCW1nJ+mpefKKrleWG+USa3HARBc3zWLTb1cc321bKDLxXrYkZjUVc7y2TSDRKbupeW9IHjvGE01hFbo3wCHx0+kNkenbdKO4KZo3297jK0vkZHsA2lXS7SOb+WArfs2EGBFIJ0eR/LdfTH34oVjsIyzRipe6OWV6YTQrqrW6v/7VXV9fj759LpUM8HHXjVfOEXp31Psa3nCHsEzw5P3Bn8tTAxiQc8NemijjeRois1SRwg"
|
||||
},
|
||||
{
|
||||
"key": "csp_Duopan",
|
||||
"name": "☁️蜡笔┃网盘4K",
|
||||
"type": 3,
|
||||
"quickSearch": 1,
|
||||
"changeable": "0",
|
||||
"timeout": 15,
|
||||
"api": "csp_Duopan",
|
||||
"filterable": 1,
|
||||
"ext": "PfoQ21FsXzLNOjwZ8RymNbY02A9VYBmEHmajoh4nXXACJNPrFj69vwxLj4d68ngPJt1wGvT+PkUSe7Ve1o+8RfpcIgYf7LjjHi4sx2hg57mhdmuP1DykCFCSlHwod+owmc53QmJuMs2SFn4Xeui077ckz2HYEja6zFdw5FDx1ko6D6lkQzK2FDRT7tMYjOXswOcpONJ6hA87KN+UJ6aiBHrzD4tENYc0UvImSwakK5A9rN7at/RviVt+nu5o8IBC19uR4eCpBDpnpoY2/PpOWQ=="
|
||||
},
|
||||
{
|
||||
"key": "天天",
|
||||
"name": "🚀秒播┃1080P",
|
||||
"type": 3,
|
||||
"quickSearch": 1,
|
||||
"searchable": 1,
|
||||
"api": "csp_AppRJ",
|
||||
"timeout": 12,
|
||||
"ext": "vxw35/hHSj07Q+maxQzOVMq1rjRCOTXpUCx8iKu5jIg="
|
||||
},
|
||||
{
|
||||
"key": "csp_Wwys",
|
||||
"name": "🌾农民┃1080P",
|
||||
"type": 3,
|
||||
"api": "csp_Wwys",
|
||||
"timeout": 12,
|
||||
"ext": "https://vip.wwgz.cn:5200"
|
||||
},
|
||||
{
|
||||
"key": "csp_Music",
|
||||
"name": "🎵音乐┃在线",
|
||||
"type": 3,
|
||||
"api": "csp_Music",
|
||||
"quickSearch": 0,
|
||||
"timeout": 12,
|
||||
"searchable": 0,
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 1.333
|
||||
},
|
||||
"ext": ""
|
||||
},
|
||||
{
|
||||
"key": "88看球",
|
||||
"name": "🏀叭叭┃体育",
|
||||
"type": 3,
|
||||
"api": "csp_Kanqiu",
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 1.333
|
||||
},
|
||||
"searchable": 0,
|
||||
"quickSearch": 0,
|
||||
"filterable": 1,
|
||||
"timeout": 12,
|
||||
"order_num": 0,
|
||||
"changeable": 0
|
||||
},
|
||||
{
|
||||
"key": "瓜子",
|
||||
"name": "🏀瓜子┃体育",
|
||||
"type": 3,
|
||||
"api": "csp_GuaziTY",
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 1.333
|
||||
},
|
||||
"searchable": 0,
|
||||
"quickSearch": 0,
|
||||
"filterable": 1,
|
||||
"timeout": 12,
|
||||
"order_num": 0,
|
||||
"changeable": 0
|
||||
},
|
||||
{
|
||||
"key": "csp_Bili",
|
||||
"name": "📺哔哩┃哔哩",
|
||||
"type": 3,
|
||||
"api": "csp_Bili",
|
||||
"quickSearch": 0,
|
||||
"timeout": 12,
|
||||
"searchable": 1,
|
||||
"ext": {
|
||||
"json": "https://cik07-cos.7moor-fs2.com/im/4d2c3f00-7d4c-11e5-af15-41bf63ae4ea0/db3b02559ec04736/bili.json",
|
||||
"cookie": ""
|
||||
},
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 1.333
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "葫芦",
|
||||
"name": "🪽葫芦┃1080P",
|
||||
"type": 3,
|
||||
"api": "csp_AppGet",
|
||||
"ext": "https://mobile-1251126973.cos.ap-guangzhou.myqcloud.com/maccos_config.txt|8R33VQSxzmCaHpEX|V122|okhttp/3.10.0"
|
||||
},
|
||||
{
|
||||
"key": "新首发",
|
||||
"name": "👻标清┃1080P",
|
||||
"type": 3,
|
||||
"api": "csp_AppGet",
|
||||
"ext": "https://yun-1316442804.cos.ap-guangzhou.myqcloud.com/601.txt|FTgP4Gq8zPiqbt7M|V122|okhttp/3.10.0"
|
||||
},
|
||||
{
|
||||
"key": "四叶草",
|
||||
"name": "🍀幸运┃1080P",
|
||||
"type": 3,
|
||||
"api": "csp_AppGet",
|
||||
"ext": "https://yzysap.oss-cn-hangzhou.aliyuncs.com/sss.txt|wNCwbXzr0Bm6cS2C|V122|okhttp/3.10.0"
|
||||
},
|
||||
{
|
||||
"key": "爱营",
|
||||
"name": "💥爱影┃1080P",
|
||||
"type": 3,
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"api": "csp_AppGet",
|
||||
"ext": "https://aysappto.oss-cn-chengdu.aliyuncs.com/q23.txt|nzEqOgYk3QzHuEP8|V122|okhttp/3.10.0"
|
||||
},
|
||||
{
|
||||
"key": "3QQQ",
|
||||
"name": "🍅大鹅┃1080P",
|
||||
"type": 3,
|
||||
"timeout": 15,
|
||||
"api": "csp_App3Q",
|
||||
"ext": "https://asd123sx23xdacsx.top"
|
||||
},
|
||||
{
|
||||
"key": "山楂",
|
||||
"name": "🔴山楂┃1080P",
|
||||
"type": 3,
|
||||
"timeout": 15,
|
||||
"api": "./api/shanzha.py",
|
||||
"ext": ""
|
||||
},
|
||||
{
|
||||
"key": "csp_SaoHuo",
|
||||
"name": "🔥火火┃1080P",
|
||||
"type": 3,
|
||||
"api": "csp_SaoHuo"
|
||||
},
|
||||
{
|
||||
"key": "csp_Czsapp",
|
||||
"name": "🏭厂长┃影视",
|
||||
"type": 3,
|
||||
"api": "csp_Czsapp",
|
||||
"ext": "https://www.4kcz.com"
|
||||
},
|
||||
{
|
||||
"key": "麦田",
|
||||
"name": "🌾麦田┃1080P",
|
||||
"type": 3,
|
||||
"api": "csp_AppV6",
|
||||
"ext": "http://172.247.227.203:25321/mtys.php"
|
||||
},
|
||||
{
|
||||
"key": "听心99",
|
||||
"name": "🦉欣欣┃1080P",
|
||||
"type": 3,
|
||||
"api": "csp_App99",
|
||||
"ext": {
|
||||
"host": "https://api.12321app.com/api",
|
||||
"LoginPath": "/app/log",
|
||||
"version": "0b4328287a5d953e",
|
||||
"appkey": "a0a18659a9977a47e53442cd084b536c",
|
||||
"versionName": "2.8.1",
|
||||
"name": "听心视频",
|
||||
"package": "com.iksp.adsys.jjsp",
|
||||
"buildNumber": "2001",
|
||||
"buildSignature": "03DD38CE4C3D62D0F0DEFACC06768D14EB382C7BD77A05B2EBF4D66E154A0D47"
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "剧圈99",
|
||||
"name": "🫎剧圈丨1080P",
|
||||
"type": 3,
|
||||
"api": "csp_App99",
|
||||
"ext": {
|
||||
"host": "http://124.221.3.182:19987/app/bn",
|
||||
"appkey": "d1f0c269eab74d93821fffc9befdbbba",
|
||||
"versionName": "1.2.0",
|
||||
"name": "剧圈圈",
|
||||
"package": "com.qingtangxiaozhuan.xyz",
|
||||
"buildNumber": "2002",
|
||||
"buildSignature": "054FA8DDA4319C6B6A9B954CA5777541C993F00B1B0BD4394F7EDE48184C4594"
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "顾我99",
|
||||
"name": "🖼️顾我丨1080P",
|
||||
"type": 3,
|
||||
"api": "csp_App99",
|
||||
"ext": {
|
||||
"host": "http://117.50.200.113:19987/app/bn",
|
||||
"LoginPath": "/app/log",
|
||||
"appkey": "040f9b1bc5e942569b5c3e63943306ab",
|
||||
"versionName": "4.3.1",
|
||||
"name": "顾我追剧",
|
||||
"package": "com.guwozhuijux.app",
|
||||
"buildNumber": "2001",
|
||||
"buildSignature": "5AD4436C4730FFE26910C86278B80F3E661C317FFC3616F702D20A729262624A"
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "荐片",
|
||||
"name": "🧲荐片┃1080P",
|
||||
"quickSearch": 0,
|
||||
"changeable": "0",
|
||||
"searchable": 1,
|
||||
"timeout": 15,
|
||||
"type": 3,
|
||||
"api": "csp_Jianpian",
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 1.333
|
||||
},
|
||||
"ext": "https://api.ztcgi.com"
|
||||
},
|
||||
{
|
||||
"key": "Huya",
|
||||
"name": "🎮虎牙┃1080P",
|
||||
"type": 3,
|
||||
"jar": "./jars/Huya.jar",
|
||||
"api": "csp_Huya",
|
||||
"searchable": 0,
|
||||
"quickSearch": 0,
|
||||
"changeable": 0,
|
||||
"filterable": 1,
|
||||
"timeout": 10,
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 1.433
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "Douyu",
|
||||
"name": "🎮斗鱼┃1080P",
|
||||
"type": 3,
|
||||
"api": "csp_Douyu",
|
||||
"jar": "./jars/Huya.jar",
|
||||
"searchable": 0,
|
||||
"quickSearch": 0,
|
||||
"changeable": 0,
|
||||
"filterable": 1,
|
||||
"timeout": 10,
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 1.433
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "csp_duanju",
|
||||
"name": "🔥短剧┃1080P",
|
||||
"type": 3,
|
||||
"timeout": 12,
|
||||
"api": "csp_DuanJu"
|
||||
},
|
||||
{
|
||||
"key": "csp_Gz360",
|
||||
"name": "🍉瓜子┃1080P",
|
||||
"type": 3,
|
||||
"timeout": 12,
|
||||
"searchable": 1,
|
||||
"quickSearch": 0,
|
||||
"api": "csp_Gz360"
|
||||
},
|
||||
{
|
||||
"key": "csp_Jpys",
|
||||
"name": "🥇金牌┃1080P",
|
||||
"type": 3,
|
||||
"timeout": 12,
|
||||
"searchable": 1,
|
||||
"quickSearch": 0,
|
||||
"api": "csp_Jpys",
|
||||
"ext": "https://y2s52n7.com"
|
||||
},
|
||||
{
|
||||
"key": "csp_MiSou",
|
||||
"name": "🔍米搜┃盘搜",
|
||||
"type": 3,
|
||||
"timeout": 12,
|
||||
"searchable": 1,
|
||||
"quickSearch": 0,
|
||||
"api": "csp_MiSou"
|
||||
},
|
||||
{
|
||||
"key": "csp_TingBook",
|
||||
"name": "📖听书┃娱乐",
|
||||
"type": 3,
|
||||
"api": "csp_TingBook"
|
||||
},
|
||||
{
|
||||
"key": "Aid",
|
||||
"name": "🚑 急救┃知识",
|
||||
"type": 3,
|
||||
"api": "csp_FirstAid",
|
||||
"searchable": 0,
|
||||
"quickSearch": 0,
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 3.8
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "push_agent",
|
||||
"name": "📤 推送┃播放",
|
||||
"type": 3,
|
||||
"filterable": 0,
|
||||
"changeable": 0,
|
||||
"api": "csp_Push",
|
||||
"searchable": 1,
|
||||
"quickSearch": 1,
|
||||
"ext": ""
|
||||
}
|
||||
],
|
||||
"parses": [
|
||||
{
|
||||
"name": "📦 Json聚合",
|
||||
"type": 3,
|
||||
"url": "Demo"
|
||||
},
|
||||
{
|
||||
"name": "🎬 影视聚合",
|
||||
"type": 3,
|
||||
"url": "影视"
|
||||
},
|
||||
{
|
||||
"name": "🐮 牛牛解析",
|
||||
"type": 1,
|
||||
"url": "",
|
||||
"ext": {
|
||||
"flag": [
|
||||
"QD4K",
|
||||
"iyf",
|
||||
"duanju",
|
||||
"gzcj",
|
||||
"GTV",
|
||||
"GZYS",
|
||||
"weggz",
|
||||
"Ace"
|
||||
],
|
||||
"header": {
|
||||
"User-Agent": "okhttp/4.9.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "🌃 夜幕解析",
|
||||
"type": 0,
|
||||
"url": ""
|
||||
}
|
||||
],
|
||||
"rules": [
|
||||
{
|
||||
"name": "农民",
|
||||
"hosts": [
|
||||
"toutiaovod.com"
|
||||
],
|
||||
"regex": [
|
||||
"video/tos/cn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "火山",
|
||||
"hosts": [
|
||||
"huoshan.com"
|
||||
],
|
||||
"regex": [
|
||||
"item_id="
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "抖音",
|
||||
"hosts": [
|
||||
"douyin.com"
|
||||
],
|
||||
"regex": [
|
||||
"is_play_url="
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "磁力广告",
|
||||
"hosts": [
|
||||
"magnet"
|
||||
],
|
||||
"regex": [
|
||||
"更多",
|
||||
"请访问",
|
||||
"example",
|
||||
"社 區",
|
||||
"x u u",
|
||||
"直 播",
|
||||
"更 新",
|
||||
"社 区",
|
||||
"有趣",
|
||||
"有 趣",
|
||||
"英皇体育",
|
||||
"全中文AV在线",
|
||||
"澳门皇冠赌场",
|
||||
"哥哥快来",
|
||||
"美女荷官",
|
||||
"裸聊",
|
||||
"新片首发",
|
||||
"UUE29"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "饭团点击",
|
||||
"hosts": [
|
||||
"dadagui",
|
||||
"freeok",
|
||||
"dadagui"
|
||||
],
|
||||
"script": [
|
||||
"document.querySelector(\"#playleftiframe\").contentWindow.document.querySelector(\"#start\").click();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "毛驴点击",
|
||||
"hosts": [
|
||||
"www.maolvys.com"
|
||||
],
|
||||
"script": [
|
||||
"document.getElementsByClassName('swal-buttonswal-button--confirm')[0].click()"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# by @嗷呜
|
||||
import json
|
||||
import random
|
||||
import sys
|
||||
from base64 import b64encode, b64decode
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
# 引入 RSA 加解密所需模块
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Cipher import PKCS1_v1_5
|
||||
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
|
||||
class Spider(Spider):
|
||||
|
||||
def init(self, extend=""):
|
||||
did = self.getdid()
|
||||
self.headers.update({'deviceId': did})
|
||||
token = self.gettk()
|
||||
self.headers.update({'token': token})
|
||||
|
||||
def getName(self):
|
||||
pass
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
# 1. 修改为主机域名
|
||||
host = 'http://qkys.qukanwh.com'
|
||||
|
||||
# 2. 同步原脚本的配置请求头
|
||||
headers = {
|
||||
'HOST': 'qkys.qukanwh.com',
|
||||
'User-Agent': 'okhttp/4.12.0',
|
||||
'client': 'app',
|
||||
'deviceType': 'Android',
|
||||
'Referer': ''
|
||||
}
|
||||
|
||||
# 3. 导入原脚本中的 RSA 密钥对与配置
|
||||
publicKey_str = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCoYt0BP77U+DM08BiI/QbSRIfxijXo85BTPqIM1Ow8BNwhLETzRIZ+dEwdWDbydG/PspgBAfRpGaYVdJYtvaC2JnoO8+Ik6qMWojfEJxSFLa0Pb0A892tun4gsxoEMjcreZ+YGyaBxAfqX0BSMfdrOgIYaZQjYrw9TRLlUT31QoQIDAQAB\n-----END PUBLIC KEY-----"
|
||||
privateKey_str = "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCquQQ5r6+yJI8CDFkXRp8vUsdD45ov8EP12ooLs56ca2DQXaSNGS9910bAPVA9chkp0mKIvKqjAsHz5Tl9EeNPblarGEeJUIxpxZtiSqNTpvtiD/TjhpzuHYic7RAfQ/h7p/ypE8ymU42pYjsB5t26Mv6XgkLV+jzrSf73HlCuS0iMyLmt6zz3Mw9izM13EpB8iFLtfbbYymycKTx4RAmPQLwhNGex/AlUIYxXP4R2yyaa4W6mEtc6aME2QuzJFxPgP3HJ9NBx/LWVn4skxWjZ7zg+VRQRHnjyVaSLu3Z5gN5ITWCyE32qaHJa6WBahZj5jWhRyAG1bQ+xKJa8lBL5AgMBAAECggEAUwv9SjJ0PSwbhNuM2w23kcWquROWhYtTA91zGY4esehqB/IFgb2mpIh8Gje5OKqwIu/8jpd4SiOlRYdUF8sD0DfUYRZGdj2AkFNX6tBz8tVfo6wvbB6naA1lzzBij1L5JO3qsjS3cJFkb+kg2yP66AC2Z+0tpfk8eRhdtshAZwfcd1DEGt1uAvYL1eaUK9HRvpt9lPeGcHERDl2hBd4uyaF0K1O+zF9y59nYbTySWPxRZq3sFEE85xRMlstD7YZi7W2gKvMFRD4/FKmrZ3m7aKJRITtyKOyyPcYmepNv3Qv7kk59Pg38n2WWQ0Ra/bCH3E48YNCnQvZMpitkTfJhoQKBgQDbnROOYTP8OTJ6f/qhoGjxeO3x1VOaOp8l0x7b0SCfoqNGS0Cyiqj72BmJtPMPqSTjn6MmNzqbg1KOdhXyzNozs+i5ccW1M56j96mr5I/Z0FpE3oyIHNfDDBlf9M8YQqEF9oYxniYYft9oapO7cRQkHER6qpvnHTavwlv4m78CXwKBgQDHAjs2YlpKDdI1lcbZJCc7TwtH+Pd2bUki8YXafWNcPhITQHbOZjr310eK1QJC6GJncjkOqbX7yv3ivvTO35FZTQhuA1xEG1P00FG8bE0tHYPIwQHi9y0eA5cieMdo8E6XYria1mw/3fqSQEsfZyJlR32JQIoGAipM8iO1X2nZpwKBgDkMFIhnt5lNQk+P7wsNIDWZtDWdtJnboHuy29E+Abt2A/O+mI/IdRz2hau/1WO8DFkUnszOi+rZshhPlGP90rCbi1igtTrcrdjp/KkqNjPea5R4OwkgdOu1uOG0NheXNzzVTQaWjk7Opjn5dWa7eP/oV+GFb/oZHJuLYVizHGsBAoGADA7rjZEKDYCm4w5PPSr+oY5ZjaPdQrS+gLqHtMRyN82fBMGcMUdqfUfzEstzVqCEDeaS5HuOBlK3bXzKkppjUTjksN3NQmcxgBz7RuJ9DqXCLXDcb2cwuafYCYOt+YLOEEgwDVm+t2P44dG5e46hO+fICH/7nP+WlpD5buz4GfMCgYB57r3g/6hi9WUDnfc7ZAzWMqR0EhJVYKYy+KFEtdIPzhkkIHq5RASe88E9kzoGoZFdb3tIjvGZWcHerirrqWkMsuQtP/Qi0zjieid5tAPj+r4kbiCVTw0E0jnmPBzGInQi7lpeTTKnG1fbyS5lBS+WmHfIuzpECgCkxhaT+LJJkg==\n-----END PRIVATE KEY-----"
|
||||
|
||||
# RSA 公钥加密实现
|
||||
def rsa_encrypt(self, text):
|
||||
try:
|
||||
key = RSA.import_key(self.publicKey_str)
|
||||
cipher = PKCS1_v1_5.new(key)
|
||||
cipher_text = cipher.encrypt(text.encode('utf-8'))
|
||||
return b64encode(cipher_text).decode('utf-8')
|
||||
except Exception as e:
|
||||
print(f"RSA加密失败: {e}")
|
||||
return ""
|
||||
|
||||
# RSA 私钥解密实现
|
||||
def rsa_decrypt(self, text):
|
||||
try:
|
||||
key = RSA.import_key(self.privateKey_str)
|
||||
cipher = PKCS1_v1_5.new(key)
|
||||
raw_bytes = b64decode(text.encode('utf-8'))
|
||||
|
||||
decrypted = b""
|
||||
offset = 0
|
||||
while offset < len(raw_bytes):
|
||||
chunk = raw_bytes[offset:offset + 256]
|
||||
decrypted += cipher.decrypt(chunk, None)
|
||||
offset += 256
|
||||
return decrypted.decode('utf-8')
|
||||
except Exception as e:
|
||||
print(f"RSA解密失败: {e}")
|
||||
return ""
|
||||
|
||||
def homeContent(self, filter):
|
||||
data = self.post(f"{self.host}/api/v1/app/screen/screenType", headers=self.headers).json()
|
||||
result = {}
|
||||
cate = {
|
||||
"类型": "type",
|
||||
"地区": "area",
|
||||
"年份": "year"
|
||||
}
|
||||
sort = {
|
||||
'key': 'sort',
|
||||
'name': '排序',
|
||||
'value': [{'n': '最新', 'v': 'NEWEST'}, {'n': '热门', 'v': 'HOT'}, {'n': '收藏', 'v': 'COLLECT'}]
|
||||
}
|
||||
classes = []
|
||||
filters = {}
|
||||
for k in data.get('data', []):
|
||||
classes.append({
|
||||
'type_name': k['name'],
|
||||
'type_id': str(k['id'])
|
||||
})
|
||||
filters[str(k['id'])] = []
|
||||
for v in k.get('children', []):
|
||||
if v['name'] in cate:
|
||||
filters[str(k['id'])].append({
|
||||
'name': v['name'],
|
||||
'key': cate[v['name']],
|
||||
'value': [{'n': i['name'], 'v': i['name']} for i in v.get('children', [])]
|
||||
})
|
||||
filters[str(k['id'])].append(sort)
|
||||
result['class'] = classes
|
||||
result['filters'] = filters
|
||||
return result
|
||||
|
||||
def homeVideoContent(self):
|
||||
jdata = {
|
||||
"condition": {
|
||||
"sreecnTypeEnum": "NEWEST"
|
||||
},
|
||||
"pageNum": 1,
|
||||
"pageSize": 40
|
||||
}
|
||||
data = self.post(f"{self.host}/api/v1/app/screen/screenMovie", headers=self.headers, json=jdata).json()
|
||||
return {'list': self.getlist(data.get('data', {}).get('records', []))}
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
# 保持最纯粹的条件字段,移除任何空字符串占位
|
||||
condition = {
|
||||
'sreecnTypeEnum': 'NEWEST',
|
||||
'typeId': int(tid) if str(tid).isdigit() else tid
|
||||
}
|
||||
|
||||
if extend:
|
||||
if 'sort' in extend:
|
||||
condition['sreecnTypeEnum'] = extend.pop('sort')
|
||||
condition.update(extend)
|
||||
|
||||
jdata = {
|
||||
'condition': condition,
|
||||
'pageNum': int(pg),
|
||||
'pageSize': 40,
|
||||
}
|
||||
|
||||
try:
|
||||
data = self.post(f"{self.host}/api/v1/app/screen/screenMovie", headers=self.headers, json=jdata).json()
|
||||
result = {}
|
||||
if data and data.get('data') and 'records' in data['data']:
|
||||
result['list'] = self.getlist(data['data']['records'])
|
||||
else:
|
||||
result['list'] = []
|
||||
result['page'] = pg
|
||||
result['pagecount'] = 9999
|
||||
result['limit'] = 40
|
||||
result['total'] = 999999
|
||||
return result
|
||||
except Exception as e:
|
||||
print(f"分类获取错误: {e}")
|
||||
return {'list': [], 'page': pg}
|
||||
|
||||
def detailContent(self, ids):
|
||||
ids = ids[0].split('@@')
|
||||
jdata = {"id": int(ids[0]), "typeId": ids[-1]}
|
||||
v = self.post(f"{self.host}/api/v1/app/play/movieDesc", headers=self.headers, json=jdata).json()
|
||||
v = v.get('data', {})
|
||||
vod = {
|
||||
'type_name': v.get('typeId', ''),
|
||||
'vod_year': v.get('year', ''),
|
||||
'vod_area': v.get('area', ''),
|
||||
'vod_actor': v.get('star', ''),
|
||||
'vod_director': v.get('director', ''),
|
||||
'vod_content': v.get('introduce', ''),
|
||||
'vod_play_from': '',
|
||||
'vod_play_url': ''
|
||||
}
|
||||
|
||||
play_params = {
|
||||
"id": int(ids[0]),
|
||||
"source": 0,
|
||||
"typeId": ids[-1]
|
||||
}
|
||||
encrypt_payload = {"key": self.rsa_encrypt(json.dumps(play_params))}
|
||||
|
||||
c_res = self.post(f"{self.host}/api/v1/app/play/movieDetails", headers=self.headers, json=encrypt_payload).json()
|
||||
decrypted_play_str = self.rsa_decrypt(c_res.get('data', ''))
|
||||
if not decrypted_play_str:
|
||||
return {'list': [vod]}
|
||||
|
||||
decrypted_play_data = json.loads(decrypted_play_str)
|
||||
l = decrypted_play_data.get('moviePlayerList', [])
|
||||
if not l:
|
||||
return {'list': [vod]}
|
||||
|
||||
n = {str(i['id']): i['moviePlayerName'] for i in l}
|
||||
|
||||
m = play_params.copy()
|
||||
m.update({'playerId': l[0]['id']})
|
||||
|
||||
first_source_payload = {"key": self.rsa_encrypt(json.dumps(m))}
|
||||
first_res = self.post(f"{self.host}/api/v1/app/play/movieDetails", headers=self.headers, json=first_source_payload).json()
|
||||
|
||||
decrypted_first_str = self.rsa_decrypt(first_res.get('data', ''))
|
||||
if decrypted_first_str:
|
||||
decrypted_first_episode = json.loads(decrypted_first_str)
|
||||
pd = self.getv(m, decrypted_first_episode.get('episodeList', []))
|
||||
else:
|
||||
pd = {}
|
||||
|
||||
if len(l) > 1:
|
||||
with ThreadPoolExecutor(max_workers=len(l)-1) as executor:
|
||||
future_to_player = {executor.submit(self.getd, play_params, player): player for player in l[1:]}
|
||||
for future in future_to_player:
|
||||
try:
|
||||
o, p = future.result()
|
||||
if p:
|
||||
pd.update(self.getv(o, p))
|
||||
except Exception as e:
|
||||
print(f"多线路请求失败: {e}")
|
||||
w, e = [], []
|
||||
for i, x in pd.items():
|
||||
if x:
|
||||
w.append(n.get(i, '未知线路'))
|
||||
e.append(x)
|
||||
vod['vod_play_from'] = '$$$'.join(w)
|
||||
vod['vod_play_url'] = '$$$'.join(e)
|
||||
return {'list': [vod]}
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
jdata = {
|
||||
"condition": {
|
||||
"value": str(key)
|
||||
},
|
||||
"pageNum": int(pg),
|
||||
"pageSize": 40
|
||||
}
|
||||
try:
|
||||
data = self.post(f"{self.host}/api/v1/app/search/searchMovie", headers=self.headers, json=jdata).json()
|
||||
return {'list': self.getlist(data.get('data', {}).get('records', [])), 'page': pg}
|
||||
except Exception as e:
|
||||
print(f"搜索请求失败: {e}")
|
||||
return {'list': [], 'page': pg}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
raw_id_str = self.d64(id)
|
||||
if not raw_id_str:
|
||||
return {'parse': 0, 'url': ''}
|
||||
jdata = json.loads(raw_id_str)
|
||||
encrypt_payload = {"key": self.rsa_encrypt(json.dumps(jdata))}
|
||||
data = self.post(f"{self.host}/api/v1/app/play/movieDetails", headers=self.headers, json=encrypt_payload).json()
|
||||
|
||||
try:
|
||||
decrypted_url_data = json.loads(self.rsa_decrypt(data.get('data', '')))
|
||||
playerUrl = decrypted_url_data.get('url', '')
|
||||
if not playerUrl:
|
||||
return {'parse': 0, 'url': ''}
|
||||
|
||||
params = {'playerUrl': playerUrl, 'playerId': jdata['playerId']}
|
||||
pd = self.fetch(f"{self.host}/api/v1/app/play/analysisMovieUrl", headers=self.headers, params=params).json()
|
||||
url, p = pd.get('data', ''), 0
|
||||
except Exception as e:
|
||||
print(f"解析流媒体直链失败: {e}")
|
||||
url, p = "", 0
|
||||
return {'parse': p, 'url': url, 'header': {'User-Agent': 'okhttp/4.12.0'}}
|
||||
|
||||
def localProxy(self, param):
|
||||
pass
|
||||
|
||||
def liveContent(self, url):
|
||||
pass
|
||||
|
||||
def gettk(self):
|
||||
self.headers.update({'deviceId': self.getdid()})
|
||||
try:
|
||||
data = self.fetch(f"{self.host}/api/v1/app/user/visitorInfo", headers=self.headers).json()
|
||||
return data.get('data', {}).get('token', '')
|
||||
except:
|
||||
return ""
|
||||
|
||||
def getdid(self):
|
||||
did = self.getCache('ldid')
|
||||
if not did:
|
||||
hex_chars = '0123456789abcdef'
|
||||
did = ''.join(random.choice(hex_chars) for _ in range(16))
|
||||
self.setCache('ldid', did)
|
||||
return did
|
||||
|
||||
def getd(self, jdata, player):
|
||||
x = jdata.copy()
|
||||
x.update({'playerId': player['id']})
|
||||
encrypt_payload = {"key": self.rsa_encrypt(json.dumps(x))}
|
||||
response = self.post(f"{self.host}/api/v1/app/play/movieDetails", headers=self.headers, json=encrypt_payload).json()
|
||||
decrypted_str = self.rsa_decrypt(response.get('data', ''))
|
||||
if decrypted_str:
|
||||
decrypted_episode = json.loads(decrypted_str)
|
||||
return x, decrypted_episode.get('episodeList', [])
|
||||
return x, []
|
||||
|
||||
def getv(self, d, c):
|
||||
f = {str(d['playerId']): ''}
|
||||
g = []
|
||||
for i in c:
|
||||
j = d.copy()
|
||||
j.update({'episodeId': i['id']})
|
||||
g.append(f"{i['episode']}${self.e64(json.dumps(j))}")
|
||||
f[str(d['playerId'])] = '#'.join(g)
|
||||
return f
|
||||
|
||||
def getlist(self, data):
|
||||
videos = []
|
||||
for i in data:
|
||||
if not i.get('id'):
|
||||
continue
|
||||
videos.append({
|
||||
'vod_id': f"{i['id']}@@{i.get('typeId', '')}",
|
||||
'vod_name': i.get('name', ''),
|
||||
'vod_pic': i.get('cover', ''),
|
||||
'vod_year': i.get('year', ''),
|
||||
'vod_remarks': i.get('totalEpisode', '')
|
||||
})
|
||||
return videos
|
||||
|
||||
def e64(self, text):
|
||||
try:
|
||||
return b64encode(text.encode('utf-8')).decode('utf-8')
|
||||
except:
|
||||
return ""
|
||||
|
||||
def d64(self, encoded_text):
|
||||
try:
|
||||
return b64decode(encoded_text.encode('utf-8')).decode('utf-8')
|
||||
except:
|
||||
return ""
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user