Sync all projects
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
# -*- 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
|
||||
Reference in New Issue
Block a user