This commit is contained in:
parent
91cb168035
commit
e6db2e3a87
|
|
@ -0,0 +1,229 @@
|
|||
{
|
||||
"spider": "./se.jar;md5;875ce871703d1c382e0498711b9d3ba0",
|
||||
"logo": "./Q.jpg",
|
||||
"sites": [
|
||||
{
|
||||
"key": "jable",
|
||||
"name": "jable",
|
||||
"type": 3,
|
||||
"quickSearch": 1,
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"filterable": 1,
|
||||
"timeout": 60,
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 1.48},
|
||||
"api": "csp_GM",
|
||||
"ext": {
|
||||
"userScript": "./drpy_js/jable.user.js",
|
||||
"debug": false,
|
||||
"webViewSettings": {
|
||||
"blockNetworkImage": true,
|
||||
"blockList": [
|
||||
"*.ico*",
|
||||
"*.png*",
|
||||
"*.css*",
|
||||
"https://*.adsco.re/*",
|
||||
"https://*.googleapis.com/*",
|
||||
"https://*.googlesyndication.com/*",
|
||||
"https://*.googletagmanager.com/*",
|
||||
"https://*.hpyjmp.com/*",
|
||||
"https://*.magsrv.com/*",
|
||||
"https://*.mnaspm.com/*",
|
||||
"https://*.shukriya90.com/*",
|
||||
"https://*.tapioni.com/*",
|
||||
"https://*.tsyndicate.com/*",
|
||||
"https://assets.jable.tv/assets/js/player.js"]},
|
||||
"spider": {
|
||||
"homeContent": {
|
||||
"loadUrl": "https://jable.tv/"},
|
||||
"categoryContent": {
|
||||
"loadUrl": "https://jable.tv/${tid:-latest-updates}/?from=${pg:-1}${sort_by:-}"},
|
||||
"detailContent": {
|
||||
"loadUrl": "https://jable.tv/videos/${id}/"},
|
||||
"searchContent": {
|
||||
"loadUrl": "https://jable.tv/search/${key}/?from=${pg:-1}"}}}
|
||||
},
|
||||
{
|
||||
"key": "MissAV",
|
||||
"name": "MissAV",
|
||||
"type": 3,
|
||||
"quickSearch": 1,
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"filterable": 1,
|
||||
"timeout": 60,
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 1.49},
|
||||
"api": "csp_GM",
|
||||
"ext": {
|
||||
"userScript": "./drpy_js/missav.user.js",
|
||||
"debug": false,
|
||||
"webViewSettings": {
|
||||
"blockNetworkImage": true,
|
||||
"blockList": [
|
||||
"*.ico",
|
||||
"*.png",
|
||||
"*.css",
|
||||
"*.svg",
|
||||
"https://*.cloudflareinsights.com/*",
|
||||
"https://*.googletagmanager.com/*",
|
||||
"https://*.ktkjmp.com/*",
|
||||
"https://*.magsrv.com/*",
|
||||
"https://*.mnaspm.com/*",
|
||||
"https://*.myavlive.com/*",
|
||||
"https://*.recombee.com/*",
|
||||
"https://*.rmhfrtnd.com/*",
|
||||
"https://*.trackwilltrk.com/*",
|
||||
"https://*.tsyndicate.com/*",
|
||||
"https://missav.com/fonts/*",
|
||||
"https://tsyndicate.com/*",
|
||||
"https://hartattenuate.com/*"]},
|
||||
"spider": {
|
||||
"homeContent": {
|
||||
"loadUrl": "https://missav.ws/cn/"},
|
||||
"categoryContent": {
|
||||
"loadUrl": "https://missav.ws/cn/${tid}?page=${pg:-1}${filter:-}${sort:-}"},
|
||||
"detailContent": {
|
||||
"loadUrl": "https://missav.ws/cn/${id}"},
|
||||
"searchContent": {
|
||||
"loadUrl": "https://missav.ws/cn/search/${key}?page=${pg:-1}"}}}
|
||||
},
|
||||
{
|
||||
"key": "xojav",
|
||||
"name": "xojav",
|
||||
"type": 3,
|
||||
"quickSearch": 1,
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"filterable": 1,
|
||||
"timeout": 60,
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 1.78},
|
||||
"api": "csp_GM",
|
||||
"ext": {
|
||||
"userScript": "./drpy_js/xojav.user.js",
|
||||
"debug": false,
|
||||
"webViewSettings": {
|
||||
"blockNetworkImage": true,
|
||||
"blockList": [
|
||||
"*.css*",
|
||||
"*.ico*",
|
||||
"*.png*",
|
||||
"*.svg",
|
||||
"https://*.googleapis.com/*",
|
||||
"https://*.googletagmanager.com/*",
|
||||
"https://*.magsrv.com/*",
|
||||
"https://*.pemsrv.com/*"]},
|
||||
"spider": {
|
||||
"homeContent": {
|
||||
"loadUrl": "https://xojav.tv/?lang=zh"},
|
||||
"categoryContent": {
|
||||
"loadUrl": "https://xojav.tv/${tid}${sort_by:-}&mode=async&function=get_block&from=${pg:-1}"},
|
||||
"detailContent": {
|
||||
"loadUrl": "https://xojav.tv/videos/${id}"},
|
||||
"searchContent": {
|
||||
"loadUrl": "https://xojav.tv/search/${key}/?mode=async&function=get_block&sort_by=most_relevant&from_videos=${pg:-1}"}}}
|
||||
},
|
||||
{
|
||||
"key": "missav",
|
||||
"name": "missav",
|
||||
"type": 3,
|
||||
"searchable": 1,
|
||||
"quickSearch": 0,
|
||||
"filterable": 0,
|
||||
"api": "./drpy_js/miss.py",
|
||||
"ext": {
|
||||
"site": "https://missav.ai",
|
||||
"cfgo": "./drpy_js/cf-proxy-linux-arm64",
|
||||
"plp": "",
|
||||
"proxy": {
|
||||
"http": "socks5://192.177.139.220:9000",
|
||||
"https": "socks5://192.177.139.220:9000"}}
|
||||
},
|
||||
{
|
||||
"key": "lav",
|
||||
"name": "lav",
|
||||
"type": 3,
|
||||
"api": "./drpy_js/lav.py",
|
||||
"searchable": 1,
|
||||
"quickSearch": 1,
|
||||
"filterable": 0,
|
||||
"changeable": 0,
|
||||
"ext": {
|
||||
"proxy": {},
|
||||
"plp": ""}
|
||||
},
|
||||
{
|
||||
"key": "肉視頻",
|
||||
"name": "肉視頻",
|
||||
"type": 3,
|
||||
"api": "./drpy_js/rou.py",
|
||||
"searchable": 1,
|
||||
"quickSearch": 0,
|
||||
"filterable": 0,
|
||||
"changeable": 0
|
||||
},
|
||||
{
|
||||
"key": "肉视频",
|
||||
"name": "肉视频2",
|
||||
"type": 3,
|
||||
"api": "./drpy_js/rsp.py",
|
||||
"searchable": 1,
|
||||
"quickSearch": 1,
|
||||
"filterable": 0,
|
||||
"changeable": 0,
|
||||
"ext": {
|
||||
"proxy": {},
|
||||
"plp": ""}
|
||||
},
|
||||
{
|
||||
"key": "51吸瓜",
|
||||
"name": "吃瓜",
|
||||
"type": 3,
|
||||
"api": "./drpy_js/吸瓜.py",
|
||||
"searchable": 1,
|
||||
"filterable": 0,
|
||||
"changeable": 0
|
||||
},
|
||||
{
|
||||
"key": "py_BadNews",
|
||||
"name": "BadNews",
|
||||
"type": 4,
|
||||
"api": "https://py.doube.eu.org/spider?site=BadNews",
|
||||
"searchable": 1,
|
||||
"quickSearch": 0,
|
||||
"filterable": 0,
|
||||
"changeable": 0,
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 1.5}
|
||||
},
|
||||
{
|
||||
"key": "py_Miss",
|
||||
"name": "missAV",
|
||||
"type": 4,
|
||||
"api": "https://py.doube.eu.org/spider?site=Miss",
|
||||
"searchable": 1,
|
||||
"quickSearch": 0,
|
||||
"filterable": 0,
|
||||
"changeable": 0
|
||||
},
|
||||
{
|
||||
"key": "py_AiDou",
|
||||
"name": "AiDou",
|
||||
"type": 4,
|
||||
"api": "https://py.doube.eu.org/spider?site=AiDou",
|
||||
"searchable": 1,
|
||||
"quickSearch": 0,
|
||||
"filterable": 0,
|
||||
"changeable": 0,
|
||||
"style": {
|
||||
"type": "rect",
|
||||
"ratio": 1.5}
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
|
|
@ -0,0 +1,140 @@
|
|||
|
||||
# -*- coding: utf-8 -*-
|
||||
# by @嗷呜 http://asp.xpgtv.com http://item.xpgcom.com
|
||||
import sys
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
|
||||
class Spider(Spider):
|
||||
|
||||
def init(self, extend=""):
|
||||
pass
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
host='http://asp.xpgtv.com'
|
||||
|
||||
headers = {
|
||||
"User-Agent": "okhttp/3.12.11"
|
||||
}
|
||||
|
||||
def homeContent(self, filter):
|
||||
data = self.fetch(f"{self.host}/api.php/v2.vod/androidtypes",headers=self.headers,).json()
|
||||
dy = {
|
||||
"classes": "类型",
|
||||
"areas": "地区",
|
||||
"years": "年份",
|
||||
"sortby": "排序",
|
||||
}
|
||||
filters = {}
|
||||
classes = []
|
||||
for item in data['data']:
|
||||
has_non_empty_field = False
|
||||
item['sortby'] = ['updatetime', 'hits', 'score']
|
||||
demos = ['时间', '人气', '评分']
|
||||
classes.append({"type_name": item["type_name"], "type_id": str(item["type_id"])})
|
||||
for key in dy:
|
||||
if key in item and len(item[key]) > 1:
|
||||
has_non_empty_field = True
|
||||
break
|
||||
if has_non_empty_field:
|
||||
filters[str(item["type_id"])] = []
|
||||
for dkey in item:
|
||||
if dkey in dy and len(item[dkey]) > 1:
|
||||
values = item[dkey]
|
||||
value_array = [
|
||||
{"n": demos[idx] if dkey == "sortby" else value.strip(), "v": value.strip()}
|
||||
for idx, value in enumerate(values)
|
||||
if value.strip() != ""
|
||||
]
|
||||
filters[str(item["type_id"])].append(
|
||||
{"key": dkey, "name": dy[dkey], "value": value_array}
|
||||
)
|
||||
result = {}
|
||||
result["class"] = classes
|
||||
result["filters"] = filters
|
||||
return result
|
||||
|
||||
def homeVideoContent(self):
|
||||
rsp = self.fetch(f"{self.host}/api.php/v2.main/androidhome", headers=self.headers).json()
|
||||
videos = []
|
||||
for i in rsp['data']['list']:videos.extend(self.getlist(i['list']))
|
||||
return {'list':videos}
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
params = {
|
||||
"page": pg,
|
||||
"type": tid,
|
||||
"area":extend.get('areaes',''),
|
||||
"year":extend.get('yeares',''),
|
||||
"sortby":extend.get('sortby',''),
|
||||
"class":extend.get('classes','')
|
||||
}
|
||||
params={i:v for i,v in params.items() if v}
|
||||
rsp = self.fetch(f'{self.host}/api.php/v2.vod/androidfilter10086', headers=self.headers, params=params).json()
|
||||
result = {}
|
||||
result['list'] = self.getlist(rsp['data'])
|
||||
result['page'] = pg
|
||||
result['pagecount'] = 9999
|
||||
result['limit'] = 90
|
||||
result['total'] = 999999
|
||||
return result
|
||||
|
||||
def detailContent(self, ids):
|
||||
rsp = self.fetch(f'{self.host}/api.php/v3.vod/androiddetail2?vod_id={ids[0]}', headers=self.headers).json()
|
||||
v = rsp['data']
|
||||
vod = {
|
||||
'vod_year':v.get('year'),
|
||||
'vod_area':v.get('area'),
|
||||
'vod_lang':v.get('lang'),
|
||||
'type_name':v.get('className'),
|
||||
'vod_actor':v.get('actor'),
|
||||
'vod_director':v.get('director'),
|
||||
'vod_content':v.get('content'),
|
||||
'vod_play_from': '老僧酿酒',
|
||||
'vod_play_url': '#'.join([f"{i['key']}${i['url']}" for i in v['urls']])
|
||||
}
|
||||
return {'list':[vod]}
|
||||
|
||||
def searchContent(self, key, quick, pg='1'):
|
||||
rsp = self.fetch(f'{self.host}/api.php/v2.vod/androidsearch10086?page={pg}&wd={key}', headers=self.headers).json()
|
||||
return {'list':self.getlist(rsp['data']),'page':pg}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
header = {
|
||||
'user_id': 'XPGBOX',
|
||||
'token2': 'XFxIummRrngadHB4TCzeUaleebTX10Vl/ftCvGLPeI5tN2Y/liZ5tY5e4t8=',
|
||||
'version': 'XPGBOX com.phoenix.tv1.5.5',
|
||||
'hash': '524f',
|
||||
'screenx': '2331',
|
||||
'user-agent': 'okhttp/3.12.11',
|
||||
'user-agent': 'Lavf/58.12.100',
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
|
||||
'token': 'VkxTyy6Krh4hd3lrQySUCJlsDYzzxxBbttphr3DiQNhmJkwoyEEm2YEu8qcOFGz2SmxGbIaSC91pa+8+VE9+SPQjGWY/wnqwKk1McYhsGyVVvHRAF0B1mD7922ara1o3k/EwZ1xyManr90EeUSxI7rPOLBwX5zeOri31MeyDfBnIdhckWld4V1k2ZfZ3QKbN',
|
||||
'timestamp': '1749174636',
|
||||
'screeny': '1121',
|
||||
}
|
||||
if 'http' not in id:id=f"http://c.xpgtv.net/m3u8/{id}.m3u8"
|
||||
return {"parse": 0, "url": id, "header": header}
|
||||
|
||||
def localProxy(self, param):
|
||||
pass
|
||||
|
||||
def getlist(self,data):
|
||||
videos = []
|
||||
for vod in data:
|
||||
r=f"更新至{vod.get('updateInfo')}" if vod.get('updateInfo') else ''
|
||||
videos.append({
|
||||
"vod_id": vod['id'],
|
||||
"vod_name": vod['name'],
|
||||
"vod_pic": vod['pic'],
|
||||
"vod_remarks": r or vod['score']
|
||||
})
|
||||
return videos
|
||||
|
|
@ -0,0 +1,407 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# by @嗷呜
|
||||
import os,copy,requests,gzip,json,re,sys,time,uuid
|
||||
from urllib.parse import unquote
|
||||
from base64 import b64decode
|
||||
from Crypto.Hash import SHA1, HMAC
|
||||
from pyquery import PyQuery as pq
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
|
||||
|
||||
class Spider(Spider):
|
||||
|
||||
def init(self, extend="{}"):
|
||||
config = json.loads(extend)
|
||||
self.process = None
|
||||
self.host = config['site']
|
||||
self.plp = config.get('plp', '')
|
||||
self.proxy = config.get('proxy', {})
|
||||
self.one_mark, gobool = self.start_proxy(config.get('cfgo'))
|
||||
self.cfproxy = 'http://127.0.0.1:12525?url=' if gobool else ''
|
||||
self.headers = {
|
||||
'referer': f'{self.host}',
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0'
|
||||
}
|
||||
pass
|
||||
|
||||
def getName(self):
|
||||
pass
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
def copy_file(self, source_path):
|
||||
target_filename = os.path.basename(source_path)
|
||||
try:
|
||||
from java.io import File
|
||||
from java.lang import Class
|
||||
from java.nio.file import Files, Paths, StandardCopyOption
|
||||
|
||||
source_file = File(source_path)
|
||||
if not source_file.exists() or not source_file.isFile():
|
||||
self.log(f"❌ 源文件不存在: {source_path}")
|
||||
return False
|
||||
|
||||
python_class = Class.forName("com.chaquo.python.Python")
|
||||
get_instance_method = python_class.getMethod("getInstance")
|
||||
python_instance = get_instance_method.invoke(None)
|
||||
|
||||
get_platform_method = python_class.getMethod("getPlatform")
|
||||
platform = get_platform_method.invoke(python_instance)
|
||||
|
||||
get_application_method = platform.getClass().getMethod("getApplication")
|
||||
application = get_application_method.invoke(platform)
|
||||
context = application.getApplicationContext()
|
||||
files_dir = context.getFilesDir().getAbsolutePath()
|
||||
target_path = files_dir + "/" + target_filename
|
||||
|
||||
target_file = File(target_path)
|
||||
if target_file.exists() and target_file.isFile() and target_file.length() == source_file.length():
|
||||
target_file.setExecutable(True)
|
||||
self.log(f"⚠️ 文件已存在: {target_path}")
|
||||
return target_path
|
||||
|
||||
Files.copy(
|
||||
Paths.get(source_path),
|
||||
Paths.get(target_path),
|
||||
StandardCopyOption.REPLACE_EXISTING
|
||||
)
|
||||
|
||||
File(target_path).setExecutable(True)
|
||||
self.log(f"✅ 复制完成: {target_path}")
|
||||
return target_path
|
||||
|
||||
except Exception as e:
|
||||
self.log(f"❌ 复制失败: {e}")
|
||||
return False
|
||||
|
||||
def start_proxy(self,path, port=12525):
|
||||
try:
|
||||
if not path:
|
||||
msg = "文件不存在"
|
||||
self.log(msg)
|
||||
return msg, False
|
||||
from java.lang import ProcessBuilder
|
||||
from java.io import File
|
||||
from android.os import Environment
|
||||
external_storage = Environment.getExternalStorageDirectory().getAbsolutePath()
|
||||
absolute_path = os.path.abspath(path)
|
||||
absolute_path = unquote(external_storage + absolute_path.split('/file')[-1])
|
||||
c_file=self.copy_file(absolute_path)
|
||||
if not c_file:
|
||||
msg = f"无法复制文件"
|
||||
self.log(msg)
|
||||
return msg, False
|
||||
if self.examine(port):
|
||||
self.proxy={}
|
||||
msg = f"✅ 代理已启动:{port}"
|
||||
self.log(msg)
|
||||
return msg, True
|
||||
oder=[c_file, "-port", str(port)]
|
||||
proxy=self.proxy.get('http','')
|
||||
if proxy:
|
||||
oder.extend(['-proxy',proxy])
|
||||
pb = ProcessBuilder(oder)
|
||||
pb.directory(File(c_file).getParentFile())
|
||||
self.process = pb.start()
|
||||
time.sleep(1)
|
||||
if self.process and self.process.isAlive() and self.examine(port):
|
||||
self.proxy = {}
|
||||
msg = f"✅ 代理已启动:{port}"
|
||||
self.log(msg)
|
||||
return msg,True
|
||||
else:
|
||||
msg = "❌ 代理启动失败"
|
||||
self.log(msg)
|
||||
return msg,False
|
||||
|
||||
except Exception as e:
|
||||
msg = "❌ 启动代理异常"
|
||||
self.log(f"{msg}: {e}")
|
||||
return msg, False
|
||||
|
||||
def examine(self,port):
|
||||
import socket
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(1)
|
||||
result = sock.connect_ex(('127.0.0.1', int(port)))
|
||||
sock.close()
|
||||
if result == 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
xhost='https://client-rapi-missav.recombee.com'
|
||||
|
||||
countr='/dm15/cn'
|
||||
|
||||
ccccc='H4sIAAAAAAAAA4uuViqpLEiNz0vMTVWyUlB6Nqfhxf6Jz2ZveTZtg5IORC4zBSSTkmtqaKKfnKefl1quVKuDrm/ahid75zzZ0fV0RxOGPgsLkL6i1JzUxOJULHqnL3i+oPHZ1san7bvQ9ZoZGYL0luYlp+YV5xelpugCDcnGNOPp0s1P9sx4sqPhxfIOVDOAuhOTS4pSi4tTizH1Pd+4++m8bgwd6al5RdiUP+2f+GJhz9OpbRg6chOzU4uAOmIBkkRrDlIBAAA='
|
||||
|
||||
fts = 'H4sIAAAAAAAAA23P30rDMBQG8FeRXM8X8FVGGZk90rA0HU3SMcZgXjn8V6p2BS2KoOiFAwUn2iK+TBP7GBpYXbG9/c6Pc77TnaABjNHOFtojVIDPUQcx7IJJvl9ydX30GwSYSpN0J4iZgTqJiywrPlN1vm/GJiPMJgGxJaZo2qnc3WXDuZIKMqSwUcX7Ui8O1DJRH3Gldh3CgMM2l31BhNGW8euq3PNFrac+PVNZ2NYzjMrbY53c6/Sm2uwDBczB7mGxqaDTWfkV6atXvXiu4FD2KeHOf3nxViahjv8YxwHYtWfyQ3NvFZYP85oSno3HvYDAiNevPqnosWFHAAPahnU6b2DXY8Jp0bO8QdfEmlo/SBd5PPUBAAA='
|
||||
|
||||
actfts = 'H4sIAAAAAAAAA5WVS2sUQRRG/0rT6xTcqq5Xiwjm/X6sQxZjbBLRBBeOIEGIIEgWrtwI4lJEQsjGhU6Iv2bGcf6FVUUydW/d1SxT55sDfbpmsn9WP+/e1A+q+rh7dnT8qp6rT3snXTz4N7icXH4OB697L/rxZP+sPo1g+Ot8PPg+vvoyOb+IOJ7Vb+fuqGxkJSrZmMOTexiORDjAGxs3GvDGinCANjp5NPbo4NHYo5PHYI8OHoM9JnkM9pjgMdhjksdijwkeiz02eSz22OCx2GOTx2GPDR6HPS55HPa44HHY45LHY48LHo89Pnk89vjg8djjk6fFHh88bfAcxNXduz/sv0Qvfnz74+/X65lf/OMqfzD9ndF8geYzWijQQkaLBVrMaKlASxktF2g5o5UCrWS0WqDVjNYKtJbReoHWM9oo0EZGmwXazGirQFsZbRdoO6OdAu1ktFug3Yz2CrRH70TvqEN3YvT75+TP+5nvxMNKwf0pCIWur4JwM5spVCAaRJtI9ZQ2IPBPg47UTKkGgb/wJlI7pQYE/ho/QsiCaFv61E+7J338Izj6MJi8+xSefnhzO/PTK1CmGt58G118zM+pDBloPtBk0PBBQwaKDxQZSD6QZAB8QN6UbNlAtmTg+cCTgeMDRwaWDywZ8JKSlJS8pCQlJS8pSUnJS0pSUvKSkpSUvKQkJYGXBFISeEkgJYGXBFISeEkgJYGXBFISeEkgJYGXBFISeEkgJYGXBFISeElI/7QO/gOZ7bAksggAAA=='
|
||||
def homeContent(self, filter):
|
||||
one={"vod_name": "go状态","vod_pic": "https://img-blog.csdnimg.cn/6f8b58d3daf14b5696e85c710f18a571.png","action": "action","vod_remarks": self.one_mark,"style": {"type": "rect","ratio": 1.33}}
|
||||
html = pq(requests.get(f"{self.cfproxy}{self.host}{self.countr}",headers=self.headers,proxies=self.proxy).content)
|
||||
result = {}
|
||||
filters = {}
|
||||
classes=self.ungzip(self.ccccc)
|
||||
for i in classes:
|
||||
id=i['type_id']
|
||||
filters[id] = copy.deepcopy(self.ungzip(self.fts))
|
||||
if 'cn/actresses' in id:filters[id].extend(self.ungzip(self.actfts))
|
||||
result['class'] = classes
|
||||
result['filters'] = filters
|
||||
result['list'] = self.getlist(html('.grid-cols-2.md\\:grid-cols-3 .thumbnail.group'))
|
||||
result['list'].insert(0, one)
|
||||
return result
|
||||
|
||||
def homeVideoContent(self):
|
||||
pass
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
params={
|
||||
'page':pg
|
||||
}
|
||||
ft = {
|
||||
'filters': extend.get('filters', ''),
|
||||
'sort': extend.get('sort', '')
|
||||
}
|
||||
if tid in ['cn/genres', 'cn/makers']:
|
||||
ft = {}
|
||||
elif tid == 'cn/actresses':
|
||||
ft = {
|
||||
'height': extend.get('height', ''),
|
||||
'cup': extend.get('cup', ''),
|
||||
'debut': extend.get('debut', ''),
|
||||
'age': extend.get('age', ''),
|
||||
'sort': extend.get('sort', '')
|
||||
}
|
||||
params.update(ft)
|
||||
params={k: v for k, v in params.items() if v}
|
||||
req = requests.Request(
|
||||
url=f"{self.host}/{tid}",
|
||||
params=params,
|
||||
).prepare()
|
||||
data=pq(requests.get(f"{self.cfproxy}{req.url}",headers=self.headers,proxies=self.proxy).content)
|
||||
result = {}
|
||||
if tid in ['cn/genres', 'cn/makers']:
|
||||
videos = self.gmsca(data)
|
||||
elif tid == 'cn/actresses':
|
||||
videos = self.actca(data)
|
||||
else:
|
||||
videos = self.getlist(data('.grid-cols-2.md\\:grid-cols-3 .thumbnail.group'))
|
||||
result['list'] = videos
|
||||
result['page'] = pg
|
||||
result['pagecount'] = 9999
|
||||
result['limit'] = 90
|
||||
result['total'] = 999999
|
||||
return result
|
||||
|
||||
def detailContent(self, ids):
|
||||
urlllll=f"{self.cfproxy}{self.host}/{ids[0]}"
|
||||
v=pq(requests.get(urlllll,headers=self.headers,proxies=self.proxy).content)
|
||||
sctx=v('body script').text()
|
||||
urls=self.execute_js(sctx)
|
||||
if not urls:urls=f"嗅探${urlllll}"
|
||||
c=v('.space-y-2 .text-secondary')
|
||||
ac,dt,cd,bq=[],[],[],['点击展开↓↓↓\n']
|
||||
for i in c.items():
|
||||
xxx=i('span').text()
|
||||
if re.search(r"导演:|发行商:",xxx):
|
||||
dt.extend(['[a=cr:' + json.dumps({'id': j.attr('href').split('/',3)[-1], 'name': j.text()}) + '/]' + j.text() + '[/a]' for j in i('a').items()])
|
||||
elif re.search(r"女优:",xxx):
|
||||
ac.extend(['[a=cr:' + json.dumps({'id': j.attr('href').split('/',3)[-1], 'name': j.text()}) + '/]' + j.text() + '[/a]' for j in i('a').items()])
|
||||
elif re.search(r"类型:|系列:",xxx):
|
||||
bq.extend(['[a=cr:' + json.dumps({'id': j.attr('href').split('/',3)[-1], 'name': j.text()}) + '/]' + j.text() + '[/a]' for j in i('a').items()])
|
||||
elif re.search(r"标籤:",xxx):
|
||||
cd.extend(['[a=cr:' + json.dumps({'id': j.attr('href').split('/',3)[-1], 'name': j.text()}) + '/]' + j.text() + '[/a]' for j in i('a').items()])
|
||||
np={'MissAV':urls,'Recommend':self.getfov(ids[0])}
|
||||
vod = {
|
||||
'type_name': c.eq(-3)('a').text(),
|
||||
'vod_year': c.eq(0)('time').text(),
|
||||
'vod_remarks': ' '.join(cd),
|
||||
'vod_actor': ' '.join(ac),
|
||||
'vod_director': ' '.join(dt),
|
||||
'vod_content': f"{' '.join(bq)}\n{v('.text-secondary.break-all').text()}"
|
||||
}
|
||||
names,plist=[],[]
|
||||
for i,j in np.items():
|
||||
if j:
|
||||
names.append(i)
|
||||
plist.append(j)
|
||||
vod['vod_play_from']='$$$'.join(names)
|
||||
vod['vod_play_url']='$$$'.join(plist)
|
||||
return {'list': [vod]}
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
req = requests.Request(
|
||||
url=f"{self.host}/search/{key}",
|
||||
params={'page': pg},
|
||||
).prepare()
|
||||
data = pq(requests.get(f"{self.cfproxy}{req.url}", headers=self.headers, proxies=self.proxy).content)
|
||||
return {'list': self.getlist(data('.grid-cols-2.md\\:grid-cols-3 .thumbnail.group')),'page':pg}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
p=0 if '.m3u8' in id else 1
|
||||
if flag == 'Recommend':
|
||||
urlllll = f"{self.cfproxy}{self.host}/{id}"
|
||||
try:
|
||||
v = pq(requests.get(urlllll, headers=self.headers, proxies=self.proxy).content)
|
||||
sctx = v('body script').text()
|
||||
url = self.execute_js(sctx)
|
||||
if not url: raise Exception("没有找到地址")
|
||||
p,id=0,url.split('$')[-1]
|
||||
except:
|
||||
p,id=1,urlllll
|
||||
return {'parse': p, 'url': id if p else f"{self.plp}{id}", 'header': self.headers}
|
||||
|
||||
def localProxy(self, param):
|
||||
pass
|
||||
|
||||
def getlist(self,data):
|
||||
videos = []
|
||||
names,ids=[],[]
|
||||
for i in data.items():
|
||||
k = i('.overflow-hidden.shadow-lg a')
|
||||
id=k.eq(0).attr('href')
|
||||
name=i('.text-secondary').text()
|
||||
if id and id not in ids and name not in names:
|
||||
ids.append(id)
|
||||
names.append(name)
|
||||
videos.append({
|
||||
'vod_id': id.split('/',3)[-1],
|
||||
'vod_name': name,
|
||||
'vod_pic': k.eq(0)('img').attr('data-src'),
|
||||
'vod_year': '' if len(list(k.items())) < 3 else k.eq(1).text(),
|
||||
'vod_remarks': k.eq(-1).text(),
|
||||
'style': {"type": "rect", "ratio": 1.33}
|
||||
})
|
||||
return videos
|
||||
|
||||
def gmsca(self,data):
|
||||
acts=[]
|
||||
for i in data('.grid.grid-cols-2.md\\:grid-cols-3 div').items():
|
||||
id=i('.text-nord13').attr('href')
|
||||
acts.append({
|
||||
'vod_id':id.split('/', 3)[-1] if id else id,
|
||||
'vod_name': i('.text-nord13').text(),
|
||||
'vod_pic': '',
|
||||
'vod_remarks': i('.text-nord10').text(),
|
||||
'vod_tag': 'folder',
|
||||
'style': {"type": "rect", "ratio": 2}
|
||||
})
|
||||
return acts
|
||||
|
||||
def actca(self,data):
|
||||
acts=[]
|
||||
for i in data('.max-w-full ul li').items():
|
||||
id=i('a').attr('href')
|
||||
acts.append({
|
||||
'vod_id': id.split('/', 3)[-1] if id else id,
|
||||
'vod_name': i('img').attr('alt'),
|
||||
'vod_pic': i('img').attr('src'),
|
||||
'vod_year': i('.text-nord10').eq(-1).text(),
|
||||
'vod_remarks': i('.text-nord10').eq(0).text(),
|
||||
'vod_tag': 'folder',
|
||||
'style': {"type": "oval"}
|
||||
})
|
||||
return acts
|
||||
|
||||
def getfov(self, url):
|
||||
try:
|
||||
h=self.headers.copy()
|
||||
ids=url.split('/')
|
||||
h.update({'referer':f'{self.host}/{url}/'})
|
||||
t=str(int(time.time()))
|
||||
params = {
|
||||
'frontend_timestamp': t,
|
||||
'frontend_sign': self.getsign(f"/missav-default/batch/?frontend_timestamp={t}"),
|
||||
}
|
||||
uid=str(uuid.uuid4())
|
||||
json_data = {
|
||||
'requests': [
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': f'/recomms/items/{ids[-1]}/items/',
|
||||
'params': {
|
||||
'targetUserId': uid,
|
||||
'count': 13,
|
||||
'scenario': 'desktop-watch-next-side',
|
||||
'returnProperties': True,
|
||||
'includedProperties': [
|
||||
'title_cn',
|
||||
'duration',
|
||||
'has_chinese_subtitle',
|
||||
'has_english_subtitle',
|
||||
'is_uncensored_leak',
|
||||
'dm',
|
||||
],
|
||||
'cascadeCreate': True,
|
||||
},
|
||||
},
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': f'/recomms/items/{ids[-1]}/items/',
|
||||
'params': {
|
||||
'targetUserId': uid,
|
||||
'count': 12,
|
||||
'scenario': 'desktop-watch-next-bottom',
|
||||
'returnProperties': True,
|
||||
'includedProperties': [
|
||||
'title_cn',
|
||||
'duration',
|
||||
'has_chinese_subtitle',
|
||||
'has_english_subtitle',
|
||||
'is_uncensored_leak',
|
||||
'dm',
|
||||
],
|
||||
'cascadeCreate': True,
|
||||
},
|
||||
},
|
||||
],
|
||||
'distinctRecomms': True,
|
||||
}
|
||||
data = requests.post(f'{self.xhost}/missav-default/batch/', params=params,headers=h, json=json_data,proxies=self.proxy).json()
|
||||
vdata=[]
|
||||
for i in data:
|
||||
for j in i['json']['recomms']:
|
||||
if j.get('id'):
|
||||
vdata.append(f"{j['values']['title_cn']}${j['id']}")
|
||||
return '#'.join(vdata)
|
||||
except Exception as e:
|
||||
self.log(f"获取推荐失败: {e}")
|
||||
return ''
|
||||
|
||||
def getsign(self, text):
|
||||
message_bytes = text.encode('utf-8')
|
||||
key_bytes = b'Ikkg568nlM51RHvldlPvc2GzZPE9R4XGzaH9Qj4zK9npbbbTly1gj9K4mgRn0QlV'
|
||||
h = HMAC.new(key_bytes, digestmod=SHA1)
|
||||
h.update(message_bytes)
|
||||
signature = h.hexdigest()
|
||||
return signature
|
||||
|
||||
def ungzip(self, data):
|
||||
result=gzip.decompress(b64decode(data)).decode('utf-8')
|
||||
return json.loads(result)
|
||||
|
||||
def execute_js(self, jstxt):
|
||||
js_code = re.search(r"eval\(function\(p,a,c,k,e,d\).*?return p}(.*?)\)\)", jstxt).group(0)
|
||||
try:
|
||||
from com.whl.quickjs.wrapper import QuickJSContext
|
||||
ctx = QuickJSContext.create()
|
||||
result=ctx.evaluate(f"{js_code}\nsource")
|
||||
ctx.destroy()
|
||||
return f"多画质${result}"
|
||||
except Exception as e:
|
||||
self.log(f"执行失败: {e}")
|
||||
return None
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,236 @@
|
|||
// ==UserScript==
|
||||
// @name Jable
|
||||
// @namespace gmspider
|
||||
// @version 2024.12.03
|
||||
// @description Jable GMSpider
|
||||
// @author Luomo
|
||||
// @match https://jable.tv/*
|
||||
// @require https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.slim.min.js
|
||||
// @grant unsafeWindow
|
||||
// ==/UserScript==
|
||||
console.log(JSON.stringify(GM_info));
|
||||
(function () {
|
||||
const GMSpiderArgs = {};
|
||||
if (typeof GmSpiderInject !== 'undefined') {
|
||||
let args = JSON.parse(GmSpiderInject.GetSpiderArgs());
|
||||
GMSpiderArgs.fName = args.shift();
|
||||
GMSpiderArgs.fArgs = args;
|
||||
} else {
|
||||
GMSpiderArgs.fName = "homeContent";
|
||||
GMSpiderArgs.fArgs = [true];
|
||||
}
|
||||
Object.freeze(GMSpiderArgs);
|
||||
const GmSpider = (function () {
|
||||
function listVideos(result) {
|
||||
result.pagecount = parseInt($(".pagination .page-item:last").text());
|
||||
$("[id^='list_videos_'] .row:first .video-img-box").each(function (i) {
|
||||
const subTitle = $(this).find(".sub-title").text().split('\n');
|
||||
const remarks = [
|
||||
"👁️" + subTitle[1].trim(),
|
||||
"❤️" + subTitle[2].trim()
|
||||
];
|
||||
const url = new URL($(this).find(".img-box a").attr("href"));
|
||||
result.list.push({
|
||||
vod_id: url.pathname.split('/').at(2).toUpperCase(),
|
||||
vod_name: $(this).find(".title").text(),
|
||||
vod_pic: $(this).find(".img-box img").data("src"),
|
||||
vod_remarks: remarks.join(" "),
|
||||
vod_year: $(this).find(".absolute-bottom-right").text().trim()
|
||||
})
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
return {
|
||||
homeContent: function (filter) {
|
||||
let result = {
|
||||
class: [
|
||||
{type_id: "latest-updates", type_name: "最近更新"},
|
||||
{type_id: "hot", type_name: "热门影片"},
|
||||
{type_id: "categories/chinese-subtitle", type_name: "中文字幕"},
|
||||
{type_id: "new-release", type_name: "全新上市"},
|
||||
{type_id: "categories", type_name: "主题&标签"},
|
||||
],
|
||||
filters: {
|
||||
hot: [{
|
||||
key: "sort_by",
|
||||
name: "时间",
|
||||
value: [
|
||||
{
|
||||
n: "所有时间",
|
||||
v: "&sort_by=video_viewed"
|
||||
},
|
||||
{
|
||||
n: "本月热门",
|
||||
v: "&sort_by=video_viewed_month"
|
||||
},
|
||||
{
|
||||
n: "本周热门",
|
||||
v: "&sort_by=video_viewed_week"
|
||||
},
|
||||
{
|
||||
n: "今日热门",
|
||||
v: "&sort_by=video_viewed_today"
|
||||
}
|
||||
]
|
||||
}],
|
||||
"categories/chinese-subtitle": [{
|
||||
key: "sort_by",
|
||||
name: "时间",
|
||||
value: [
|
||||
{
|
||||
n: "近期最佳",
|
||||
v: "&sort_by=post_date_and_popularity"
|
||||
},
|
||||
{
|
||||
n: "最近更新",
|
||||
v: "&sort_by=post_date"
|
||||
},
|
||||
{
|
||||
n: "最多观看",
|
||||
v: "&sort_by=video_viewed"
|
||||
},
|
||||
{
|
||||
n: "最高收藏",
|
||||
v: "&sort_by=most_favourited"
|
||||
}
|
||||
]
|
||||
}],
|
||||
categories: [{
|
||||
key: "sort_by",
|
||||
name: "时间",
|
||||
value: [
|
||||
{
|
||||
n: "近期最佳",
|
||||
v: "&sort_by=post_date_and_popularity"
|
||||
},
|
||||
{
|
||||
n: "最近更新",
|
||||
v: "&sort_by=post_date"
|
||||
},
|
||||
{
|
||||
n: "最多观看",
|
||||
v: "&sort_by=video_viewed"
|
||||
},
|
||||
{
|
||||
n: "最高收藏",
|
||||
v: "&sort_by=most_favourited"
|
||||
}
|
||||
]
|
||||
}]
|
||||
},
|
||||
list: []
|
||||
};
|
||||
let itemList = [];
|
||||
$(".video-img-box").has(".detail").has("img").each(function () {
|
||||
const url = new URL($(this).find(".img-box a").attr("href"));
|
||||
if (url.hostname === "jable.tv") {
|
||||
itemList.push({
|
||||
vod_id: url.pathname.split('/').at(2).toUpperCase(),
|
||||
vod_name: $(this).find(".title").text(),
|
||||
vod_pic: $(this).find("img").data("src"),
|
||||
vod_year: $(this).find(".absolute-bottom-right").text().trim()
|
||||
})
|
||||
}
|
||||
});
|
||||
result.list = itemList.filter((item, index) => {
|
||||
return itemList.findIndex(i => i.vod_id === item.vod_id) === index
|
||||
});
|
||||
return result;
|
||||
},
|
||||
categoryContent: function (tid, pg, filter, extend) {
|
||||
let result = {
|
||||
list: [],
|
||||
pagecount: 1
|
||||
};
|
||||
if (tid === "categories") {
|
||||
$("#list_categories_video_categories_list .video-img-box").each(function () {
|
||||
const url = new URL($(this).find("a").attr("href")).pathname.split('/');
|
||||
result.list.push({
|
||||
vod_id: url[1] + "/" + url[2],
|
||||
vod_name: $(this).find("h4").text(),
|
||||
vod_pic: $(this).find("img").attr("src"),
|
||||
vod_remarks: $(this).find(".absolute-center span").text(),
|
||||
vod_tag: "folder",
|
||||
style: {
|
||||
"type": "rect",
|
||||
"ratio": 1
|
||||
}
|
||||
})
|
||||
});
|
||||
const tags = [];
|
||||
$(".app-nav .title-box:gt(0)").each(function () {
|
||||
const remark = $(this).text();
|
||||
$(this).next(".row").find(".tag").each(function () {
|
||||
const url = new URL($(this).attr("href")).pathname.split('/');
|
||||
result.list.push({
|
||||
vod_id: url[1] + "/" + url[2],
|
||||
vod_name: $(this).text(),
|
||||
vod_remarks: remark,
|
||||
vod_tag: "folder",
|
||||
})
|
||||
});
|
||||
});
|
||||
result.pagecount = 1;
|
||||
} else {
|
||||
listVideos(result);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
detailContent: function (ids) {
|
||||
let vodActor = [], categories = [], tags = [];
|
||||
$(".video-info .info-header .models .model").each(function () {
|
||||
const url = new URL($(this).attr("href")).pathname.split('/');
|
||||
const id = url[1] + "/" + url[2];
|
||||
const name = $(this).find(".rounded-circle").data("original-title");
|
||||
vodActor.push(`[a=cr:{"id":"${id}","name":"${name}"}/]${name}[/a]`);
|
||||
});
|
||||
$(".video-info .tags .cat").each(function () {
|
||||
const url = new URL($(this).attr("href")).pathname.split('/');
|
||||
const id = url[1] + "/" + url[2];
|
||||
const name = $(this).text();
|
||||
categories.push(`[a=cr:{"id":"${id}","name":"${name}"}/]#${name}[/a]`);
|
||||
});
|
||||
$(".video-info .tags a:not(.cat)").each(function () {
|
||||
const url = new URL($(this).attr("href")).pathname.split('/');
|
||||
const id = url[1] + "/" + url[2];
|
||||
const name = $(this).text();
|
||||
tags.push(`[a=cr:{"id":"${id}","name":"${name}"}/]#${name}[/a]`);
|
||||
});
|
||||
const vod = {
|
||||
vod_id: ids[0],
|
||||
vod_name: ids[0].toUpperCase(),
|
||||
vod_pic: $("#player").attr("poster"),
|
||||
vod_year: "更新於 " + $(".video-info .info-header .mr-3:first").text() + " " + $(".video-info .info-header .inactive-color").text(),
|
||||
vod_remarks: tags.join(" "),
|
||||
vod_actor: vodActor.join(" ") + " " + categories.join(" "),
|
||||
vod_content: $(".video-info h4").text(),
|
||||
vod_play_from: $(".video-info .info-header .header-right h6").children().remove().end().text().trim(),
|
||||
vod_play_url: "老僧酿酒$" + unsafeWindow.hlsUrl,
|
||||
};
|
||||
return {list: [vod]};
|
||||
},
|
||||
searchContent: function (key, quick, pg) {
|
||||
const result = {
|
||||
list: [],
|
||||
pagecount: 1
|
||||
};
|
||||
listVideos(result);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
})();
|
||||
$(document).ready(function () {
|
||||
let result = "";
|
||||
if ($("#cf-wrapper").length > 0) {
|
||||
console.log("源站不可用:" + $('title').text());
|
||||
GM_toastLong("源站不可用:" + $('title').text());
|
||||
} else {
|
||||
result = GmSpider[GMSpiderArgs.fName](...GMSpiderArgs.fArgs);
|
||||
}
|
||||
console.log(result);
|
||||
if (typeof GmSpiderInject !== 'undefined') {
|
||||
GmSpiderInject.SetSpiderResult(JSON.stringify(result));
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
# coding=utf-8
|
||||
# !/usr/bin/python
|
||||
# 嗷呜
|
||||
import sys
|
||||
from base64 import b64encode, b64decode
|
||||
from Crypto.Hash import MD5, SHA256
|
||||
sys.path.append("..")
|
||||
from base.spider import Spider
|
||||
from Crypto.Cipher import AES
|
||||
import json
|
||||
import time
|
||||
|
||||
|
||||
class Spider(Spider):
|
||||
|
||||
def getName(self):
|
||||
return "lav"
|
||||
|
||||
def init(self, extend=""):
|
||||
self.id = self.ms(str(int(time.time() * 1000)))[:16]
|
||||
pass
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def action(self, action):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
host = "http://sir_new.tiansexyl.tv"
|
||||
t = str(int(time.time() * 1000))
|
||||
headers = {'User-Agent': 'okhttp-okgo/jeasonlzy', 'Connection': 'Keep-Alive',
|
||||
'Content-Type': 'application/x-www-form-urlencoded'}
|
||||
|
||||
def homeContent(self, filter):
|
||||
cateManual = {"演员": "actor", "分类": "avsearch", }
|
||||
classes = []
|
||||
for k in cateManual:
|
||||
classes.append({'type_name': k, 'type_id': cateManual[k]})
|
||||
j = {'code': 'homePage', 'mod': 'down', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv',
|
||||
'app_type': 'rn', 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn',
|
||||
'oauth_id': self.id}
|
||||
|
||||
body = self.aes(j)
|
||||
data = self.post(f'{self.host}/api.php?t={str(int(time.time() * 1000))}', data=body, headers=self.headers).json()['data']
|
||||
data1 = self.aes(data, False)['data']
|
||||
self.r = data1['r']
|
||||
for i, d in enumerate(data1['avTag']):
|
||||
# if i == 4:
|
||||
# break
|
||||
classes.append({'type_name': d['name'], 'type_id': d['tag']})
|
||||
resutl = {}
|
||||
resutl["class"] = classes
|
||||
return resutl
|
||||
|
||||
def homeVideoContent(self):
|
||||
pass
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
id = tid.split("@@")
|
||||
result = {}
|
||||
result["page"] = pg
|
||||
result["pagecount"] = 9999
|
||||
result["limit"] = 90
|
||||
result["total"] = 999999
|
||||
if id[0] == 'avsearch':
|
||||
if pg == '1':
|
||||
j = {'code': 'avsearch', 'mod': 'search', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv',
|
||||
'app_type': 'rn', 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn',
|
||||
'oauth_id': self.id}
|
||||
if len(id) > 1:
|
||||
j = {'code': 'find', 'mod': 'tag', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv',
|
||||
'app_type': 'rn', 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn',
|
||||
'oauth_id': self.id, 'type': 'av', 'dis': 'new', 'page': str(pg), 'tag': id[1]}
|
||||
elif id[0] == 'actor':
|
||||
j = {'mod': 'actor', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv', 'app_type': 'rn',
|
||||
'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn', 'oauth_id': self.id,
|
||||
'page': str(pg), 'filter': ''}
|
||||
if len(id) > 1:
|
||||
j = {'code': 'eq', 'mod': 'actor', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv',
|
||||
'app_type': 'rn', 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn',
|
||||
'oauth_id': self.id, 'page': str(pg), 'id': id[1], 'actor': id[2]}
|
||||
else:
|
||||
j = {'code': 'search', 'mod': 'av', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv',
|
||||
'app_type': 'rn', 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn',
|
||||
'oauth_id': self.id, 'page': str(pg), 'tag': id[0]}
|
||||
|
||||
body = self.aes(j)
|
||||
data = self.post(f'{self.host}/api.php?t={str(int(time.time() * 1000))}', data=body, headers=self.headers).json()['data']
|
||||
data1 = self.aes(data, False)['data']
|
||||
videos = []
|
||||
if tid == 'avsearch' and len(id) == 1:
|
||||
for item in data1:
|
||||
videos.append({"vod_id": id[0] + "@@" + str(item.get('tags')), 'vod_name': item.get('name'),
|
||||
'vod_pic': self.imgs(item.get('ico')), 'vod_tag': 'folder',
|
||||
'style': {"type": "rect", "ratio": 1.33}})
|
||||
elif tid == 'actor' and len(id) == 1:
|
||||
for item in data1:
|
||||
videos.append({"vod_id": id[0] + "@@" + str(item.get('id')) + "@@" + item.get('name'),
|
||||
'vod_name': item.get('name'), 'vod_pic': self.imgs(item.get('cover')),
|
||||
'vod_tag': 'folder', 'style': {"type": "oval"}})
|
||||
else:
|
||||
for item in data1:
|
||||
if item.get('_id'):
|
||||
videos.append({"vod_id": str(item.get('id')), 'vod_name': item.get('title'),
|
||||
'vod_pic': self.imgs(item.get('cover_thumb') or item.get('cover_full')),
|
||||
'vod_remarks': item.get('good'), 'style': {"type": "rect", "ratio": 1.33}})
|
||||
result["list"] = videos
|
||||
return result
|
||||
|
||||
def detailContent(self, ids):
|
||||
id = ids[0]
|
||||
j = {'code': 'detail', 'mod': 'av', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv',
|
||||
'app_type': 'rn', 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn',
|
||||
'oauth_id': self.id, 'id': id}
|
||||
body = self.aes(j)
|
||||
data = self.post(f'{self.host}/api.php?t={str(int(time.time() * 1000))}', data=body, headers=self.headers).json()['data']
|
||||
data1 = self.aes(data, False)['line']
|
||||
vod = {}
|
||||
play = []
|
||||
for itt in data1:
|
||||
a = itt['line'].get('s720')
|
||||
if a:
|
||||
b = a.split('.')
|
||||
b[0] = 'https://m3u8'
|
||||
a = '.'.join(b)
|
||||
play.append(itt['info']['tips'] + "$" + a)
|
||||
break
|
||||
vod["vod_play_from"] = '老僧酿酒'
|
||||
vod["vod_play_url"] = "#".join(play)
|
||||
result = {"list": [vod]}
|
||||
return result
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
pass
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
url = self.getProxyUrl() + "&url=" + b64encode(id.encode('utf-8')).decode('utf-8') + "&type=m3u8"
|
||||
self.hh = {'User-Agent': 'dd', 'Connection': 'Keep-Alive', 'Referer': self.r}
|
||||
result = {}
|
||||
result["parse"] = 0
|
||||
result["url"] = url
|
||||
result["header"] = self.hh
|
||||
return result
|
||||
|
||||
def localProxy(self, param):
|
||||
url = param["url"]
|
||||
if param.get('type') == "m3u8":
|
||||
return self.vod(b64decode(url).decode('utf-8'))
|
||||
else:
|
||||
return self.img(url)
|
||||
|
||||
def vod(self, url):
|
||||
data = self.fetch(url, headers=self.hh).text
|
||||
key = bytes.fromhex("13d47399bda541b85e55830528d4e66f1791585b2d2216f23215c4c63ebace31")
|
||||
iv = bytes.fromhex(data[:32])
|
||||
data = data[32:]
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
|
||||
data_bytes = bytes.fromhex(data)
|
||||
decrypted = cipher.decrypt(data_bytes)
|
||||
encoded = decrypted.decode("utf-8").replace("\x08", "")
|
||||
return [200, "application/vnd.apple.mpegur", encoded]
|
||||
|
||||
def imgs(self, url):
|
||||
return self.getProxyUrl() + '&url=' + url
|
||||
|
||||
def img(self, url):
|
||||
type = url.split('.')[-1]
|
||||
data = self.fetch(url).text
|
||||
key = bytes.fromhex("ba78f184208d775e1553550f2037f4af22cdcf1d263a65b4d5c74536f084a4b2")
|
||||
iv = bytes.fromhex(data[:32])
|
||||
data = data[32:]
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
|
||||
data_bytes = bytes.fromhex(data)
|
||||
decrypted = cipher.decrypt(data_bytes)
|
||||
return [200, f"image/{type}", decrypted]
|
||||
|
||||
def ms(self, data, m=False):
|
||||
h = MD5.new()
|
||||
if m:
|
||||
h = SHA256.new()
|
||||
h.update(data.encode('utf-8'))
|
||||
return h.hexdigest()
|
||||
|
||||
def aes(self, data, operation=True):
|
||||
key = bytes.fromhex("620f15cfdb5c79c34b3940537b21eda072e22f5d7151456dec3932d7a2b22c53")
|
||||
t = str(int(time.time()))
|
||||
ivt = self.ms(t)
|
||||
if operation:
|
||||
data = json.dumps(data, separators=(',', ':'))
|
||||
iv = bytes.fromhex(ivt)
|
||||
else:
|
||||
iv = bytes.fromhex(data[:32])
|
||||
data = data[32:]
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
|
||||
if operation:
|
||||
data_bytes = data.encode('utf-8')
|
||||
encrypted = cipher.encrypt(data_bytes)
|
||||
ep = f'{ivt}{encrypted.hex()}'
|
||||
edata = f"data={ep}×tamp={t}0d27dfacef1338483561a46b246bf36d"
|
||||
sign = self.ms(self.ms(edata, True))
|
||||
edata = f"timestamp={t}&data={ep}&sign={sign}"
|
||||
return edata
|
||||
else:
|
||||
data_bytes = bytes.fromhex(data)
|
||||
decrypted = cipher.decrypt(data_bytes)
|
||||
return json.loads(decrypted.decode('utf-8'))
|
||||
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
// ==UserScript==
|
||||
// @name MissAV
|
||||
// @namespace gmspider
|
||||
// @version 2024.12.03
|
||||
// @description MissAV GMSpider
|
||||
// @author Luomo
|
||||
// @match https://missav.*/*
|
||||
// @require https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.slim.min.js
|
||||
// @grant unsafeWindow
|
||||
// ==/UserScript==
|
||||
console.log(JSON.stringify(GM_info));
|
||||
(function () {
|
||||
const GMSpiderArgs = {};
|
||||
if (typeof GmSpiderInject !== 'undefined') {
|
||||
let args = JSON.parse(GmSpiderInject.GetSpiderArgs());
|
||||
GMSpiderArgs.fName = args.shift();
|
||||
GMSpiderArgs.fArgs = args;
|
||||
} else {
|
||||
GMSpiderArgs.fName = "detailContent";
|
||||
GMSpiderArgs.fArgs = [true];
|
||||
}
|
||||
Object.freeze(GMSpiderArgs);
|
||||
const GmSpider = (function () {
|
||||
const filter = {
|
||||
key: "filter",
|
||||
name: "过滤",
|
||||
value: [{
|
||||
n: "所有",
|
||||
v: ""
|
||||
}, {
|
||||
n: "单人作品",
|
||||
v: "&filters=individual"
|
||||
}, {
|
||||
n: "多人作品",
|
||||
v: "&filters=multiple"
|
||||
}, {
|
||||
n: "中文字幕",
|
||||
v: "&filters=chinese-subtitle"
|
||||
}]
|
||||
};
|
||||
const filterWithoutSort = [
|
||||
filter
|
||||
];
|
||||
const defaultFilter = [
|
||||
filter,
|
||||
{
|
||||
key: "sort",
|
||||
name: "排序方式",
|
||||
value: [
|
||||
{
|
||||
n: "发行日期",
|
||||
v: "&sort=released_at"
|
||||
},
|
||||
{
|
||||
n: "最近更新",
|
||||
v: "&sort=published_at"
|
||||
},
|
||||
{
|
||||
n: "收藏数",
|
||||
v: "&sort=saved"
|
||||
},
|
||||
{
|
||||
n: "今日浏览数",
|
||||
v: "&sort=today_views"
|
||||
},
|
||||
{
|
||||
n: "本周浏览数",
|
||||
v: "&sort=weekly_views"
|
||||
},
|
||||
{
|
||||
n: "本月浏览数",
|
||||
v: "&sort=monthly_views"
|
||||
},
|
||||
{
|
||||
n: "总浏览数",
|
||||
v: "&sort=views"
|
||||
}
|
||||
]
|
||||
}];
|
||||
|
||||
function pageList(result) {
|
||||
result.pagecount = parseInt($("#price-currency").text().replace(/[^0-9]/ig, ""));
|
||||
result.total = result.pagecount * result.limit;
|
||||
$(".gap-5 .thumbnail").each(function (i) {
|
||||
result.list.push({
|
||||
vod_id: $(this).find(".text-secondary").attr("alt"),
|
||||
vod_name: $(this).find(".text-secondary").text().trim(),
|
||||
vod_pic: $(this).find("img").data("src"),
|
||||
vod_year: $(this).find(".right-1").text().trim(),
|
||||
vod_remarks: $(this).find(".left-1").text().trim(),
|
||||
})
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function categoryList(result) {
|
||||
$(".gap-4 div").each(function () {
|
||||
result.list.push({
|
||||
vod_id: getCategoryFromUrl($(this).find(".text-nord13").attr("href")),
|
||||
vod_name: $(this).find(".text-nord13").text().trim(),
|
||||
vod_remarks: $(this).find(".text-nord10 a").text().trim(),
|
||||
vod_tag: "folder",
|
||||
style: {
|
||||
"type": "rect",
|
||||
"ratio": 2
|
||||
}
|
||||
})
|
||||
});
|
||||
result.limit = 36;
|
||||
result.pagecount = parseInt($("#price-currency").text().replace(/[^0-9]/ig, ""));
|
||||
result.total = result.pagecount * result.limit;
|
||||
return result;
|
||||
}
|
||||
|
||||
function getCategoryFromUrl(url) {
|
||||
return url.split('/cn/').at(1);
|
||||
}
|
||||
|
||||
function formatDetail(detail, ...keys) {
|
||||
let format = "";
|
||||
for (let key of keys) {
|
||||
format += key in detail ? (Array.isArray(detail[key]) ? detail[key].join(" ") : detail[key]) : "";
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
return {
|
||||
homeContent: function (filter) {
|
||||
let result = {
|
||||
class: [
|
||||
{type_id: "new", type_name: "所有影片"},
|
||||
{type_id: "madou", type_name: "麻豆传媒"},
|
||||
{type_id: "chinese-subtitle", type_name: "中文字幕"},
|
||||
{type_id: "uncensored-leak", type_name: "无码流出"},
|
||||
{type_id: "actresses/ranking", type_name: "热门女优"},
|
||||
{type_id: "makers", type_name: "发行商"},
|
||||
{type_id: "genres", type_name: "类型"},
|
||||
],
|
||||
filters: {
|
||||
"new": defaultFilter,
|
||||
"madou": defaultFilter,
|
||||
"chinese-subtitle": defaultFilter,
|
||||
"uncensored-leak": defaultFilter,
|
||||
"actresses/ranking": defaultFilter,
|
||||
"makers": defaultFilter,
|
||||
"genres": defaultFilter
|
||||
},
|
||||
list: []
|
||||
};
|
||||
$(".gap-5:eq(5) .thumbnail").each(function () {
|
||||
result.list.push({
|
||||
vod_id: $(this).find(".text-secondary").attr("alt"),
|
||||
vod_name: $(this).find(".text-secondary").text().trim(),
|
||||
vod_pic: $(this).find("img").data("src"),
|
||||
vod_year: $(this).find(".absolute").text().trim()
|
||||
})
|
||||
});
|
||||
console.log(result);
|
||||
return result;
|
||||
},
|
||||
categoryContent: function (tid, pg, filter, extend) {
|
||||
let result = {
|
||||
list: [],
|
||||
limit: 12,
|
||||
total: 0,
|
||||
page: pg,
|
||||
pagecount: 0
|
||||
};
|
||||
if (tid === "actresses/ranking") {
|
||||
$(".gap-4 .space-y-4").each(function () {
|
||||
result.list.push({
|
||||
vod_id: getCategoryFromUrl($(this).find(".space-y-2 a").attr("href")),
|
||||
vod_name: $(this).find(".truncate").text().trim(),
|
||||
vod_pic: $(this).find("img").length > 0 ? $(this).find("img").attr("src") : "",
|
||||
vod_remarks: $(this).find(".text-sm").text().trim(),
|
||||
vod_tag: "folder",
|
||||
style: {
|
||||
"type": "rect",
|
||||
"ratio": 1
|
||||
}
|
||||
})
|
||||
});
|
||||
result.limit = 100;
|
||||
result.total = 100;
|
||||
result.pagecount = 1;
|
||||
} else if (tid === "makers") {
|
||||
function getNavs(name) {
|
||||
$("nav.hidden .relative a.group span:contains('" + name + "')").parents(".relative:first").find(".py-1 a").each(function () {
|
||||
result.list.push({
|
||||
vod_id: getCategoryFromUrl($(this).attr("href")),
|
||||
vod_name: $(this).text().trim(),
|
||||
vod_remarks: name,
|
||||
vod_tag: "folder",
|
||||
style: {
|
||||
"type": "rect",
|
||||
"ratio": 2
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (pg == 1) {
|
||||
getNavs("国产 AV");
|
||||
getNavs("无码影片");
|
||||
getNavs("素人");
|
||||
}
|
||||
result = categoryList(result)
|
||||
} else if (tid === "genres") {
|
||||
result = categoryList(result)
|
||||
} else {
|
||||
result = pageList(result);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
detailContent: function (ids) {
|
||||
let detail = {};
|
||||
$(".space-y-2:not(.list-disc) .text-secondary").each(function () {
|
||||
const key = $(this).find("span:first").text().replace(":", "");
|
||||
if ($(this).find("a").length === 0) {
|
||||
detail[key] = $(this).find("span:first").remove().end().text().trim();
|
||||
} else {
|
||||
detail[key] = [];
|
||||
$(this).find("a").each(function () {
|
||||
const id = getCategoryFromUrl($(this).attr("href"));
|
||||
const name = $(this).text();
|
||||
detail[key].push(`[a=cr:{"id":"${id}","name":"${name}"}/]${name}[/a]`);
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
console.log($('a.items-center:contains("显示更多")'));
|
||||
const vod = {
|
||||
vod_id: ids[0],
|
||||
vod_name: ids[0].toUpperCase(),
|
||||
vod_pic: $("head link[as=image]").attr("href"),
|
||||
vod_year: $("#space-y-2 time").text(),
|
||||
vod_remarks: formatDetail(detail, "类型"),
|
||||
vod_actor: formatDetail(detail, "女优"),
|
||||
vod_content: $('a.items-center:contains("显示更多")').length > 0 ? $("head meta[name=description]").attr("content") : $("head meta[property='og:title']").attr("content"),
|
||||
vod_play_from: "老僧酿酒",
|
||||
vod_play_url: "名妓读经$" + hls.url,
|
||||
};
|
||||
console.log({list: [vod]})
|
||||
return {list: [vod]};
|
||||
},
|
||||
searchContent: function (key, quick, pg) {
|
||||
let result = {
|
||||
list: [],
|
||||
limit: 12,
|
||||
total: 0,
|
||||
page: pg,
|
||||
pagecount: 0
|
||||
};
|
||||
result = pageList(result);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
})();
|
||||
$(document).ready(function () {
|
||||
let result = "";
|
||||
if ($("#cf-wrapper").length > 0) {
|
||||
console.log("源站不可用:" + $('title').text());
|
||||
GM_toastLong("源站不可用:" + $('title').text());
|
||||
} else {
|
||||
result = GmSpider[GMSpiderArgs.fName](...GMSpiderArgs.fArgs);
|
||||
}
|
||||
console.log(result);
|
||||
if (typeof GmSpiderInject !== 'undefined') {
|
||||
GmSpiderInject.SetSpiderResult(JSON.stringify(result));
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Author : Doubebly
|
||||
# @Time : 2025/1/20 14:55
|
||||
|
||||
import sys
|
||||
import requests
|
||||
from lxml import etree
|
||||
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
|
||||
|
||||
class Spider(Spider):
|
||||
def getName(self):
|
||||
return "Rou"
|
||||
|
||||
def init(self, extend):
|
||||
self.home_url = 'https://rou.video'
|
||||
self.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"}
|
||||
|
||||
def getDependence(self):
|
||||
return []
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def homeContent(self, filter):
|
||||
url = self.home_url + '/cat'
|
||||
try:
|
||||
res = requests.get(url, headers=self.headers)
|
||||
if res.status_code != 200:
|
||||
return {'class': [], 'msg': f'status_code: {res.status_code}'}
|
||||
root = etree.HTML(res.text.encode('utf-8'))
|
||||
name_list = root.xpath('//div[@class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-3"]/a/text()')
|
||||
url_list = root.xpath('//div[@class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-3"]/a/@href')
|
||||
if len(name_list) < 1 or len(url_list) < 1:
|
||||
return {'class': [], 'msg': '获取的数据为空'}
|
||||
a = []
|
||||
for name, url in zip(name_list, url_list):
|
||||
a.append({'type_name': name, 'type_id': url})
|
||||
return {'class': a}
|
||||
except requests.exceptions.RequestException as e:
|
||||
return {'class': [], 'msg': str(e)}
|
||||
|
||||
def homeVideoContent(self):
|
||||
url = self.home_url + '/home'
|
||||
try:
|
||||
res = requests.get(url, headers=self.headers)
|
||||
if res.status_code != 200:
|
||||
return {'list': [], 'parse': 0, 'jx': 0, 'msg': f'status_code: {res.status_code}'}
|
||||
root = etree.HTML(res.text.encode('utf-8'))
|
||||
data_list = root.xpath('//div[@class="aspect-video relative"]/a')
|
||||
if len(data_list) < 1:
|
||||
return {'list': [], 'parse': 0, 'jx': 0, 'msg': '获取的数据为空'}
|
||||
a = []
|
||||
for i in data_list:
|
||||
vod_remarks = i.xpath('./div[2]/text()')
|
||||
vod_year = i.xpath('./div[3]/text()')
|
||||
vod_name = i.xpath('./img/@alt')
|
||||
|
||||
a.append(
|
||||
{
|
||||
'vod_id': i.xpath('./@href')[0],
|
||||
'vod_name': vod_name[0] if len(vod_name[0]) > 0 else vod_name[1],
|
||||
'vod_pic': i.xpath('./img/@src')[0],
|
||||
'vod_remarks': vod_remarks[0] if vod_remarks else '',
|
||||
'vod_year': vod_year[0] if vod_year else '',
|
||||
'style': {"type": "rect", "ratio": 1.5}
|
||||
}
|
||||
)
|
||||
return {'list': a, 'parse': 0, 'jx': 0}
|
||||
except requests.exceptions.RequestException as e:
|
||||
return {'list': [], 'parse': 0, 'jx': 0, 'msg': str(e)}
|
||||
|
||||
def categoryContent(self, cid, page, filter, ext):
|
||||
url = f'{self.home_url}{cid}?order=createdAt&page={page}'
|
||||
try:
|
||||
res = requests.get(url, headers=self.headers)
|
||||
if res.status_code != 200:
|
||||
return {'list': [], 'parse': 0, 'jx': 0, 'msg': f'status_code: {res.status_code}'}
|
||||
root = etree.HTML(res.text.encode('utf-8'))
|
||||
data_list = root.xpath('//div[@class="aspect-video relative"]/a')
|
||||
if len(data_list) < 1:
|
||||
return {'list': [], 'parse': 0, 'jx': 0, 'msg': '获取的数据为空'}
|
||||
a = []
|
||||
for i in data_list:
|
||||
vod_remarks = i.xpath('./div[2]/text()')
|
||||
vod_year = i.xpath('./div[3]/text()')
|
||||
vod_name = i.xpath('./img/@alt')
|
||||
a.append(
|
||||
{
|
||||
'vod_id': i.xpath('./@href')[0],
|
||||
'vod_name': vod_name[0] if len(vod_name[0]) > 0 else vod_name[1],
|
||||
'vod_pic': i.xpath('./img/@src')[0],
|
||||
'vod_remarks': vod_remarks[0] if vod_remarks else '',
|
||||
'vod_year': vod_year[0] if vod_year else '',
|
||||
'style': {"type": "rect", "ratio": 1.5}
|
||||
}
|
||||
)
|
||||
return {'list': a, 'parse': 0, 'jx': 0}
|
||||
except requests.exceptions.RequestException as e:
|
||||
return {'list': [], 'parse': 0, 'jx': 0, 'msg': str(e)}
|
||||
|
||||
def detailContent(self, did):
|
||||
ids = did[0]
|
||||
video_list = []
|
||||
url = self.home_url + f'/api{ids}'
|
||||
h = {
|
||||
'accept': '*/*',
|
||||
'accept-language': 'zh-CN,zh;q=0.9',
|
||||
'cache-control': 'no-cache',
|
||||
'content-type': 'application/json',
|
||||
'referer': 'https://rou.video',
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
}
|
||||
try:
|
||||
res = requests.get(url, headers=h)
|
||||
if res.status_code != 200:
|
||||
return {'list': [], 'parse': 0, 'jx': 0, 'msg': f'status_code: {res.status_code}'}
|
||||
play_url = res.json()['video']['videoUrl']
|
||||
video_list.append(
|
||||
{
|
||||
'type_name': '',
|
||||
'vod_id': ids,
|
||||
'vod_name': '',
|
||||
'vod_remarks': '',
|
||||
'vod_year': '',
|
||||
'vod_area': '',
|
||||
'vod_actor': '',
|
||||
'vod_director': '书生玩剑',
|
||||
'vod_content': '',
|
||||
'vod_play_from': '老僧酿酒',
|
||||
'vod_play_url': f'名妓读经${play_url}',
|
||||
|
||||
}
|
||||
)
|
||||
return {"list": video_list, 'parse': 0, 'jx': 0}
|
||||
except requests.RequestException as e:
|
||||
return {'list': [], 'msg': e}
|
||||
|
||||
def searchContent(self, key, quick, page='1'):
|
||||
url = f'{self.home_url}/search?q={key}&page={page}'
|
||||
try:
|
||||
res = requests.get(url, headers=self.headers)
|
||||
if res.status_code != 200:
|
||||
return {'list': [], 'parse': 0, 'jx': 0, 'msg': f'status_code: {res.status_code}'}
|
||||
root = etree.HTML(res.text.encode('utf-8'))
|
||||
data_list = root.xpath('//div[@class="aspect-video relative"]/a')
|
||||
if len(data_list) < 1:
|
||||
return {'list': [], 'parse': 0, 'jx': 0, 'msg': '获取的数据为空'}
|
||||
a = []
|
||||
for i in data_list:
|
||||
vod_remarks = i.xpath('./div[2]/text()')
|
||||
vod_year = i.xpath('./div[3]/text()')
|
||||
vod_name = i.xpath('./img/@alt')
|
||||
a.append(
|
||||
{
|
||||
'vod_id': i.xpath('./@href')[0],
|
||||
'vod_name': vod_name[0] if len(vod_name[0]) > 0 else vod_name[1],
|
||||
'vod_pic': i.xpath('./img/@src')[0],
|
||||
'vod_remarks': vod_remarks[0] if vod_remarks else '',
|
||||
'vod_year': vod_year[0] if vod_year else '',
|
||||
'style': {"type": "rect", "ratio": 1.5}
|
||||
}
|
||||
)
|
||||
return {'list': a, 'parse': 0, 'jx': 0}
|
||||
except requests.exceptions.RequestException as e:
|
||||
return {'list': [], 'parse': 0, 'jx': 0, 'msg': str(e)}
|
||||
|
||||
def playerContent(self, flag, pid, vipFlags):
|
||||
return {'url': pid, "header": self.headers, 'parse': 0, 'jx': 0}
|
||||
|
||||
def localProxy(self, params):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
return '正在Destroy'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# by @嗷呜
|
||||
import json
|
||||
import sys
|
||||
import requests
|
||||
from pyquery import PyQuery as pq
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
|
||||
|
||||
class Spider(Spider):
|
||||
|
||||
def init(self, extend='{}'):
|
||||
config=json.loads(extend)
|
||||
self.proxies=config.get('proxies',{})
|
||||
self.plp=config.get('plp','')
|
||||
self.session=requests.session()
|
||||
self.session.proxies=self.proxies
|
||||
pass
|
||||
|
||||
def getName(self):
|
||||
pass
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
host='https://rou.video'
|
||||
|
||||
headers = {
|
||||
'referer': f'{host}/',
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36',
|
||||
}
|
||||
|
||||
def homeContent(self, filter):
|
||||
cdata=self.getpq(self.session.get(f'{self.host}/cat', headers=self.headers))
|
||||
result = {}
|
||||
classes = []
|
||||
filters = {}
|
||||
for k in cdata('.space-y-8 section').items():
|
||||
id=k('h2 a').attr('href')
|
||||
classes.append({
|
||||
'type_name': k('h2').text(),
|
||||
'type_id': id
|
||||
})
|
||||
filters[id]=[{'key':'order','name':'order','value':[{'n':'观看','v':'viewCount'},{'n':'点赞','v':'likeCount'}]}].copy()
|
||||
if k('.grid.grid-cols-2 a'):
|
||||
filters[id].append({
|
||||
'key': 'type',
|
||||
'name': 'type',
|
||||
'value': [{
|
||||
'n': i.text(),
|
||||
'v': i.attr('href')
|
||||
}for i in k('.grid.grid-cols-2 a').items()]
|
||||
})
|
||||
result['class'] = classes
|
||||
result['filters'] = filters
|
||||
return result
|
||||
|
||||
def homeVideoContent(self):
|
||||
res = self.getpq(self.session.get(f'{self.host}/home', headers=self.headers))
|
||||
videos=self.getlist(res('.grid.grid-cols-2.lg\\:grid-cols-4 div.aspect-video.relative'))
|
||||
return {'list':videos}
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
tid=extend.get('type') or tid
|
||||
params= {
|
||||
'order': extend.get('order',''),
|
||||
'page': pg,
|
||||
}
|
||||
data=self.getpq(self.session.get(f'{self.host}{tid}',params=params, headers=self.headers))
|
||||
result = {}
|
||||
result['list'] = self.getlist(data('.grid.grid-cols-2 div.aspect-video.relative'))
|
||||
result['page'] = pg
|
||||
result['pagecount'] = 9999
|
||||
result['limit'] = 90
|
||||
result['total'] = 999999
|
||||
return result
|
||||
|
||||
def detailContent(self, ids):
|
||||
data=self.getpq(self.session.get(f'{self.host}{ids[0]}', headers=self.headers))
|
||||
url=self.session.get(f"{self.host}/api{ids[0]}",headers=self.headers).json()['video']['videoUrl']
|
||||
n=data('.md\\:col-span-2 .px-2 .hidden').eq(0).text() or 'xxxx'
|
||||
vod = {
|
||||
'vod_content': ' '.join(['[a=cr:' + json.dumps({'id': j.attr('href'), 'name': j.text()}) + '/]' + j.text() + '[/a]' for j in data('.flex.justify-between div a').items()]),
|
||||
'vod_play_from': '老僧酿酒',
|
||||
'vod_play_url': f"{n}${url}"
|
||||
}
|
||||
return {'list':[vod]}
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
params = {'q': key,'page': pg}
|
||||
data=self.getpq(self.session.get(f'{self.host}/search',params=params, headers=self.headers))
|
||||
return {'list':self.getlist(data('.grid.grid-cols-2 div.aspect-video.relative')),'page':pg}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
return {'parse': 0, 'url': f"{self.plp}{id}", 'header': self.headers}
|
||||
|
||||
def localProxy(self, param):
|
||||
pass
|
||||
|
||||
def liveContent(self, url):
|
||||
pass
|
||||
|
||||
def getlist(self,data):
|
||||
videos = []
|
||||
for i in data.items():
|
||||
videos.append({
|
||||
'vod_id': i('a').attr('href'),
|
||||
'vod_name': i('img.relative.w-full').attr('alt'),
|
||||
'vod_pic': i('img.relative.w-full').attr('src'),
|
||||
'vod_year': i('.absolute.top-1').text(),
|
||||
'vod_remarks': i('.absolute.bottom-1').text(),
|
||||
'style': {"type": "rect", "ratio": 1.33}
|
||||
})
|
||||
return videos
|
||||
|
||||
def getpq(self, data):
|
||||
try:
|
||||
return pq(data.text)
|
||||
except Exception as e:
|
||||
print(f"{str(e)}")
|
||||
return pq(data.text.encode('utf-8'))
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
// ==UserScript==
|
||||
// @name XOJAV
|
||||
// @namespace gmspider
|
||||
// @version 2024.12.02
|
||||
// @description XOJAV GMSpider
|
||||
// @author Luomo
|
||||
// @match https://xojav.tv/*
|
||||
// @require https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.slim.min.js
|
||||
// @grant unsafeWindow
|
||||
// ==/UserScript==
|
||||
console.log(JSON.stringify(GM_info));
|
||||
(function () {
|
||||
const GMSpiderArgs = {};
|
||||
if (typeof GmSpiderInject !== 'undefined') {
|
||||
let args = JSON.parse(GmSpiderInject.GetSpiderArgs());
|
||||
GMSpiderArgs.fName = args.shift();
|
||||
GMSpiderArgs.fArgs = args;
|
||||
} else {
|
||||
GMSpiderArgs.fName = "searchContent";
|
||||
GMSpiderArgs.fArgs = [["ssni-748"]];
|
||||
}
|
||||
Object.freeze(GMSpiderArgs);
|
||||
const GmSpider = (function () {
|
||||
function listVideos(select) {
|
||||
let vods = [];
|
||||
$(select).each(function () {
|
||||
const remarks = [
|
||||
"👁️" + $(this).find(".card-video__stats .num:first").text().trim(),
|
||||
"❤️" + $(this).find(".card-video__fav-button .num").text().trim()
|
||||
];
|
||||
const url = new URL($(this).find(".card-video__title a").attr("href"));
|
||||
vods.push({
|
||||
vod_id: url.pathname.split('/').at(2).toUpperCase(),
|
||||
vod_name: $(this).find(".card-video__img img").attr("alt"),
|
||||
vod_pic: $(this).find(".card-video__img img").data("src"),
|
||||
vod_remarks: remarks.join(" "),
|
||||
vod_year: $(this).find(".card-video__duration").text().trim()
|
||||
})
|
||||
})
|
||||
return vods;
|
||||
}
|
||||
|
||||
return {
|
||||
homeContent: function (filter) {
|
||||
let result = {
|
||||
class: [
|
||||
{type_id: "latest-updates?sort_by=release_at", type_name: "最近更新"},
|
||||
{type_id: "categories/taiwan-av?sort_by=release_at", type_name: "台湾AV"},
|
||||
{type_id: "stars?sort_by=stars", type_name: "近期最佳"},
|
||||
{type_id: "hot?sort_by=views", type_name: "热门"},
|
||||
{type_id: "categories?", type_name: "所有分类"},
|
||||
],
|
||||
filters: {
|
||||
"categories/taiwan-av?sort_by=release_at": [{
|
||||
key: "sort_by",
|
||||
name: "排序",
|
||||
value: [
|
||||
{n: "近期最佳", v: "&sort_by=stars"},
|
||||
{n: "观看数", v: "&sort_by=views"},
|
||||
{n: "最近更新", v: "&sort_by=release_at"}
|
||||
]
|
||||
}],
|
||||
"categories?": [{
|
||||
key: "sort_by",
|
||||
name: "排序",
|
||||
value: [
|
||||
{n: "近期最佳", v: "&sort_by=stars"},
|
||||
{n: "观看数", v: "&sort_by=views"},
|
||||
{n: "最近更新", v: "&sort_by=release_at"},
|
||||
]
|
||||
}]
|
||||
},
|
||||
list: []
|
||||
};
|
||||
let itemList = listVideos(".card-video");
|
||||
result.list = itemList.filter((item, index) => {
|
||||
return itemList.findIndex(i => i.vod_id === item.vod_id) === index
|
||||
});
|
||||
return result;
|
||||
},
|
||||
categoryContent: function (tid, pg, filter, extend) {
|
||||
let result = {
|
||||
list: [],
|
||||
pagecount: 1
|
||||
};
|
||||
if (tid === "categories?") {
|
||||
$(".padding-bottom-xl").each(function () {
|
||||
let remarks = $(this).find(".title--listing").text().trim();
|
||||
$(this).find(".card-cat-v2").each(function () {
|
||||
const url = new URL($(this).find(".card-cat-v2__link").attr("href")).pathname.split('/');
|
||||
result.list.push({
|
||||
vod_id: url[1] + "/" + url[2] + "?sort_by=release_at",
|
||||
vod_name: $(this).find(".card-cat-v2__title h4").text(),
|
||||
vod_pic: $(this).find("img").attr("src"),
|
||||
vod_remarks: remarks,
|
||||
vod_tag: "folder",
|
||||
style: {
|
||||
"type": "rect",
|
||||
"ratio": 0.7
|
||||
}
|
||||
})
|
||||
});
|
||||
})
|
||||
result.pagecount = 1;
|
||||
} else {
|
||||
result.list = listVideos(".card-video");
|
||||
result.pagecount = $('.pagination__list li[class] .pagination__item:last').text().trim();
|
||||
}
|
||||
return result;
|
||||
},
|
||||
detailContent: function (ids) {
|
||||
let categories = [], tags = [];
|
||||
$(".content-details__meta a").each(function () {
|
||||
const url = new URL($(this).attr("href")).pathname.split('/');
|
||||
const id = url[1] + "/" + url[2] + "?sort_by=release_at";
|
||||
const name = $(this).text().trim();
|
||||
if (name.length > 0) {
|
||||
if (url[1] === "categories") {
|
||||
categories.push(`[a=cr:{"id":"${id}","name":"${name}"}/]${name}[/a]`);
|
||||
} else {
|
||||
tags.push(`[a=cr:{"id":"${id}","name":"${name}"}/]${name}[/a]`);
|
||||
}
|
||||
}
|
||||
})
|
||||
const vod = {
|
||||
vod_id: ids[0],
|
||||
vod_name: ids[0].toUpperCase(),
|
||||
vod_year: $(".content-details__meta time").text(),
|
||||
vod_remarks: categories.join(" "),
|
||||
vod_actor: tags.join(" "),
|
||||
vod_content: $(".content-details__title").text(),
|
||||
vod_play_from: "老僧酿酒",
|
||||
vod_play_url: "名妓读经$" + unsafeWindow.stream,
|
||||
};
|
||||
return {list: [vod]};
|
||||
},
|
||||
searchContent: function (key, quick, pg) {
|
||||
const result = {
|
||||
list: [],
|
||||
pagecount: 1
|
||||
};
|
||||
result.list = listVideos(".card-video");
|
||||
result.pagecount = Math.ceil($('.title--sub-title').text().replace(/[^0-9]/ig, "") / 24)
|
||||
return result;
|
||||
}
|
||||
};
|
||||
})();
|
||||
$(document).ready(function () {
|
||||
let result = "";
|
||||
if ($("#cf-wrapper").length > 0) {
|
||||
console.log("源站不可用:" + $('title').text());
|
||||
GM_toastLong("源站不可用:" + $('title').text());
|
||||
} else {
|
||||
result = GmSpider[GMSpiderArgs.fName](...GMSpiderArgs.fArgs);
|
||||
}
|
||||
console.log(result);
|
||||
if (typeof GmSpiderInject !== 'undefined') {
|
||||
GmSpiderInject.SetSpiderResult(JSON.stringify(result));
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
|
@ -0,0 +1,324 @@
|
|||
// ==UserScript==
|
||||
// @name yfsp
|
||||
// @namespace gmspider
|
||||
// @version 2024.11.12
|
||||
// @description 爱壹帆 GMSpider
|
||||
// @author Luomo
|
||||
// @match https://m.yfsp.tv/*
|
||||
// @require https://cdn.jsdelivr.net/gh/CatVodSpider-GM/Spiders-Lib@main/lib/browser-extension-url-match-1.2.0.min.js
|
||||
// @require https://cdn.jsdelivr.net/npm/ajax-hook@3.0.3/dist/ajaxhook.umd.min.js
|
||||
// @grant GM_setValue
|
||||
// @grant GM_getValue
|
||||
// @grant unsafeWindow
|
||||
// @run-at document-start
|
||||
// ==/UserScript==
|
||||
console.log(JSON.stringify(GM_info));
|
||||
(function () {
|
||||
const GMSpiderArgs = {};
|
||||
if (typeof GmSpiderInject !== 'undefined') {
|
||||
let args = JSON.parse(GmSpiderInject.GetSpiderArgs());
|
||||
GMSpiderArgs.fName = args.shift();
|
||||
GMSpiderArgs.fArgs = args;
|
||||
} else {
|
||||
// GMSpiderArgs.fName = "homeContent";
|
||||
// GMSpiderArgs.fArgs = [true];
|
||||
// GMSpiderArgs.fName = "categoryContent";
|
||||
// GMSpiderArgs.fArgs = ["movie", 2, true, {}];
|
||||
// GMSpiderArgs.fName = "detailContent";
|
||||
// GMSpiderArgs.fArgs = [["XOkJ0XqSwI2"]];
|
||||
GMSpiderArgs.fName = "searchContent";
|
||||
GMSpiderArgs.fArgs = ["小巷人家", false, 1];
|
||||
}
|
||||
Object.freeze(GMSpiderArgs);
|
||||
(function () {
|
||||
switch (GMSpiderArgs.fName) {
|
||||
case "searchContent":
|
||||
localStorage.setItem("historyList", JSON.stringify([GMSpiderArgs.fArgs [0]]));
|
||||
break;
|
||||
}
|
||||
})();
|
||||
let hookConfigs = {
|
||||
"homeContent": [{
|
||||
dataKey: "navigationbar",
|
||||
matcher: matchPattern("https://*.yfsp.tv/api/list/navigationbar?*").assertValid()
|
||||
}, {
|
||||
dataKey: "index",
|
||||
matcher: matchPattern("https://*.yfsp.tv/api/list/index?*").assertValid()
|
||||
}],
|
||||
"categoryContent": [{
|
||||
dataKey: "filtertagsdata",
|
||||
matcher: matchPattern("https://*.yfsp.tv/api/list/getfiltertagsdata?*").assertValid()
|
||||
}, {
|
||||
dataKey: "conditionfilterdata",
|
||||
matcher: matchPattern("https://*.yfsp.tv/api/list/getconditionfilterdata?*").assertValid(),
|
||||
onRequestHook: function (config, handler) {
|
||||
let url = new URL(config.url);
|
||||
url.searchParams.set('page', GMSpiderArgs.fArgs[1]);
|
||||
config.url = url.toString();
|
||||
}
|
||||
}],
|
||||
"detailContent": [{
|
||||
dataKey: "videodetails",
|
||||
matcher: matchPattern("https://*.yfsp.tv/api/video/videodetails?*").assertValid()
|
||||
}, {
|
||||
dataKey: "playdata",
|
||||
matcher: matchPattern("https://*.yfsp.tv/api/video/getplaydata?*").assertValid()
|
||||
}, {
|
||||
dataKey: "videochoosegather",
|
||||
require: false,
|
||||
matcher: matchPattern("https://*.yfsp.tv/api/video/videochoosegather?*").assertValid()
|
||||
}],
|
||||
"playerContent": [{
|
||||
dataKey: "playdata",
|
||||
matcher: matchPattern("https://*.yfsp.tv/api/video/getplaydata?*").assertValid()
|
||||
}],
|
||||
"searchContent": [{
|
||||
dataKey: "titlegetdata",
|
||||
matcher: matchPattern("https://*.yfsp.tv/api/list/gettitlegetdata?*").assertValid()
|
||||
}, {
|
||||
matcher: matchPattern("https://*.yfsp.tv/api/home/gethotsearch?*").assertValid(),
|
||||
onResponseHook: function (response, handler) {
|
||||
document.querySelector(".search-log span").dispatchEvent(new Event("click"));
|
||||
}
|
||||
}],
|
||||
};
|
||||
const GmSpider = (function () {
|
||||
const categoryFilterCachePrefix = "category.";
|
||||
return {
|
||||
homeContent: function (filter) {
|
||||
let result = {
|
||||
class: [],
|
||||
filters: {},
|
||||
list: []
|
||||
};
|
||||
let categoryIds = [];
|
||||
hookResult.navigationbar.data.list.forEach((item) => {
|
||||
if (item.type === 1) {
|
||||
result.class.push({
|
||||
type_id: item.routeName,
|
||||
type_name: item.name
|
||||
});
|
||||
categoryIds.push(item.categoryId);
|
||||
// const cacheFilter = GM_getValue(item.routeName);
|
||||
// console.log("cacheFilter", item.routeName, cacheFilter);
|
||||
const cacheFilter = localStorage.getItem(categoryFilterCachePrefix + item.routeName);
|
||||
console.log("localStorage", item.routeName, localStorage.getItem(item.routeName));
|
||||
if (typeof cacheFilter !== "undefined" && cacheFilter !== null) {
|
||||
result.filters[item.routeName] = JSON.parse(cacheFilter);
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
hookResult.index.data.list.forEach((item) => {
|
||||
if (categoryIds.includes(item.type)) {
|
||||
item.list.forEach((media) => {
|
||||
if (!media.isRecommend) {
|
||||
result.list.push({
|
||||
vod_id: media.mediaKey,
|
||||
vod_name: media.title,
|
||||
vod_pic: media.coverImgUrl,
|
||||
vod_remarks: media.updateStatus,
|
||||
vod_year: media.mediaType
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
return result;
|
||||
},
|
||||
categoryContent: function (tid, pg, filter, extend) {
|
||||
let result = {
|
||||
list: [],
|
||||
pagecount: 1000
|
||||
};
|
||||
let cacheFilters = [];
|
||||
hookResult.filtertagsdata.data.list.forEach(classify => {
|
||||
let cacheFilter = {
|
||||
key: "index-" + classify.list[0].index,
|
||||
name: classify.name,
|
||||
value: []
|
||||
}
|
||||
classify.list.forEach((item) => {
|
||||
cacheFilter.value.push({
|
||||
n: item.classifyName,
|
||||
v: (item.index > 0 ? "," : "") + item.classifyId
|
||||
});
|
||||
})
|
||||
cacheFilters.push(cacheFilter);
|
||||
})
|
||||
// GM_setValue(tid, JSON.stringify(cacheFilters));
|
||||
localStorage.setItem(categoryFilterCachePrefix + tid, JSON.stringify(cacheFilters));
|
||||
console.log("cacheFilter", tid, cacheFilters);
|
||||
hookResult.conditionfilterdata.data.list.forEach((media) => {
|
||||
result.list.push({
|
||||
vod_id: media.mediaKey,
|
||||
vod_name: media.title,
|
||||
vod_pic: media.coverImgUrl,
|
||||
vod_remarks: media.updateStatus,
|
||||
vod_year: media.regional
|
||||
})
|
||||
})
|
||||
return result;
|
||||
},
|
||||
detailContent: function (ids) {
|
||||
const videodetails = hookResult.videodetails.data.detailInfo;
|
||||
let mediaUrl = "";
|
||||
let episodeKey = "";
|
||||
hookResult.playdata.data.list.forEach((item) => {
|
||||
if (mediaUrl === "" && item.mediaUrl !== "") {
|
||||
mediaUrl = item.mediaUrl;
|
||||
episodeKey = item.episodeKey;
|
||||
}
|
||||
})
|
||||
let media = [];
|
||||
if (videodetails.videoType !== 0) {
|
||||
if (typeof hookResult.videochoosegather !== "undefined") {
|
||||
hookResult.videochoosegather.data.list.forEach((item) => {
|
||||
if (videodetails.episodeTitle === item.episodeTitle) {
|
||||
media.push({
|
||||
name: item.episodeTitle,
|
||||
type: "finalUrl",
|
||||
ext: {
|
||||
"header": {
|
||||
"User-Agent": window.navigator.userAgent,
|
||||
"Referer": window.location.href
|
||||
},
|
||||
"url": mediaUrl
|
||||
}
|
||||
});
|
||||
} else {
|
||||
media.push({
|
||||
name: item.episodeTitle,
|
||||
type: "webview",
|
||||
ext: {
|
||||
replace: {
|
||||
mediaKey: item.mediaKey,
|
||||
episodeKey: item.episodeKey
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
spiderExecuted = false;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
media.push({
|
||||
name: videodetails.episodeTitle,
|
||||
type: "finalUrl",
|
||||
ext: {
|
||||
"header": {
|
||||
"User-Agent": window.navigator.userAgent,
|
||||
"Referer": window.location.href
|
||||
},
|
||||
"url": mediaUrl
|
||||
}
|
||||
})
|
||||
}
|
||||
return {
|
||||
vod_id: videodetails.mediaKey,
|
||||
vod_name: videodetails.title,
|
||||
vod_pic: videodetails.coverImgUrl,
|
||||
vod_actor: videodetails.actor,
|
||||
vod_director: videodetails.director,
|
||||
vod_tag: videodetails.cidMapper,
|
||||
vod_area: videodetails.regional,
|
||||
vod_content: videodetails.introduce,
|
||||
vod_play_data: [{
|
||||
from: "老僧酿酒",
|
||||
media: media
|
||||
}]
|
||||
};
|
||||
},
|
||||
playerContent: function (flag, id, vipFlags) {
|
||||
let mediaUrl = "";
|
||||
hookResult.playdata.data.list.forEach((item) => {
|
||||
if (mediaUrl === "" && item.mediaUrl !== "") {
|
||||
mediaUrl = item.mediaUrl;
|
||||
}
|
||||
})
|
||||
return {
|
||||
type: "finalUrl",
|
||||
ext: {
|
||||
"header": {
|
||||
"User-Agent": window.navigator.userAgent,
|
||||
"Referer": window.location.href
|
||||
},
|
||||
"url": mediaUrl
|
||||
}
|
||||
};
|
||||
},
|
||||
searchContent: function (key, quick, pg) {
|
||||
console.log(hookResult);
|
||||
let result = {
|
||||
list: [],
|
||||
pagecount: 1
|
||||
};
|
||||
if (pg == 1) {
|
||||
hookResult.titlegetdata.data.list.forEach((media) => {
|
||||
result.list.push({
|
||||
vod_id: media.mediaKey,
|
||||
vod_name: media.title,
|
||||
vod_pic: media.coverImgUrl,
|
||||
vod_remarks: media.updateStatus,
|
||||
vod_year: media.regional
|
||||
})
|
||||
})
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
})();
|
||||
let spiderExecuted = false;
|
||||
let dataReadyCount = 0;
|
||||
let hookResult = {};
|
||||
const {unProxy, originXhr} = proxy({
|
||||
onRequest: (config, handler) => {
|
||||
hookConfigs[GMSpiderArgs.fName].forEach((hookConfig) => {
|
||||
if (typeof hookConfig.onRequestHook === "function" && hookConfig.matcher.match(config.url)) {
|
||||
hookConfig.onRequestHook(config, handler);
|
||||
}
|
||||
});
|
||||
handler.next(config);
|
||||
},
|
||||
onResponse: (response, handler) => {
|
||||
if (!spiderExecuted) {
|
||||
let dataTodoCount = 0;
|
||||
hookConfigs[GMSpiderArgs.fName].forEach((hookConfig) => {
|
||||
if (typeof hookConfig.dataKey !== "undefined") {
|
||||
if (hookConfig?.require !== false) {
|
||||
dataTodoCount++;
|
||||
}
|
||||
if (hookConfig.matcher.match(response.config.url)) {
|
||||
if (hookConfig?.require !== false) {
|
||||
dataReadyCount++;
|
||||
}
|
||||
try {
|
||||
let data = JSON.parse(response.response);
|
||||
if (typeof data === 'object' && data) {
|
||||
hookResult[hookConfig.dataKey] = data;
|
||||
} else {
|
||||
hookResult[hookConfig.dataKey] = response.response;
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeof hookConfig.onResponseHook === "function" && hookConfig.matcher.match(response.config.url)) {
|
||||
hookConfig.onResponseHook(response, handler);
|
||||
}
|
||||
});
|
||||
if (dataTodoCount === dataReadyCount) {
|
||||
spiderExecuted = true;
|
||||
const result = GmSpider[GMSpiderArgs.fName](...GMSpiderArgs.fArgs);
|
||||
console.log(result);
|
||||
if (typeof GmSpiderInject !== 'undefined' && spiderExecuted) {
|
||||
GmSpiderInject.SetSpiderResult(JSON.stringify(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
handler.next(response);
|
||||
}
|
||||
}, unsafeWindow)
|
||||
})();
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,383 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# by @嗷呜
|
||||
import json
|
||||
import random
|
||||
import re
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from base64 import b64decode, b64encode
|
||||
from urllib.parse import urlparse
|
||||
import requests
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import unpad
|
||||
from pyquery import PyQuery as pq
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
|
||||
|
||||
class Spider(Spider):
|
||||
|
||||
def init(self, extend=""):
|
||||
try:self.proxies = json.loads(extend).get('proxy',{})
|
||||
except:self.proxies = {}
|
||||
self.headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
|
||||
'Pragma': 'no-cache',
|
||||
'Cache-Control': 'no-cache',
|
||||
'sec-ch-ua-platform': '"macOS"',
|
||||
'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="134", "Google Chrome";v="134"',
|
||||
'DNT': '1',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'Origin': '',
|
||||
'Sec-Fetch-Site': 'cross-site',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9',
|
||||
}
|
||||
self.host=self.host_late(self.gethosts())
|
||||
self.headers.update({'Origin': self.host, 'Referer': f"{self.host}/"})
|
||||
self.getcnh()
|
||||
pass
|
||||
|
||||
def getName(self):
|
||||
pass
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
def homeContent(self, filter):
|
||||
data=self.getpq(requests.get(self.host, headers=self.headers,proxies=self.proxies).text)
|
||||
result = {}
|
||||
classes = []
|
||||
for k in list(data('.navbar-nav.mr-auto').children('li').items())[1:-3]:
|
||||
if k('ul'):
|
||||
for j in k('ul li').items():
|
||||
classes.append({
|
||||
'type_name': j('a').text(),
|
||||
'type_id': j('a').attr('href').strip()+'/',
|
||||
})
|
||||
else:
|
||||
classes.append({
|
||||
'type_name': k('a').text(),
|
||||
'type_id': k('a').attr('href').strip()+'/',
|
||||
})
|
||||
result['class'] = classes
|
||||
result['list'] = self.getlist(data('#index article a'))
|
||||
return result
|
||||
|
||||
def getcnh(self):
|
||||
data=self.getpq(requests.get(f"{self.host}/homeway.html", headers=self.headers,proxies=self.proxies).text)
|
||||
url=data('.post-content[itemprop="articleBody"] blockquote p').eq(0)('a').attr('href')
|
||||
parsed_url = urlparse(url)
|
||||
host = parsed_url.scheme + "://" + parsed_url.netloc
|
||||
self.setCache('host_51cn',host)
|
||||
|
||||
def homeVideoContent(self):
|
||||
pass
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
if '@folder' in tid:
|
||||
id=tid.replace('@folder','')
|
||||
videos=self.getfod(id)
|
||||
else:
|
||||
data=self.getpq(requests.get(f"{self.host}{tid}{pg}", headers=self.headers,proxies=self.proxies).text)
|
||||
videos=self.getlist(data('#archive article a'),tid)
|
||||
result = {}
|
||||
result['list'] = videos
|
||||
result['page'] = pg
|
||||
result['pagecount'] = 1 if '@folder' in tid else 99999
|
||||
result['limit'] = 90
|
||||
result['total'] = 999999
|
||||
return result
|
||||
|
||||
def getfod(self, id):
|
||||
url = f"{self.host}{id}"
|
||||
data = self.getpq(requests.get(url, headers=self.headers, proxies=self.proxies).text)
|
||||
vdata=data('.post-content[itemprop="articleBody"]')
|
||||
r=['.txt-apps','.line','blockquote','.tags','.content-tabs']
|
||||
for i in r:vdata.remove(i)
|
||||
p=vdata('p')
|
||||
videos=[]
|
||||
for i,x in enumerate(vdata('h2').items()):
|
||||
c=i*2
|
||||
videos.append({
|
||||
'vod_id': p.eq(c)('a').attr('href'),
|
||||
'vod_name': p.eq(c).text(),
|
||||
'vod_pic': f"{self.getProxyUrl()}&url={p.eq(c+1)('img').attr('data-xkrkllgl')}&type=img",
|
||||
'vod_remarks':x.text()
|
||||
})
|
||||
return videos
|
||||
|
||||
def detailContent(self, ids):
|
||||
url=f"{self.host}{ids[0]}"
|
||||
data=self.getpq(requests.get(url, headers=self.headers,proxies=self.proxies).text)
|
||||
vod = {'vod_play_from': '老僧酿酒'}
|
||||
try:
|
||||
clist = []
|
||||
if data('.tags .keywords a'):
|
||||
for k in data('.tags .keywords a').items():
|
||||
title = k.text()
|
||||
href = k.attr('href')
|
||||
clist.append('[a=cr:' + json.dumps({'id': href, 'name': title}) + '/]' + title + '[/a]')
|
||||
vod['vod_content'] = ' '.join(clist)
|
||||
except:
|
||||
vod['vod_content'] = data('.post-title').text()
|
||||
try:
|
||||
plist=[]
|
||||
if data('.dplayer'):
|
||||
for c, k in enumerate(data('.dplayer').items(), start=1):
|
||||
config = json.loads(k.attr('data-config'))
|
||||
plist.append(f"视频{c}${config['video']['url']}")
|
||||
vod['vod_play_url']='#'.join(plist)
|
||||
except:
|
||||
vod['vod_play_url']=f"可能没有视频${url}"
|
||||
return {'list':[vod]}
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
data=self.getpq(requests.get(f"{self.host}/search/{key}/{pg}", headers=self.headers,proxies=self.proxies).text)
|
||||
return {'list':self.getlist(data('#archive article a')),'page':pg}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
p=1
|
||||
if '.m3u8' in id:p,id=0,self.proxy(id)
|
||||
return {'parse': p, 'url': id, 'header': self.headers}
|
||||
|
||||
def localProxy(self, param):
|
||||
if param.get('type') == 'img':
|
||||
res=requests.get(param['url'], headers=self.headers, proxies=self.proxies, timeout=10)
|
||||
return [200,res.headers.get('Content-Type'),self.aesimg(res.content)]
|
||||
elif param.get('type') == 'm3u8':return self.m3Proxy(param['url'])
|
||||
else:return self.tsProxy(param['url'])
|
||||
|
||||
def proxy(self, data, type='m3u8'):
|
||||
if data and len(self.proxies):return f"{self.getProxyUrl()}&url={self.e64(data)}&type={type}"
|
||||
else:return data
|
||||
|
||||
def m3Proxy(self, url):
|
||||
url=self.d64(url)
|
||||
ydata = requests.get(url, headers=self.headers, proxies=self.proxies, allow_redirects=False)
|
||||
print(ydata.text)
|
||||
data = ydata.content.decode('utf-8')
|
||||
if ydata.headers.get('Location'):
|
||||
url = ydata.headers['Location']
|
||||
data = requests.get(url, headers=self.headers, proxies=self.proxies).content.decode('utf-8')
|
||||
lines = data.strip().split('\n')
|
||||
last_r = url[:url.rfind('/')]
|
||||
parsed_url = urlparse(url)
|
||||
durl = parsed_url.scheme + "://" + parsed_url.netloc
|
||||
iskey=True
|
||||
for index, string in enumerate(lines):
|
||||
if iskey and 'URI' in string:
|
||||
pattern = r'URI="([^"]*)"'
|
||||
match = re.search(pattern, string)
|
||||
if match:
|
||||
lines[index] = re.sub(pattern, f'URI="{self.proxy(match.group(1), "mkey")}"', string)
|
||||
iskey=False
|
||||
continue
|
||||
if '#EXT' not in string:
|
||||
if 'http' not in string:
|
||||
domain = last_r if string.count('/') < 2 else durl
|
||||
string = domain + ('' if string.startswith('/') else '/') + string
|
||||
lines[index] = self.proxy(string, string.split('.')[-1].split('?')[0])
|
||||
data = '\n'.join(lines)
|
||||
return [200, "application/vnd.apple.mpegur", data]
|
||||
|
||||
def tsProxy(self, url):
|
||||
url = self.d64(url)
|
||||
data = requests.get(url, headers=self.headers, proxies=self.proxies, stream=True)
|
||||
return [200, data.headers['Content-Type'], data.content]
|
||||
|
||||
def e64(self, text):
|
||||
try:
|
||||
text_bytes = text.encode('utf-8')
|
||||
encoded_bytes = b64encode(text_bytes)
|
||||
return encoded_bytes.decode('utf-8')
|
||||
except Exception as e:
|
||||
print(f"Base64编码错误: {str(e)}")
|
||||
return ""
|
||||
|
||||
def d64(self, encoded_text):
|
||||
try:
|
||||
encoded_bytes = encoded_text.encode('utf-8')
|
||||
decoded_bytes = b64decode(encoded_bytes)
|
||||
return decoded_bytes.decode('utf-8')
|
||||
except Exception as e:
|
||||
print(f"Base64解码错误: {str(e)}")
|
||||
return ""
|
||||
|
||||
def gethosts(self):
|
||||
url='https://51cg.fun'
|
||||
curl=self.getCache('host_51cn')
|
||||
if curl:
|
||||
try:
|
||||
data=self.getpq(requests.get(curl, headers=self.headers, proxies=self.proxies).text)('a').attr('href')
|
||||
if data:
|
||||
parsed_url = urlparse(data)
|
||||
url = parsed_url.scheme + "://" + parsed_url.netloc
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
html = self.getpq(requests.get(url, headers=self.headers, proxies=self.proxies).text)
|
||||
html_pattern = r"Base64\.decode\('([^']+)'\)"
|
||||
html_match = re.search(html_pattern, html('script').eq(-1).text(), re.DOTALL)
|
||||
if not html_match:raise Exception("未找到html")
|
||||
html = self.getpq(b64decode(html_match.group(1)).decode())('script').eq(-4).text()
|
||||
return self.hstr(html)
|
||||
except Exception as e:
|
||||
self.log(f"获取: {str(e)}")
|
||||
return ""
|
||||
|
||||
def hstr(self, html):
|
||||
pattern = r"(backupLine\s*=\s*\[\])\s+(words\s*=)"
|
||||
replacement = r"\1, \2"
|
||||
html = re.sub(pattern, replacement, html)
|
||||
data = f"""
|
||||
var Vx = {{
|
||||
range: function(start, end) {{
|
||||
const result = [];
|
||||
for (let i = start; i < end; i++) {{
|
||||
result.push(i);
|
||||
}}
|
||||
return result;
|
||||
}},
|
||||
|
||||
map: function(array, callback) {{
|
||||
const result = [];
|
||||
for (let i = 0; i < array.length; i++) {{
|
||||
result.push(callback(array[i], i, array));
|
||||
}}
|
||||
return result;
|
||||
}}
|
||||
}};
|
||||
|
||||
Array.prototype.random = function() {{
|
||||
return this[Math.floor(Math.random() * this.length)];
|
||||
}};
|
||||
|
||||
var location = {{
|
||||
protocol: "https:"
|
||||
}};
|
||||
|
||||
function executeAndGetResults() {{
|
||||
var allLines = lineAry.concat(backupLine);
|
||||
var resultStr = JSON.stringify(allLines);
|
||||
return resultStr;
|
||||
}};
|
||||
{html}
|
||||
executeAndGetResults();
|
||||
"""
|
||||
return self.p_qjs(data)
|
||||
|
||||
def p_qjs(self, js_code):
|
||||
try:
|
||||
from com.whl.quickjs.wrapper import QuickJSContext
|
||||
ctx = QuickJSContext.create()
|
||||
result_json = ctx.evaluate(js_code)
|
||||
ctx.destroy()
|
||||
return json.loads(result_json)
|
||||
|
||||
except Exception as e:
|
||||
self.log(f"执行失败: {e}")
|
||||
return []
|
||||
|
||||
def get_domains(self):
|
||||
html = self.getpq(requests.get("https://51cg.fun", headers=self.headers,proxies=self.proxies).text)
|
||||
html_pattern = r"Base64\.decode\('([^']+)'\)"
|
||||
html_match = re.search(html_pattern, html('script').eq(-1).text(), re.DOTALL)
|
||||
if not html_match:
|
||||
raise Exception("未找到html")
|
||||
html = b64decode(html_match.group(1)).decode()
|
||||
words_pattern = r"words\s*=\s*'([^']+)'"
|
||||
words_match = re.search(words_pattern, html, re.DOTALL)
|
||||
if not words_match:
|
||||
raise Exception("未找到words")
|
||||
words = words_match.group(1).split(',')
|
||||
main_pattern = r"lineAry\s*=.*?words\.random\(\)\s*\+\s*'\.([^']+)'"
|
||||
domain_match = re.search(main_pattern, html, re.DOTALL)
|
||||
if not domain_match:
|
||||
raise Exception("未找到主域名")
|
||||
domain_suffix = domain_match.group(1)
|
||||
domains = []
|
||||
for _ in range(3):
|
||||
random_word = random.choice(words)
|
||||
domain = f"https://{random_word}.{domain_suffix}"
|
||||
domains.append(domain)
|
||||
return domains
|
||||
|
||||
def host_late(self, url_list):
|
||||
if isinstance(url_list, str):
|
||||
urls = [u.strip() for u in url_list.split(',')]
|
||||
else:
|
||||
urls = url_list
|
||||
|
||||
if len(urls) <= 1:
|
||||
return urls[0] if urls else ''
|
||||
|
||||
results = {}
|
||||
threads = []
|
||||
|
||||
def test_host(url):
|
||||
try:
|
||||
start_time = time.time()
|
||||
response = requests.head(url,headers=self.headers,proxies=self.proxies,timeout=1.0, allow_redirects=False)
|
||||
delay = (time.time() - start_time) * 1000
|
||||
results[url] = delay
|
||||
except Exception as e:
|
||||
results[url] = float('inf')
|
||||
|
||||
for url in urls:
|
||||
t = threading.Thread(target=test_host, args=(url,))
|
||||
threads.append(t)
|
||||
t.start()
|
||||
|
||||
for t in threads:
|
||||
t.join()
|
||||
|
||||
return min(results.items(), key=lambda x: x[1])[0]
|
||||
|
||||
def getlist(self,data,tid=''):
|
||||
videos = []
|
||||
l='/mrdg' in tid
|
||||
for k in data.items():
|
||||
a=k.attr('href')
|
||||
b=k('h2').text()
|
||||
c=k('span[itemprop="datePublished"]').text()
|
||||
if a and b and c:
|
||||
videos.append({
|
||||
'vod_id': f"{a}{'@folder' if l else ''}",
|
||||
'vod_name': b.replace('\n', ' '),
|
||||
'vod_pic': self.getimg(k('script').text()),
|
||||
'vod_remarks': c,
|
||||
'vod_tag':'folder' if l else '',
|
||||
'style': {"type": "rect", "ratio": 1.33}
|
||||
})
|
||||
return videos
|
||||
|
||||
def getimg(self, text):
|
||||
match = re.search(r"loadBannerDirect\('([^']+)'", text)
|
||||
if match:
|
||||
url = match.group(1)
|
||||
return f"{self.getProxyUrl()}&url={url}&type=img"
|
||||
else:
|
||||
return ''
|
||||
|
||||
def aesimg(self, word):
|
||||
key = b'f5d965df75336270'
|
||||
iv = b'97b60394abc2fbe1'
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||||
decrypted = unpad(cipher.decrypt(word), AES.block_size)
|
||||
return decrypted
|
||||
|
||||
def getpq(self, data):
|
||||
try:
|
||||
return pq(data)
|
||||
except Exception as e:
|
||||
print(f"{str(e)}")
|
||||
return pq(data.encode('utf-8'))
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,536 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Author : Doubebly
|
||||
# @Time : 2025/3/22 21:03
|
||||
import json
|
||||
import sys
|
||||
import requests
|
||||
from lxml import etree, html
|
||||
import re
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
|
||||
|
||||
class Spider(Spider):
|
||||
def getName(self):
|
||||
return "爱瓜TV"
|
||||
|
||||
def init(self, extend):
|
||||
self.home_url = 'https://aigua1.com'
|
||||
self.headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
|
||||
"Referer": "https://aigua1.com/",
|
||||
}
|
||||
self.image_domain = "https://vres.wbadl.cn" # 圖片域名
|
||||
|
||||
self.default_play_url = 'https://sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4'
|
||||
|
||||
def getDependence(self):
|
||||
return []
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def homeContent(self, filter):
|
||||
result = {
|
||||
'class': [
|
||||
{'type_id': '2', 'type_name': '电视剧'},
|
||||
{'type_id': '1', 'type_name': '电影'},
|
||||
{'type_id': '3', 'type_name': '综艺'},
|
||||
{'type_id': '4', 'type_name': '动漫'},
|
||||
{'type_id': '32', 'type_name': '纪录片'}
|
||||
],
|
||||
'filters': {
|
||||
'1': [ # 电影筛选条件
|
||||
{'name': '剧情', 'key': 'class', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '魔幻', 'v': '179'},
|
||||
{'n': '动作', 'v': '154'},
|
||||
{'n': '科幻', 'v': '159'},
|
||||
{'n': '惊悚', 'v': '156'},
|
||||
{'n': '犯罪', 'v': '157'},
|
||||
{'n': '剧情', 'v': '161'},
|
||||
{'n': '悬疑', 'v': '160'},
|
||||
{'n': '奇幻', 'v': '226'},
|
||||
{'n': '爱情', 'v': '155'},
|
||||
{'n': '战争', 'v': '164'},
|
||||
{'n': '恐怖', 'v': '169'},
|
||||
{'n': '喜剧', 'v': '153'},
|
||||
{'n': '冒险', 'v': '280'},
|
||||
{'n': '灾难', 'v': '281'},
|
||||
{'n': '歌舞', 'v': '282'},
|
||||
{'n': '动画', 'v': '283'},
|
||||
{'n': '经典', 'v': '284'},
|
||||
{'n': '同性', 'v': '285'},
|
||||
{'n': '网络电影', 'v': '286'},
|
||||
{'n': '其他', 'v': '178'}
|
||||
]},
|
||||
{'name': '地区', 'key': 'area', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '大陆', 'v': '18'},
|
||||
{'n': '日本', 'v': '24'},
|
||||
{'n': '香港', 'v': '20'},
|
||||
{'n': '韩国', 'v': '21'},
|
||||
{'n': '台湾', 'v': '23'},
|
||||
{'n': '英国', 'v': '22'},
|
||||
{'n': '东南亚', 'v': '29'},
|
||||
{'n': '欧美', 'v': '19'},
|
||||
{'n': '其它', 'v': '30'}
|
||||
]},
|
||||
{'name': '年份', 'key': 'year', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '2025', 'v': '131'},
|
||||
{'n': '2024', 'v': '130'},
|
||||
{'n': '2023', 'v': '129'},
|
||||
{'n': '2022', 'v': '21'},
|
||||
{'n': '2021', 'v': '22'},
|
||||
{'n': '2020', 'v': '23'},
|
||||
{'n': '2019', 'v': '24'},
|
||||
{'n': '2018', 'v': '25'},
|
||||
{'n': '2017', 'v': '26'},
|
||||
{'n': '2016', 'v': '27'},
|
||||
{'n': '2015', 'v': '28'},
|
||||
{'n': '2014', 'v': '29'},
|
||||
{'n': '2013', 'v': '30'},
|
||||
{'n': '2012', 'v': '31'},
|
||||
{'n': '2011', 'v': '32'},
|
||||
{'n': '2010', 'v': '33'},
|
||||
{'n': '2009', 'v': '34'},
|
||||
{'n': '2008', 'v': '35'},
|
||||
{'n': '更早', 'v': '127'}
|
||||
]},
|
||||
{'name': '状态', 'key': 'status', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '完结', 'v': '1'},
|
||||
{'n': '更新中', 'v': '2'}
|
||||
]},
|
||||
{'name': '排序', 'key': 'by', 'value': [
|
||||
{'n': '添加时间', 'v': 'new'},
|
||||
{'n': '人气高低', 'v': 'hot'},
|
||||
{'n': '评分高低', 'v': 'score'}
|
||||
]}
|
||||
],
|
||||
'2': [ # 电视剧筛选条件
|
||||
{'name': '剧情', 'key': 'class', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '短剧', 'v': '364'},
|
||||
{'n': '偶像', 'v': '251'},
|
||||
{'n': '爱情', 'v': '252'},
|
||||
{'n': '言情', 'v': '253'},
|
||||
{'n': '古装', 'v': '254'},
|
||||
{'n': '历史', 'v': '255'},
|
||||
{'n': '玄幻', 'v': '256'},
|
||||
{'n': '谍战', 'v': '257'},
|
||||
{'n': '历险', 'v': '258'},
|
||||
{'n': '都市', 'v': '259'},
|
||||
{'n': '科幻', 'v': '260'},
|
||||
{'n': '军旅', 'v': '261'},
|
||||
{'n': '喜剧', 'v': '262'},
|
||||
{'n': '武侠', 'v': '263'},
|
||||
{'n': '江湖', 'v': '264'},
|
||||
{'n': '罪案', 'v': '265'},
|
||||
{'n': '青春', 'v': '266'},
|
||||
{'n': '家庭', 'v': '267'},
|
||||
{'n': '战争', 'v': '268'},
|
||||
{'n': '悬疑', 'v': '269'},
|
||||
{'n': '穿越', 'v': '270'},
|
||||
{'n': '宫廷', 'v': '271'},
|
||||
{'n': '神话', 'v': '272'},
|
||||
{'n': '商战', 'v': '273'},
|
||||
{'n': '警匪', 'v': '274'},
|
||||
{'n': '动作', 'v': '275'},
|
||||
{'n': '惊悚', 'v': '276'},
|
||||
{'n': '剧情', 'v': '277'},
|
||||
{'n': '同性', 'v': '278'},
|
||||
{'n': '奇幻', 'v': '279'},
|
||||
{'n': '其他', 'v': '231'}
|
||||
]},
|
||||
{'name': '地区', 'key': 'area', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '大陆', 'v': '18'},
|
||||
{'n': '日本', 'v': '24'},
|
||||
{'n': '香港', 'v': '20'},
|
||||
{'n': '韩国', 'v': '21'},
|
||||
{'n': '台湾', 'v': '23'},
|
||||
{'n': '英国', 'v': '22'},
|
||||
{'n': '东南亚', 'v': '29'},
|
||||
{'n': '欧美', 'v': '19'},
|
||||
{'n': '其它', 'v': '30'}
|
||||
]},
|
||||
{'name': '年份', 'key': 'year', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '2025', 'v': '131'},
|
||||
{'n': '2024', 'v': '130'},
|
||||
{'n': '2023', 'v': '129'},
|
||||
{'n': '2022', 'v': '21'},
|
||||
{'n': '2021', 'v': '22'},
|
||||
{'n': '2020', 'v': '23'},
|
||||
{'n': '2019', 'v': '24'},
|
||||
{'n': '2018', 'v': '25'},
|
||||
{'n': '2017', 'v': '26'},
|
||||
{'n': '2016', 'v': '27'},
|
||||
{'n': '2015', 'v': '28'},
|
||||
{'n': '2014', 'v': '29'},
|
||||
{'n': '2013', 'v': '30'},
|
||||
{'n': '2012', 'v': '31'},
|
||||
{'n': '2011', 'v': '32'},
|
||||
{'n': '2010', 'v': '33'},
|
||||
{'n': '2009', 'v': '34'},
|
||||
{'n': '2008', 'v': '35'},
|
||||
{'n': '更早', 'v': '127'}
|
||||
]},
|
||||
{'name': '状态', 'key': 'status', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '完结', 'v': '1'},
|
||||
{'n': '更新中', 'v': '2'}
|
||||
]},
|
||||
{'name': '排序', 'key': 'by', 'value': [
|
||||
{'n': '添加时间', 'v': 'new'},
|
||||
{'n': '人气高低', 'v': 'hot'},
|
||||
{'n': '评分高低', 'v': 'score'}
|
||||
]}
|
||||
],
|
||||
'3': [ # 综艺筛选条件
|
||||
{'name': '类型', 'key': 'class', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '生活', 'v': '229'},
|
||||
{'n': '脱口秀', 'v': '228'},
|
||||
{'n': '真人秀', 'v': '227'},
|
||||
{'n': '访谈', 'v': '168'},
|
||||
{'n': '选秀', 'v': '287'},
|
||||
{'n': '网综', 'v': '288'},
|
||||
{'n': '搞笑', 'v': '289'},
|
||||
{'n': '竞技', 'v': '290'},
|
||||
{'n': '情感', 'v': '291'},
|
||||
{'n': '演唱会', 'v': '292'},
|
||||
{'n': '晚会', 'v': '293'},
|
||||
{'n': '其他', 'v': '232'}
|
||||
]},
|
||||
{'name': '地区', 'key': 'area', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '大陆', 'v': '18'},
|
||||
{'n': '日本', 'v': '24'},
|
||||
{'n': '香港', 'v': '20'},
|
||||
{'n': '韩国', 'v': '21'},
|
||||
{'n': '台湾', 'v': '23'},
|
||||
{'n': '东南亚', 'v': '29'},
|
||||
{'n': '欧美', 'v': '19'},
|
||||
{'n': '其它', 'v': '30'}
|
||||
]},
|
||||
{'name': '年份', 'key': 'year', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '2025', 'v': '131'},
|
||||
{'n': '2024', 'v': '130'},
|
||||
{'n': '2023', 'v': '129'},
|
||||
{'n': '2022', 'v': '21'},
|
||||
{'n': '2021', 'v': '22'},
|
||||
{'n': '2020', 'v': '23'},
|
||||
{'n': '2019', 'v': '24'},
|
||||
{'n': '2018', 'v': '25'},
|
||||
{'n': '2017', 'v': '26'},
|
||||
{'n': '2016', 'v': '27'},
|
||||
{'n': '2015', 'v': '28'},
|
||||
{'n': '2014', 'v': '29'},
|
||||
{'n': '2013', 'v': '30'},
|
||||
{'n': '2012', 'v': '31'},
|
||||
{'n': '2011', 'v': '32'},
|
||||
{'n': '2010', 'v': '33'},
|
||||
{'n': '2009', 'v': '34'},
|
||||
{'n': '2008', 'v': '35'},
|
||||
{'n': '更早', 'v': '127'}
|
||||
]},
|
||||
{'name': '状态', 'key': 'status', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '完结', 'v': '1'},
|
||||
{'n': '更新中', 'v': '2'}
|
||||
]},
|
||||
{'name': '排序', 'key': 'by', 'value': [
|
||||
{'n': '添加时间', 'v': 'new'},
|
||||
{'n': '人气高低', 'v': 'hot'},
|
||||
{'n': '评分高低', 'v': 'score'}
|
||||
]}
|
||||
],
|
||||
'4': [ # 动漫筛选条件
|
||||
{'name': '类型', 'key': 'class', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '儿童', 'v': '363'},
|
||||
{'n': '格斗', 'v': '167'},
|
||||
{'n': '热血', 'v': '165'},
|
||||
{'n': '机战', 'v': '166'},
|
||||
{'n': '少女', 'v': '294'},
|
||||
{'n': '竞技', 'v': '295'},
|
||||
{'n': '科幻', 'v': '296'},
|
||||
{'n': '爆笑', 'v': '297'},
|
||||
{'n': '推理', 'v': '298'},
|
||||
{'n': '魔幻', 'v': '299'},
|
||||
{'n': '冒险', 'v': '300'},
|
||||
{'n': '恋爱', 'v': '301'},
|
||||
{'n': '校园', 'v': '302'},
|
||||
{'n': '治愈', 'v': '303'},
|
||||
{'n': '泡面', 'v': '304'},
|
||||
{'n': '穿越', 'v': '305'},
|
||||
{'n': '灵异', 'v': '306'},
|
||||
{'n': '耽美', 'v': '307'},
|
||||
{'n': '剧场版', 'v': '308'},
|
||||
{'n': '其他', 'v': '170'}
|
||||
]},
|
||||
{'name': '地区', 'key': 'area', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '大陆', 'v': '18'},
|
||||
{'n': '日本', 'v': '24'},
|
||||
{'n': '香港', 'v': '20'},
|
||||
{'n': '韩国', 'v': '21'},
|
||||
{'n': '台湾', 'v': '23'},
|
||||
{'n': '英国', 'v': '22'},
|
||||
{'n': '东南亚', 'v': '29'},
|
||||
{'n': '欧美', 'v': '19'},
|
||||
{'n': '其它', 'v': '30'}
|
||||
]},
|
||||
{'name': '年份', 'key': 'year', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '2025', 'v': '131'},
|
||||
{'n': '2024', 'v': '130'},
|
||||
{'n': '2023', 'v': '129'},
|
||||
{'n': '2022', 'v': '21'},
|
||||
{'n': '2021', 'v': '22'},
|
||||
{'n': '2020', 'v': '23'},
|
||||
{'n': '2019', 'v': '24'},
|
||||
{'n': '2018', 'v': '25'},
|
||||
{'n': '2017', 'v': '26'},
|
||||
{'n': '2016', 'v': '27'},
|
||||
{'n': '2015', 'v': '28'},
|
||||
{'n': '2014', 'v': '29'},
|
||||
{'n': '2013', 'v': '30'},
|
||||
{'n': '2012', 'v': '31'},
|
||||
{'n': '2011', 'v': '32'},
|
||||
{'n': '2010', 'v': '33'},
|
||||
{'n': '2009', 'v': '34'},
|
||||
{'n': '2008', 'v': '35'},
|
||||
{'n': '更早', 'v': '127'}
|
||||
]},
|
||||
{'name': '状态', 'key': 'status', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '完结', 'v': '1'},
|
||||
{'n': '更新中', 'v': '2'}
|
||||
]},
|
||||
{'name': '排序', 'key': 'by', 'value': [
|
||||
{'n': '添加时间', 'v': 'new'},
|
||||
{'n': '人气高低', 'v': 'hot'},
|
||||
{'n': '评分高低', 'v': 'score'}
|
||||
]}
|
||||
],
|
||||
'32': [ # 纪录片筛选条件
|
||||
{'name': '类型', 'key': 'class', 'value': [
|
||||
{'n': '全部', 'v': '0'} # HTML未提供具体类型,仅保留“全部”
|
||||
]},
|
||||
{'name': '地区', 'key': 'area', 'value': [
|
||||
{'n': '全部', 'v': '0'} # HTML未提供具体地区,仅保留“全部”
|
||||
]},
|
||||
{'name': '年份', 'key': 'year', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '2025', 'v': '131'},
|
||||
{'n': '2024', 'v': '130'},
|
||||
{'n': '2023', 'v': '129'},
|
||||
{'n': '2022', 'v': '21'},
|
||||
{'n': '2021', 'v': '22'},
|
||||
{'n': '2020', 'v': '23'},
|
||||
{'n': '2019', 'v': '24'},
|
||||
{'n': '2018', 'v': '25'},
|
||||
{'n': '2017', 'v': '26'},
|
||||
{'n': '2016', 'v': '27'},
|
||||
{'n': '2015', 'v': '28'},
|
||||
{'n': '2014', 'v': '29'},
|
||||
{'n': '2013', 'v': '30'},
|
||||
{'n': '2012', 'v': '31'},
|
||||
{'n': '2011', 'v': '32'},
|
||||
{'n': '2010', 'v': '33'},
|
||||
{'n': '2009', 'v': '34'},
|
||||
{'n': '2008', 'v': '35'},
|
||||
{'n': '更早', 'v': '127'}
|
||||
]},
|
||||
{'name': '状态', 'key': 'status', 'value': [
|
||||
{'n': '全部', 'v': '0'},
|
||||
{'n': '完结', 'v': '1'},
|
||||
{'n': '更新中', 'v': '2'}
|
||||
]},
|
||||
{'name': '排序', 'key': 'by', 'value': [
|
||||
{'n': '添加时间', 'v': 'new'},
|
||||
{'n': '人气高低', 'v': 'hot'},
|
||||
{'n': '评分高低', 'v': 'score'}
|
||||
]}
|
||||
]
|
||||
}
|
||||
}
|
||||
# print(f"Debug homeContent: {result}")
|
||||
return result
|
||||
|
||||
def homeVideoContent(self):
|
||||
d = []
|
||||
try:
|
||||
res = requests.get(self.home_url, headers=self.headers)
|
||||
res.encoding = 'utf-8' # 根据实际情况设置编码
|
||||
root = etree.HTML(res.text.encode('utf-8'))
|
||||
data_list = root.xpath('//div[@class="video-box-new"]/div[@class="Movie-list"]')
|
||||
for i in data_list:
|
||||
d.append(
|
||||
{
|
||||
'vod_id': i.xpath('./a[@class="Movie movie-height"]/@href')[0].split('=')[-1],
|
||||
'vod_name': i.xpath('./a[2]/text()')[0].strip(),
|
||||
'vod_pic': i.xpath('./a[1]/img/@originalsrc')[0],
|
||||
'vod_remarks': i.xpath('./div[@class="Movie-type02"]/div[2]/text()')[0].strip()
|
||||
}
|
||||
)
|
||||
return {'list': d, 'parse': 0, 'jx': 0}
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return {'list': d, 'parse': 0, 'jx': 0}
|
||||
|
||||
def categoryContent(self, cid, page, filter, ext):
|
||||
_class = ext.get('class', '0') # 剧情/类型
|
||||
_area = ext.get('area', '0') # 地区
|
||||
_year = ext.get('year', '0') # 年份
|
||||
_status = ext.get('status', '0') # 状态
|
||||
_by = ext.get('by', 'new') # 排序
|
||||
|
||||
url = self.home_url + f'/video/refresh-cate?page_num={page}&sorttype=desc&channel_id={cid}&tag={_class}&area={_area}&year={_year}&status={_status}&sort={_by}&page_size=28'
|
||||
d = []
|
||||
try:
|
||||
res = requests.get(url, headers=self.headers)
|
||||
data_list = res.json()['data']['list']
|
||||
for i in data_list:
|
||||
d.append(
|
||||
{
|
||||
'vod_id': i['video_id'],
|
||||
'vod_name': i['video_name'],
|
||||
'vod_pic': i['cover'],
|
||||
'vod_remarks': i['flag'],
|
||||
}
|
||||
)
|
||||
return {'list': d, 'parse': 0, 'jx': 0}
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return {'list': d, 'parse': 0, 'jx': 0}
|
||||
|
||||
def detailContent(self, did):
|
||||
ids = did[0]
|
||||
video_list = []
|
||||
url = self.home_url + f'/video/detail?video_id={ids}'
|
||||
try:
|
||||
res = requests.get(url, headers=self.headers)
|
||||
root = etree.HTML(res.text.encode('utf-8'))
|
||||
# vod_play_from_list = root.xpath('//span[@class="source-item-label"]/text()')
|
||||
vod_play_from = '$$$'.join(['老僧酿酒', '名妓读经', '书生玩剑'])
|
||||
# 电视剧
|
||||
play_list1 = root.xpath('//ul[contains(@class, "qy-episode-num")]')
|
||||
# print(play_list1)
|
||||
# 电影
|
||||
# play_list2 = root.xpath('//ul[contains(@class, "qy-play-list")]')
|
||||
play_list2 = root.xpath('//ul[@id="srctab-1"]')
|
||||
# print(play_list2)
|
||||
vod_play_url_list = []
|
||||
if len(play_list1) > 0:
|
||||
play_list = play_list1[:-1]
|
||||
# print(play_list)
|
||||
|
||||
elif len(play_list2) > 0:
|
||||
play_list = play_list2
|
||||
# print(play_list)
|
||||
else:
|
||||
play_list = []
|
||||
|
||||
for i in play_list:
|
||||
name_list1 = i.xpath('.//div[@class="select-link"]/text()')
|
||||
name_list2 = i.xpath('.//span[@class="title-link"]/text()')
|
||||
name_list3 = i.xpath('./li/text()')
|
||||
# print(name_list1)
|
||||
# print(name_list2)
|
||||
# print(name_list3)
|
||||
# print(name_list1 + name_list2 + name_list3)
|
||||
name_list = name_list1 + name_list2 + name_list3
|
||||
url_list = i.xpath('./li/@data-chapter-id')
|
||||
vod_play_url_list.append(
|
||||
'#'.join([_name.strip() + '$' + f'{ids}-{_url}' for _name, _url in zip(name_list, url_list)])
|
||||
)
|
||||
|
||||
|
||||
# print(vod_play_url_list*3)
|
||||
vod_play_url = '$$$'.join(vod_play_url_list*3)
|
||||
# print(vod_play_url_list)
|
||||
video_list.append({
|
||||
'type_name': '',
|
||||
'vod_id': ids,
|
||||
'vod_name': '',
|
||||
'vod_remarks': '',
|
||||
'vod_year': '',
|
||||
'vod_area': '',
|
||||
'vod_actor': '',
|
||||
'vod_director': '',
|
||||
'vod_content': '',
|
||||
'vod_play_from': vod_play_from,
|
||||
'vod_play_url': vod_play_url
|
||||
})
|
||||
return {"list": video_list, 'parse': 0, 'jx': 0}
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error in detailContent: {e}")
|
||||
return {'list': [], 'msg': str(e)}
|
||||
|
||||
def searchContent(self, key, quick, page='1'):
|
||||
if str(page) != '1':
|
||||
return {'list': [], 'parse': 0, 'jx': 0}
|
||||
url = f'{self.home_url}/video/refresh-video?page_num=1&sorttype=desc&page_size=28&tvNum=7&sort=new&keyword={key}'
|
||||
d = []
|
||||
try:
|
||||
res = requests.get(url, headers=self.headers)
|
||||
res.encoding = 'utf-8'
|
||||
root = etree.HTML(res.text)
|
||||
data_list = root.xpath('//div[@class="SSbox"]')
|
||||
for i in data_list:
|
||||
d.append(
|
||||
{
|
||||
'vod_id': i.xpath('./a/@href')[0].split('=')[-1],
|
||||
'vod_name': ''.join(i.xpath('.//span/text()')),
|
||||
'vod_pic': i.xpath('./a/img/@originalsrc')[0],
|
||||
'vod_remarks': i.xpath('.//div[@class="SSjgTitle"]/text()')[0],
|
||||
}
|
||||
)
|
||||
return {'list': d, 'parse': 0, 'jx': 0}
|
||||
except Exception as e:
|
||||
print(f"Error in searchContent: {e}")
|
||||
return {'list': [], 'parse': 0, 'jx': 0}
|
||||
|
||||
def playerContent(self, flag, pid, vipFlags):
|
||||
url = 'https://aigua1.com/video/play-url?videoId=230907&sourceId=0&citycode=HKG&chapterId=2916522'
|
||||
a = pid.split('-')
|
||||
videoId = a[0]
|
||||
chapterId = a[1]
|
||||
url = self.home_url + f'/video/play-url?videoId={videoId}&sourceId=0&citycode=HKG&chapterId={chapterId}'
|
||||
try:
|
||||
res = requests.get(url, headers=self.headers)
|
||||
play_url_list = res.json()['data']['urlinfo']['resource_url']
|
||||
if flag == '线路一':
|
||||
play_url = play_url_list['1']
|
||||
pass
|
||||
elif flag == '线路二':
|
||||
play_url = play_url_list['16']
|
||||
else:
|
||||
play_url = play_url_list['21']
|
||||
return {'url': play_url, 'parse': 0, 'jx': 0, 'header': self.headers}
|
||||
except Exception as e:
|
||||
print(f"Error in playerContent: {e}")
|
||||
return {'url': self.default_play_url, 'parse': 0, 'jx': 0}
|
||||
|
||||
def localProxy(self, params):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
return '正在Destroy'
|
||||
|
||||
def get_data(self):
|
||||
url = self.home_url + 'https://aigua1.com/video/refresh-cate?page_num=1&sorttype=desc&channel_id=0&tag=0&area=0&year=0&page_size=28&sort=new'
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
|
|
@ -0,0 +1,476 @@
|
|||
var rule = {
|
||||
title: '瓜子',
|
||||
host: 'https://api.8utdtcq.com',
|
||||
url: '/App/IndexList/indexList',
|
||||
// homeUrl: 'http://124.222.116.5/homedata/home.json',
|
||||
searchUrl: '/App/Index/findMoreVod#**',
|
||||
searchable: 2,
|
||||
quickSearch: 1,
|
||||
filterable: 1,
|
||||
class_name: '电影&电视剧&动漫&综艺&短剧',
|
||||
class_url: '1&2&4&3&64',
|
||||
filter: 'H4sIAAAAAAAAA+2a7U4aQRSG/3sVht/bZHf5WnorjWlo4YfphwlqE2NMtGoLWIsmFbRi2qYqoBgxtVVR8GZ2duUuOmchfuDuDHI2xJhD4hGYyTzv7hlm57yZ6aFh/gpogefDL5y38Jq+fuc0vklO8eZAPJWMB5S7Te/j75JebR/ibyeTd8Z1H/9mMBiJLZZb8+WusW7GhC5q4F7jzP3+Qsh2qbXxSQjpdMGSWrsb1umhkNTpgr6mXM06a4qvqd0FS7KqJbv5VUgyLxfsRsHKHyos+9NauuR3U2HNE7bZUKyFHP/E0hXF+rPmfOEMp/A/+HS1dOT827m0cwd2ZgOvtrBjFatCtZ0u6Fz/qHDp4ly3u2BJ5mmRLRfM+ndxupdrrL6rWPkaTwLb+sVveA3ubatStbZ2+B2GAdDTbvGfeZ4X62h3uU+6883I9adbCtxXoqlkPOW1Erm1PeKVSFf1kBDhdPCBEpRRgn5QdBlF94OiySiaHxRVRvEj+1pMQuEdfKAYMorhByUqo0T9oERklAiaoqnPtDA7O5aRwgoPIQhBCDoEDQJ+aqgq55vnvyUSVJXjVGCqQFdBhwqKVNCmRiBEIRgQ8HMp1ossLRZTFR40CDqEIIQQhDCECIQoBAMCXpbRmywDZBkgywBZBsgyQJYBsgyQZYAsA2QZeFnW5rFVqIhT6ONzcXzylddj0aXpET8VWbZsNop25rOIE0Zn52PVzq9KKHoMfTH5IsuUJJgIlmKnj6z5RQkliqaUVtnZuYRioBMzt2LN5iUUfF4yJfkd01T0xaTXzXpGhtF8+MnY32SZCeKnWX2PNdZkvxn0TbPnmq3vTdnVoCeanT20G3uyn6ZLbvpeocdSE55LtEtbf2u0fX7BVtLCNTrxcjSBf7wVZ3lxKeHEE4mJUX6FPsDs+QMJbPz1WAqPau2vs7TYHvJGeU0N591Ie0z+1H80fluxxr7UyW8jv438Nk8S+W2D8NugghOnk/y2Lgr5bQ+kkN9GfpurBPLbHiKL/LaB+W2bDbNeYpmS0D7Q/dk3yzBBfzbNMkzInx2zDIM3EJ19rAyD9lzam1gZBu3tWX9P2HZehsGbe86mWIZBu3vXu3ChteOC6XsxIGsHAXs61k6IrJ0uCFk7niSydtxJZO146CBrxxNC1g5ZO0IKWTvdFLJ2bkkga4esnYFaO+bpAVTC2bJ1sS8854A/g9I2KuQk9DGU4Y71Ike5eEl9J4tKbwTs6ZTeQSq9uyBUenuSqPR2J1Hp7aGDSm9PCJXeVHoLKVR6d1Oo9L4lgUpvKr0He6rC2Rfziu4qI9yl6+iDFXCqIlfrgYQ+W8H3f3xj1gPJp+MVPZBcTlj0PSuoxkfAnkCNPzTzH+StPxCsRAAA',
|
||||
// limit: 6,
|
||||
//double: false,
|
||||
play_parse: true,
|
||||
lazy: $js.toString(() => {
|
||||
let d = [];
|
||||
//console.log("wangzhi==="+input)
|
||||
var vod_id = input.split("/")[0];
|
||||
var vurl_id = input.split("/")[1];
|
||||
var resolution = input.split("?")[1]
|
||||
|
||||
function Encrypt(plainText) {
|
||||
let key = CryptoJS.enc.Utf8.parse("mvXBSW7ekreItNsT");
|
||||
let iv = CryptoJS.enc.Utf8.parse("2U3IrJL8szAKp0Fj");
|
||||
// 将文本加密为 AES/CBC/PKCS5Padding 格式
|
||||
let encrypted = CryptoJS.AES.encrypt(plainText, key, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
|
||||
// 获取加密结果并转为 Hex 格式
|
||||
let encryptedHex = encrypted.ciphertext.toString(CryptoJS.enc.Hex);
|
||||
return encryptedHex.toUpperCase(); // 返回大写 Hex 格式
|
||||
}
|
||||
|
||||
function Decrypt(word, key, iv) {
|
||||
let encryptedHexStr = CryptoJS.enc.Hex.parse(word);
|
||||
|
||||
// 使用AES/CBC/PKCS5Padding模式进行解密
|
||||
let decrypt = CryptoJS.AES.decrypt({
|
||||
ciphertext: encryptedHexStr
|
||||
}, key, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC, // 使用CBC模式
|
||||
padding: CryptoJS.pad.Pkcs7 // 使用PKCS#7填充
|
||||
});
|
||||
|
||||
// 将解密后的数据转换为原始文本
|
||||
let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
|
||||
|
||||
// 返回解密后的文本
|
||||
return decryptedStr;
|
||||
}
|
||||
var timestamp = new Date().getTime() / 1000; //log(timestamp)
|
||||
var t = timestamp.toString().split('.')[0]; //log(t)
|
||||
var request_key = JSON.stringify({
|
||||
"domain_type": "8",
|
||||
"vod_id": vod_id,
|
||||
"type": "play",
|
||||
"resolution": resolution,
|
||||
"vurl_id": vurl_id
|
||||
}); //log(request_key)
|
||||
var request_key2 = Encrypt(request_key); //log(request_key2)
|
||||
var signature = 'token_id=,token=1be86e8e18a9fa18b2b8d5432699dad0.ac008ed650fd087bfbecf2fda9d82e9835253ef24843e6b18fcd128b10763497bcf9d53e959f5377cde038c20ccf9d17f604c9b8bb6e61041def86729b2fc7408bd241e23c213ac57f0226ee656e2bb0a583ae0e4f3bf6c6ab6c490c9a6f0d8cdfd366aacf5d83193671a8f77cd1af1ff2e9145de92ec43ec87cf4bdc563f6e919fe32861b0e93b118ec37d8035fbb3c.59dd05c5d9a8ae726528783128218f15fe6f2c0c8145eddab112b374fcfe3d79,phone_type=1,request_key=' + request_key2 + ',app_id=1,time=' + t + ',keys=ZH8gpdp9bxjuG2NK97sol3o7Uiz+9eVEaVMlE2Fk3j7EResM3YHnECZUH7BONNTjpy7RVNi/YimGuNYriC7Cmswv4PNYiFYzw9QhlqZKwNfCM6IUpFZ0T4rZx8G78zkv2tNVbfYC4qNQedGi07nWZ33dlSuVxROVfY5JxOWHMI0=*&zvdvdvddbfikkkumtmdwqppp?|4Y!s!2br'; //log(signature)
|
||||
var signature2 = md5(signature); //log(signature2)
|
||||
var body = 'token=1be86e8e18a9fa18b2b8d5432699dad0.ac008ed650fd087bfbecf2fda9d82e9835253ef24843e6b18fcd128b10763497bcf9d53e959f5377cde038c20ccf9d17f604c9b8bb6e61041def86729b2fc7408bd241e23c213ac57f0226ee656e2bb0a583ae0e4f3bf6c6ab6c490c9a6f0d8cdfd366aacf5d83193671a8f77cd1af1ff2e9145de92ec43ec87cf4bdc563f6e919fe32861b0e93b118ec37d8035fbb3c.59dd05c5d9a8ae726528783128218f15fe6f2c0c8145eddab112b374fcfe3d79&token_id=&phone_type=1&time=' + t + '&phone_model=xiaomi-22021211rc&keys=ZH8gpdp9bxjuG2NK97sol3o7Uiz%2B9eVEaVMlE2Fk3j7EResM3YHnECZUH7BONNTjpy7RVNi%2FYimGuNYriC7Cmswv4PNYiFYzw9QhlqZKwNfCM6IUpFZ0T4rZx8G78zkv2tNVbfYC4qNQedGi07nWZ33dlSuVxROVfY5JxOWHMI0%3D&request_key=' + request_key2 + '&signature=' + signature2 + '&app_id=1&ad_version=1'; //log(body)
|
||||
|
||||
var html = fetch('https://api.8utdtcq.com/App/Resource/VurlDetail/showOne', {
|
||||
headers: {
|
||||
'Cache-Control': 'no-cache',
|
||||
'Version': '2406025',
|
||||
'PackageName': 'com.uf076bf0c246.qe439f0d5e.m8aaf56b725a.ifeb647346f',
|
||||
'Ver': '1.9.2',
|
||||
'Referer': 'https://api.8utdtcq.com',
|
||||
'X-Customer-Client-Ip': '127.0.0.1',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Host': 'api.8utdtcq.com',
|
||||
'Connection': 'Keep-Alive',
|
||||
//'Accept-Encoding': 'gzip',
|
||||
'User-Agent': 'okhttp/3.12.0'
|
||||
},
|
||||
body: body,
|
||||
method: 'POST',
|
||||
rejectCoding: true
|
||||
}); //log(html)
|
||||
|
||||
var data = JSON.parse(html).data;
|
||||
// //console.log("dddddd====="+JSON.stringify(data))
|
||||
var response_key = data.response_key; //log(response_key)
|
||||
var keys = data.keys; //log(keys)
|
||||
|
||||
var bodykey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGAe6hKrWLi1zQmjTT1ozbE4QdFeJGNxubxld6GrFGximxfMsMB6BpJhpcTouAqywAFppiKetUBBbXwYsYU1wNr648XVmPmCMCy4rY8vdliFnbMUj086DU6Z+/oXBdWU3/b1G0DN3E9wULRSwcKZT3wj/cCI1vsCm3gj2R5SqkA9Y0CAwEAAQKBgAJH+4CxV0/zBVcLiBCHvSANm0l7HetybTh/j2p0Y1sTXro4ALwAaCTUeqdBjWiLSo9lNwDHFyq8zX90+gNxa7c5EqcWV9FmlVXr8VhfBzcZo1nXeNdXFT7tQ2yah/odtdcx+vRMSGJd1t/5k5bDd9wAvYdIDblMAg+wiKKZ5KcdAkEA1cCakEN4NexkF5tHPRrR6XOY/XHfkqXxEhMqmNbB9U34saTJnLWIHC8IXys6Qmzz30TtzCjuOqKRRy+FMM4TdwJBAJQZFPjsGC+RqcG5UvVMiMPhnwe/bXEehShK86yJK/g/UiKrO87h3aEu5gcJqBygTq3BBBoH2md3pr/W+hUMWBsCQQChfhTIrdDinKi6lRxrdBnn0Ohjg2cwuqK5zzU9p/N+S9x7Ck8wUI53DKm8jUJE8WAG7WLj/oCOWEh+ic6NIwTdAkEAj0X8nhx6AXsgCYRql1klbqtVmL8+95KZK7PnLWG/IfjQUy3pPGoSaZ7fdquG8bq8oyf5+dzjE/oTXcByS+6XRQJAP/5ciy1bL3NhUhsaOVy55MHXnPjdcTX0FaLi+ybXZIfIQ2P4rb19mVq1feMbCXhz+L1rG8oat5lYKfpe8k83ZA=="; //log(bodykey)
|
||||
var bodykeyiv = JSON.parse(RSA.decode(keys, bodykey)); //log(bodykeyiv)
|
||||
var key = CryptoJS.enc.Utf8.parse(bodykeyiv.key); //log(key)
|
||||
var iv = CryptoJS.enc.Utf8.parse(bodykeyiv.iv); //log(iv)
|
||||
var html2 = Decrypt(response_key, key, iv); //log(html2)
|
||||
var url = JSON.parse(html2).url; //log(url)
|
||||
input = {
|
||||
url: url,
|
||||
parse: 0,
|
||||
header: rule.headers
|
||||
}
|
||||
setResult(d)
|
||||
}),
|
||||
// 推荐: $js.toString(() => {
|
||||
// let d = [];
|
||||
// let data = JSON.parse(request(input))
|
||||
// data.forEach(item => {
|
||||
// item.datas.forEach(it => {
|
||||
// let id = `http://114.132.55.23/bl/mb/api.php/provide/vod/?ac=videolist&wd=${it.title}&`;
|
||||
// d.push({
|
||||
// url: id,
|
||||
// title: it.title,
|
||||
// img: it.pic,
|
||||
// desc: it.acr,
|
||||
// })
|
||||
// });
|
||||
// });
|
||||
// setResult(d)
|
||||
// }),
|
||||
一级: $js.toString(() => {
|
||||
let d = [];
|
||||
|
||||
function Encrypt(plainText) {
|
||||
let key = CryptoJS.enc.Utf8.parse("mvXBSW7ekreItNsT");
|
||||
let iv = CryptoJS.enc.Utf8.parse("2U3IrJL8szAKp0Fj");
|
||||
// 将文本加密为 AES/CBC/PKCS5Padding 格式
|
||||
let encrypted = CryptoJS.AES.encrypt(plainText, key, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
|
||||
// 获取加密结果并转为 Hex 格式
|
||||
let encryptedHex = encrypted.ciphertext.toString(CryptoJS.enc.Hex);
|
||||
return encryptedHex.toUpperCase(); // 返回大写 Hex 格式
|
||||
}
|
||||
|
||||
function Decrypt(word, key, iv) {
|
||||
let encryptedHexStr = CryptoJS.enc.Hex.parse(word);
|
||||
|
||||
// 使用AES/CBC/PKCS5Padding模式进行解密
|
||||
let decrypt = CryptoJS.AES.decrypt({
|
||||
ciphertext: encryptedHexStr
|
||||
}, key, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC, // 使用CBC模式
|
||||
padding: CryptoJS.pad.Pkcs7 // 使用PKCS#7填充
|
||||
});
|
||||
|
||||
// 将解密后的数据转换为原始文本
|
||||
let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
|
||||
|
||||
// 返回解密后的文本
|
||||
return decryptedStr;
|
||||
}
|
||||
|
||||
function getbody3(key, t) {
|
||||
var signature = 'token_id=,token=1be86e8e18a9fa18b2b8d5432699dad0.ac008ed650fd087bfbecf2fda9d82e9835253ef24843e6b18fcd128b10763497bcf9d53e959f5377cde038c20ccf9d17f604c9b8bb6e61041def86729b2fc7408bd241e23c213ac57f0226ee656e2bb0a583ae0e4f3bf6c6ab6c490c9a6f0d8cdfd366aacf5d83193671a8f77cd1af1ff2e9145de92ec43ec87cf4bdc563f6e919fe32861b0e93b118ec37d8035fbb3c.59dd05c5d9a8ae726528783128218f15fe6f2c0c8145eddab112b374fcfe3d79,phone_type=1,request_key=' + key + ',app_id=1,time=' + t + ',keys=qDpotE2bedimK3QGqlyV5ieXXC3EhaPLQ+IOJyHnHflCj5w/7ESK7FgywMvrgjxbx0GklEFLI4+JshgySe633OIRstuktwdiCy3CT+fLSpuxBJDIlfXQDaeH3ig1wiB0JsZ601XHiFweGMu4tZfnSpHg3OnoL6nz/uurUif2OK4=*&zvdvdvddbfikkkumtmdwqppp?|4Y!s!2br'; //log(signature)
|
||||
var signature2 = md5(signature).toUpperCase(); //log(signature2)
|
||||
var body = 'token=1be86e8e18a9fa18b2b8d5432699dad0.ac008ed650fd087bfbecf2fda9d82e9835253ef24843e6b18fcd128b10763497bcf9d53e959f5377cde038c20ccf9d17f604c9b8bb6e61041def86729b2fc7408bd241e23c213ac57f0226ee656e2bb0a583ae0e4f3bf6c6ab6c490c9a6f0d8cdfd366aacf5d83193671a8f77cd1af1ff2e9145de92ec43ec87cf4bdc563f6e919fe32861b0e93b118ec37d8035fbb3c.59dd05c5d9a8ae726528783128218f15fe6f2c0c8145eddab112b374fcfe3d79&token_id=&phone_type=1&time=' + t + '&phone_model=xiaomi-22021211rc&keys=qDpotE2bedimK3QGqlyV5ieXXC3EhaPLQ%2BIOJyHnHflCj5w%2F7ESK7FgywMvrgjxbx0GklEFLI4%2BJshgySe633OIRstuktwdiCy3CT%2BfLSpuxBJDIlfXQDaeH3ig1wiB0JsZ601XHiFweGMu4tZfnSpHg3OnoL6nz%2FuurUif2OK4%3D&request_key=' + key + '&signature=' + signature2 + '&app_id=1&ad_version=1';
|
||||
return body
|
||||
}
|
||||
const bodykey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGAe6hKrWLi1zQmjTT1ozbE4QdFeJGNxubxld6GrFGximxfMsMB6BpJhpcTouAqywAFppiKetUBBbXwYsYU1wNr648XVmPmCMCy4rY8vdliFnbMUj086DU6Z+/oXBdWU3/b1G0DN3E9wULRSwcKZT3wj/cCI1vsCm3gj2R5SqkA9Y0CAwEAAQKBgAJH+4CxV0/zBVcLiBCHvSANm0l7HetybTh/j2p0Y1sTXro4ALwAaCTUeqdBjWiLSo9lNwDHFyq8zX90+gNxa7c5EqcWV9FmlVXr8VhfBzcZo1nXeNdXFT7tQ2yah/odtdcx+vRMSGJd1t/5k5bDd9wAvYdIDblMAg+wiKKZ5KcdAkEA1cCakEN4NexkF5tHPRrR6XOY/XHfkqXxEhMqmNbB9U34saTJnLWIHC8IXys6Qmzz30TtzCjuOqKRRy+FMM4TdwJBAJQZFPjsGC+RqcG5UvVMiMPhnwe/bXEehShK86yJK/g/UiKrO87h3aEu5gcJqBygTq3BBBoH2md3pr/W+hUMWBsCQQChfhTIrdDinKi6lRxrdBnn0Ohjg2cwuqK5zzU9p/N+S9x7Ck8wUI53DKm8jUJE8WAG7WLj/oCOWEh+ic6NIwTdAkEAj0X8nhx6AXsgCYRql1klbqtVmL8+95KZK7PnLWG/IfjQUy3pPGoSaZ7fdquG8bq8oyf5+dzjE/oTXcByS+6XRQJAP/5ciy1bL3NhUhsaOVy55MHXnPjdcTX0FaLi+ybXZIfIQ2P4rb19mVq1feMbCXhz+L1rG8oat5lYKfpe8k83ZA==";
|
||||
|
||||
function gethtml(u, body, headers) {
|
||||
var hd = fetch(u, {
|
||||
headers: headers,
|
||||
body: body,
|
||||
method: 'POST',
|
||||
rejectCoding: true
|
||||
});
|
||||
var banner = JSON.parse(hd).data;
|
||||
var response_key = banner.response_key; //log()
|
||||
var keys = banner.keys; //log(keys)
|
||||
var bodykeyiv = JSON.parse(RSA.decode(keys, bodykey));
|
||||
var key = CryptoJS.enc.Utf8.parse(bodykeyiv.key);
|
||||
var iv = CryptoJS.enc.Utf8.parse(bodykeyiv.iv);
|
||||
var html = Decrypt(response_key, key, iv);
|
||||
return html
|
||||
}
|
||||
|
||||
function hqsub(MY_CATE) {
|
||||
var subs = ["5", "12", "30", "22", ""]
|
||||
var tids = ["1", "2", "4", "3", "64"]
|
||||
let index = tids.indexOf(MY_CATE);
|
||||
if (index !== -1) {
|
||||
return subs[index];
|
||||
}
|
||||
return ""; // 或者根据需要返回其他值
|
||||
}
|
||||
var headers = {
|
||||
'Cache-Control': 'no-cache',
|
||||
'Version': '2406025',
|
||||
'PackageName': 'com.uf076bf0c246.qe439f0d5e.m8aaf56b725a.ifeb647346f',
|
||||
'Ver': '1.9.2',
|
||||
'Referer': 'https://api.8utdtcq.com',
|
||||
'X-Customer-Client-Ip': '127.0.0.1',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Host': 'api.8utdtcq.com',
|
||||
'Connection': 'Keep-Alive',
|
||||
//'Accept-Encoding': 'gzip',
|
||||
'User-Agent': 'okhttp/3.12.0'
|
||||
}
|
||||
var tid = MY_CATE;
|
||||
var sub = hqsub(MY_CATE)
|
||||
var timestamp = new Date().getTime() / 1000;
|
||||
var t = timestamp.toString().split('.')[0];
|
||||
var request_key = JSON.stringify({
|
||||
"area": (MY_FL.area || 0).toString(),
|
||||
"sub": (MY_FL.sub || sub).toString(),
|
||||
"year": (MY_FL.year || 0).toString(),
|
||||
"pageSize": "30",
|
||||
"sort": (MY_FL.sort || "d_id").toString(),
|
||||
"page": MY_PAGE,
|
||||
"tid": tid
|
||||
});
|
||||
var request_key2 = Encrypt(request_key);
|
||||
var body = getbody3(request_key2, t)
|
||||
var html2 = gethtml("https://api.8utdtcq.com/App/IndexList/indexList", body, headers)
|
||||
//console.log("tttttlieb=="+html2)
|
||||
var list = JSON.parse(html2).list; //log(list)
|
||||
list.forEach(data => {
|
||||
d.push({
|
||||
title: data.vod_name,
|
||||
desc: data.vod_continu == 0 ? '电影' : '更新至' + data.vod_continu + '集',
|
||||
year: data.vod_scroe,
|
||||
img: data.vod_pic,
|
||||
url: `${data.vod_id}/${data.vod_continu}`,
|
||||
})
|
||||
})
|
||||
setResult(d)
|
||||
}),
|
||||
二级: $js.toString(() => {
|
||||
// var d = [];
|
||||
function Encrypt(plainText) {
|
||||
let key = CryptoJS.enc.Utf8.parse("mvXBSW7ekreItNsT");
|
||||
let iv = CryptoJS.enc.Utf8.parse("2U3IrJL8szAKp0Fj");
|
||||
// 将文本加密为 AES/CBC/PKCS5Padding 格式
|
||||
let encrypted = CryptoJS.AES.encrypt(plainText, key, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
|
||||
// 获取加密结果并转为 Hex 格式
|
||||
let encryptedHex = encrypted.ciphertext.toString(CryptoJS.enc.Hex);
|
||||
return encryptedHex.toUpperCase(); // 返回大写 Hex 格式
|
||||
}
|
||||
|
||||
function Decrypt(word, key, iv) {
|
||||
let encryptedHexStr = CryptoJS.enc.Hex.parse(word);
|
||||
|
||||
// 使用AES/CBC/PKCS5Padding模式进行解密
|
||||
let decrypt = CryptoJS.AES.decrypt({
|
||||
ciphertext: encryptedHexStr
|
||||
}, key, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC, // 使用CBC模式
|
||||
padding: CryptoJS.pad.Pkcs7 // 使用PKCS#7填充
|
||||
});
|
||||
|
||||
// 将解密后的数据转换为原始文本
|
||||
let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
|
||||
|
||||
// 返回解密后的文本
|
||||
return decryptedStr;
|
||||
}
|
||||
|
||||
function getbody2(key, t) {
|
||||
var signature = 'token_id=,token=1be86e8e18a9fa18b2b8d5432699dad0.ac008ed650fd087bfbecf2fda9d82e9835253ef24843e6b18fcd128b10763497bcf9d53e959f5377cde038c20ccf9d17f604c9b8bb6e61041def86729b2fc7408bd241e23c213ac57f0226ee656e2bb0a583ae0e4f3bf6c6ab6c490c9a6f0d8cdfd366aacf5d83193671a8f77cd1af1ff2e9145de92ec43ec87cf4bdc563f6e919fe32861b0e93b118ec37d8035fbb3c.59dd05c5d9a8ae726528783128218f15fe6f2c0c8145eddab112b374fcfe3d79,phone_type=1,request_key=' + key + ',app_id=1,time=' + t + ',keys=Qmxi5ciWXbQzkr7o+SUNiUuQxQEf8/AVyUWY4T/BGhcXBIUz4nOyHBGf9A4KbM0iKF3yp9M7WAY0rrs5PzdTAOB45plcS2zZ0wUibcXuGJ29VVGRWKGwE9zu2vLwhfgjTaaDpXo4rby+7GxXTktzJmxvneOUdYeHi+PZsThlvPI=*&zvdvdvddbfikkkumtmdwqppp?|4Y!s!2br'; //log(signature)
|
||||
var signature2 = md5(signature); //log(signature2)
|
||||
var body = 'token=1be86e8e18a9fa18b2b8d5432699dad0.ac008ed650fd087bfbecf2fda9d82e9835253ef24843e6b18fcd128b10763497bcf9d53e959f5377cde038c20ccf9d17f604c9b8bb6e61041def86729b2fc7408bd241e23c213ac57f0226ee656e2bb0a583ae0e4f3bf6c6ab6c490c9a6f0d8cdfd366aacf5d83193671a8f77cd1af1ff2e9145de92ec43ec87cf4bdc563f6e919fe32861b0e93b118ec37d8035fbb3c.59dd05c5d9a8ae726528783128218f15fe6f2c0c8145eddab112b374fcfe3d79&token_id=&phone_type=1&time=' + t + '&phone_model=xiaomi-22021211rc&keys=Qmxi5ciWXbQzkr7o%2BSUNiUuQxQEf8%2FAVyUWY4T%2FBGhcXBIUz4nOyHBGf9A4KbM0iKF3yp9M7WAY0rrs5PzdTAOB45plcS2zZ0wUibcXuGJ29VVGRWKGwE9zu2vLwhfgjTaaDpXo4rby%2B7GxXTktzJmxvneOUdYeHi%2BPZsThlvPI%3D&request_key=' + key + '&signature=' + signature2 + '&app_id=1&ad_version=1'; //log(body)
|
||||
return body
|
||||
}
|
||||
const bodykey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGAe6hKrWLi1zQmjTT1ozbE4QdFeJGNxubxld6GrFGximxfMsMB6BpJhpcTouAqywAFppiKetUBBbXwYsYU1wNr648XVmPmCMCy4rY8vdliFnbMUj086DU6Z+/oXBdWU3/b1G0DN3E9wULRSwcKZT3wj/cCI1vsCm3gj2R5SqkA9Y0CAwEAAQKBgAJH+4CxV0/zBVcLiBCHvSANm0l7HetybTh/j2p0Y1sTXro4ALwAaCTUeqdBjWiLSo9lNwDHFyq8zX90+gNxa7c5EqcWV9FmlVXr8VhfBzcZo1nXeNdXFT7tQ2yah/odtdcx+vRMSGJd1t/5k5bDd9wAvYdIDblMAg+wiKKZ5KcdAkEA1cCakEN4NexkF5tHPRrR6XOY/XHfkqXxEhMqmNbB9U34saTJnLWIHC8IXys6Qmzz30TtzCjuOqKRRy+FMM4TdwJBAJQZFPjsGC+RqcG5UvVMiMPhnwe/bXEehShK86yJK/g/UiKrO87h3aEu5gcJqBygTq3BBBoH2md3pr/W+hUMWBsCQQChfhTIrdDinKi6lRxrdBnn0Ohjg2cwuqK5zzU9p/N+S9x7Ck8wUI53DKm8jUJE8WAG7WLj/oCOWEh+ic6NIwTdAkEAj0X8nhx6AXsgCYRql1klbqtVmL8+95KZK7PnLWG/IfjQUy3pPGoSaZ7fdquG8bq8oyf5+dzjE/oTXcByS+6XRQJAP/5ciy1bL3NhUhsaOVy55MHXnPjdcTX0FaLi+ybXZIfIQ2P4rb19mVq1feMbCXhz+L1rG8oat5lYKfpe8k83ZA==";
|
||||
|
||||
function gethtml(u, body, headers) {
|
||||
var hd = fetch(u, {
|
||||
headers: headers,
|
||||
body: body,
|
||||
method: 'POST',
|
||||
rejectCoding: true
|
||||
});
|
||||
var banner = JSON.parse(hd).data;
|
||||
var response_key = banner.response_key; //log()
|
||||
var keys = banner.keys; //log(keys)
|
||||
var bodykeyiv = JSON.parse(RSA.decode(keys, bodykey));
|
||||
var key = CryptoJS.enc.Utf8.parse(bodykeyiv.key);
|
||||
var iv = CryptoJS.enc.Utf8.parse(bodykeyiv.iv);
|
||||
var html = Decrypt(response_key, key, iv);
|
||||
return html
|
||||
}
|
||||
const headers = {
|
||||
'Cache-Control': 'no-cache',
|
||||
'Version': '2406025',
|
||||
'PackageName': 'com.uf076bf0c246.qe439f0d5e.m8aaf56b725a.ifeb647346f',
|
||||
'Ver': '1.9.2',
|
||||
'Referer': 'https://api.8utdtcq.com',
|
||||
'X-Customer-Client-Ip': '127.0.0.1',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Host': 'api.8utdtcq.com',
|
||||
'Connection': 'Keep-Alive',
|
||||
//'Accept-Encoding': 'gzip',
|
||||
'User-Agent': 'okhttp/3.12.0'
|
||||
}
|
||||
// var MY_URL = MY_URL.split("##")[1]; //log(MY_URL)
|
||||
input = input.replace('https://api.8utdtcq.com/', '');
|
||||
//console.log("input----===="+input)
|
||||
|
||||
// var vod_continu = input.split("/")[1]; //log(vod_id)
|
||||
var vod_id = input.split("/")[0];
|
||||
//console.log("vod----===="+vod_id)
|
||||
var timestamp = new Date().getTime() / 1000;
|
||||
var t = timestamp.toString().split('.')[0];
|
||||
var request_key = JSON.stringify({
|
||||
"token_id": "393668",
|
||||
"vod_id": vod_id,
|
||||
"mobile_time": t,
|
||||
"token": "1be86e8e18a9fa18b2b8d5432699dad0.ac008ed650fd087bfbecf2fda9d82e9835253ef24843e6b18fcd128b10763497bcf9d53e959f5377cde038c20ccf9d17f604c9b8bb6e61041def86729b2fc7408bd241e23c213ac57f0226ee656e2bb0a583ae0e4f3bf6c6ab6c490c9a6f0d8cdfd366aacf5d83193671a8f77cd1af1ff2e9145de92ec43ec87cf4bdc563f6e919fe32861b0e93b118ec37d8035fbb3c.59dd05c5d9a8ae726528783128218f15fe6f2c0c8145eddab112b374fcfe3d79"
|
||||
});
|
||||
var request_key2 = Encrypt(request_key);
|
||||
var body = getbody2(request_key2, t)
|
||||
var html = gethtml("https://api.8utdtcq.com/App/IndexPlay/playInfo", body, headers)
|
||||
var data2 = JSON.parse(html).vodInfo; //console.log("hwudwudg-===="+JSON.stringify(data2))
|
||||
var request_key3 = JSON.stringify({
|
||||
"vurl_cloud_id": "2",
|
||||
"vod_d_id": vod_id
|
||||
}); //log(request_key3)
|
||||
var request_key4 = Encrypt(request_key3); //log(request_key4)
|
||||
var body2 = getbody2(request_key4, t)
|
||||
|
||||
var html3 = gethtml("https://api.8utdtcq.com/App/Resource/Vurl/show", body2, headers); //log(html3)
|
||||
|
||||
var list = JSON.parse(html3).list;
|
||||
let nnnmm = [];
|
||||
list.forEach(item => {
|
||||
// 获取play对象的所有值
|
||||
const playParams = Object.values(item.play);
|
||||
let lastParam = null;
|
||||
|
||||
// 从数组的最后一个元素开始,向前查找,直到找到一个非空的param值
|
||||
for (let i = playParams.length - 1; i >= 0; i--) {
|
||||
if (playParams[i].param) {
|
||||
lastParam = playParams[i].param;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用正则表达式匹配vurl_id
|
||||
const vurlIdMatch = lastParam.match(/vurl_id=(\d+)/);
|
||||
const resolution = lastParam.match(/resolution=(\d+)/);
|
||||
// 如果匹配成功,将title和vurl_id组合后push到result数组
|
||||
if (vurlIdMatch) {
|
||||
nnnmm.push(`${item.title}$${vod_id}/${vurlIdMatch[1]}?${resolution[1]}`);
|
||||
}
|
||||
});
|
||||
VOD = {
|
||||
title: data2.vod_name,
|
||||
type: data2.videoTag.toString(),
|
||||
desc: data2.vod_use_content,
|
||||
vod_actor: data2.vod_actor,
|
||||
vod_area: data2.vod_area,
|
||||
vod_director: data2.vod_director,
|
||||
img: data2.vod_pic,
|
||||
vod_play_from: '老僧酿酒',
|
||||
vod_play_url: nnnmm.join('#')
|
||||
}
|
||||
}),
|
||||
搜索: $js.toString(() => {
|
||||
let d = [];
|
||||
|
||||
function Encrypt(plainText) {
|
||||
let key = CryptoJS.enc.Utf8.parse("mvXBSW7ekreItNsT");
|
||||
let iv = CryptoJS.enc.Utf8.parse("2U3IrJL8szAKp0Fj");
|
||||
// 将文本加密为 AES/CBC/PKCS5Padding 格式
|
||||
let encrypted = CryptoJS.AES.encrypt(plainText, key, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
|
||||
// 获取加密结果并转为 Hex 格式
|
||||
let encryptedHex = encrypted.ciphertext.toString(CryptoJS.enc.Hex);
|
||||
return encryptedHex.toUpperCase(); // 返回大写 Hex 格式
|
||||
}
|
||||
|
||||
function Decrypt(word, key, iv) {
|
||||
let encryptedHexStr = CryptoJS.enc.Hex.parse(word);
|
||||
|
||||
// 使用AES/CBC/PKCS5Padding模式进行解密
|
||||
let decrypt = CryptoJS.AES.decrypt({
|
||||
ciphertext: encryptedHexStr
|
||||
}, key, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC, // 使用CBC模式
|
||||
padding: CryptoJS.pad.Pkcs7 // 使用PKCS#7填充
|
||||
});
|
||||
|
||||
// 将解密后的数据转换为原始文本
|
||||
let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
|
||||
|
||||
// 返回解密后的文本
|
||||
return decryptedStr;
|
||||
}
|
||||
|
||||
function getbody3(key, t) {
|
||||
var signature = 'token_id=,token=1be86e8e18a9fa18b2b8d5432699dad0.ac008ed650fd087bfbecf2fda9d82e9835253ef24843e6b18fcd128b10763497bcf9d53e959f5377cde038c20ccf9d17f604c9b8bb6e61041def86729b2fc7408bd241e23c213ac57f0226ee656e2bb0a583ae0e4f3bf6c6ab6c490c9a6f0d8cdfd366aacf5d83193671a8f77cd1af1ff2e9145de92ec43ec87cf4bdc563f6e919fe32861b0e93b118ec37d8035fbb3c.59dd05c5d9a8ae726528783128218f15fe6f2c0c8145eddab112b374fcfe3d79,phone_type=1,request_key=' + key + ',app_id=1,time=' + t + ',keys=qDpotE2bedimK3QGqlyV5ieXXC3EhaPLQ+IOJyHnHflCj5w/7ESK7FgywMvrgjxbx0GklEFLI4+JshgySe633OIRstuktwdiCy3CT+fLSpuxBJDIlfXQDaeH3ig1wiB0JsZ601XHiFweGMu4tZfnSpHg3OnoL6nz/uurUif2OK4=*&zvdvdvddbfikkkumtmdwqppp?|4Y!s!2br'; //log(signature)
|
||||
var signature2 = md5(signature); //log(signature2)
|
||||
var body = 'token=1be86e8e18a9fa18b2b8d5432699dad0.ac008ed650fd087bfbecf2fda9d82e9835253ef24843e6b18fcd128b10763497bcf9d53e959f5377cde038c20ccf9d17f604c9b8bb6e61041def86729b2fc7408bd241e23c213ac57f0226ee656e2bb0a583ae0e4f3bf6c6ab6c490c9a6f0d8cdfd366aacf5d83193671a8f77cd1af1ff2e9145de92ec43ec87cf4bdc563f6e919fe32861b0e93b118ec37d8035fbb3c.59dd05c5d9a8ae726528783128218f15fe6f2c0c8145eddab112b374fcfe3d79&token_id=&phone_type=1&time=' + t + '&phone_model=xiaomi-22021211rc&keys=qDpotE2bedimK3QGqlyV5ieXXC3EhaPLQ%2BIOJyHnHflCj5w%2F7ESK7FgywMvrgjxbx0GklEFLI4%2BJshgySe633OIRstuktwdiCy3CT%2BfLSpuxBJDIlfXQDaeH3ig1wiB0JsZ601XHiFweGMu4tZfnSpHg3OnoL6nz%2FuurUif2OK4%3D&request_key=' + key + '&signature=' + signature2 + '&app_id=1&ad_version=1';
|
||||
return body
|
||||
}
|
||||
const bodykey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGAe6hKrWLi1zQmjTT1ozbE4QdFeJGNxubxld6GrFGximxfMsMB6BpJhpcTouAqywAFppiKetUBBbXwYsYU1wNr648XVmPmCMCy4rY8vdliFnbMUj086DU6Z+/oXBdWU3/b1G0DN3E9wULRSwcKZT3wj/cCI1vsCm3gj2R5SqkA9Y0CAwEAAQKBgAJH+4CxV0/zBVcLiBCHvSANm0l7HetybTh/j2p0Y1sTXro4ALwAaCTUeqdBjWiLSo9lNwDHFyq8zX90+gNxa7c5EqcWV9FmlVXr8VhfBzcZo1nXeNdXFT7tQ2yah/odtdcx+vRMSGJd1t/5k5bDd9wAvYdIDblMAg+wiKKZ5KcdAkEA1cCakEN4NexkF5tHPRrR6XOY/XHfkqXxEhMqmNbB9U34saTJnLWIHC8IXys6Qmzz30TtzCjuOqKRRy+FMM4TdwJBAJQZFPjsGC+RqcG5UvVMiMPhnwe/bXEehShK86yJK/g/UiKrO87h3aEu5gcJqBygTq3BBBoH2md3pr/W+hUMWBsCQQChfhTIrdDinKi6lRxrdBnn0Ohjg2cwuqK5zzU9p/N+S9x7Ck8wUI53DKm8jUJE8WAG7WLj/oCOWEh+ic6NIwTdAkEAj0X8nhx6AXsgCYRql1klbqtVmL8+95KZK7PnLWG/IfjQUy3pPGoSaZ7fdquG8bq8oyf5+dzjE/oTXcByS+6XRQJAP/5ciy1bL3NhUhsaOVy55MHXnPjdcTX0FaLi+ybXZIfIQ2P4rb19mVq1feMbCXhz+L1rG8oat5lYKfpe8k83ZA==";
|
||||
|
||||
function gethtml(u, body, headers) {
|
||||
var hd = fetch(u, {
|
||||
headers: headers,
|
||||
body: body,
|
||||
method: 'POST',
|
||||
rejectCoding: true
|
||||
});
|
||||
var banner = JSON.parse(hd).data;
|
||||
var response_key = banner.response_key; //log()
|
||||
//console.log("response_key=="+response_key)
|
||||
var keys = banner.keys; //log(keys)
|
||||
var bodykeyiv = JSON.parse(RSA.decode(keys, bodykey));
|
||||
//console.log("rsaxxxx=="+JSON.stringify(bodykeyiv))
|
||||
var key = CryptoJS.enc.Utf8.parse(bodykeyiv.key);
|
||||
var iv = CryptoJS.enc.Utf8.parse(bodykeyiv.iv);
|
||||
var html = Decrypt(response_key, key, iv);
|
||||
//console.log("nskjsnwkjdnejd===qqxxxq="+JSON.stringify(html))
|
||||
return html
|
||||
}
|
||||
var timestamp = new Date().getTime() / 1000;
|
||||
var t = timestamp.toString().split('.')[0];
|
||||
var url = input.split("#")[0]; //url
|
||||
var request_key11 = input.split("#")[1]
|
||||
|
||||
var request_key = JSON.stringify({
|
||||
"keywords": request_key11,
|
||||
"order_val": "1"
|
||||
})
|
||||
//console.log("nskjsnwkjdnejd===qqxxxq=tttt"+request_key)
|
||||
var request_key2 = Encrypt(request_key);
|
||||
var body = getbody3(request_key2, t)
|
||||
var headers = {
|
||||
'Cache-Control': 'no-cache',
|
||||
'Version': '2406025',
|
||||
'PackageName': 'com.uf076bf0c246.qe439f0d5e.m8aaf56b725a.ifeb647346f',
|
||||
'Ver': '1.9.2',
|
||||
'Referer': 'https://api.8utdtcq.com',
|
||||
'X-Customer-Client-Ip': '127.0.0.1',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Host': 'api.8utdtcq.com',
|
||||
'Connection': 'Keep-Alive',
|
||||
'User-Agent': 'okhttp/3.12.0'
|
||||
}
|
||||
var html = gethtml(url, body, headers)
|
||||
//console.log("nskjsnwkjdnejd===="+html)
|
||||
|
||||
var list = JSON.parse(html).list; //log(list)
|
||||
//console.log("nskjsnwkjdnejd===qqqqq="+list)
|
||||
list.forEach(data => {
|
||||
d.push({
|
||||
title: data.vod_name,
|
||||
desc: data.vod_continu == 0 ? '电影' : '更新至' + data.vod_continu + '集',
|
||||
content: data.vod_addtime,
|
||||
img: data.vod_pic,
|
||||
url: `${data.vod_id}/${data.vod_continu}`,
|
||||
})
|
||||
})
|
||||
setResult(d)
|
||||
}),
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
广东珠江经济台,https://lhttp.qtfm.cn/live/1259/64k.mp3?app_id=web
|
||||
加州星岛中文粤语台,http://nap.casthost.net:8765/m3u8
|
||||
新城知讯台,https://1603884249.rsc.cdn77.org/1603884249/tracks-a1/mono.ts.m3u8
|
||||
新城采讯台,https://1946218710.rsc.cdn77.org/1946218710/tracks-a1/mono.ts.m3u8
|
||||
深圳飞扬971,https://lhttp.qtfm.cn/live/1271/64k.mp3?app_id=web
|
||||
茂名综合广播,https://lhttp.qtfm.cn/live/20500088/64k.mp3?app_id=web
|
||||
清晨音乐,https://live.ximalaya.com/radio-first-page-app/live/1011/64.m3u8
|
||||
怀集音乐,https://live.ximalaya.com/radio-first-page-app/live/966/64.m3u8
|
||||
粤语,https://live.ximalaya.com/radio-first-page-app/live/999/64.m3u8
|
||||
经典,https://live.ximalaya.com/radio-first-page-app/live/2689/64.m3u8
|
||||
亚洲热歌,https://live.ximalaya.com/radio-first-page-app/live/1908/64.m3u8
|
||||
年代音乐,https://live.ximalaya.com/radio-first-page-app/live/763/64.m3u8
|
||||
FM105.6,https://live.ximalaya.com/radio-first-page-app/live/325/64.m3u8
|
||||
音悦台,https://live.ximalaya.com/radio-first-page-app/live/2684/64.m3u8
|
||||
年代965,https://live.ximalaya.com/radio-first-page-app/live/2878/64.m3u8
|
||||
经典调频1038,https://live.ximalaya.com/radio-first-page-app/live/2728/64.m3u8
|
||||
化州人民广播电台,https://lhttp.qtfm.cn/live/15318689/64k.mp3?app_id=web
|
||||
马来西亚988友声有色,https://22243.live.streamtheworld.com/988_FMAAC.aac
|
||||
Yes933,https://playerservices.streamtheworld.com/api/livestream-redirect/YES933_PREM.aac
|
||||
澳门fm99.5,https://fm995.ddns.net/hls1/fm995.m3u8
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,8 @@
|
|||
#订阅名
|
||||
地址(支持m3u订阅、tvbox配置文件中live选项的直播地址订阅)
|
||||
|
||||
相对路径说明
|
||||
以./开头,相对位置是本订阅文件
|
||||
以/开头,存储卡的根目录
|
||||
#电台
|
||||
./电台.txt
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
var rule = {
|
||||
title:'腾云驾雾',
|
||||
host:'https://v.%71%71.com',
|
||||
// homeUrl:'/channel/choice?listpage=1&channel=choice&sort=18&_all=1',
|
||||
homeUrl:'/x/bu/pagesheet/list?_all=1&append=1&channel=choice&listpage=1&offset=0&pagesize=21&iarea=-1&sort=18',
|
||||
detailUrl:'https://node.video.%71%71.com/x/api/float_vinfo2?cid=fyid',
|
||||
// searchUrl:'https://node.video.%71%71.com/x/api/msearch?keyWord=**',
|
||||
searchUrl:'https://pbaccess.video.%71%71.com/trpc.videosearch.smartboxServer.HttpRountRecall/Smartbox?query=**&appID=3172&appKey=lGhFIPeD3HsO9xEp&pageNum=(fypage-1)&pageSize=10',
|
||||
// searchUrl:'http://s.video.qq.com/smartbox?plat=2&ver=0&num=29&otype=json&query=**',
|
||||
searchable:2,
|
||||
filterable:1,
|
||||
multi:1,
|
||||
// url:'/channel/fyclass?listpage=fypage&channel=fyclass&sort=18&_all=1',
|
||||
url:'/x/bu/pagesheet/list?_all=1&append=1&channel=fyclass&listpage=1&offset=((fypage-1)*21)&pagesize=21&iarea=-1',
|
||||
filter_url:'sort={{fl.sort or 18}}&year={{fl.year}}&pay={{fl.pay}}',
|
||||
filter:{'choice': [{'key': 'sort', 'name': '排序', 'value': [{'n': '最热', 'v': '18'}, {'n': '最新', 'v': '19'}, {'n': '好评', 'v': '16'}, {'n': '高分好评', 'v': '21'}]}, {'key': 'pay', 'name': '资费', 'value': [{'n': '全部', 'v': '-1'}, {'n': '免费', 'v': '867'}, {'n': '会员', 'v': '6'}]}, {'key': 'year', 'name': '年代', 'value': [{'n': '全部', 'v': '-1'}, {'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', 'v': '2016'}, {'n': '2015', 'v': '2015'}]}], 'tv': [{'key': 'sort', 'name': '排序', 'value': [{'n': '最热', 'v': '18'}, {'n': '最新', 'v': '19'}, {'n': '好评', 'v': '16'}, {'n': '高分好评', 'v': '21'}]}, {'key': 'pay', 'name': '资费', 'value': [{'n': '全部', 'v': '-1'}, {'n': '免费', 'v': '867'}, {'n': '会员', 'v': '6'}]}, {'key': 'year', 'name': '年代', 'value': [{'n': '全部', 'v': '-1'}, {'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', 'v': '2016'}, {'n': '2015', 'v': '2015'}]}], 'movie': [{'key': 'sort', 'name': '排序', 'value': [{'n': '最热', 'v': '18'}, {'n': '最新', 'v': '19'}, {'n': '好评', 'v': '16'}, {'n': '高分好评', 'v': '21'}]}, {'key': 'pay', 'name': '资费', 'value': [{'n': '全部', 'v': '-1'}, {'n': '免费', 'v': '867'}, {'n': '会员', 'v': '6'}]}, {'key': 'year', 'name': '年代', 'value': [{'n': '全部', 'v': '-1'}, {'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', 'v': '2016'}, {'n': '2015', 'v': '2015'}]}], 'variety': [{'key': 'sort', 'name': '排序', 'value': [{'n': '最热', 'v': '18'}, {'n': '最新', 'v': '19'}, {'n': '好评', 'v': '16'}, {'n': '高分好评', 'v': '21'}]}, {'key': 'pay', 'name': '资费', 'value': [{'n': '全部', 'v': '-1'}, {'n': '免费', 'v': '867'}, {'n': '会员', 'v': '6'}]}, {'key': 'year', 'name': '年代', 'value': [{'n': '全部', 'v': '-1'}, {'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', 'v': '2016'}, {'n': '2015', 'v': '2015'}]}], 'cartoon': [{'key': 'sort', 'name': '排序', 'value': [{'n': '最热', 'v': '18'}, {'n': '最新', 'v': '19'}, {'n': '好评', 'v': '16'}, {'n': '高分好评', 'v': '21'}]}, {'key': 'pay', 'name': '资费', 'value': [{'n': '全部', 'v': '-1'}, {'n': '免费', 'v': '867'}, {'n': '会员', 'v': '6'}]}, {'key': 'year', 'name': '年代', 'value': [{'n': '全部', 'v': '-1'}, {'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', 'v': '2016'}, {'n': '2015', 'v': '2015'}]}], 'child': [{'key': 'sort', 'name': '排序', 'value': [{'n': '最热', 'v': '18'}, {'n': '最新', 'v': '19'}, {'n': '好评', 'v': '16'}, {'n': '高分好评', 'v': '21'}]}, {'key': 'pay', 'name': '资费', 'value': [{'n': '全部', 'v': '-1'}, {'n': '免费', 'v': '867'}, {'n': '会员', 'v': '6'}]}, {'key': 'year', 'name': '年代', 'value': [{'n': '全部', 'v': '-1'}, {'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', 'v': '2016'}, {'n': '2015', 'v': '2015'}]}], 'doco': [{'key': 'sort', 'name': '排序', 'value': [{'n': '最热', 'v': '18'}, {'n': '最新', 'v': '19'}, {'n': '好评', 'v': '16'}, {'n': '高分好评', 'v': '21'}]}, {'key': 'pay', 'name': '资费', 'value': [{'n': '全部', 'v': '-1'}, {'n': '免费', 'v': '867'}, {'n': '会员', 'v': '6'}]}, {'key': 'year', 'name': '年代', 'value': [{'n': '全部', 'v': '-1'}, {'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', 'v': '2016'}, {'n': '2015', 'v': '2015'}]}]},
|
||||
headers:{
|
||||
'User-Agent':'PC_UA',
|
||||
'Referer':'https://v.qq.com/',
|
||||
'Origin':'https://v.qq.com/'
|
||||
},
|
||||
timeout:5000,
|
||||
// class_parse:'.site_channel a;a&&Text;a&&href;channel/(.*)',
|
||||
cate_exclude:'会员|游戏|全部',
|
||||
class_name:'精选&电视剧&电影&综艺&动漫&少儿&纪录片',
|
||||
class_url:'choice&tv&movie&variety&cartoon&child&doco',
|
||||
limit:20,
|
||||
// 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',
|
||||
一级:'.list_item;img&&alt;img&&src;a&&Text;a&&data-float',
|
||||
// 二级:{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.title;data.moviecategory[0]+data.moviecategory[1]","img":"data.cdncover","desc":"data.area[0];data.director[0]","content":"data.description","tabs":"data.playlink_sites","lists":"data.playlinksdetail.#idv.default_url"},
|
||||
二级:'',
|
||||
二级:'js:VOD={};let d=[];let video_list=[];let video_lists=[];let list=[];let QZOutputJson;let html=fetch(input,fetch_params);let sourceId=/get_playsource/.test(input)?input.match(/id=(\\d*?)&/)[1]:input.split("cid=")[1];let cid=sourceId;let detailUrl="https://v.%71%71.com/detail/m/"+cid+".html";log("详情页:"+detailUrl);var pdfh=jsp.pdfh;var pd=jsp.pd;try{let json=JSON.parse(html);VOD={vod_url:input,vod_name:json.c.title,type_name:json.typ.join(","),vod_actor:json.nam.join(","),vod_year:json.c.year,vod_content:json.c.description,vod_remarks:json.rec,vod_pic:urljoin2(input,json.c.pic)}}catch(e){log("解析片名海报等基础信息发生错误:"+e.message)}if(/get_playsource/.test(input)){eval(html);let indexList=QZOutputJson.PlaylistItem.indexList;indexList.forEach(function(it){let dataUrl="https://s.video.qq.com/get_playsource?id="+sourceId+"&plat=2&type=4&data_type=3&range="+it+"&video_type=10&plname=qq&otype=json";eval(fetch(dataUrl,fetch_params));let vdata=QZOutputJson.PlaylistItem.videoPlayList;vdata.forEach(function(item){d.push({title:item.title,pic_url:item.pic,desc:item.episode_number+"\\t\\t\\t播放量:"+item.thirdLine,url:item.playUrl})});video_lists=video_lists.concat(vdata)})}else{let json=JSON.parse(html);video_lists=json.c.video_ids;let url="https://v.qq.com/x/cover/"+sourceId+".html";if(video_lists.length===1){let vid=video_lists[0];url="https://v.qq.com/x/cover/"+cid+"/"+vid+".html";d.push({title:"在线播放",url:url})}else if(video_lists.length>1){for(let i=0;i<video_lists.length;i+=30){video_list.push(video_lists.slice(i,i+30))}video_list.forEach(function(it,idex){let o_url="https://union.video.qq.com/fcgi-bin/data?otype=json&tid=1804&appid=20001238&appkey=6c03bbe9658448a4&union_platform=1&idlist="+it.join(",");let o_html=fetch(o_url,fetch_params);eval(o_html);QZOutputJson.results.forEach(function(it1){it1=it1.fields;let url="https://v.qq.com/x/cover/"+cid+"/"+it1.vid+".html";d.push({title:it1.title,pic_url:it1.pic160x90.replace("/160",""),desc:it1.video_checkup_time,url:url,type:it1.category_map&&it1.category_map.length>1?it1.category_map[1]:""})})})}}let yg=d.filter(function(it){return it.type&&it.type!=="正片"});let zp=d.filter(function(it){return!(it.type&&it.type!=="正片")});VOD.vod_play_from=yg.length<1?"qq":"qq$$$qq 预告及花絮";VOD.vod_play_url=yg.length<1?d.map(function(it){return it.title+"$"+it.url}).join("#"):[zp,yg].map(function(it){return it.map(function(its){return its.title+"$"+its.url}).join("#")}).join("$$$");',
|
||||
// 二级:'js:VOD={};let d=[];let video_list=[];let video_lists=[];let list=[];let QZOutputJson;let html=fetch(input,fetch_params);let sourceId=/get_playsource/.test(input)?input.match(/id=(\\d*?)&/)[1]:input.split("cid=")[1];let cid=sourceId;let detailUrl="https://v.%71%71.com/detail/m/"+cid+".html";log("详情页:"+detailUrl);var pdfh=jsp.pdfh;var pd=jsp.pd;try{let json=JSON.parse(html);VOD={vod_url:input,vod_name:json.c.title,type_name:json.typ.join(","),vod_actor:json.nam.join(","),vod_year:json.c.year,vod_content:json.c.description,vod_remarks:json.rec,vod_pic:urljoin2(input,json.c.pic)}}catch(e){log("解析片名海报等基础信息发生错误:"+e.message)}if(/get_playsource/.test(input)){eval(html);let indexList=QZOutputJson.PlaylistItem.indexList;indexList.forEach(function(it){let dataUrl="https://s.video.qq.com/get_playsource?id="+sourceId+"&plat=2&type=4&data_type=3&range="+it+"&video_type=10&plname=qq&otype=json";eval(fetch(dataUrl,fetch_params));let vdata=QZOutputJson.PlaylistItem.videoPlayList;vdata.forEach(function(item){d.push({title:item.title,pic_url:item.pic,desc:item.episode_number+"\\t\\t\\t播放量:"+item.thirdLine,url:item.playUrl})});video_lists=video_lists.concat(vdata)})}else{let json=JSON.parse(html);video_lists=json.c.video_ids;let url="https://v.qq.com/x/cover/"+sourceId+".html";if(json.c.type===10){let dataUrl="https://s.video.qq.com/get_playsource?id="+json.c.column_id+"&plat=2&type=2&data_type=3&video_type=8&plname=qq&otype=json";let o_html=fetch(dataUrl,fetch_params);eval(o_html);video_lists=[];let indexList=QZOutputJson.PlaylistItem.indexList;indexList.forEach(function(it){let dataUrl="https://s.video.qq.com/get_playsource?id="+json.c.column_id+"&plat=2&type=4&data_type=3&range="+it+"&video_type=10&plname=qq&otype=json";eval(fetch(dataUrl,fetch_params));let vdata=QZOutputJson.PlaylistItem.videoPlayList;vdata.forEach(function(item){d.push({title:item.title,pic_url:item.pic,desc:item.episode_number+"\\t\\t\\t播放量:"+item.thirdLine,url:item.playUrl})});video_lists=video_lists.concat(vdata)})}else if(video_lists.length===1){d.push({title:"在线播放",url:url})}else if(video_lists.length>1){for(let i=0;i<video_lists.length;i+=30){video_list.push(video_lists.slice(i,i+30))}video_list.forEach(function(it,idex){let o_url="https://union.video.qq.com/fcgi-bin/data?otype=json&tid=1804&appid=20001238&appkey=6c03bbe9658448a4&union_platform=1&idlist="+it.join(",");let o_html=fetch(o_url,fetch_params);eval(o_html);QZOutputJson.results.forEach(function(it1){it1=it1.fields;let url="https://v.qq.com/x/cover/"+cid+"/"+it1.vid+".html";d.push({title:it1.title,pic_url:it1.pic160x90.replace("/160",""),desc:it1.video_checkup_time,url:url,type:it1.category_map&&it1.category_map.length>1?it1.category_map[1]:""})})})}}let yg=d.filter(function(it){return it.type&&it.type!=="正片"});let zp=d.filter(function(it){return!(it.type&&it.type!=="正片")});VOD.vod_play_from=yg.length<1?"qq":"qq$$$qq 预告及花絮";VOD.vod_play_url=yg.length<1?d.map(function(it){return it.title+"$"+it.url}).join("#"):[zp,yg].map(function(it){return it.map(function(its){return its.title+"$"+its.url}).join("#")}).join("$$$");',
|
||||
// 搜索:'json:uiData;data[0].title;data[0].posterPic;.titleMarkLabelList[1].primeText;data[0].id;data[0].publishDate',
|
||||
搜索:"js:var d=[];let html=request(input);let json=JSON.parse(html);if(json.data.smartboxItemList.length>0){for(let vod of json.data.smartboxItemList.filter(it=>it.basicDoc&&it.basicDoc.id)){let cid=vod.basicDoc.id;let title=vod.basicDoc.title;let url='https://node.video.qq.com/x/api/float_vinfo2?cid='+cid;if(vod.videoInfo&&vod.videoInfo.imgUrl){d.push({title:title,img:vod.videoInfo.imgUrl,url:url,content:'',desc:vod.videoInfo.typeName||''})}else{let html1=request(url);let data=JSON.parse(html1);d.push({title:data.c.title,img:data.c.pic,url:url,content:data.c.description,desc:data.rec})}}};setResult(d);",
|
||||
// 搜索:'json:item;word;dc;class;id;sn',
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,463 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Author : Doubebly
|
||||
# @Time : 2025/5/29 22:07
|
||||
|
||||
|
||||
import sys
|
||||
import hashlib
|
||||
import time
|
||||
import requests
|
||||
import re
|
||||
import json
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
|
||||
|
||||
class Spider(Spider):
|
||||
def getName(self):
|
||||
return "Aidianying"
|
||||
|
||||
def init(self, extend):
|
||||
self.home_url = 'https://m.sdzhgt.com/'
|
||||
self.ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
|
||||
self.error_url = "https://sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4"
|
||||
|
||||
def getDependence(self):
|
||||
return []
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def homeContent(self, filter):
|
||||
return {
|
||||
'class': [{'type_id': '1', 'type_name': '电影'},
|
||||
{'type_id': '2', 'type_name': '电视剧'},
|
||||
{'type_id': '3', 'type_name': '综艺'},
|
||||
{'type_id': '4', 'type_name': '动漫'}],
|
||||
'filters': {
|
||||
'1': [
|
||||
{'key': 'type',
|
||||
'name': '类型',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '喜剧', 'v': '/type/22'},
|
||||
{'n': '动作', 'v': '/type/23'},
|
||||
{'n': '科幻', 'v': '/type/30'},
|
||||
{'n': '爱情', 'v': '/type/26'},
|
||||
{'n': '悬疑', 'v': '/type/27'},
|
||||
{'n': '奇幻', 'v': '/type/87'},
|
||||
{'n': '剧情', 'v': '/type/37'},
|
||||
{'n': '恐怖', 'v': '/type/36'},
|
||||
{'n': '犯罪', 'v': '/type/35'},
|
||||
{'n': '动画', 'v': '/type/33'},
|
||||
{'n': '惊悚', 'v': '/type/34'},
|
||||
{'n': '战争', 'v': '/type/25'},
|
||||
{'n': '冒险', 'v': '/type/31'},
|
||||
{'n': '灾难', 'v': '/type/81'},
|
||||
{'n': '伦理', 'v': '/type/83'},
|
||||
{'n': '其他', 'v': '/type/43'}]},
|
||||
{'key': 'area',
|
||||
'name': '地区',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '中国大陆', 'v': '/area/中国大陆'},
|
||||
{'n': '中国香港', 'v': '/area/中国香港'},
|
||||
{'n': '中国台湾', 'v': '/area/中国台湾'},
|
||||
{'n': '美国', 'v': '/area/美国'},
|
||||
{'n': '日本', 'v': '/area/日本'},
|
||||
{'n': '韩国', 'v': '/area/韩国'},
|
||||
{'n': '印度', 'v': '/area/印度'},
|
||||
{'n': '泰国', 'v': '/area/泰国'},
|
||||
{'n': '其他', 'v': '/area/其他'}]},
|
||||
{'key': 'year',
|
||||
'name': '年份',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '2024', 'v': '/year/2024'},
|
||||
{'n': '2023', 'v': '/year/2023'},
|
||||
{'n': '2022', 'v': '/year/2022'},
|
||||
{'n': '2021', 'v': '/year/2021'},
|
||||
{'n': '2020', 'v': '/year/2020'},
|
||||
{'n': '2019', 'v': '/year/2019'},
|
||||
{'n': '2018', 'v': '/year/2018'},
|
||||
{'n': '2017', 'v': '/year/2017'},
|
||||
{'n': '2016', 'v': '/year/2016'},
|
||||
{'n': '2015', 'v': '/year/2015'},
|
||||
{'n': '2014', 'v': '/year/2014'},
|
||||
{'n': '2013', 'v': '/year/2013'},
|
||||
{'n': '2012', 'v': '/year/2012'},
|
||||
{'n': '2011', 'v': '/year/2011'},
|
||||
{'n': '2010', 'v': '/year/2010'},
|
||||
{'n': '2009~2000', 'v': '/year/2009~2000'}]},
|
||||
{'key': 'lang',
|
||||
'name': '语言',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '国语', 'v': '/lang/国语'},
|
||||
{'n': '英语', 'v': '/lang/英语'},
|
||||
{'n': '粤语', 'v': '/lang/粤语'},
|
||||
{'n': '韩语', 'v': '/lang/韩语'},
|
||||
{'n': '日语', 'v': '/lang/日语'},
|
||||
{'n': '其他', 'v': '/lang/其他'}]},
|
||||
{'key': 'by',
|
||||
'name': '排序',
|
||||
'value': [{'n': '上映时间', 'v': '/sortType/1/sortOrder/0'},
|
||||
{'n': '人气高低', 'v': '/sortType/3/sortOrder/0'},
|
||||
{'n': '评分高低', 'v': '/sortType/4/sortOrder/0'}]}
|
||||
],
|
||||
'2': [
|
||||
{'key': 'type',
|
||||
'name': '类型',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '国产剧', 'v': '/type/14'},
|
||||
{'n': '欧美剧', 'v': '/type/15'},
|
||||
{'n': '港台剧', 'v': '/type/16'},
|
||||
{'n': '日韩剧', 'v': '/type/62'},
|
||||
{'n': '其他剧', 'v': '/type/68'}]},
|
||||
{'key': 'class',
|
||||
'name': '剧情',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '古装', 'v': '/class/古装'},
|
||||
{'n': '战争', 'v': '/class/战争'},
|
||||
{'n': '喜剧', 'v': '/class/喜剧'},
|
||||
{'n': '家庭', 'v': '/class/家庭'},
|
||||
{'n': '犯罪', 'v': '/class/犯罪'},
|
||||
{'n': '动作', 'v': '/class/动作'},
|
||||
{'n': '奇幻', 'v': '/class/奇幻'},
|
||||
{'n': '剧情', 'v': '/class/剧情'},
|
||||
{'n': '历史', 'v': '/class/历史'},
|
||||
{'n': '短片', 'v': '/class/短片'}]},
|
||||
{'key': 'area',
|
||||
'name': '地区',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '中国大陆', 'v': '/area/中国大陆'},
|
||||
{'n': '中国香港', 'v': '/area/中国香港'},
|
||||
{'n': '中国台湾', 'v': '/area/中国台湾'},
|
||||
{'n': '日本', 'v': '/area/日本'},
|
||||
{'n': '韩国', 'v': '/area/韩国'},
|
||||
{'n': '美国', 'v': '/area/美国'},
|
||||
{'n': '泰国', 'v': '/area/泰国'},
|
||||
{'n': '其他', 'v': '/area/其他'}]},
|
||||
{'key': 'year',
|
||||
'name': '时间',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '2024', 'v': '/year/2024'},
|
||||
{'n': '2023', 'v': '/year/2023'},
|
||||
{'n': '2022', 'v': '/year/2022'},
|
||||
{'n': '2021', 'v': '/year/2021'},
|
||||
{'n': '2020', 'v': '/year/2020'},
|
||||
{'n': '2019', 'v': '/year/2019'},
|
||||
{'n': '2018', 'v': '/year/2018'},
|
||||
{'n': '2017', 'v': '/year/2017'},
|
||||
{'n': '2016', 'v': '/year/2016'},
|
||||
{'n': '2015', 'v': '/year/2015'},
|
||||
{'n': '2014', 'v': '/year/2014'},
|
||||
{'n': '2013', 'v': '/year/2013'},
|
||||
{'n': '2012', 'v': '/year/2012'},
|
||||
{'n': '2011', 'v': '/year/2011'},
|
||||
{'n': '2010', 'v': '/year/2010'}]},
|
||||
{'key': 'lang',
|
||||
'name': '语言',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '普通话', 'v': '/lang/普通话'},
|
||||
{'n': '英语', 'v': '/lang/英语'},
|
||||
{'n': '粤语', 'v': '/lang/粤语'},
|
||||
{'n': '韩语', 'v': '/lang/韩语'},
|
||||
{'n': '日语', 'v': '/lang/日语'},
|
||||
{'n': '泰语', 'v': '/lang/泰语'},
|
||||
{'n': '其他', 'v': '/lang/其他'}, ]},
|
||||
{'key': 'by',
|
||||
'name': '排序',
|
||||
'value': [{'n': '最近更新', 'v': '/sortType/1/sortOrder/0'},
|
||||
{'n': '添加时间', 'v': '/sortType/2/sortOrder/0'},
|
||||
{'n': '人气高低', 'v': '/sortType/3/sortOrder/0'},
|
||||
{'n': '评分高低', 'v': '/sortType/4/sortOrder/0'}]}
|
||||
],
|
||||
'3': [
|
||||
{'key': 'type',
|
||||
'name': '类型',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '国产综艺', 'v': '/type/69'},
|
||||
{'n': '港台综艺', 'v': '/type/70'},
|
||||
{'n': '日韩综艺', 'v': '/type/72'},
|
||||
{'n': '欧美综艺', 'v': '/type/73'}]},
|
||||
{'key': 'class',
|
||||
'name': '剧情',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '真人秀', 'v': '/class/真人秀'},
|
||||
{'n': '音乐', 'v': '/class/音乐'},
|
||||
{'n': '脱口秀', 'v': '/class/脱口秀'}]},
|
||||
{'key': 'area',
|
||||
'name': '地区',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '中国大陆', 'v': '/area/中国大陆'},
|
||||
{'n': '中国香港', 'v': '/area/中国香港'},
|
||||
{'n': '中国台湾', 'v': '/area/中国台湾'},
|
||||
{'n': '日本', 'v': '/area/日本'},
|
||||
{'n': '韩国', 'v': '/area/韩国'},
|
||||
{'n': '美国', 'v': '/area/美国'},
|
||||
{'n': '其他', 'v': '/area/其他'}]},
|
||||
{'key': 'year',
|
||||
'name': '时间',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '2024', 'v': '/year/2024'},
|
||||
{'n': '2023', 'v': '/year/2023'},
|
||||
{'n': '2022', 'v': '/year/2022'},
|
||||
{'n': '2021', 'v': '/year/2021'},
|
||||
{'n': '2020', 'v': '/year/2020'}]},
|
||||
{'key': 'lang',
|
||||
'name': '语言',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '国语', 'v': '/lang/国语'},
|
||||
{'n': '英语', 'v': '/lang/英语'},
|
||||
{'n': '粤语', 'v': '/lang/粤语'},
|
||||
{'n': '韩语', 'v': '/lang/韩语'},
|
||||
{'n': '日语', 'v': '/lang/日语'},
|
||||
{'n': '其他', 'v': '/lang/其他'}, ]},
|
||||
{'key': 'by',
|
||||
'name': '排序',
|
||||
'value': [{'n': '最近更新', 'v': '/sortType/1/sortOrder/0'},
|
||||
{'n': '添加时间', 'v': '/sortType/2/sortOrder/0'},
|
||||
{'n': '人气高低', 'v': '/sortType/3/sortOrder/0'},
|
||||
{'n': '评分高低', 'v': '/sortType/4/sortOrder/0'}]}
|
||||
],
|
||||
'4': [
|
||||
{'key': 'type',
|
||||
'name': '类型',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '国产动漫', 'v': '/type/75'},
|
||||
{'n': '日韩动漫', 'v': '/type/76'},
|
||||
{'n': '欧美动漫', 'v': '/type/77'}]},
|
||||
{'key': 'class',
|
||||
'name': '剧情',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '喜剧', 'v': '/class/喜剧'},
|
||||
{'n': '科幻', 'v': '/class/科幻'},
|
||||
{'n': '热血', 'v': '/class/热血'},
|
||||
{'n': '冒险', 'v': '/class/冒险'},
|
||||
{'n': '动作', 'v': '/class/动作'},
|
||||
{'n': '运动', 'v': '/class/运动'},
|
||||
{'n': '战争', 'v': '/class/战争'},
|
||||
{'n': '儿童', 'v': '/class/儿童'}]},
|
||||
{'key': 'area',
|
||||
'name': '地区',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '中国大陆', 'v': '/area/中国大陆'},
|
||||
{'n': '日本', 'v': '/area/日本'},
|
||||
{'n': '美国', 'v': '/area/美国'},
|
||||
{'n': '其他', 'v': '/area/其他'}]},
|
||||
{'key': 'year',
|
||||
'name': '时间',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '2024', 'v': '/year/2024'},
|
||||
{'n': '2023', 'v': '/year/2023'},
|
||||
{'n': '2022', 'v': '/year/2022'},
|
||||
{'n': '2021', 'v': '/year/2021'},
|
||||
{'n': '2020', 'v': '/year/2020'},
|
||||
{'n': '2019', 'v': '/year/2019'},
|
||||
{'n': '2018', 'v': '/year/2018'},
|
||||
{'n': '2017', 'v': '/year/2017'},
|
||||
{'n': '2016', 'v': '/year/2016'},
|
||||
{'n': '2015', 'v': '/year/2015'},
|
||||
{'n': '2014', 'v': '/year/2014'},
|
||||
{'n': '2013', 'v': '/year/2013'},
|
||||
{'n': '2012', 'v': '/year/2012'},
|
||||
{'n': '2011', 'v': '/year/2011'},
|
||||
{'n': '2010', 'v': '/year/2010'}]},
|
||||
{'key': 'lang',
|
||||
'name': '语言',
|
||||
'value': [{'n': '全部', 'v': ''},
|
||||
{'n': '国语', 'v': '/lang/国语'},
|
||||
{'n': '英语', 'v': '/lang/英语'},
|
||||
{'n': '日语', 'v': '/lang/日语'},
|
||||
{'n': '其他', 'v': '/lang/其他'}]},
|
||||
{'key': 'by',
|
||||
'name': '排序',
|
||||
'value': [{'n': '最近更新', 'v': '/sortType/1/sortOrder/0'},
|
||||
{'n': '添加时间', 'v': '/sortType/2/sortOrder/0'},
|
||||
{'n': '人气高低', 'v': '/sortType/3/sortOrder/0'},
|
||||
{'n': '评分高低', 'v': '/sortType/4/sortOrder/0'}]}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
def homeVideoContent(self):
|
||||
video_list = []
|
||||
t = str(int(time.time() * 1000))
|
||||
# t = '1723292093234'
|
||||
data = f'key=cb808529bae6b6be45ecfab29a4889bc&t={t}'
|
||||
data_md5 = hashlib.md5(data.encode()).hexdigest()
|
||||
data_sha1 = hashlib.sha1(data_md5.encode()).hexdigest()
|
||||
h = {
|
||||
"User-Agent": self.ua,
|
||||
'referer': self.home_url, 't': t, 'sign': data_sha1}
|
||||
try:
|
||||
res = requests.get(f'{self.home_url}/api/mw-movie/anonymous/home/hotSearch', headers=h)
|
||||
data_list = res.json()['data']
|
||||
for i in data_list:
|
||||
video_list.append(
|
||||
{
|
||||
'vod_id': i['vodId'],
|
||||
'vod_name': i['vodName'],
|
||||
'vod_pic': i['vodPic'],
|
||||
'vod_remarks': i['vodVersion'] if i['typeId1'] == 1 else i['vodRemarks']
|
||||
}
|
||||
)
|
||||
except requests.RequestException as e:
|
||||
return {
|
||||
'list': [],
|
||||
'parse': 0,
|
||||
'jx': 0
|
||||
}
|
||||
|
||||
return {
|
||||
'list': video_list,
|
||||
'parse': 0,
|
||||
'jx': 0
|
||||
}
|
||||
|
||||
def categoryContent(self, cid, page, filter, ext):
|
||||
t = cid
|
||||
_type = ext.get('type') if ext.get('type') else ''
|
||||
__class = ext.get('class') if ext.get('class') else ''
|
||||
_area = ext.get('area') if ext.get('area') else ''
|
||||
_year = ext.get('year') if ext.get('year') else ''
|
||||
_lang = ext.get('lang') if ext.get('lang') else ''
|
||||
_by = ext.get('by') if ext.get('by') else ''
|
||||
video_list = []
|
||||
h = {
|
||||
"User-Agent": self.ua,
|
||||
'referer': self.home_url,
|
||||
}
|
||||
try:
|
||||
res = requests.get(
|
||||
f'{self.home_url}/vod/show/id/{t}{_type}{__class}{_area}{_year}{_lang}{_by}/page/{page}',
|
||||
headers=h)
|
||||
aa = re.findall(r'\\"list\\":(.*?)}}}]', res.text)
|
||||
if not aa:
|
||||
return {'list': [], 'parse': 0, 'jx': 0}
|
||||
bb = aa[0].replace('\\"', '"')
|
||||
data_list = json.loads(bb)
|
||||
for i in data_list:
|
||||
video_list.append(
|
||||
{
|
||||
'vod_id': i['vodId'],
|
||||
'vod_name': i['vodName'],
|
||||
'vod_pic': i['vodPic'],
|
||||
'vod_remarks': i['vodVersion'] if i['typeId1'] == 1 else i['vodRemarks']
|
||||
}
|
||||
)
|
||||
except requests.RequestException as e:
|
||||
return {'list': [], 'msg': e}
|
||||
return {'list': video_list, 'parse': 0, 'jx': 0}
|
||||
|
||||
def detailContent(self, did):
|
||||
ids = did[0]
|
||||
video_list = []
|
||||
t = str(int(time.time() * 1000))
|
||||
# t = '1723292093234'
|
||||
data = f'id={ids}&key=cb808529bae6b6be45ecfab29a4889bc&t={t}'
|
||||
data_md5 = hashlib.md5(data.encode()).hexdigest()
|
||||
data_sha1 = hashlib.sha1(data_md5.encode()).hexdigest()
|
||||
h = {
|
||||
"User-Agent": self.ua,
|
||||
'referer': self.home_url,
|
||||
't': t, 'sign': data_sha1
|
||||
}
|
||||
try:
|
||||
res = requests.get(f'{self.home_url}/api/mw-movie/anonymous/video/detail?id={ids}', headers=h)
|
||||
data = res.json()['data']
|
||||
play_list = data['episodeList']
|
||||
vod_play_url = []
|
||||
for i in play_list:
|
||||
name = i['name']
|
||||
url = ids + '/' + str(i['nid'])
|
||||
vod_play_url.append(name + '$' + url)
|
||||
|
||||
video_list.append(
|
||||
{
|
||||
'type_name': data['typeName'],
|
||||
'vod_id': ids,
|
||||
'vod_name': data['vodName'],
|
||||
'vod_remarks': data['vodRemarks'],
|
||||
'vod_year': data['vodYear'],
|
||||
'vod_area': data['vodArea'],
|
||||
'vod_actor': data['vodActor'],
|
||||
'vod_director': data['vodDirector'],
|
||||
'vod_content': data['vodContent'],
|
||||
'vod_play_from': '老僧酿酒',
|
||||
'vod_play_url': '#'.join(vod_play_url)
|
||||
|
||||
}
|
||||
)
|
||||
except requests.RequestException as e:
|
||||
return {'list': [], 'msg': e}
|
||||
return {"list": video_list, 'parse': 0, 'jx': 0}
|
||||
|
||||
def searchContent(self, key, quick, page='1'):
|
||||
wd = key
|
||||
video_list = []
|
||||
t = str(int(time.time() * 1000))
|
||||
data = f'keyword={wd}&pageNum={page}&pageSize=12&key=cb808529bae6b6be45ecfab29a4889bc&t={t}'
|
||||
data_md5 = hashlib.md5(data.encode()).hexdigest()
|
||||
data_sha1 = hashlib.sha1(data_md5.encode()).hexdigest()
|
||||
h = {
|
||||
"User-Agent": self.ua,
|
||||
'referer': self.home_url,
|
||||
't': t, 'sign': data_sha1
|
||||
}
|
||||
try:
|
||||
response = requests.get(
|
||||
f'{self.home_url}/api/mw-movie/anonymous/video/searchByWord?keyword={wd}&pageNum={page}&pageSize=12',
|
||||
headers=h,
|
||||
)
|
||||
data_list = response.json()['data']['result']['list']
|
||||
for i in data_list:
|
||||
video_list.append(
|
||||
{
|
||||
'vod_id': i['vodId'],
|
||||
'vod_name': i['vodName'],
|
||||
'vod_pic': i['vodPic'],
|
||||
'vod_remarks': i['vodVersion'] if i['typeId1'] == 1 else i['vodRemarks']
|
||||
}
|
||||
)
|
||||
except requests.RequestException as e:
|
||||
return {'list': [], 'msg': e}
|
||||
return {'list': video_list, 'parse': 0, 'jx': 0}
|
||||
|
||||
def playerContent(self, flag, pid, vipFlags):
|
||||
url = pid
|
||||
play_url = self.error_url
|
||||
data = url.split('/')
|
||||
_id = data[0]
|
||||
_nid = data[1]
|
||||
t = str(int(time.time() * 1000))
|
||||
# t = '1723292093234'
|
||||
data = f'id={_id}&nid={_nid}&key=cb808529bae6b6be45ecfab29a4889bc&t={t}'
|
||||
data_md5 = hashlib.md5(data.encode()).hexdigest()
|
||||
data_sha1 = hashlib.sha1(data_md5.encode()).hexdigest()
|
||||
h = {
|
||||
"User-Agent": self.ua,
|
||||
'referer': self.home_url,
|
||||
't': t, 'sign': data_sha1
|
||||
}
|
||||
h2 = {
|
||||
"User-Agent": self.ua,
|
||||
}
|
||||
try:
|
||||
res = requests.get(
|
||||
f'{self.home_url}/api/mw-movie/anonymous/v2/video/episode/url?id={_id}&nid={_nid}',
|
||||
headers=h)
|
||||
play_url = res.json()['data']['list'][0]['url']
|
||||
except requests.RequestException as e:
|
||||
return {"url": play_url, "header": h2, "parse": 0, "jx": 0}
|
||||
|
||||
return {"url": play_url, "header": h2, "parse": 0, "jx": 0}
|
||||
|
||||
def localProxy(self, params):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
return '正在Destroy'
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
Binary file not shown.
Loading…
Reference in New Issue