Files
2026-07-05 04:58:38 +00:00

289 lines
11 KiB
Python

# -*- coding: utf-8 -*-
# 本资源来源于互联网公开渠道,仅可用于个人学习爬虫技术。
# 严禁将其用于任何商业用途,下载后请于 24 小时内删除,搜索结果均来自源站,本人不承担任何责任。
from base.spider import Spider
import re,sys,uuid,json,hashlib,urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
sys.path.append('..')
class Spider(Spider):
headers,nextVal,host,appid,appkey,udid,bundlerId,source,version,versionCode = {
'User-Agent': "Dart/3.1 (dart:io)",
'Accept-Encoding': "gzip",
'content-type': "application/json; charset=utf-8"
},{'search':{'key':'','value':''},'category':{}},'','','','','','','',''
def init(self, extend=""):
ext = json.loads(extend)
hosts,appid,appkey,udid,bundlerId,source,version,versionCode = ext['host'],ext['appId'],ext['appkey'],ext['udid'],ext['bundlerId'],ext['source'],ext['version'],ext['versionCode']
if not(hosts and appid and appkey and udid and bundlerId and source and version and versionCode): return
self.appid = appid
self.appkey = appkey
self.udid = udid
self.bundlerId = bundlerId
self.source = source
self.version = version
self.versionCode = versionCode
hosts_list = hosts.split(',')
for i in hosts_list:
if re.match(r'^https?://[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(:\d+)?/?$',i):
self.host = i
else:
try:
response = self.fetch(i, headers=self.headers,verify=False).json()
for j in response:
try:
print(j)
if j.startswith('http'):
self.host = j
break
except Exception:
continue
if self.host: break
except Exception:
continue
def homeContent(self, filter):
if not self.host: return None
response = self.post(f'{self.host}/v2/api/home/header', data=self.payload(), headers=self.headers, verify=False).json()
classes = []
for i in response['data']['channeList']:
if isinstance(i,dict):
classes.append({'type_id': i['channelId'], 'type_name': i['channelName']})
return {'class': classes}
def homeVideoContent(self):
if not self.host: return None
response = self.post(f'{self.host}/v2/api/home/body', data=self.payload(), headers=self.headers, verify=False).json()
topic_list = response['data']['vodTopicList']
videos = []
for i in topic_list:
if isinstance(i,dict):
for j in i['vodList']:
try:
year = j['flags'].split(' / ')[0].strip()
except Exception:
year = None
videos.append({
'vod_id': j['vodId'],
'vod_name': j['vodName'],
'vod_pic': j['coverImg'],
'vod_remarks': j['remark'] or f"评分:{j['score']}",
'vod_year': year
})
return {'list': videos}
def categoryContent(self, tid, pg, filters, extend):
if not self.host: return None
if tid.startswith('actor@'):
if pg != '1': return None
worker_id = tid.split('actor@',1)[1]
try:
worker_id = int(worker_id)
except Exception:
worker_id = worker_id
payload = self.payload({'vodWorkerId':worker_id})
path = 'vodWorker/detail'
else:
cache_nextVal_ = self.nextVal['category'].get(tid)
if pg != '1' and not cache_nextVal_: return None
if cache_nextVal_:
cache_nextVal = cache_nextVal_
else:
cache_nextVal = ''
payload = self.payload({
'nextCount': 18,
'nextVal': cache_nextVal,
'queryValueJson': '[{"filerName":"channelId","filerValue":'+ tid +'}]',
'sortType': '',
})
path = 'search/queryNow'
response = self.post(f'{self.host}/v1/api/{path}', data=payload, headers=self.headers, verify=False).json()
data = response['data']
if data.get('hasNext') == 1:
nextVal = data['nextVal']
if nextVal:
self.nextVal['category'][tid] = nextVal
else:
self.nextVal['category'][tid] = ''
videos =[]
for i in data.get('items',data.get('vodList',[])):
try:
year = i['flags'].split(' / ')[0].strip()
except Exception:
year = None
videos.append({
'vod_id': i['vodId'],
'vod_name': i['vodName'],
'vod_pic': i['coverImg'],
'vod_remarks': i['remark'] or f"评分:{i['score']}",
'vod_year': year,
'vod_content': i['intro']
})
return {'list': videos, 'page': pg}
def searchContent(self, key, quick, pg="1"):
if not self.host: return None
if pg != '1': return None
self.nextVal['search']['value'] = ''
current_key = self.nextVal['search']['key']
current_value = self.nextVal['search']['value']
if current_key == key:
if current_value == '' and str(pg) != '1':
return None
cache_nextVal = current_value or ''
else:
self.nextVal['search']['key'] = key
cache_nextVal = ''
payload = self.payload({
"keyword": key,
"nextVal": cache_nextVal
})
response = self.post(f'{self.host}/v1/api/search/search', data=payload, headers=self.headers, verify=False).json()
data = response['data']
if data['hasNext'] == 1:
nextVal = data['nextVal']
if nextVal:
self.nextVal['search']['key'] = key
self.nextVal['search']['value'] = nextVal
else:
self.nextVal['search']['value'] = ''
videos = []
for i in data['items']:
try:
year = i['flags'].split(' / ')[0].strip()
except Exception:
year = None
videos.append({
'vod_id': i['vodId'],
'vod_name': i['vodName'],
'vod_pic': i['coverImg'],
'vod_remarks': i['remark'] or f"评分:{i['score']}",
'vod_year': year,
'vod_content': i['intro']
})
return {'list': videos, 'page': pg}
def detailContent(self, ids):
try:
video_id = int(ids[0])
except Exception:
video_id = ids[0]
payload = self.payload({'vodId':video_id})
response = self.post(f'{self.host}/v2/api/vodInfo/index', data=payload, headers=self.headers, verify=False).json()
data = response['data']
play_urls, play_from = [], []
for i in data['playerList']:
play_from.append(i['playerName'])
urls = []
for j in i['epList']:
urls.append(f"{j['epName']}${j['epId']}")
play_urls.append('#'.join(urls))
video = {
'vod_id': data['vodId'],
'vod_name': data['vodName'],
'vod_pic': data['coverImg'],
'vod_remarks': data['updateRemark'],
'vod_year': data['year'],
'vod_area': data['areaName'],
'vod_actor': self.actor(data['actorList']),
'vod_director': self.actor(data['directorList']),
'vod_content': data['intro'],
'vod_play_from': '$$$'.join(play_from),
'vod_play_url': '$$$'.join(play_urls)
}
return {'list':[video]}
def playerContent(self, flag, id, vipFlags):
try:
vodEpId = int(id)
except Exception:
vodEpId = id
payload = self.payload({'vodEpId':vodEpId})
response = self.post(f'{self.host}/v2/api/vodInfo/epDetail', data=payload, headers=self.headers, verify=False).json()
data = response['data']
urls = []
for i in data:
try:
showName, vodResolution = i.get('showName'), i.get('vodResolution')
if showName and vodResolution:
payload2 = self.payload({'epId': vodEpId, 'vodResolution': vodResolution})
response2 = self.post(f'{self.host}/v2/api/vodInfo/playUrl', data=payload2, headers=self.headers, verify=False).json()
url = response2['data']['playUrl']
if not url.startswith('http'): continue
urls.append(showName)
urls.append(url)
except Exception as e:
print(e)
continue
headers = {
'User-Agent': "ExoPlayer",
'Connection': "Keep-Alive",
'Accept-Encoding': "gzip"
}
return {'parse':0,'url':urls,'header':headers}
def actor(self,data):
director_list = []
try:
for i in data:
if isinstance(i, dict) and i.get('vodWorkerName'):
if i.get('vodWorkerId'):
director_list.append(f'[a=cr:{{"id":"actor@{i["vodWorkerId"]}","name":"{i["vodWorkerName"]}"}}/]{i["vodWorkerName"]}[/a]')
else:
director_list.append(i.get('vodWorkerName'))
actor = ', '.join(director_list)
except Exception:
actor = None
return actor
def payload(self, data=None):
payload = {
"appId": self.appid,
"bundlerId": self.bundlerId
}
if data: payload.update(data)
payload.update({
"cus1tom": "cus3tom",
"deviceInfo": "xiaomi",
"osInfo": "15",
"otherParam": "1",
"patchNumber": 0,
"requestId": str(uuid.uuid4()),
"source": self.source,
"udid": self.udid,
"version": self.version,
"versionCode": self.versionCode
})
return json.dumps(self.sign(payload))
def sign(self, data):
param_str = self.dict_to_url_params(dict(sorted(data.items())))
full_str = f"{param_str}&appKey={self.appkey}" if param_str else f"appKey={self.appkey}"
return {**data, "sign": self.md5(full_str)}
def dict_to_url_params(self, d):
return '&'.join(f"{key}={value}" for key, value in d.items() if value != "")
def md5(self,data):
md5_hash = hashlib.md5()
if isinstance(data, int): data = str(data)
md5_hash.update(data.encode('utf-8'))
return md5_hash.hexdigest()
def localProxy(self, param):
pass
def getName(self):
pass
def isVideoFormat(self, url):
pass
def manualVideoCheck(self):
pass
def destroy(self):
pass