feat(spider): 添加爱看短剧和锦鲤短剧接口

- 新增爱看短剧和锦鲤短剧两个短剧平台的接口实现
- 更新 api.json 配置,添加新接口的信息
- 优化了短剧内容的获取和解析逻辑
This commit is contained in:
Wang.Luo 2025-07-25 00:03:40 +08:00
parent 52649e3431
commit 00d70c636a
8 changed files with 356 additions and 268 deletions

20
XBPQ/免费影视.json Normal file
View File

@ -0,0 +1,20 @@
{
"站名": "",
"主页url": "https://www.freeok.ac",
"请求头": "User-Agent$MOBILE_UA",
"编码": "UTF-8",
"数组": "",
"图片": "data-original=\"&&\"",
"标题": "",
"链接": "href=\"&&\"",
"副标题": "",
"线路数组": "module-tab-item&&</div>",
"线路标题": "data-dropdown-value=\"&&\"",
"播放数组": "",
"播放标题": "",
"跳转播放链接": "urlDecode(Base64(var player_*url\":\"&&\"))",
"搜索url": "https://www.freeok.ac/vodsearch/-------------.html?wd={wd}",
"简介": "<p>&&</p>",
"分类url": "https://www.freeok.ac/type/{cateId}.html",
"分类": "电影$1#连续剧$2#动漫$3#综艺$4#短剧$24"
}

51
XBPQ/明星影视.json Normal file
View File

@ -0,0 +1,51 @@
{
"作者": "",
"站名": "明星影院",
"请求头": "User-Agent$MOBILE_UA",
"编码": "UTF-8",
"图片代理": "",
"直接播放": "0",
"播放请求头": "",
"过滤词": "",
"主页url": "https://mxvod.com",
"首页": "120",
"起始页": "1",
"分类url": "https://mxvod.com/vodshow/{cateId}-{area}-{by}-{class}-{lang}-{letter}---{catePg}---{year}.html",
"分类": "电影$dianying#电视剧$dianshiju#综艺$zongyi#动漫$dongman#短剧$duanju",
"二次截取": "module-items\"&&id=\"page",
"数组": "lazyloaded&&/a>",
"标题": "title=*>&&<",
"图片": "data-src=\"&&\"",
"副标题": "class\">&&<",
"链接": "href=\"&&\"[替换:vodplay>>voddetail#-1-1.html>>.html]",
"影片年代": "-----------*.html\">&&</",
"影片地区": "video:area\" content=\"&&\"",
"影片类型": "video:class\" content=\"&&\"",
"状态": "tag-link-red\">&&</div>",
"导演": "导演:&&</div>",
"主演": "主演:&&\">",
"简介": "vod_content\"&&</div>",
"线路数组": "data-dropdown&&/small>",
"线路标题": "value=\"&&\"+【共+<small>&&<+集】",
"播放数组": "id=\"sort-item&&</div>",
"播放列表": "<a&&/a>",
"播放标题": "<span>&&<",
"播放链接": "href=\"&&\"",
"跳转播放链接": "var player_*\"url\":\"&&\"",
"搜索请求头": "User-Agent$MOBILE_UA",
"搜索url": "https://mxvod.com/vodsearch/{wd}----------{pg}---.html",
"搜索模式": "1",
"搜索数组": "lazyload\"&&/a>",
"搜索标题": "title=\"&&\"",
"搜索图片": "data-src=\"&&\"",
"搜索副标题": "title=*>&&<",
"搜索链接": "href=\"&&\"",
"筛选": "1",
"类型": "动作片$dongzuopian#喜剧片$xijupian#爱情片$aiqingpian#科幻片$kehuanpian#恐怖片$kongbupian#战争片$zhanzhengpian#剧情片$juqingpian#动画片$donghuapian#悬疑片$xuanyi#纪录片$jilupian#奇幻片$qihuanpian#灾难片$zainanpian||国产剧$guochanju#欧美剧$oumeiju#日剧$riju#韩剧$hanju#港台剧$gangtai#海外剧$haiwai||大陆综艺$daluzongyi#港台综艺$gangtaizongyi#欧美综艺$oumeizongyi#日韩综艺$rihanzongyi#海外综艺$haiwaizongyi||国产动漫$guochandongman#日韩动漫$rihandongman#欧美动漫$oumeidongman#海外动漫$haiwaidongman||空",
"剧情": "喜剧&爱情&恐怖&动作&科幻&剧情&战争&警匪&犯罪&动画&奇幻&武侠&冒险&枪战&恐怖&悬疑&惊悚&经典&青春&文艺&微电影&古装&历史&运动&农村&儿童&网络电影||古装&战争&青春偶像&喜剧&家庭&犯罪&动作&奇幻&剧情&历史&经典&乡村&情景&商战&网剧&其他||选秀&情感&访谈&播报&旅游&音乐&美食&纪实&曲艺&生活&游戏互动&财经&求职||情感&科幻&热血&推理&搞笑&冒险&萝莉&校园&动作&机战&运动&战争&少年&少女&社会&原创&亲子&益智&励志&其他||古装&虐恋&逆袭&神豪&重生&复仇&穿越&甜宠&强者&萌宝&其它",
"年份": "1990-2025",
"年份值": "*",
"语言值": "*",
"排序": "时间&人气&评分",
"排序值": "time&hits&score"
}

