金牌.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. # -*- coding: utf-8 -*-
  2. # by @嗷呜
  3. import json
  4. import sys
  5. import threading
  6. import uuid
  7. import requests
  8. sys.path.append('..')
  9. from base.spider import Spider
  10. import time
  11. from Crypto.Hash import MD5, SHA1
  12. class Spider(Spider):
  13. '''
  14. 配置示例:
  15. {
  16. "key": "xxxx",
  17. "name": "xxxx",
  18. "type": 3,
  19. "api": ".所在路径/金牌.py",
  20. "searchable": 1,
  21. "quickSearch": 1,
  22. "filterable": 1,
  23. "changeable": 1,
  24. "ext": {
  25. "site": "https://www.jiabaide.cn,域名2,域名3"
  26. }
  27. },
  28. '''
  29. def init(self, extend=""):
  30. if extend:
  31. hosts=json.loads(extend)['site']
  32. self.host = self.host_late(hosts)
  33. pass
  34. def getName(self):
  35. pass
  36. def isVideoFormat(self, url):
  37. pass
  38. def manualVideoCheck(self):
  39. pass
  40. def destroy(self):
  41. pass
  42. def homeContent(self, filter):
  43. cdata = self.fetch(f"{self.host}/api/mw-movie/anonymous/get/filer/type", headers=self.getheaders()).json()
  44. fdata = self.fetch(f"{self.host}/api/mw-movie/anonymous/v1/get/filer/list", headers=self.getheaders()).json()
  45. result = {}
  46. classes = []
  47. filters={}
  48. for k in cdata['data']:
  49. classes.append({
  50. 'type_name': k['typeName'],
  51. 'type_id': str(k['typeId']),
  52. })
  53. sort_values = [{"n": "最近更新", "v": "2"},{"n": "人气高低", "v": "3"}, {"n": "评分高低", "v": "4"}]
  54. for tid, d in fdata['data'].items():
  55. current_sort_values = sort_values.copy()
  56. if tid == '1':
  57. del current_sort_values[0]
  58. filters[tid] = [
  59. {"key": "type", "name": "类型",
  60. "value": [{"n": i["itemText"], "v": i["itemValue"]} for i in d["typeList"]]},
  61. *([] if not d["plotList"] else [{"key": "v_class", "name": "剧情",
  62. "value": [{"n": i["itemText"], "v": i["itemText"]}
  63. for i in d["plotList"]]}]),
  64. {"key": "area", "name": "地区",
  65. "value": [{"n": i["itemText"], "v": i["itemText"]} for i in d["districtList"]]},
  66. {"key": "year", "name": "年份",
  67. "value": [{"n": i["itemText"], "v": i["itemText"]} for i in d["yearList"]]},
  68. {"key": "lang", "name": "语言",
  69. "value": [{"n": i["itemText"], "v": i["itemText"]} for i in d["languageList"]]},
  70. {"key": "sort", "name": "排序", "value": current_sort_values}
  71. ]
  72. result['class'] = classes
  73. result['filters'] = filters
  74. return result
  75. def homeVideoContent(self):
  76. data1 = self.fetch(f"{self.host}/api/mw-movie/anonymous/v1/home/all/list", headers=self.getheaders()).json()
  77. data2=self.fetch(f"{self.host}/api/mw-movie/anonymous/home/hotSearch",headers=self.getheaders()).json()
  78. data=[]
  79. for i in data1['data'].values():
  80. data.extend(i['list'])
  81. data.extend(data2['data'])
  82. vods=self.getvod(data)
  83. return {'list':vods}
  84. def categoryContent(self, tid, pg, filter, extend):
  85. params = {
  86. "area": extend.get('area', ''),
  87. "filterStatus": "1",
  88. "lang": extend.get('lang', ''),
  89. "pageNum": pg,
  90. "pageSize": "30",
  91. "sort": extend.get('sort', '1'),
  92. "sortBy": "1",
  93. "type": extend.get('type', ''),
  94. "type1": tid,
  95. "v_class": extend.get('v_class', ''),
  96. "year": extend.get('year', '')
  97. }
  98. data = self.fetch(f"{self.host}/api/mw-movie/anonymous/video/list?{self.js(params)}", headers=self.getheaders(params)).json()
  99. result = {}
  100. result['list'] = self.getvod(data['data']['list'])
  101. result['page'] = pg
  102. result['pagecount'] = 9999
  103. result['limit'] = 90
  104. result['total'] = 999999
  105. return result
  106. def detailContent(self, ids):
  107. data=self.fetch(f"{self.host}/api/mw-movie/anonymous/video/detail?id={ids[0]}",headers=self.getheaders({'id':ids[0]})).json()
  108. vod=self.getvod([data['data']])[0]
  109. vod['vod_play_from']='嗷呜有金牌'
  110. vod['vod_play_url'] = '#'.join(
  111. f"{i['name'] if len(vod['episodelist']) > 1 else vod['vod_name']}${ids[0]}@@{i['nid']}" for i in
  112. vod['episodelist'])
  113. vod.pop('episodelist', None)
  114. return {'list':[vod]}
  115. def searchContent(self, key, quick, pg="1"):
  116. params = {
  117. "keyword": key,
  118. "pageNum": pg,
  119. "pageSize": "8",
  120. "sourceCode": "1"
  121. }
  122. data=self.fetch(f"{self.host}/api/mw-movie/anonymous/video/searchByWord?{self.js(params)}",headers=self.getheaders(params)).json()
  123. vods=self.getvod(data['data']['result']['list'])
  124. return {'list':vods,'page':pg}
  125. def playerContent(self, flag, id, vipFlags):
  126. self.header = {
  127. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.61 Chrome/126.0.6478.61 Not/A)Brand/8 Safari/537.36',
  128. 'sec-ch-ua-platform': '"Windows"',
  129. 'DNT': '1',
  130. 'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
  131. 'sec-ch-ua-mobile': '?0',
  132. 'Origin': self.host,
  133. 'Referer': f'{self.host}/'
  134. }
  135. ids=id.split('@@')
  136. pdata = self.fetch(f"{self.host}/api/mw-movie/anonymous/v2/video/episode/url?clientType=1&id={ids[0]}&nid={ids[1]}",headers=self.getheaders({'clientType':'1','id': ids[0], 'nid': ids[1]})).json()
  137. vlist=[]
  138. for i in pdata['data']['list']:vlist.extend([i['resolutionName'],i['url']])
  139. return {'parse':0,'url':vlist,'header':self.header}
  140. def localProxy(self, param):
  141. pass
  142. def host_late(self, url_list):
  143. if isinstance(url_list, str):
  144. urls = [u.strip() for u in url_list.split(',')]
  145. else:
  146. urls = url_list
  147. if len(urls) <= 1:
  148. return urls[0] if urls else ''
  149. results = {}
  150. threads = []
  151. def test_host(url):
  152. try:
  153. start_time = time.time()
  154. response = requests.head(url, timeout=1.0, allow_redirects=False)
  155. delay = (time.time() - start_time) * 1000
  156. results[url] = delay
  157. except Exception as e:
  158. results[url] = float('inf')
  159. for url in urls:
  160. t = threading.Thread(target=test_host, args=(url,))
  161. threads.append(t)
  162. t.start()
  163. for t in threads:
  164. t.join()
  165. return min(results.items(), key=lambda x: x[1])[0]
  166. def md5(self, sign_key):
  167. md5_hash = MD5.new()
  168. md5_hash.update(sign_key.encode('utf-8'))
  169. md5_result = md5_hash.hexdigest()
  170. return md5_result
  171. def js(self, param):
  172. return '&'.join(f"{k}={v}" for k, v in param.items())
  173. def getheaders(self, param=None):
  174. if param is None:param = {}
  175. t=str(int(time.time()*1000))
  176. param['key']='cb808529bae6b6be45ecfab29a4889bc'
  177. param['t']=t
  178. sha1_hash = SHA1.new()
  179. sha1_hash.update(self.md5(self.js(param)).encode('utf-8'))
  180. sign = sha1_hash.hexdigest()
  181. deviceid = str(uuid.uuid4())
  182. headers = {
  183. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.61 Chrome/126.0.6478.61 Not/A)Brand/8 Safari/537.36',
  184. 'Accept': 'application/json, text/plain, */*',
  185. 'sign': sign,
  186. 't': t,
  187. 'deviceid':deviceid
  188. }
  189. return headers
  190. def convert_field_name(self, field):
  191. field = field.lower()
  192. if field.startswith('vod') and len(field) > 3:
  193. field = field.replace('vod', 'vod_')
  194. if field.startswith('type') and len(field) > 4:
  195. field = field.replace('type', 'type_')
  196. return field
  197. def getvod(self, array):
  198. return [{self.convert_field_name(k): v for k, v in item.items()} for item in array]