diff --git a/lib/AppV2.py b/lib/AppV2.py deleted file mode 100644 index 2718b0b..0000000 --- a/lib/AppV2.py +++ /dev/null @@ -1,263 +0,0 @@ -# -*- coding: utf-8 -*- -# by @嗷呜 -# 基于原作者 @嗷呜 版本修改,仅可用于个人学习用途 - -from base.spider import Spider -from urllib.parse import urlparse, urlencode -import re,sys,time,json,urllib3,hashlib,datetime -urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) -sys.path.append('..') - -class Spider(Spider): - headers,api,apisignkey,datasignkey = {'User-Agent': 'okhttp/4.12.0',},'', '' , '' - - def init(self, extend=""): - ext = extend.rstrip() - if ext.startswith('http'): - self.api = ext.rstrip('/') - else: - arr = json.loads(ext) - self.api = arr['api'].rstrip('/') - self.apisignkey = arr.get('apisignkey', '') - if self.apisignkey: - self.datasignkey = arr.get('datasignkey', '6QQNUsP3PkD2ajJCPCY8') - - def homeContent(self, filter): - if self.api.endswith('v1.vod'): - path = '/types' - if self.apisignkey and self.datasignkey: - path = self.datasign(path) - data = self.fetch(f"{self.api}{path}", headers=self.headers, verify=False).json() - data = data['data'] - else: - data = self.fetch(f"{self.api}/nav?token=", headers=self.headers, verify=False).json() - keys = ["class", "area", "lang", "year", "letter", "by", "sort"] - filters = {} - classes = [] - for item in data.get('list',data.get('data',[])): - has_non_empty_field = False - jsontype_extend = item["type_extend"] - classes.append({"type_name": item["type_name"], "type_id": item["type_id"]}) - for key in keys: - if key in jsontype_extend and jsontype_extend[key].strip() != "": - has_non_empty_field = True - break - if has_non_empty_field: - filters[str(item["type_id"])] = [] - for dkey in jsontype_extend: - if dkey in keys and jsontype_extend[dkey].strip() != "": - values = jsontype_extend[dkey].split(",") - value_array = [{"n": value.strip(), "v": value.strip()} for value in values if - value.strip() != ""] - filters[str(item["type_id"])].append({"key": dkey, "name": dkey, "value": value_array}) - result = {"class": classes, "filters": filters} - return result - - def homeVideoContent(self): - if self.api.endswith('v1.vod'): - path = '/vodPhbAll' - if self.apisignkey and self.datasignkey: - keytime = self.keytime() - path += self.datasign(f'?apikey={self.apikey()}&keytime={keytime}',keytime) - data = self.fetch(f"{self.api}{path}", headers=self.headers, verify=False).json() - data = data['data'] - else: - data = self.fetch(f"{self.api}/index_video?token=", headers=self.headers, verify=False).json() - videos = [] - if self.api.endswith('v1.vod'): - for item in data['list']: videos.extend(item['vod_list']) - elif 'list' in data: - for item in data['list']: videos.extend(item['vlist']) - elif 'data' in data: - for item in data['data']: videos.extend(item['vlist']) - return {'list': videos} - - def categoryContent(self, tid, pg, filter, extend): - if self.api.endswith('v1.vod'): - path = f"?type={tid}&class={extend.get('class', '')}&lang={extend.get('lang', '')}&area={extend.get('area', '')}&year={extend.get('year', '')}&by=&page={pg}&limit=9" - if self.apisignkey and self.datasignkey: - keytime = self.keytime() - path = self.datasign(f'{path}&apikey={self.apikey()}&keytime={keytime}' ,keytime) - data = self.fetch(f"{self.api}{path}", headers=self.headers, verify=False).json() - data = data['data'] - else: - params = {'tid': tid, 'class': extend.get('class', ''), 'area': extend.get('area', ''), 'lang': extend.get('lang', ''), 'year': extend.get('year', ''), 'limit': '18', 'pg': pg} - data = self.fetch(f"{self.api}/video", params=params, headers=self.headers, verify=False).json() - if 'data' in data: - data = {'list':data['data']} - return data - - def searchContent(self, key, quick, pg="1"): - if self.api.endswith('v1.vod'): - path = f"?page={pg}&limit=10&wd={key}" - if self.apisignkey and self.datasignkey: - keytime = self.keytime() - path = self.datasign(f'{path}&apikey={self.apikey()}&keytime={keytime}',keytime) - else: - path = f"/search?text={key}&pg={pg}" - data = self.fetch(f"{self.api}{path}", headers=self.headers, verify=False).json() - data2 = data.get('list',data.get('data',[])) - if 'type' in data2: - for item in data2: - item.pop('type', None) - if not 'list' in data2: - data2 = {'list': data2, 'page': pg} - return data2 - - def detailContent(self, ids): - if self.api.endswith('v1.vod'): - path = f'/detail?vod_id={ids[0]}&rel_limit=10' - if self.apisignkey and self.datasignkey: - keytime = self.keytime() - path = self.datasign(f'{path}&apikey={self.apikey()}&keytime={keytime}',keytime) - data = self.fetch(f"{self.api}{path}", headers=self.headers, verify=False).json() - else: - data = self.fetch(f"{self.api}/video_detail?id={ids[0]}", headers=self.headers, verify=False).json() - data = data['data'] - if 'vod_info' in data: - data = data['vod_info'] - show = '' - vod_play_url = '' - if 'vod_url_with_player' in data: - for i in data['vod_url_with_player']: - show += i.get('name', '') + '$$$' - parse_api = i.get('parse_api','') - if parse_api and parse_api.startswith('http'): - url = i.get('url','') - if url: - url2 = '#'.join([i+ '@' + parse_api for i in url.split('#')]) - vod_play_url += url2 + '$$$' - else: - vod_play_url += i.get('url','') + '$$$' - data.pop('vod_url_with_player') - if 'vod_play_list' in data: - for i in data['vod_play_list']: - parses = '' - player_info = i['player_info'] - show += f"{player_info['show']}({i['from']})$$$" - parse = player_info.get('parse','') - parse2 = player_info.get('parse2','') - if 'parse' in player_info and parse.startswith('http'): - parses += parse + ',' - if 'parse2' in player_info and parse2.startswith('http') and parse2 != parse: - parses += parse2 - parses = parses.rstrip(',') - url = '' - for j in i['urls']: - if parse: - url += f"{j['name']}${j['url']}@{parses}#" - else: - url += f"{j['name']}${j['url']}#" - url = url.rstrip('#') - vod_play_url += url + '$$$' - if 'vod_play_list' in data: - data.pop('vod_play_list') - if 'rel_vods' in data: - data.pop('rel_vods') - if 'type' in data: - data.pop('type') - data['vod_play_from'] = show.rstrip('$$$') - data['vod_play_url'] = vod_play_url.rstrip('$$$') - return {'list': [data]} - - def playerContent(self, flag, id, vipFlags): - video_pattern = re.compile(r'https?:\/\/.*\.(?:m3u8|mp4|flv)') - jx, url, ua = 0, '', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36' - if '@' in id: - rawurl, jxapi = id.split('@', 1) - if ',' in jxapi: - jxapis = jxapi.split(',', 1) - else: - jxapis = [jxapi] - for jxapi_ in jxapis: - try: - res = self.fetch(f"{jxapi_}{rawurl}", headers=self.headers, timeout=10, verify=False).json() - url = res.get('url', '') - if url.startswith('http'): - jxua = res.get('ua') - if jxua: - ua = jxua - except Exception: - url = '' - continue - if url.startswith('http'): - jx = 0 - else: - url = rawurl - jx = 0 if video_pattern.match(rawurl) else 1 - else: - url = id - jx = 0 if video_pattern.match(id) else 1 - if url.startswith('NBY'): - jx, url = 0, '' - return {'jx': jx, 'parse': 0, 'url': url, 'header': {'User-Agent': ua}} - - def keytime(self): - return str(int(datetime.datetime.now().timestamp())) - - def md5(self, str): - hash_obj = hashlib.md5() - hash_obj.update(str.encode('utf-8')) - return hash_obj.hexdigest() - - def apikey(self): - date = datetime.datetime.now() - year = str(date.year) - hour = str(date.hour) - minute = str(date.minute) - - if len(hour) < 2: - hour = "0" + hour - if len(minute) < 2: - minute = "0" + minute - - str_value = self.apisignkey - sign_str = f"{year}:{hour}:{year}:{minute}:{str_value}" - md5_hash = self.md5(sign_str) - return md5_hash - - def datasign(self, url='', timestamp=''): - parsed_url = urlparse(url) - query_params = self._parse_query_params(parsed_url.query) - if not timestamp: - timestamp = str(time.time()) - query_params["timestamp"] = timestamp - sorted_params = sorted(query_params.items(), key=lambda x: x[0]) - sign = self._generate_signature(sorted_params) - query_params["datasign"] = sign - new_query = urlencode(query_params) - new_url = parsed_url._replace(query=new_query).geturl() - return new_url - - def _parse_query_params(self, query_str): - params = {} - if not query_str: - return params - for param in query_str.split('&'): - if '=' not in param: - continue - key, value = param.split('=', 1) - if value: - params[key] = value - return params - - def _generate_signature(self, sorted_params): - param_str = '&'.join([f"{k}={v}" for k, v in sorted_params]) - raw_sign_str = f"{param_str}{self.datasignkey}" - md5_hash = hashlib.md5(raw_sign_str.encode('utf-8')).hexdigest() - return md5_hash - - def localProxy(self, param): - pass - - def getName(self): - pass - - def isVideoFormat(self, url): - pass - - def manualVideoCheck(self): - pass - - def destroy(self): - pass