38
XBPQ/麦田影视.json Normal file
View File

@ -0,0 +1,38 @@
{
"站名": "麦田appXBPQ",
"规则作者": "啦啦啦",
"请求头": "User-Agent$MOBILE_UA",
"编码": "UTF-8",
"主页url": "http://172.247.31.147:25321/mtys.php/v6/index_video",
"分类url": "http://172.247.31.147:25321/mtys.php/v6/video?pg={catePg}&tid={cateId}&class={class}&area={area}&lang={lang}&year={year}&order={by};;mr",
"分类": "电影&电视剧&综艺&动漫&少儿&短剧&直播",
"分类值": "1&2&3&4&25&26&30",
"数组": "{&&}",
"图片": "vod_pic\":\"&&\"",
"标题": "vod_name\":\"&&\"",
"副标题": "vod_remarks\":\"&&\"",
"链接": "http://172.247.31.147:25321/mtys.php/v6/video_detail?id=+vod_id\":&&,",
"线路二次截取": "vod_url_with_player\":\\[{&&}\\][替换:\"name\":\">>\"name\":\"题]",
"线路数组": "\"name\":\"&&,",
"线路标题": "题&&\"",
"播放二次截取": "vod_url_with_player\":\\[{&&}\\]",
"播放数组": "url\":&&,[替换:\">>接表题#$>>题接#\\#>>接表表题]",
"播放列表": "表&&表",
"播放标题": "题&&题",
"播放链接": "urlDecode(接&&接)",
"解析": "PD源$http://172.247.31.148:25320/jx.php?url=#NB源$https://api.nbyjson.top:7788/api/?key=ws9Lz1EtqfU09AzZKl&url=#ZB源$http://27.25.159.14:6699/api/mgapp.php?url=",
"影片类型": "vod_class\":\"&&\"",
"影片年代": "vod_year\":\"&&\"",
"影片地区": "vod_area\":\"&&\"",
"导演": "vod_director\":\"&&\"",
"主演": "vod_actor\":\"&&\"",
"简介": "vod_content\":\"&&\"",
"搜索url": "http://172.247.31.147:25321/mtys.php/v6/search?pg={pg}&tid=0&text={wd}",
"搜索模式": "1",
"搜索二次截取": "data\":\\[&&\\]",
"搜索数组": "{&&}",
"搜索图片": "vod_pic\":\"&&\"",
"搜索标题": "vod_name\":\"&&\"",
"搜索副标题": "vod_remarks\":\"&&\"",
"搜索链接": "http://172.247.31.147:25321/mtys.php/v6/video_detail?id=+vod_id\":&&,"
}

View File

