py_bilibili.py 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. # coding=utf-8
  2. # !/usr/bin/python
  3. import sys
  4. sys.path.append('..')
  5. from base.spider import Spider
  6. import json
  7. import requests
  8. import threading
  9. import time
  10. class Spider(Spider):
  11. def getName(self):
  12. return "哔哩哔哩"
  13. # 主页
  14. def homeContent(self, filter):
  15. result = {}
  16. cateManual = {
  17. #"动态": "动态",
  18. "推荐": "推荐",
  19. "热门": "热门",
  20. "排行榜": "排行榜",
  21. #"历史记录": "历史记录",
  22. # "稍后再看":"稍后再看", #意义不大,隐藏该项
  23. #"收藏": "收藏",
  24. "每周必看": "每周必看",
  25. "频道": "频道",
  26. "动画": "1",
  27. "音乐": "3",
  28. "舞蹈": "129",
  29. "游戏": "4",
  30. "鬼畜": "119",
  31. "知识": "36",
  32. "科技": "188",
  33. "运动": "234",
  34. "生活": "160",
  35. "美食": "211",
  36. "动物": "217",
  37. "汽车": "223",
  38. "时尚": "155",
  39. "娱乐": "5",
  40. "影视": "181",
  41. "入站必刷": "入站必刷",
  42. }
  43. classes = []
  44. for k in cateManual:
  45. classes.append({
  46. 'type_name': k,
  47. 'type_id': cateManual[k]
  48. })
  49. result['class'] = classes
  50. if (filter):
  51. result['filters'] = self.config['filter']
  52. return result
  53. # 用户cookies
  54. cookies = ''
  55. userid = ''
  56. csrf = ''
  57. def getCookie(self):
  58. import http.cookies
  59. # ----↓↓↓↓↓↓↓----在下方raw_cookie_line后的双引号内填写----↓↓↓↓↓↓↓----
  60. raw_cookie_line = ""
  61. simple_cookie = http.cookies.SimpleCookie(raw_cookie_line)
  62. cookie_jar = requests.cookies.RequestsCookieJar()
  63. cookie_jar.update(simple_cookie)
  64. rsp = requests.session()
  65. rsp.cookies = cookie_jar
  66. url = 'http://api.bilibili.com/x/web-interface/nav'
  67. content = self.fetch(url, headers=self.header, cookies=rsp.cookies)
  68. res = json.loads(content.text)
  69. if res["code"] == 0:
  70. self.cookies = rsp.cookies
  71. self.userid = res["data"].get('mid')
  72. self.csrf = rsp.cookies['bili_jct']
  73. return cookie_jar
  74. def __init__(self):
  75. self.getCookie()
  76. url = 'https://api.bilibili.com/x/v3/fav/folder/created/list-all?up_mid=%s&jsonp=jsonp' % self.userid
  77. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  78. content = rsp.text
  79. jo = json.loads(content)
  80. fav_list = []
  81. if jo['code'] == 0:
  82. for fav in jo['data'].get('list'):
  83. fav_dict = {
  84. 'n': fav['title'].replace("<em class=\"keyword\">", "").replace("</em>", "").replace("&quot;",
  85. '"').strip(),
  86. 'v': fav['id']}
  87. fav_list.append(fav_dict)
  88. if self.config["filter"].get('收藏'):
  89. for i in self.config["filter"].get('收藏'):
  90. if i['key'] == 'mlid':
  91. i['value'] = fav_list
  92. def init(self, extend=""):
  93. print("============{0}============".format(extend))
  94. pass
  95. def isVideoFormat(self, url):
  96. pass
  97. def manualVideoCheck(self):
  98. pass
  99. # 将超过10000的数字换成成以万和亿为单位
  100. def zh(self, num):
  101. if int(num) >= 100000000:
  102. p = round(float(num) / float(100000000), 1)
  103. p = str(p) + '亿'
  104. else:
  105. if int(num) >= 10000:
  106. p = round(float(num) / float(10000), 1)
  107. p = str(p) + '万'
  108. else:
  109. p = str(num)
  110. return p
  111. # 将秒数转化为 时分秒的格式
  112. def second_to_time(self, a):
  113. if a < 3600:
  114. return time.strftime("%M:%S", time.gmtime(a))
  115. else:
  116. return time.strftime("%H:%M:%S", time.gmtime(a))
  117. # 字符串时分秒以及分秒形式转换成秒
  118. def str2sec(self, x):
  119. x = str(x)
  120. try:
  121. h, m, s = x.strip().split(':') # .split()函数将其通过':'分隔开,.strip()函数用来除去空格
  122. return int(h) * 3600 + int(m) * 60 + int(s) # int()函数转换成整数运算
  123. except:
  124. m, s = x.strip().split(':') # .split()函数将其通过':'分隔开,.strip()函数用来除去空格
  125. return int(m) * 60 + int(s) # int()函数转换成整数运算
  126. # 按时间过滤
  127. def filter_duration(self, vodlist, key):
  128. if key == '0':
  129. return vodlist
  130. else:
  131. vod_list_new = [i for i in vodlist if
  132. self.time_diff1[key][0] <= self.str2sec(str(i["vod_remarks"])) < self.time_diff1[key][1]]
  133. return vod_list_new
  134. time_diff1 = {'1': [0, 300],
  135. '2': [300, 900], '3': [900, 1800], '4': [1800, 3600],
  136. '5': [3600, 99999999999999999999999999999999]
  137. }
  138. time_diff = '0'
  139. dynamic_offset = ''
  140. def get_dynamic(self, pg):
  141. result = {}
  142. if str(pg) == '1':
  143. url = 'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all?timezone_offset=-480&type=video&page=%s' % pg
  144. else:
  145. # print('偏移',self.dynamic_offset)
  146. url = 'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all?timezone_offset=-480&type=video&offset=%s&page=%s' % (self.dynamic_offset, pg)
  147. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  148. content = rsp.text
  149. jo = json.loads(content)
  150. if jo['code'] == 0:
  151. self.dynamic_offset = jo['data'].get('offset')
  152. videos = []
  153. vodList = jo['data']['items']
  154. for vod in vodList:
  155. up = vod['modules']["module_author"]['name']
  156. ivod = vod['modules']['module_dynamic']['major']['archive']
  157. aid = str(ivod['aid']).strip()
  158. title = ivod['title'].strip().replace("<em class=\"keyword\">", "").replace("</em>", "")
  159. img = ivod['cover'].strip()
  160. # remark = str(ivod['duration_text']).strip()
  161. remark = str(self.second_to_time(self.str2sec(ivod['duration_text']))).strip() + ' ' + str(
  162. up).strip() # 显示分钟数+up主名字
  163. videos.append({
  164. "vod_id": aid,
  165. "vod_name": title,
  166. "vod_pic": img + '@672w_378h_1c.jpg',
  167. "vod_remarks": remark
  168. })
  169. result['list'] = videos
  170. result['page'] = pg
  171. result['pagecount'] = 9999
  172. result['limit'] = 2
  173. result['total'] = 999999
  174. return result
  175. def get_hot(self, pg):
  176. result = {}
  177. url = 'https://api.bilibili.com/x/web-interface/popular?ps=10&pn={0}&ps=9'.format(pg)
  178. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  179. content = rsp.text
  180. jo = json.loads(content)
  181. if jo['code'] == 0:
  182. videos = []
  183. vodList = jo['data']['list']
  184. for vod in vodList:
  185. aid = str(vod['aid']).strip()
  186. title = vod['title'].strip().replace("<em class=\"keyword\">", "").replace("</em>", "")
  187. img = vod['pic'].strip()
  188. reason=vod['rcmd_reason']['content'].strip()
  189. if reason == '':
  190. reason= ''
  191. else:
  192. reason= ' ' + reason
  193. remark = "观看:" + self.zh(vod['stat']['view']) + " " + str(self.second_to_time(vod['duration'])).strip()
  194. videos.append({
  195. "vod_id": aid,
  196. "vod_name": title,
  197. "vod_pic": img + '@672w_378h_1c.jpg',
  198. "vod_remarks": remark + reason
  199. })
  200. result['list'] = videos
  201. result['page'] = pg
  202. result['pagecount'] = 9999
  203. result['limit'] = 2
  204. result['total'] = 999999
  205. return result
  206. def get_rcmd(self, pg):
  207. result = {}
  208. url = 'https://api.bilibili.com/x/web-interface/index/top/feed/rcmd?y_num={0}&fresh_type=3&feed_version=SEO_VIDEO&fresh_idx_1h=1&fetch_row=1&fresh_idx=1&brush=0&homepage_ver=1&ps=10'.format(
  209. pg)
  210. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  211. content = rsp.text
  212. jo = json.loads(content)
  213. if jo['code'] == 0:
  214. videos = []
  215. vodList = jo['data']['item']
  216. for vod in vodList:
  217. if vod['duration'] > 0:
  218. aid = str(vod['id']).strip()
  219. title = vod['title'].strip().replace("<em class=\"keyword\">", "").replace("</em>", "")
  220. img = vod['pic'].strip()
  221. if 'content' in vod['rcmd_reason']:
  222. reason= ' ' + vod['rcmd_reason']['content'].strip()
  223. else:
  224. reason= ''
  225. remark = "观看:" + self.zh(vod['stat']['view']) + " " + str(self.second_to_time(vod['duration'])).strip()
  226. videos.append({
  227. "vod_id": aid,
  228. "vod_name": title,
  229. "vod_pic": img + '@672w_378h_1c.jpg',
  230. "vod_remarks": remark + reason
  231. })
  232. result['list'] = videos
  233. result['page'] = pg
  234. result['pagecount'] = 9999
  235. result['limit'] = 2
  236. result['total'] = 999999
  237. return result
  238. def get_rank(self, pg):
  239. ps=9
  240. pg_max= int(pg) * ps
  241. pg_min= pg_max - ps
  242. result = {}
  243. url = 'https://api.bilibili.com/x/web-interface/ranking/v2?rid=0&type=all'
  244. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  245. content = rsp.text
  246. jo = json.loads(content)
  247. if jo['code'] == 0:
  248. videos = []
  249. vodList = jo['data']['list']
  250. pc = int(len(vodList) / ps) + 1
  251. vodList = vodList[pg_min:pg_max]
  252. for vod in vodList:
  253. aid = str(vod['aid']).strip()
  254. title = vod['title'].strip().replace("<em class=\"keyword\">", "").replace("</em>", "")
  255. img = vod['pic'].strip()
  256. remark = "观看:" + self.zh(vod['stat']['view']) + " " + str(self.second_to_time(vod['duration'])).strip()
  257. videos.append({
  258. "vod_id": aid,
  259. "vod_name": title,
  260. "vod_pic": img + '@672w_378h_1c.jpg',
  261. "vod_remarks": remark
  262. })
  263. result['list'] = videos
  264. result['page'] = pg
  265. result['pagecount'] = pc
  266. result['limit'] = 2
  267. result['total'] = 999999
  268. return result
  269. def get_history(self, pg):
  270. result = {}
  271. url = 'https://api.bilibili.com/x/v2/history?pn=%s&ps=10' % pg
  272. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  273. content = rsp.text
  274. jo = json.loads(content) # 解析api接口,转化成json数据对象
  275. if jo['code'] == 0:
  276. videos = []
  277. vodList = jo['data']
  278. for vod in vodList:
  279. if vod['duration'] > 0: # 筛选掉非视频的历史记录
  280. aid = str(vod["aid"]).strip()
  281. if 'redirect_url' in vod:
  282. if 'bangumi' in vod['redirect_url']:
  283. redirect_url = str(vod['redirect_url']).strip()
  284. ep_id = redirect_url.split(r"/")[-1]
  285. aid = ep_id.split(r"?")[0]
  286. title = vod["title"].replace("<em class=\"keyword\">", "").replace("</em>", "").replace("&quot;",
  287. '"')
  288. img = vod["pic"].strip()
  289. # 获取已观看时间
  290. if str(vod['progress']) == '-1':
  291. process = str(self.second_to_time(vod['duration'])).strip()
  292. else:
  293. process = str(self.second_to_time(vod['progress'])).strip()
  294. # 获取视频总时长
  295. total_time = str(self.second_to_time(vod['duration'])).strip()
  296. # 组合 已观看时间 / 总时长 ,赋值给 remark
  297. remark = process + ' / ' + total_time
  298. # 视频类型
  299. type = str(vod["type"]).strip()
  300. videos.append({
  301. "vod_id": aid,
  302. "vod_name": title,
  303. "vod_pic": img + '@672w_378h_1c.jpg',
  304. "vod_remarks": remark
  305. })
  306. result['list'] = videos
  307. result['page'] = pg
  308. result['pagecount'] = 9999
  309. result['limit'] = 2
  310. result['total'] = 999999
  311. return result
  312. def get_fav(self, pg, order, extend):
  313. mlid = ''
  314. fav_config = self.config["filter"].get('收藏')
  315. # 默认显示第一个收藏内容
  316. if fav_config:
  317. for i in fav_config:
  318. if i['key'] == 'mlid':
  319. if len(i['value']) > 0:
  320. mlid = i['value'][0]['v']
  321. # print(self.config["filter"].get('收藏'))
  322. if 'mlid' in extend:
  323. mlid = extend['mlid']
  324. if mlid:
  325. return self.get_fav_detail(pg=pg, mlid=mlid, order=order)
  326. else:
  327. return {}
  328. def get_fav_detail(self, pg, mlid, order):
  329. result = {}
  330. url = 'https://api.bilibili.com/x/v3/fav/resource/list?media_id=%s&order=%s&pn=%s&ps=10&platform=web&type=0' % (mlid, order, pg)
  331. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  332. content = rsp.text
  333. jo = json.loads(content)
  334. if jo['code'] == 0:
  335. videos = []
  336. vodList = jo['data']['medias']
  337. for vod in vodList:
  338. # print(vod)
  339. # 只展示类型为 视频的条目
  340. # 过滤去掉收藏中的 已失效视频;如果不喜欢可以去掉这个 if条件
  341. if vod.get('type') in [2] and vod.get('title') != '已失效视频':
  342. aid = str(vod['id']).strip()
  343. title = vod['title'].replace("<em class=\"keyword\">", "").replace("</em>", "").replace("&quot;",
  344. '"')
  345. img = vod['cover'].strip()
  346. remark = "观看:" + self.zh(vod['cnt_info']['play']) + " " + str(self.second_to_time(vod['duration'])).strip()
  347. videos.append({
  348. "vod_id": aid + '_mlid' + str(mlid),
  349. "vod_name": title,
  350. "vod_pic": img + '@672w_378h_1c.jpg',
  351. "vod_remarks": remark
  352. })
  353. # videos=self.filter_duration(videos, duration_diff)
  354. result['list'] = videos
  355. result['page'] = pg
  356. result['pagecount'] = 9999
  357. result['limit'] = 2
  358. result['total'] = 999999
  359. return result
  360. def get_up_info(self, mid, info):
  361. url = "https://api.bilibili.com/x/web-interface/card?mid={0}".format(mid)
  362. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  363. jRoot = json.loads(rsp.text)
  364. jo = jRoot['data']['card']
  365. info['mid'] = mid
  366. info['name'] = jo['name'].replace("<em class=\"keyword\">", "").replace("</em>", "")
  367. info['face'] = jo['face']
  368. info['fans'] = self.zh(jo['fans'])
  369. info['like_num'] = self.zh(jRoot['data']['like_num'])
  370. info['vod_count'] = str(jRoot['data']['archive_count']).strip()
  371. info['desc'] = jo['Official']['desc'] + " " + jo['Official']['title']
  372. if jRoot['data']['following'] == True:
  373. info['following'] = '已关注'
  374. info['followAct'] = 2
  375. info['followActName'] = '取消关注'
  376. else:
  377. info['following'] = '未关注'
  378. info['followAct'] = 1
  379. info['followActName'] = '关注'
  380. def get_zone(self, tid, pg):
  381. ps=9
  382. pg_max= int(pg) * ps
  383. pg_min= pg_max - ps
  384. result = {}
  385. url = 'https://api.bilibili.com/x/web-interface/ranking/v2?rid={0}&type=all'.format(tid)
  386. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  387. content = rsp.text
  388. jo = json.loads(content)
  389. if jo['code'] == 0:
  390. videos = []
  391. vodList = jo['data']['list']
  392. pc = int(len(vodList) / ps) + 1
  393. vodList = vodList[pg_min:pg_max]
  394. for vod in vodList:
  395. aid = str(vod['aid']).strip()
  396. title = vod['title'].strip().replace("<em class=\"keyword\">", "").replace("</em>", "")
  397. img = vod['pic'].strip()
  398. remark = "观看:" + self.zh(vod['stat']['view']) + " " + str(self.second_to_time(vod['duration'])).strip()
  399. videos.append({
  400. "vod_id": aid,
  401. "vod_name": title,
  402. "vod_pic": img + '@672w_378h_1c.jpg',
  403. "vod_remarks": remark
  404. })
  405. result['list'] = videos
  406. result['page'] = pg
  407. result['pagecount'] = pc
  408. result['limit'] = 2
  409. result['total'] = 999999
  410. return result
  411. def get_weekly(self, pg):
  412. ps=9
  413. pg_max= int(pg) * ps
  414. pg_min= pg_max - ps
  415. result = {}
  416. url1 = 'https://api.bilibili.com/x/web-interface/popular/series/list'
  417. rsp1 = self.fetch(url1, headers=self.header, cookies=self.cookies)
  418. content1 = rsp1.text
  419. jo1 = json.loads(content1)
  420. number = jo1['data']['list'][0]['number']
  421. url = 'https://api.bilibili.com/x/web-interface/popular/series/one?number=' + str(number)
  422. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  423. content = rsp.text
  424. jo = json.loads(content)
  425. if jo['code'] == 0:
  426. videos = []
  427. vodList = jo['data']['list']
  428. pc = int(len(vodList) / ps) + 1
  429. vodList = vodList[pg_min:pg_max]
  430. for vod in vodList:
  431. aid = str(vod['aid']).strip()
  432. title = vod['title'].strip()
  433. img = vod['pic'].strip()
  434. remark = "观看:" + self.zh(vod['stat']['view']) + " " + str(self.second_to_time(vod['duration'])).strip()
  435. videos.append({
  436. "vod_id": aid,
  437. "vod_name": title,
  438. "vod_pic": img + '@672w_378h_1c.jpg',
  439. "vod_remarks": remark
  440. })
  441. result['list'] = videos
  442. result['page'] = pg
  443. result['pagecount'] = pc
  444. result['limit'] = 2
  445. result['total'] = 999999
  446. return result
  447. def get_must_watch(self, pg):
  448. ps=9
  449. pg_max= int(pg) * ps
  450. pg_min= pg_max - ps
  451. result = {}
  452. url = 'https://api.bilibili.com/x/web-interface/popular/precious?page_size={0}&page={1}'.format(ps, pg)
  453. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  454. content = rsp.text
  455. jo = json.loads(content)
  456. if jo['code'] == 0:
  457. videos = []
  458. vodList = jo['data']['list']
  459. pc = int(len(vodList) / ps) + 1
  460. vodList = vodList[pg_min:pg_max]
  461. for vod in vodList:
  462. aid = str(vod['aid']).strip()
  463. title = vod['title'].strip()
  464. img = vod['pic'].strip()
  465. remark = "观看:" + self.zh(vod['stat']['view']) + " " + str(self.second_to_time(vod['duration'])).strip()
  466. videos.append({
  467. "vod_id": aid,
  468. "vod_name": title,
  469. "vod_pic": img + '@672w_378h_1c.jpg',
  470. "vod_remarks": remark
  471. })
  472. result['list'] = videos
  473. result['page'] = pg
  474. result['pagecount'] = pc
  475. result['limit'] = 2
  476. result['total'] = 999999
  477. return result
  478. def get_toview(self, pg):
  479. ps=9
  480. pg_max= int(pg) * ps
  481. pg_min= pg_max - ps
  482. result = {}
  483. url = 'https://api.bilibili.com/x/v2/history/toview'
  484. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  485. content = rsp.text
  486. jo = json.loads(content) # 解析api接口,转化成json数据对象
  487. if jo['code'] == 0:
  488. videos = []
  489. vodList = jo['data']['list']
  490. pc = int(len(vodList) / ps) + 1
  491. vodList = vodList[pg_min:pg_max]
  492. for vod in vodList:
  493. if vod['duration'] > 0:
  494. aid = str(vod["aid"]).strip()
  495. title = vod["title"].replace("<em class=\"keyword\">", "").replace("</em>", "").replace("&quot;",
  496. '"')
  497. img = vod["pic"].strip()
  498. if str(vod['progress']) == '-1':
  499. process = str(self.second_to_time(vod['duration'])).strip()
  500. else:
  501. process = str(self.second_to_time(vod['progress'])).strip()
  502. # 获取视频总时长
  503. total_time = str(self.second_to_time(vod['duration'])).strip()
  504. # 组合 已观看时间 / 总时长 ,赋值给 remark
  505. remark = process + ' / ' + total_time
  506. videos.append({
  507. "vod_id": aid + '&toview',
  508. "vod_name": title,
  509. "vod_pic": img + '@672w_378h_1c.jpg',
  510. "vod_remarks": remark
  511. })
  512. result['list'] = videos
  513. result['page'] = pg
  514. result['pagecount'] = pc
  515. result['limit'] = 2
  516. result['total'] = 999999
  517. return result
  518. chanel_offset = ''
  519. def get_channel(self, pg, cid, extend, order, duration_diff):
  520. result = {}
  521. url = 'https://api.bilibili.com/x/web-interface/search/type?search_type=video&keyword={0}&page={1}&duration={2}&order={3}&page_size=10'.format(
  522. cid, pg, duration_diff, order)
  523. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  524. content = rsp.text
  525. jo = json.loads(content)
  526. if jo.get('code') == 0:
  527. videos = []
  528. vodList = jo['data']['result']
  529. for vod in vodList:
  530. aid = str(vod['aid']).strip()
  531. title = vod['title'].replace("<em class=\"keyword\">", "").replace("</em>", "").replace("&quot;", '"')
  532. img = 'https:' + vod['pic'].strip()
  533. remark = "观看:" + self.zh(vod['play']) + "  " + str(self.second_to_time(self.str2sec(vod['duration']))).strip()
  534. videos.append({
  535. "vod_id": aid,
  536. "vod_name": title,
  537. "vod_pic": img + '@672w_378h_1c.jpg',
  538. "vod_remarks": remark
  539. })
  540. # videos=self.filter_duration(videos, duration_diff)
  541. result['list'] = videos
  542. result['page'] = pg
  543. result['pagecount'] = 9999
  544. result['limit'] = 2
  545. result['total'] = 999999
  546. return result
  547. def homeVideoContent(self):
  548. result = {}
  549. videos = self.get_rank(pg=1)['list'][0:3]
  550. result['list'] = videos
  551. return result
  552. def categoryContent(self, tid, pg, filter, extend):
  553. result = {}
  554. if len(self.cookies) <= 0:
  555. self.getCookie()
  556. if tid == "动态":
  557. return self.get_dynamic(pg=pg)
  558. elif tid == "热门":
  559. return self.get_hot(pg=pg)
  560. elif tid == '推荐':
  561. return self.get_rcmd(pg=pg)
  562. elif tid == "排行榜":
  563. return self.get_rank(pg=pg)
  564. elif tid == '历史记录':
  565. return self.get_history(pg=pg)
  566. elif tid == "每周必看":
  567. return self.get_weekly(pg=pg)
  568. elif tid == "入站必刷":
  569. return self.get_must_watch(pg=pg)
  570. elif tid == '稍后再看':
  571. return self.get_toview(pg=pg)
  572. elif tid in ("1", "3", "129", "4", "119", "36", "188", "234", "160", "211", "217", "223", "155", "5", "181"):
  573. return self.get_zone(tid=tid, pg=pg)
  574. elif tid == "收藏":
  575. order = 'mtime'
  576. if 'order' in extend:
  577. order = extend['order']
  578. return self.get_fav(pg=pg, order=order, extend=extend)
  579. elif tid == '频道':
  580. cid = '搞笑'
  581. if 'cid' in extend:
  582. cid = extend['cid']
  583. duration_diff = '0'
  584. if 'duration' in extend:
  585. duration_diff = extend['duration']
  586. order = 'totalrank'
  587. if 'order' in extend:
  588. order = extend['order']
  589. return self.get_channel(pg=pg, cid=cid, extend=extend, order=order, duration_diff=duration_diff)
  590. else:
  591. duration_diff = '0'
  592. if 'duration' in extend:
  593. duration_diff = extend['duration']
  594. order = 'totalrank'
  595. if 'order' in extend:
  596. order = extend['order']
  597. url = 'https://api.bilibili.com/x/web-interface/search/type?search_type=video&keyword={0}&page={1}&duration={2}&order={3}&page_size=10'.format(
  598. tid, pg, duration_diff, order)
  599. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  600. content = rsp.text
  601. jo = json.loads(content)
  602. if jo.get('code') == 0:
  603. videos = []
  604. vodList = jo['data']['result']
  605. for vod in vodList:
  606. aid = str(vod['aid']).strip()
  607. title = vod['title'].replace("<em class=\"keyword\">", "").replace("</em>", "").replace("&quot;",
  608. '"')
  609. img = 'https:' + vod['pic'].strip()
  610. # remark = str(vod['duration']).strip()
  611. remark = "观看:" + self.zh(vod['play']) + "  " + str(self.second_to_time(self.str2sec(vod['duration']))).strip()
  612. videos.append({
  613. "vod_id": aid,
  614. "vod_name": title,
  615. "vod_pic": img + '@672w_378h_1c.jpg',
  616. "vod_remarks": remark
  617. })
  618. # videos=self.filter_duration(videos, duration_diff)
  619. result['list'] = videos
  620. result['page'] = pg
  621. result['pagecount'] = 9999
  622. result['limit'] = 2
  623. result['total'] = 999999
  624. return result
  625. def cleanSpace(self, str):
  626. return str.replace('\n', '').replace('\t', '').replace('\r', '').replace(' ', '')
  627. up_mid = ''
  628. def detailContent(self, array):
  629. aid = array[0]
  630. if not aid.isdigit() and not 'mlid' in aid:
  631. return self.ysContent(array)
  632. mlid = ''
  633. if 'mlid' in aid:
  634. aid = aid.split('_')
  635. mlid = aid[1].replace('mlid', '')
  636. aid = aid[0]
  637. url = "https://api.bilibili.com/x/web-interface/view?aid={0}".format(aid)
  638. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  639. jRoot = json.loads(rsp.text)
  640. jo = jRoot['data']
  641. if 'redirect_url' in jo:
  642. if 'bangumi' in jo['redirect_url']:
  643. redirect_url = str(jo['redirect_url']).strip()
  644. ep_id = redirect_url.split(r"/")[-1]
  645. ep_id = ep_id.split(r"?")[0]
  646. new_array = []
  647. for i in array:
  648. new_array.append(i)
  649. new_array[0] = ep_id
  650. return self.ysContent(new_array)
  651. self.up_mid = str(jo['owner']['mid'])
  652. info = {}
  653. self.get_up_info(self.up_mid, info)
  654. title = jo['title'].replace("<em class=\"keyword\">", "").replace("</em>", "")
  655. pic = jo['pic']
  656. up_name = jo['owner']['name']
  657. if not up_name in title:
  658. title += '【' + up_name + "】"
  659. desc = jo['desc']
  660. typeName = jo['tname']
  661. date = time.strftime("%Y%m%d", time.localtime(jo['pubdate'])) # 投稿时间本地年月日表示
  662. stat = jo['stat']
  663. # 演员项展示视频状态,包括以下内容:
  664. status = "播放: " + self.zh(stat['view']) + " 弹幕: " + self.zh(stat['danmaku']) + " 点赞: " + self.zh(stat['like']) + " 收藏: " + self.zh(stat['favorite']) + " 投币: " + self.zh(stat['coin'])
  665. remark = str(jo['duration']).strip()
  666. vod = {
  667. "vod_id": aid,
  668. "vod_name": title,
  669. "vod_pic": pic,
  670. "type_name": typeName,
  671. "vod_year": date,
  672. "vod_area": "bilidanmu",
  673. "vod_remarks": remark, # 不会显示
  674. 'vod_tags': 'mv', # 不会显示
  675. "vod_actor": status,
  676. 'vod_director': up_name + ' ' + info['following'],
  677. "vod_content": desc,
  678. 'vod_play_from': 'B站$$$做点什么'
  679. #'vod_play_from': 'B站'
  680. }
  681. ja = jo['pages']
  682. playUrl = ''
  683. for tmpJo in ja:
  684. cid = tmpJo['cid']
  685. part = tmpJo['part'].replace("#", "-")
  686. playUrl += '{0}${1}_{2}#'.format(part, aid, cid)
  687. follow = '关注UP$' + str(self.up_mid) + '_1_notplay_follow'
  688. unfollow = '取消关注$' + str(self.up_mid) + '_2_notplay_follow'
  689. like = '点赞$' + str(aid) + '_1_notplay_like'
  690. unlike = '取消点赞$' + str(aid) + '_2_notplay_like'
  691. coin1 = '投1币并点赞$' + str(aid) + '_1_notplay_coin'
  692. coin2 = '投2币并点赞$' + str(aid) + '_2_notplay_coin'
  693. fav = '收藏$' + str(aid) + '_0_notplay_fav'
  694. triple = '一键三连$' + str(aid) + '_notplay_triple'
  695. secondPList = [triple, like, coin1, coin2, fav, unlike]
  696. if mlid:
  697. favdel = '取消收藏$' + str(aid) + '_'+ str(mlid) + '_notplay_fav'
  698. secondPList.append(favdel)
  699. secondP = '#'.join(secondPList)
  700. vod['vod_play_url'] = playUrl + '$$$' + secondP
  701. #vod['vod_play_url'] = playUrl
  702. if 'ugc_season' in jRoot['data']:
  703. season_title = jRoot['data']['ugc_season']['title'].replace("#", "-")
  704. sections = jRoot['data']['ugc_season']['sections']
  705. sec_len = len(sections)
  706. for section in sections:
  707. episodes = section['episodes']
  708. playUrl = ''
  709. for episode in episodes:
  710. aid = episode['aid']
  711. cid = episode['cid']
  712. ep_title = episode['title'].replace("#", "-")
  713. playUrl += '{0}${1}_{2}#'.format(ep_title, aid, cid)
  714. if sec_len > 1:
  715. sec_title = season_title + section['title'].replace("#", "-")
  716. else:
  717. sec_title = season_title
  718. vod['vod_play_from'] += '$$$' + sec_title
  719. vod['vod_play_url'] += '$$$' + playUrl
  720. result = {
  721. 'list': [
  722. vod
  723. ]
  724. }
  725. return result
  726. con = threading.Condition()
  727. def get_season(self, n, nList, fromList, urlList, season_id, season_title):
  728. url = 'https://api.bilibili.com/pgc/view/web/season?season_id={0}'.format(season_id)
  729. try:
  730. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  731. season = json.loads(rsp.text)
  732. except:
  733. with self.con:
  734. nList.remove(n)
  735. self.con.notifyAll()
  736. return
  737. episode = season['result']['episodes']
  738. if len(episode) == 0:
  739. with self.con:
  740. nList.remove(n)
  741. self.con.notifyAll()
  742. return
  743. playUrl = ''
  744. for tmpJo in episode:
  745. aid = tmpJo['aid']
  746. cid = tmpJo['cid']
  747. part = tmpJo['title'].replace("#", "-")
  748. if tmpJo['badge'] != '':
  749. part += '【' + tmpJo['badge'].replace("#", "-") + '】'
  750. part += tmpJo['long_title'].replace("#", "-")
  751. playUrl += '{0}${1}_{2}_bangumi#'.format(part, aid, cid)
  752. with self.con:
  753. while True:
  754. if n == nList[0]:
  755. fromList.append(season_title)
  756. urlList.append(playUrl)
  757. nList.remove(n)
  758. self.con.notifyAll()
  759. break
  760. else:
  761. self.con.wait()
  762. def ysContent(self, array):
  763. aid = array[0]
  764. if 'ep' in aid:
  765. aid = 'ep_id=' + aid.replace('ep', '')
  766. elif 'ss' in aid:
  767. aid = 'season_id=' + aid.replace('ss', '')
  768. else:
  769. aid = 'season_id=' + aid
  770. url = "https://api.bilibili.com/pgc/view/web/season?{0}".format(aid)
  771. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  772. jRoot = json.loads(rsp.text)
  773. jo = jRoot['result']
  774. id = jo['season_id']
  775. title = jo['title']
  776. s_title = jo['season_title']
  777. pic = jo['cover']
  778. # areas = jo['areas']['name'] 改bilidanmu显示弹幕
  779. typeName = jo['share_sub_title']
  780. date = jo['publish']['pub_time'][0:4]
  781. dec = jo['evaluate']
  782. remark = jo['new_ep']['desc']
  783. stat = jo['stat']
  784. # 演员和导演框展示视频状态,包括以下内容:
  785. status = "弹幕: " + self.zh(stat['danmakus']) + " 点赞: " + self.zh(stat['likes']) + " 投币: " + self.zh(
  786. stat['coins']) + " 追番追剧: " + self.zh(stat['favorites'])
  787. if 'rating' in jo:
  788. score = "评分: " + str(jo['rating']['score']) + ' ' + jo['subtitle']
  789. else:
  790. score = "暂无评分" + ' ' + jo['subtitle']
  791. vod = {
  792. "vod_id": id,
  793. "vod_name": title,
  794. "vod_pic": pic,
  795. "type_name": typeName,
  796. "vod_year": date,
  797. "vod_area": "bilidanmu",
  798. "vod_remarks": remark,
  799. "vod_actor": status,
  800. "vod_director": score,
  801. "vod_content": dec
  802. }
  803. playUrl = ''
  804. for tmpJo in jo['episodes']:
  805. aid = tmpJo['aid']
  806. cid = tmpJo['cid']
  807. part = tmpJo['title'].replace("#", "-")
  808. if tmpJo['badge'] != '':
  809. part += '【' + tmpJo['badge'].replace("#", "-") + '】'
  810. part += tmpJo['long_title'].replace("#", "-")
  811. playUrl += '{0}${1}_{2}_bangumi#'.format(part, aid, cid)
  812. fromList = []
  813. urlList = []
  814. if playUrl != '':
  815. fromList.append(s_title)
  816. urlList.append(playUrl)
  817. nList = []
  818. if len(jo['seasons']) > 1:
  819. n = 0
  820. for season in jo['seasons']:
  821. season_id = season['season_id']
  822. season_title = season['season_title']
  823. if season_id == id and len(fromList) > 0:
  824. isHere = fromList.index(s_title)
  825. fromList[isHere] = season_title
  826. continue
  827. n +=1
  828. nList.append(n)
  829. t = threading.Thread(target=self.get_season, args=(n, nList, fromList, urlList, season_id, season_title, ))
  830. t.start()
  831. while True:
  832. _count = threading.active_count()
  833. #计算线程数,不出结果就调大,结果少了就调小
  834. if _count <= 2:
  835. break
  836. fromList.insert(1, '追番剧/不追')
  837. urlList.insert(1, '追番剧$' + str(id) + '_add_zhui#取消追番剧$' + str(id) + '_del_zhui')
  838. vod['vod_play_from'] = '$$$'.join(fromList)
  839. vod['vod_play_url'] = '$$$'.join(urlList)
  840. result = {
  841. 'list': [
  842. vod
  843. ]
  844. }
  845. return result
  846. def searchContent(self, key, quick):
  847. url = 'https://api.bilibili.com/x/web-interface/search/type?search_type=video&keyword={0}&page=1'.format(key)
  848. rsp = self.fetch(url, cookies=self.cookies, headers=self.header)
  849. content = rsp.text
  850. jo = json.loads(content)
  851. if jo['code'] != 0:
  852. rspRetry = self.fetch(url, cookies=self.cookies, headers=self.header)
  853. content = rspRetry.text
  854. jo = json.loads(content)
  855. videos = []
  856. vodList = jo['data']['result']
  857. for vod in vodList:
  858. aid = str(vod['aid']).strip()
  859. title = vod['title'].replace("<em class=\"keyword\">", "").replace("</em>", "").replace("&quot;", '"') + '[' + key + ']'
  860. img = 'https:' + vod['pic'].strip()
  861. remark = str(self.second_to_time(self.str2sec(vod['duration']))).strip()
  862. videos.append({
  863. "vod_id": aid,
  864. "vod_name": title,
  865. "vod_pic": img + '@672w_378h_1c.jpg',
  866. "vod_remarks": remark
  867. })
  868. result = {
  869. 'list': videos
  870. }
  871. return result
  872. def post_history(self, aid, cid):
  873. data= {'aid': str(aid), 'cid': str(cid), 'csrf': str(self.csrf)}
  874. url = 'http://api.bilibili.com/x/v2/history/report'
  875. self.post(url=url, headers=self.header, cookies=self.cookies, data=data)
  876. def do_follow(self, mid, act):
  877. data= {'fid': str(mid), 'act': str(act), 'csrf': str(self.csrf)}
  878. url = 'https://api.bilibili.com/x/relation/modify'
  879. self.post(url=url, headers=self.header, cookies=self.cookies, data=data)
  880. def do_like(self, aid, act):
  881. data= {'aid': str(aid), 'like': str(act), 'csrf': str(self.csrf)}
  882. url = 'https://api.bilibili.com/x/web-interface/archive/like'
  883. self.post(url=url, headers=self.header, cookies=self.cookies, data=data)
  884. def do_coin(self, aid, coin_num):
  885. data= {'aid': str(aid), 'multiply': str(coin_num), 'select_like': '1', 'csrf': str(self.csrf)}
  886. url = 'https://api.bilibili.com/x/web-interface/coin/add'
  887. self.post(url=url, headers=self.header, cookies=self.cookies, data=data)
  888. def do_fav(self, aid, act):
  889. data= {'rid': str(aid), 'type': '2', 'csrf': str(self.csrf)}
  890. if str(act) == '0':
  891. data['add_media_ids'] = '0'
  892. else:
  893. data['del_media_ids'] = str(act)
  894. url = 'https://api.bilibili.com/x/v3/fav/resource/deal'
  895. self.post(url=url, headers=self.header, cookies=self.cookies, data=data)
  896. def do_triple(self, aid):
  897. data= {'aid': str(aid), 'csrf': str(self.csrf)}
  898. url = 'https://api.bilibili.com/x/web-interface/archive/like/triple'
  899. self.post(url=url, headers=self.header, cookies=self.cookies, data=data)
  900. def do_zhui(self, season_id, act):
  901. data= {'season_id': str(season_id), 'csrf': str(self.csrf)}
  902. url = 'https://api.bilibili.com/pgc/web/follow/{0}'.format(act)
  903. self.post(url=url, headers=self.header, cookies=self.cookies, data=data)
  904. def playerContent(self, flag, id, vipFlags):
  905. if len(self.cookies) <= 0:
  906. self.getCookie()
  907. result = {}
  908. ids = id.split("_")
  909. if len(ids) < 2:
  910. return result
  911. elif len(ids) >= 2:
  912. aid = ids[0]
  913. cid = ids[1]
  914. if 'zhui' in ids:
  915. self.do_zhui(aid, cid)
  916. return result
  917. if 'follow' in ids:
  918. self.do_follow(aid, cid)
  919. return result
  920. if 'notplay' in ids:
  921. if 'like' in ids:
  922. self.do_like(aid, cid)
  923. elif 'coin' in ids:
  924. self.do_coin(aid, cid)
  925. elif 'fav' in ids:
  926. self.do_fav(aid, cid)
  927. elif 'do_triple' in ids:
  928. self.do_dislike(aid)
  929. return result
  930. if cid == 'cid':
  931. url = "https://api.bilibili.com/x/web-interface/view?aid=%s" % str(aid)
  932. rsp = self.fetch(url, headers=self.header, cookies=self.cookies)
  933. jRoot = json.loads(rsp.text)
  934. cid = jRoot['data']['cid']
  935. url = 'https://api.bilibili.com:443/x/player/playurl?avid={0}&cid={1}&qn=116'.format(aid, cid)
  936. if 'bangumi' in ids:
  937. url = 'https://api.bilibili.com/pgc/player/web/playurl?aid={0}&cid={1}&qn=116'.format(aid, cid)
  938. self.post_history(aid, cid) # 回传播放历史记录
  939. rsp = self.fetch(url, cookies=self.cookies, headers=self.header)
  940. jRoot = json.loads(rsp.text)
  941. if jRoot['code'] == 0:
  942. if 'data' in jRoot:
  943. jo = jRoot['data']
  944. elif 'result' in jRoot:
  945. jo = jRoot['result']
  946. else:
  947. return result
  948. else:
  949. return result
  950. ja = jo['durl']
  951. maxSize = -1
  952. position = -1
  953. for i in range(len(ja)):
  954. tmpJo = ja[i]
  955. if maxSize < int(tmpJo['size']):
  956. maxSize = int(tmpJo['size'])
  957. position = i
  958. url = ''
  959. if len(ja) > 0:
  960. if position == -1:
  961. position = 0
  962. url = ja[position]['url']
  963. result["parse"] = 0
  964. result["playUrl"] = ''
  965. result["url"] = url
  966. result["header"] = {
  967. "Referer": "https://www.bilibili.com",
  968. "User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'
  969. }
  970. result["contentType"] = 'video/x-flv'
  971. return result
  972. config = {
  973. "player": {},
  974. "filter": {
  975. "关注": [{
  976. "key": "order",
  977. "name": "排序",
  978. "value": [
  979. {
  980. "n": "最常访问",
  981. "v": "attention"
  982. },
  983. {
  984. "n": "最近添加",
  985. "v": ""
  986. }
  987. ]
  988. }],
  989. "UP": [{
  990. "key": "order",
  991. "name": "排序",
  992. "value": [
  993. {
  994. "n": "最新发布",
  995. "v": "pubdate"
  996. },
  997. {
  998. "n": "最多播放",
  999. "v": "click"
  1000. },
  1001. {
  1002. "n": "最多收藏",
  1003. "v": "stow"
  1004. },
  1005. {
  1006. "n": "最早发布",
  1007. "v": "oldest"
  1008. }
  1009. ]
  1010. }],
  1011. "收藏": [{
  1012. "key": "order",
  1013. "name": "排序",
  1014. "value": [
  1015. {
  1016. "n": "收藏时间",
  1017. "v": "mtime"
  1018. },
  1019. {
  1020. "n": "播放量",
  1021. "v": "view"
  1022. },
  1023. {
  1024. "n": "投稿时间",
  1025. "v": "pubtime"
  1026. }
  1027. ]
  1028. },
  1029. {
  1030. "key": "mlid",
  1031. "name": "收藏分区",
  1032. "value": []
  1033. }],
  1034. "频道": [{
  1035. "key": "order",
  1036. "name": "排序",
  1037. "value": [
  1038. {
  1039. "n": "综合排序",
  1040. "v": "totalrank"
  1041. },
  1042. {
  1043. "n": "最新发布",
  1044. "v": "pubdate"
  1045. },
  1046. {
  1047. "n": "最多点击",
  1048. "v": "click"
  1049. },
  1050. {
  1051. "n": "最多收藏",
  1052. "v": "stow"
  1053. },
  1054. {
  1055. "n": "最多弹幕",
  1056. "v": "dm"
  1057. },
  1058. ]
  1059. },
  1060. {
  1061. "key": "duration",
  1062. "name": "时长",
  1063. "value": [{
  1064. "n": "全部",
  1065. "v": "0"
  1066. },
  1067. {
  1068. "n": "60分钟以上",
  1069. "v": "4"
  1070. },
  1071. {
  1072. "n": "30~60分钟",
  1073. "v": "3"
  1074. },
  1075. {
  1076. "n": "5~30分钟",
  1077. "v": "2"
  1078. },
  1079. {
  1080. "n": "5分钟以下",
  1081. "v": "1"
  1082. }
  1083. ]
  1084. }, {"key": "cid", "name": "分类",
  1085. "value": [{'n': '搞笑', 'v': '搞笑'}, {'n': '美食', 'v': '美食'}, {'n': '鬼畜', 'v': '鬼畜'},
  1086. {'n': '美妆', 'v': '美妆'}, {'n': 'mmd', 'v': 'mmd'}, {'n': '科普', 'v': '科普'},
  1087. {'n': 'COSPLAY', 'v': 'COSPLAY'}, {'n': '漫展', 'v': '漫展'}, {'n': 'MAD', 'v': 'MAD'},
  1088. {'n': '手书', 'v': '手书'}, {'n': '穿搭', 'v': '穿搭'}, {'n': '发型', 'v': '发型'},
  1089. {'n': '化妆教程', 'v': '化妆教程'}, {'n': '电音', 'v': '电音'}, {'n': '欧美音乐', 'v': '欧美音乐'},
  1090. {'n': '中文翻唱', 'v': '中文翻唱'}, {'n': '洛天依', 'v': '洛天依'}, {'n': '翻唱', 'v': '翻唱'},
  1091. {'n': '日文翻唱', 'v': '日文翻唱'}, {'n': '科普', 'v': '科普'}, {'n': '技术宅', 'v': '技术宅'},
  1092. {'n': '历史', 'v': '历史'}, {'n': '科学', 'v': '科学'}, {'n': '人文', 'v': '人文'},
  1093. {'n': '科幻', 'v': '科幻'}, {'n': '手机', 'v': '手机'}, {'n': '手机评测', 'v': '手机评测'},
  1094. {'n': '电脑', 'v': '电脑'}, {'n': '摄影', 'v': '摄影'}, {'n': '笔记本', 'v': '笔记本'},
  1095. {'n': '装机', 'v': '装机'}, {'n': '课堂教育', 'v': '课堂教育'}, {'n': '公开课', 'v': '公开课'},
  1096. {'n': '演讲', 'v': '演讲'}, {'n': 'PS教程', 'v': 'PS教程'}, {'n': '编程', 'v': '编程'},
  1097. {'n': '英语学习', 'v': '英语学习'}, {'n': '喵星人', 'v': '喵星人'}, {'n': '萌宠', 'v': '萌宠'},
  1098. {'n': '汪星人', 'v': '汪星人'}, {'n': '大熊猫', 'v': '大熊猫'}, {'n': '柴犬', 'v': '柴犬'},
  1099. {'n': '田园犬', 'v': '田园犬'}, {'n': '吱星人', 'v': '吱星人'}, {'n': '美食', 'v': '美食'},
  1100. {'n': '甜点', 'v': '甜点'}, {'n': '吃货', 'v': '吃货'}, {'n': '厨艺', 'v': '厨艺'},
  1101. {'n': '烘焙', 'v': '烘焙'}, {'n': '街头美食', 'v': '街头美食'},
  1102. {'n': 'A.I.Channel', 'v': 'A.I.Channel'}, {'n': '虚拟UP主', 'v': '虚拟UP主'},
  1103. {'n': '神楽めあ', 'v': '神楽めあ'}, {'n': '白上吹雪', 'v': '白上吹雪'}, {'n': '婺源', 'v': '婺源'},
  1104. {'n': 'hololive', 'v': 'hololive'}, {'n': 'EXO', 'v': 'EXO'},
  1105. {'n': '防弹少年团', 'v': '防弹少年团'}, {'n': '肖战', 'v': '肖战'}, {'n': '王一博', 'v': '王一博'},
  1106. {'n': '易烊千玺', 'v': '易烊千玺'}, {'n': '赵今麦', 'v': '赵今麦'}, {'n': '宅舞', 'v': '宅舞'},
  1107. {'n': '街舞', 'v': '街舞'}, {'n': '舞蹈教学', 'v': '舞蹈教学'}, {'n': '明星舞蹈', 'v': '明星舞蹈'},
  1108. {'n': '韩舞', 'v': '韩舞'}, {'n': '古典舞', 'v': '古典舞'}, {'n': '旅游', 'v': '旅游'},
  1109. {'n': '绘画', 'v': '绘画'}, {'n': '手工', 'v': '手工'}, {'n': 'vlog', 'v': 'vlog'},
  1110. {'n': 'DIY', 'v': 'DIY'}, {'n': '手绘', 'v': '手绘'}, {'n': '综艺', 'v': '综艺'},
  1111. {'n': '国家宝藏', 'v': '国家宝藏'}, {'n': '脱口秀', 'v': '脱口秀'}, {'n': '日本综艺', 'v': '日本综艺'},
  1112. {'n': '国内综艺', 'v': '国内综艺'}, {'n': '人类观察', 'v': '人类观察'}, {'n': '影评', 'v': '影评'},
  1113. {'n': '电影解说', 'v': '电影解说'}, {'n': '影视混剪', 'v': '影视混剪'}, {'n': '影视剪辑', 'v': '影视剪辑'},
  1114. {'n': '漫威', 'v': '漫威'}, {'n': '超级英雄', 'v': '超级英雄'}, {'n': '影视混剪', 'v': '影视混剪'},
  1115. {'n': '影视剪辑', 'v': '影视剪辑'},
  1116. {'n': '诸葛亮', 'v': '诸葛亮'}, {'n': '韩剧', 'v': '韩剧'}, {'n': '王司徒', 'v': '王司徒'},
  1117. {'n': '泰剧', 'v': '泰剧'},
  1118. {'n': '郭德纲', 'v': '郭德纲'}, {'n': '相声', 'v': '相声'}, {'n': '张云雷', 'v': '张云雷'},
  1119. {'n': '秦霄贤', 'v': '秦霄贤'}, {'n': '孟鹤堂', 'v': '孟鹤堂'}, {'n': '岳云鹏', 'v': '岳云鹏'},
  1120. {'n': '假面骑士', 'v': '假面骑士'}, {'n': '特摄', 'v': '特摄'}, {'n': '奥特曼', 'v': '奥特曼'},
  1121. {'n': '迪迦奥特曼', 'v': '迪迦奥特曼'}, {'n': '超级战队', 'v': '超级战队'}, {'n': '铠甲勇士', 'v': '铠甲勇士'},
  1122. {'n': '健身', 'v': '健身'}, {'n': '篮球', 'v': '篮球'}, {'n': '体育', 'v': '体育'},
  1123. {'n': '帕梅拉', 'v': '帕梅拉'}, {'n': '极限运动', 'v': '极限运动'}, {'n': '足球', 'v': '足球'},
  1124. {'n': '星海', 'v': '星海'}, {'n': '张召忠', 'v': '张召忠'}, {'n': '航母', 'v': '航母'},
  1125. {'n': '航天', 'v': '航天'}, {'n': '导弹', 'v': '导弹'}, {'n': '战斗机', 'v': '战斗机'}]
  1126. }
  1127. ],
  1128. }
  1129. }
  1130. header = {
  1131. "Referer": "https://www.bilibili.com",
  1132. "User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'
  1133. }
  1134. def localProxy(self, param):
  1135. return [200, "video/MP2T", action, ""]