feat(spider): 添加爱看短剧和锦鲤短剧接口
- 新增爱看短剧和锦鲤短剧两个短剧平台的接口实现 - 更新 api.json 配置,添加新接口的信息 - 优化了短剧内容的获取和解析逻辑
This commit is contained in:
parent
52649e3431
commit
00d70c636a
20
XBPQ/免费影视.json
Normal file
20
XBPQ/免费影视.json
Normal 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
51
XBPQ/明星影视.json
Normal 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
38
XBPQ/麦田影视.json
Normal 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\":&&,"
|
||||
}
|
55
api.json
55
api.json
@ -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": "面包|影视",
|
||||
|
@ -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"
|
||||
}
|
311
py/爱看短剧.py
311
py/爱看短剧.py
@ -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
147
py/锦鲤短剧.py
Normal 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
|
BIN
spider.jar
BIN
spider.jar
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user