@ -134,15 +134,15 @@
}
},
{
"key": "APP4K",
"key": "蓝光",
"name": "蓝光APP",
"type": 3,
"quickSearch": 1,
"api": "csp_AppGet",
"ext": {
"url": "http://59.153.167.186",
"dataKey": "SDSFET23215FDSF2",
"dataIv": "SDSFET23215FDSF2",
"url": "http://122.228.193.2:9654",
"dataKey": "ca94b06ca3c7d80e",
"dataIv": "ca94b06ca3c7d80e",
"deviceId": "",
"version": "119"
}
@ -356,7 +356,8 @@
"quickSearch": 1,
"api": "csp_AppGet",
"ext": {
"url": "https://www.guahd.com",
"url": "",
"site": "https://www.guahd.com/1.txt",
"dataKey": "f2A7D4B9E8C16531",
"dataIv": "f2A7D4B9E8C16531",
"deviceId": "",
@ -1037,11 +1038,26 @@
"playerType": 2
},
{
"key": "短剧",
"name": "短剧网|短剧",
"key": "爱看短剧",
"name": "爱看|短剧",
"type": 3,
"api": "csp_HBPQ",
"ext": "./XBPQ/短剧网.json"
"api": "./py/爱看短剧.py",
"searchable": 1,
"changeable": 1,
"quickSearch": 1,
"filterable": 1,
"playerType": 2
},
{
"key": "锦鲤短剧",
"name": "锦鲤|短剧",
"type": 3,
"api": "./py/锦鲤短剧.py",
"searchable": 1,
"changeable": 1,
"quickSearch": 1,
"filterable": 1,
"playerType": 2
},
{
"comment": "自定义接口开始",
@ -1645,6 +1661,20 @@
"quickSearch": 1,
"filterable": 1
},
{
"key": "明星影视",
"name": "明星|影视",
"type": 3,
"api": "csp_HBPQ",
"ext": "./XBPQ/明星影视.json"
},
{
"key": "麦田影视",
"name": "麦田|影视",
"type": 3,
"api": "csp_HBPQ",
"ext": "./XBPQ/麦田影视.json"
},
{
"key": "海纳影视",
"name": "海纳|影视",
@ -1652,6 +1682,13 @@
"api": "csp_HBPQ",
"ext": "./XBPQ/海纳影视.json"
},
{
"key": "免费影视",
"name": "免费|影视",
"type": 3,
"api": "csp_HBPQ",
"ext": "./XBPQ/免费影视.json"
},
{
"key": "面包影视",
"name": "面包|影视",

View File

@ -30,5 +30,5 @@
"type_id": "42317879720298"
}
],
"Cookie": "JSESSIONID=E1DB8AC0F708B4E282B9998F371F9E3B; cms_token=2e714955704148f99268eaa976de09ce; cms_accessToken=6272a9e68faa49c4a73c684df0c44eee; cms_refreshToken=4908d2845de044d7bcde237f66092415"
"Cookie": "cms_token=91643744d93a42f98e15b6784f0bd310; JSESSIONID=D92622710E6342FD11574AC11CF9DFC6; cms_accessToken=7dab23285f764ee3a0b8d84abdff2fe1; cms_refreshToken=2f4d43120dcc4c258c80d0a1cd2df559"
}

View File

