mirror of
https://github.com/yuanwangokk-1/TV-BOX.git
synced 2025-10-24 23:11:21 +00:00
190 lines
7.4 KiB
Python
190 lines
7.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
# by @嗷呜
|
|
import base64
|
|
import json
|
|
import re
|
|
import sys
|
|
from pprint import pprint
|
|
from Crypto.Cipher import AES
|
|
from Crypto.Util.Padding import pad
|
|
from pyquery import PyQuery as pq
|
|
sys.path.append('..')
|
|
from base.spider import Spider
|
|
|
|
|
|
class Spider(Spider):
|
|
|
|
def init(self, extend=""):
|
|
self.chost,self.token=self.gettoken()
|
|
self.phost='https://wsrv.nl?url=https://image.tmdb.org/t/p/w500'
|
|
# self.chost,self.token= 'https://api.themoviedb.org/3','eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJhZDFhYmJjMmM4YjhkY2I2NzJiYzI1Y2M3ZDcxYzVhOCIsIm5iZiI6MTczNzUxMTI4MC4wOCwic3ViIjoiNjc5MDUxNzA1NTBlNmZjM2NkZGZlOThiIiwic2NvcGVzIjpbImFwaV9yZWFkIl0sInZlcnNpb24iOjF9.fmGzxmyxA-r74R_1_wo-sPHtfOn3zyGQqzPxr3NUIII'
|
|
# print(self.chost,self.token)
|
|
self.headers.update({'authorization': f"Bearer {self.token}"})
|
|
pass
|
|
|
|
def getName(self):
|
|
pass
|
|
|
|
def isVideoFormat(self, url):
|
|
pass
|
|
|
|
def manualVideoCheck(self):
|
|
pass
|
|
|
|
def destroy(self):
|
|
pass
|
|
|
|
headers ={
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.7103.48 Safari/537.36',
|
|
'sec-ch-ua-platform': '"Windows"',
|
|
'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="136", "Google Chrome";v="136"',
|
|
'origin': 'https://nunflix.org',
|
|
'referer': 'https://nunflix.org/',
|
|
}
|
|
|
|
jx='https://111movies.com'
|
|
|
|
def homeContent(self, filter):
|
|
result = {}
|
|
cate = {
|
|
"电影": "movie",
|
|
"剧集": "tv"
|
|
}
|
|
classes = []
|
|
filters = {}
|
|
for k, j in cate.items():
|
|
classes.append({
|
|
'type_name': k,
|
|
'type_id': j
|
|
})
|
|
result['class'] = classes
|
|
result['filters'] = filters
|
|
return result
|
|
|
|
def homeVideoContent(self):
|
|
data=self.fetch(f"{self.chost}/trending/all/week",headers=self.headers).json()
|
|
return {'list':self.getlist(data['results'])}
|
|
|
|
def categoryContent(self, tid, pg, filter, extend):
|
|
params = {'page':pg}
|
|
data=self.fetch(f'{self.chost}/discover/{tid}',params=params,headers=self.headers).json()
|
|
result = {}
|
|
result['list'] = self.getlist(data['results'],tid)
|
|
result['page'] = pg
|
|
result['pagecount'] = 9999
|
|
result['limit'] = 90
|
|
result['total'] = 999999
|
|
return result
|
|
|
|
def detailContent(self, ids):
|
|
v=self.fetch(f'{self.chost}{ids[0]}',headers=self.headers).json()
|
|
if 'movie' in ids[0]:
|
|
p=f"{v.get('title') or v.get('name')}${ids[0]}"
|
|
else:
|
|
p='#'.join([f"{i.get('name')}${ids[0]}/{i.get('season_number')}/1" for i in v.get('seasons')])
|
|
vod = {
|
|
'vod_year': v.get('release_date') or v.get('last_air_date'),
|
|
'vod_area': v.get('original_language'),
|
|
'vod_remarks': v.get('tagline'),
|
|
'vod_content': v.get('overview'),
|
|
'vod_play_from': '默认',
|
|
'vod_play_url': p
|
|
}
|
|
return {'list':[vod]}
|
|
|
|
def searchContent(self, key, quick, pg="1"):
|
|
data=self.fetch(f'{self.chost}/search/multi',params={'query':key,'page':pg},headers=self.headers).json()
|
|
return {'list':self.getlist(data['results']),'page':pg}
|
|
|
|
def playerContent(self, flag, id, vipFlags):
|
|
data=self.fetch(f'{self.jx}{id}',headers=self.headers).text
|
|
jstr=json.loads(pq(data)('#__NEXT_DATA__').text())
|
|
url=self.encrypt_data(jstr['props']['pageProps'].get('data'))
|
|
return {'parse': 0, 'url': url, 'header': self.jxh()}
|
|
|
|
def getlist(self,data,tid=''):
|
|
videos = []
|
|
for i in data:
|
|
videos.append({
|
|
'vod_id': f"/{tid or i.get('media_type')}/{i.get('id')}",
|
|
'vod_name': i.get('title') or i.get('name'),
|
|
'vod_pic': f"{self.phost}{i.get('backdrop_path')}",
|
|
'vod_remarks': f"{i.get('popularity', 0):.2f}",
|
|
})
|
|
return videos
|
|
|
|
def encrypt_data(self,data_str):
|
|
key = bytes(
|
|
[1, 157, 45, 74, 228, 243, 24, 124, 194, 12, 184, 70, 3, 93, 102, 187, 254, 72, 230, 97, 57, 129, 254, 216,
|
|
223,
|
|
113, 82, 42, 62, 208, 244, 63])
|
|
iv = bytes([147, 233, 144, 118, 246, 33, 110, 119, 13, 209, 140, 42, 32, 186, 47, 89])
|
|
xkey = bytes([238, 123, 35, 56, 43, 184, 57, 233, 233, 41])
|
|
cipher = AES.new(key, AES.MODE_CBC, iv)
|
|
padded_data = pad(data_str.encode(), AES.block_size)
|
|
encrypted_data = cipher.encrypt(padded_data)
|
|
hex_data = encrypted_data.hex()
|
|
result = ""
|
|
for i in range(len(hex_data)):
|
|
char_code = ord(hex_data[i])
|
|
xor_value = xkey[i % len(xkey)]
|
|
result += chr(char_code ^ xor_value)
|
|
|
|
base64_result = base64.b64encode(result.encode('utf-8')).decode('ascii').replace('+', '-').replace('/',
|
|
'_').replace(
|
|
'=', '')
|
|
source_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
|
|
target_chars = "PpowE6rtqQ9OxFNzg_vLTJmHKi07j45fXubCVecGURsaS1ny8lBWdAD2ZkM3-YhI"
|
|
char_map = {source_chars[i]: target_chars[i] for i in range(len(source_chars))}
|
|
final_result = ''.join([char_map.get(c, c) for c in base64_result])
|
|
return self.geturl(final_result)
|
|
|
|
def geturl(self,txt):
|
|
data=self.post(f"{self.jx}/rijevra/{txt}/sr",headers=self.jxh()).json()
|
|
urls=[]
|
|
for i in data:
|
|
urls.extend([i['name'],f"{self.getProxyUrl()}&dddd={i['data']}"])
|
|
return urls
|
|
|
|
def localProxy(self, param):
|
|
try:
|
|
data=self.post(f"{self.jx}/rijevra/{param.get('dddd')}",headers=self.jxh()).json()
|
|
return [302,'application/vnd.apple.mpegurl',None,{'Location':data['url']}]
|
|
except Exception as e:
|
|
self.log(e)
|
|
return ''
|
|
|
|
def liveContent(self, url):
|
|
pass
|
|
|
|
def jxh(self):
|
|
header = self.headers.copy()
|
|
header.update({'referer': f'{self.jx}/', 'origin': self.jx, 'content-type': 'text/plain'})
|
|
header.pop('authorization', None)
|
|
return header
|
|
|
|
def gettoken(self):
|
|
host='https://nunflix.org'
|
|
data=self.fetch(f'{host}/explore/movie',headers=self.headers).text
|
|
mod=pq(data)('script[type="module"]').attr('src')
|
|
murl= mod if mod.startswith('http') else f'{host}{mod}'
|
|
print(murl)
|
|
mdd=self.fetch(murl,headers=self.headers).text
|
|
ane_match = re.search(r'Ane\s*=\s*"([^"]+)"', mdd)
|
|
ane_value = ane_match.group(1) if ane_match else ''
|
|
xne_match = re.search(r'xne\s*=\s*"([^"]+)"', mdd)
|
|
xne_value = xne_match.group(1) if xne_match else ''
|
|
if ane_value and xne_value:
|
|
return ane_value.strip(),xne_value.strip()
|
|
|
|
if __name__ == "__main__":
|
|
sp = Spider()
|
|
formatJo = sp.init()
|
|
# formatJo = sp.homeContent(False) # 主页,等于真表示启用筛选
|
|
formatJo = sp.homeVideoContent() # 主页视频
|
|
# formatJo = sp.searchContent("斗罗",False,'1') # 搜索{"area":"大陆","by":"hits","class":"国产","lg":"国语"}
|
|
# formatJo = sp.categoryContent('movie', '1', False, {}) # 分类
|
|
# formatJo = sp.detailContent(['/tv/93405']) # 详情
|
|
# formatJo = sp.playerContent("","/tv/93405/1/1",{}) # 播放
|
|
# formatJo = sp.localProxy({"dddd":""}) # 播放
|
|
pprint(formatJo)
|