@ -1,29 +1,14 @@
# -*- coding: utf-8 -*-
# by @嗷呜
import base64
import binascii
import json
import random
import sys
import time
import uuid
from base64 import b64decode, b64encode
from Crypto.Cipher import AES
from Crypto.Hash import MD5
from Crypto.Util.Padding import unpad, pad
from pyquery import PyQuery as pq
sys.path.append('..')
from base.spider import Spider
class Spider(Spider):
def init(self, extend=""):
self.ut = False
# self.did, self.ntid =self.getdid()
self.did, self.ntid = 'e59eb2465f61b9ca','65a0de19b3a2ec93fa479ad6'
self.token, self.uid = self.gettoken()
self.phost, self.phz,self.mphost=self.getpic()
# self.phost, self.phz,self.mphost = ('https://dbtp.tgydy.com','.log','https://dplay.nbzsmc.com')
pass
def getName(self):
@ -38,238 +23,34 @@ class Spider(Spider):
def destroy(self):
pass
host='http://192.151.245.34:8089'
host='http://www.toule.top'
def md5(self, text):
h = MD5.new()
h.update(text.encode('utf-8'))
return h.hexdigest()
def uuid(self):
return str(uuid.uuid4())
def getdid(self):
did = self.random_str(16)
ntid = self.random_str(24)
return did, ntid
# try:
# if self.getCache('did'):
# return self.getCache('did'), self.getCache('ntid')
# else:
# self.setCache('did', did)
# self.setCache('ntid', ntid)
# return did, ntid
# except Exception as e:
# self.setCache('did', did)
# self.setCache('ntid', ntid)
# return did, ntid
def aes(self, text, bool=True):
key = b64decode('c0k4N1RfKTY1U1cjJERFRA==')
iv = b64decode('VzIjQWRDVkdZSGFzSEdEVA==')
if bool:
cipher = AES.new(key, AES.MODE_CBC, iv)
ct_bytes = cipher.encrypt(pad(text.encode("utf-8"), AES.block_size))
ct = b64encode(ct_bytes).decode("utf-8")
return ct
else:
cipher = AES.new(key, AES.MODE_CBC, iv)
pt = unpad(cipher.decrypt(b64decode(text)), AES.block_size)
ptt=json.loads(pt.decode("utf-8"))
return ptt
def random_str(self,length=24):
hex_chars = '0123456789abcdef'
return ''.join(random.choice(hex_chars) for _ in range(length))
def gettoken(self):
params={"deviceId":self.did,"deviceModel":"8848钛晶手机","devicePlatform":"1","tenantId":self.ntid}
data=self.getdata('/supports/anonyLogin',params)
self.ut=True
return data['data']['token'], data['data']['userId']
def getdata(self,path,params=None):
t = int(time.time()*1000)
n=self.md5(f'{self.uuid()}{t}')
if params:
ct=self.aes(json.dumps(params))
else:
ct=f'{t}{n}'
s=self.md5(f'{ct}8j@78m.367HGDF')
headers = {
'User-Agent': 'okhttp-okgo/jeasonlzy',
'Connection': 'Keep-Alive',
'Accept-Language': 'zh-CN,zh;q=0.8',
'tenantId': self.ntid,
'n': n,
't': str(int(t/1000)),
's': s,
}
if self.ut:
headers['ta-token'] = self.token
headers['userId'] = self.uid
if params:
params={'ct':ct}
response = self.post(f'{self.host}{path}', headers=headers, json=params).text
else:
response = self.fetch(f'{self.host}{path}', headers=headers).text
data=self.aes(response[1:-1],False)
return data
def getpic(self):
try:
at = int(time.time() * 1000)
t=str(int(at/ 1000))
n = self.md5(f'{self.uuid()}{at}')
headers = {
'Host': '192.151.245.34:8089',
'User-Agent': 'okhttp-okgo/jeasonlzy',
'Connection': 'Keep-Alive',
'Accept-Language': 'zh-CN,zh;q=0.8',
'tenantId': self.ntid,
'userId': self.uid,
'ta-token': self.token,
'n': n,
't': t,
's': self.md5(f'{t}{n}8j@78m.367HGDF')
}
params = {
'tenantId': self.ntid,
}
response = self.fetch(f'{self.host}/supports/configs', params=params, headers=headers).text
data=self.aes(response[1:-1],False)
config = {
'image_cdn': '',
'image_cdn_path': '',
'cdn-domain': ''
}
for item in data.get('data', []):
name = item.get('name')
records = item.get('records', [])
if name in config and records:
value = records[0].get('value', '')
if name == 'cdn-domain':
value = value.split('#')[0]
config[name] = value
return config['image_cdn'], config['image_cdn_path'], config['cdn-domain']
except Exception as e:
print(f"Error in getpic: {e}")
return 'https://dbtp.tgydy.com', '.log', 'https://dplay.nbzsmc.com'
def getlist(self,data):
vod=[]
for i in data:
vod.append({
'vod_id': f'{i.get("movieId")}@{i.get("entryNum")}',
'vod_name': i.get('title'),
'vod_pic': f'{self.getProxyUrl()}&path={i.get("thumbnail")}',
'vod_year': i.get('score'),
'vod_remarks': f'{i.get("entryNum")}'
})
return vod
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
'Referer':f'{host}/',
'Origin':host
}
def homeContent(self, filter):
data=self.getdata('/movies/classifies')
data=self.getpq()
result = {}
cateManual = {
"榜单": "ranking/getTodayHotRank",
"专辑": "getTMovieFolderPage",
"剧场": "getClassMoviePage2",
"演员": "follow/getRecommendActorPage",
}
classes = []
for k in cateManual:
for k in data('.swiper-wrapper .swiper-slide').items():
classes.append({
'type_name': k,
'type_id': cateManual[k]
'type_name': k.text(),
'type_id': k.text()
})
filters = {}
if data.get('data'):
filters["getClassMoviePage2"] = [
{
"key": "type",
"name": "分类",
"value": [
{"n": item["name"], "v": item["classifyId"]}
for item in data["data"]
]
}
]
filters["ranking/getTodayHotRank"] = [
{
"key": "type",
"name": "榜单",
"value": [
{"n": "播放榜", "v": "getWeekHotPlayRank"},
{"n": "高赞榜", "v": "getWeekStarRank"},
{"n": "追剧榜", "v": "getSubTMoviePage"},
{"n": "高分榜", "v": "ranking/getScoreRank"}
]
}
]
filters["follow/getRecommendActorPage"] = [
{
"key": "type",
"name": "性别",
"value": [
{"n": "", "v": "0"},
{"n": "", "v": "1"}
]
}
]
result['class'] = classes
result['filters'] = filters
result['list'] = self.getlist(data('.container.items ul li'))
return result
def homeVideoContent(self):
params = {"pageNo":"1","pageSize":"30","platform":"1","deviceId":self.did,"tenantId":self.ntid}
data=self.getdata('/news/getRecommendTMoviePage',params)
vod=self.getlist(data['data']['records'])
return {'list':vod}
pass
def categoryContent(self, tid, pg, filter, extend):
params={}
path = f'/news/{tid}'
if tid=='getClassMoviePage2':
parama={"pageNo":pg,"pageSize":"30","orderFlag":"0","haveActor":"-1","classifyId":extend.get('type','-1'),"tagId":""}
elif 'rank' in tid:
path=f'/news/{extend.get("type") or tid}'
parama={"pageNo":pg,"pageSize":"30"}
elif 'follow' in tid:
parama={"pageNo":pg,"pageSize":"20"}
if extend.get('type'):
path=f'/news/getActorPage'
parama={"pageNo":pg,"pageSize":"50","sex":extend.get('type')}
elif tid=='getTMovieFolderPage':
parama={"pageNo":pg,"pageSize":"20"}
elif '@' in tid:
path='/news/getActorTMoviePage'
parama={"id":tid.split('@')[0],"pageNo":pg,"pageSize":"30"}
params['platform'] = '1'
params['deviceId'] = self.did
params['tenantId'] = self.ntid
data=self.getdata(path,parama)
vods=[]
if 'follow' in tid:
for i in data['data']['records']:
vods.append({
'vod_id': f'{i.get("id")}@',
'vod_name': i.get('name'),
'vod_pic': i.get('avatar'),
'vod_tag': 'folder',
'vod_remarks': f'作品{i.get("movieNum")}',
'style': {"type": "oval"}
})
else:
vdata=data['data']['records']
if tid=='getTMovieFolderPage':
vdata=[j for i in data['data']['records'] for j in i['movieList']]
vods=self.getlist(vdata)
data=self.getpq(f"/index.php/vod/show/class/{tid}/id/1/page/{pg}.html")
result = {}
result['list'] = vods
result['list'] = self.getlist(data('.container.items ul li'))
result['page'] = pg
result['pagecount'] = 9999
result['limit'] = 90
@ -277,38 +58,52 @@ class Spider(Spider):
return result
def detailContent(self, ids):
ids=ids[0].split('@')
params = {"pageNo": "1", "pageSize": ids[1], "movieId": ids[0], "platform": "1", "deviceId": self.did, "tenantId": self.ntid}
data = self.getdata('/news/getEntryPage', params)
print(data)
plist=[f'{i.get("entryNum")}集${i.get("mp4PlayAddress") or i.get("playAddress")}' for i in data['data']['records']]
data=self.getpq(ids[0])
v=data('.container.detail-content')
vod = {
'vod_remarks': v('.items-tags a').text(),
'vod_content': v('.text-content .detail').text(),
'vod_play_from': '爱看短剧',
'vod_play_url': '#'.join(plist),
'vod_play_url': '#'.join([f"{i.text()}${i('a').attr('href')}" for i in data('.swiper-wrapper .swiper-slide').items()])
}
return {'list':[vod]}
def searchContent(self, key, quick, pg="1"):
params = {"pageNo": pg, "pageSize": "20", "keyWord": key, "orderFlag": "0", "platform": "1", "deviceId": self.did, "tenantId": self.ntid}
data = self.getdata('/news/searchTMoviePage', params)
vod = self.getlist(data['data']['records'])
return {'list':vod,'page':pg}
data=self.getpq(f"/index.php/vod/search/page/{pg}/wd/{key}.html")
return {'list':self.getlist(data('.container.items ul li')),'page':pg}
def playerContent(self, flag, id, vipFlags):
return {'parse': 0, 'url': f'{self.mphost}{id}', 'header': {'User-Agent':'Dalvik/2.1.0 (Linux; U; Android 11; M2012K10C Build/RP1A.200720.011)'}}
data=self.getpq(id)
try:
jstr=data('.player-content script').eq(0).text()
jt=json.loads(jstr.split('=',1)[-1])
p,url=0,jt['url']
except Exception as e:
print(f"获取播放地址失败: {e}")
p,url=1,f'{self.host}{id}'
return {'parse': p, 'url': url, 'header': self.headers}
def localProxy(self, param):
type=param.get('path').split('.')[-1]
data=self.fetch(f'{self.phost}{param.get("path")}{self.phz}',headers={'User-Agent':'Dalvik/2.1.0 (Linux; U; Android 11; M2012K10C Build/RP1A.200720.011)'})
def decrypt(encrypted_text):
try:
key = base64.urlsafe_b64decode("iM41VipvCFtToAFFRExEXw==")
iv = base64.urlsafe_b64decode("0AXRTXzmMSrlRSemWb4sVQ==")
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted_padded = cipher.decrypt(encrypted_text)
decrypted_data = unpad(decrypted_padded, AES.block_size)
return decrypted_data
except (binascii.Error, ValueError):
return None
return [200, f'image/{type}', decrypt(data.content)]
pass
def liveContent(self, url):
pass
def getpq(self, path=''):
data=self.fetch(f"{self.host}{path}",headers=self.headers).text
try:
return pq(data)
except Exception as e:
print(f"{str(e)}")
return pq(data.encode('utf-8'))
def getlist(self,data):
videos = []
for i in data.items():
videos.append({
'vod_id': i('.image-line').attr('href'),
'vod_name': i('img').attr('alt'),
'vod_pic': i('img').attr('src'),
'vod_remarks': i('.remarks.light').text()
})
return videos

147
py/锦鲤短剧.py Normal file
View File

@ -0,0 +1,147 @@
from base.spider import Spider
import re,sys,json
sys.path.append('..')
class Spider(Spider):
api_host = 'https://api.jinlidj.com'
origin = 'https://www.jinlidj.com'
api_path = '/api/search'
headers = {
'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",
'Content-Type': "application/json",
'accept-language': "zh-CN,zh;q=0.9",
'cache-control': "no-cache",
'origin': origin,
'pragma': "no-cache",
'priority': "u=1, i",
'referer': origin+'/',
'sec-ch-ua': "\"Not)A;Brand\";v=\"8\", \"Chromium\";v=\"138\", \"Google Chrome\";v=\"138\"",
'sec-ch-ua-mobile': "?0",
'sec-ch-ua-platform': "\"Windows\"",
'sec-fetch-dest': "empty",
'sec-fetch-mode': "cors",
'sec-fetch-site': "same-site"
}
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': '战斗热血'}, {'type_id': 5, 'type_name': '伦理现实'}, {'type_id': 6, 'type_name': '时空穿越'}, {'type_id': 7, 'type_name': '权谋身份'}]}
def homeVideoContent(self):
payload = {
"page": 1,
"limit": 24,
"type_id": "",
"year": "",
"keyword": ""
}
response = self.post(f"{self.api_host}{self.api_path}", data=json.dumps(payload), headers=self.headers).json()
data = response['data']
videos = []
for i in data['list']:
videos.append({
'vod_id': i.get('vod_id'),
'vod_name': i.get('vod_name'),
'vod_class': i.get('vod_class'),
'vod_pic': i.get('vod_pic'),
'vod_year': i.get('vod_year'),
'vod_remarks': i.get('vod_total')+'',
'vod_score': i.get('vod_score')
})
return {'list': videos}
def detailContent(self, ids):
response = self.post(f'{self.api_host}/api/detail/{ids[0]}', data=json.dumps({}), headers=self.headers).json()
data = response['data']
videos = []
vod_play_url = ''
for name,url in data['player'].items():
vod_play_url += f'{name}${url}#'
vod_play_url.rstrip('#')
videos.append({
'vod_id': data.get('vod_id'),
'vod_name': data.get('vod_name'),
'vod_content': data.get('vod_blurb'),
'vod_remarks': '集数:' + data.get('vod_total'),
"vod_director": data.get('vod_director'),
"vod_actor": data.get('vod_actor'),
'vod_year': data.get('vod_year'),
'vod_area': data.get('vod_area'),
'vod_play_from': '锦鲤短剧',
'vod_play_url': vod_play_url
})
return {'list': videos}
def searchContent(self, key, quick, pg="1"):
payload = {
"page": pg,
"limit": 24,
"type_id": "",
"keyword": key
}
response = self.post(f'{self.api_host}{self.api_path}', data=json.dumps(payload), headers=self.headers).json()
data = response['data']
videos = []
for i in data['list']:
videos.append({
"vod_id": i['vod_id'],
"vod_name": i['vod_name'],
"vod_class": i['vod_class'],
"vod_pic": i['vod_pic'],
'vod_year': i.get('vod_year'),
"vod_remarks": i['vod_total'] + ''
})
return {'list': videos, 'page': pg, 'total': data['total'], 'limit': 24}
def categoryContent(self, tid, pg, filter, extend):
payload = {
"page": pg,
"limit": 24,
"type_id": tid,
"year": "",
"keyword": ""
}
response = self.post(f'{self.api_host}{self.api_path}', data=json.dumps(payload), headers=self.headers).json()
data = response['data']
videos = []
for i in data['list']:
videos.append({
'vod_id': i.get('vod_id'),
'vod_name': i.get('vod_name'),
'vod_class': i.get('vod_class'),
'vod_pic': i.get('vod_pic'),
'vod_remarks': i.get('vod_total')+'',
'vod_year': i.get('vod_year'),
'vod_score': i.get('vod_score')
})
return {'list': videos}
def playerContent(self, flag, id, vipflags):
parse = 0
header = {'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'}
try:
response = self.fetch(id, headers=self.headers).text
match = re.search(r'let\s+data\s*=\s*(\{[^}]*http[^}]*\});', response, re.IGNORECASE)
data = match.group(1)
data2 = json.loads(data)
url = data2['url']
except Exception:
url, parse, header = id, 1, self.headers
return {'parse': parse, 'url': url,'header': header}
def init(self, extend=''):
pass
def getName(self):
pass
def isVideoFormat(self, url):
pass
def manualVideoCheck(self):
pass
def destroy(self):
pass
def localProxy(self, param):
pass

Binary file not shown.