B站影视.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  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. from requests import session, utils
  8. import os
  9. import time
  10. import base64
  11. class Spider(Spider): # 元类 默认的元类 type
  12. def getName(self):
  13. return "哔哩影视"
  14. def init(self, extend=""):
  15. print("============{0}============".format(extend))
  16. pass
  17. def isVideoFormat(self, url):
  18. pass
  19. def manualVideoCheck(self):
  20. pass
  21. def homeContent(self, filter):
  22. result = {}
  23. cateManual = {
  24. "番剧": "1",
  25. "国创": "4",
  26. "电影": "2",
  27. "电视剧": "5",
  28. "纪录片": "3",
  29. "综艺": "7",
  30. "全部": "全部",
  31. "追番": "追番",
  32. "追剧": "追剧",
  33. "时间表": "时间表",
  34. }
  35. classes = []
  36. for k in cateManual:
  37. classes.append({
  38. 'type_name': k,
  39. 'type_id': cateManual[k]
  40. })
  41. result['class'] = classes
  42. if (filter):
  43. result['filters'] = self.config['filter']
  44. return result
  45. cookies = ''
  46. userid = ''
  47. def getCookie(self):
  48. # --------↓↓↓↓↓↓↓------在下方cookies_str后的双引号内填写-------↓↓↓↓↓↓↓--------
  49. cookies_str = "_uuid=5E4B2B98-1014A-84D8-FA33-EC210C5BEC10DA82367infoc; buvid3=E9D0A426-85E9-E6C7-C75E-206A3E1BEB4D81910infoc; b_nut=1666168082; buvid4=4FC87B9C-3540-2275-688C-8612D3EA719B81910-022101916-ZLe640jXRAMHySuaCe9aUw==; rpdid=|(k|u)YYm)uY0J'uYYYuY)uuu; i-wanna-go-back=-1; fingerprint=9c214a6da0197a48e576ccf22e9f0ac7; buvid_fp_plain=undefined; nostalgia_conf=-1; DedeUserID=3493076028885079; DedeUserID__ckMd5=60a8757a1f4d6ae9; buvid_fp=9c214a6da0197a48e576ccf22e9f0ac7; CURRENT_QUALITY=80; b_ut=5; PVID=2; bp_video_offset_3493076028885079=undefined; bsource=search_google; SESSDATA=42b8ada6,1683277266,4bd05*b2; bili_jct=2dbe39aea02b41324395630a24d4775f; sid=89gnel66; innersign=0; b_lsid=9EF63922_1844D55A286; CURRENT_FNVAL=4048",
  50. if cookies_str:
  51. cookies = dict([co.strip().split('=', 1) for co in cookies_str.split(';')])
  52. bili_jct = cookies['bili_jct']
  53. SESSDATA = cookies['SESSDATA']
  54. DedeUserID = cookies['DedeUserID']
  55. cookies_jar = {"bili_jct": bili_jct,
  56. 'SESSDATA': SESSDATA,
  57. 'DedeUserID': DedeUserID
  58. }
  59. rsp = session()
  60. rsp.cookies = cookies_jar
  61. content = self.fetch("https://api.bilibili.com/x/web-interface/nav", cookies=rsp.cookies)
  62. res = json.loads(content.text)
  63. if res["code"] == 0:
  64. self.cookies = rsp.cookies
  65. self.userid = res["data"].get('mid')
  66. return rsp.cookies
  67. rsp = self.fetch("https://www.bilibili.com/")
  68. self.cookies = rsp.cookies
  69. return rsp.cookies
  70. # 将超过10000的数字换成成以万和亿为单位
  71. def zh(self, num):
  72. if int(num) >= 100000000:
  73. p = round(float(num) / float(100000000), 1)
  74. p = str(p) + '亿'
  75. else:
  76. if int(num) >= 10000:
  77. p = round(float(num) / float(10000), 1)
  78. p = str(p) + '万'
  79. else:
  80. p = str(num)
  81. return p
  82. def homeVideoContent(self):
  83. result = {}
  84. videos = self.get_rank(1)['list'][0:5]
  85. for i in [4, 2, 5, 3, 7]:
  86. videos += self.get_rank2(i)['list'][0:5]
  87. result['list'] = videos
  88. return result
  89. def get_rank(self, tid):
  90. result = {}
  91. url = 'https://api.bilibili.com/pgc/web/rank/list?season_type={0}&day=3'.format(tid)
  92. rsp = self.fetch(url, cookies=self.cookies)
  93. content = rsp.text
  94. jo = json.loads(content)
  95. if jo['code'] == 0:
  96. videos = []
  97. vodList = jo['result']['list']
  98. for vod in vodList:
  99. aid = str(vod['season_id']).strip()
  100. title = vod['title'].strip()
  101. img = vod['cover'].strip()
  102. remark = vod['new_ep']['index_show']
  103. videos.append({
  104. "vod_id": aid,
  105. "vod_name": title,
  106. "vod_pic": img,
  107. "vod_remarks": remark
  108. })
  109. result['list'] = videos
  110. result['page'] = 1
  111. result['pagecount'] = 1
  112. result['limit'] = 90
  113. result['total'] = 999999
  114. return result
  115. def get_rank2(self, tid):
  116. result = {}
  117. url = 'https://api.bilibili.com/pgc/season/rank/web/list?season_type={0}&day=3'.format(tid)
  118. rsp = self.fetch(url, cookies=self.cookies)
  119. content = rsp.text
  120. jo = json.loads(content)
  121. if jo['code'] == 0:
  122. videos = []
  123. vodList = jo['data']['list']
  124. for vod in vodList:
  125. aid = str(vod['season_id']).strip()
  126. title = vod['title'].strip()
  127. img = vod['cover'].strip()
  128. remark = vod['new_ep']['index_show']
  129. videos.append({
  130. "vod_id": aid,
  131. "vod_name": title,
  132. "vod_pic": img,
  133. "vod_remarks": remark
  134. })
  135. result['list'] = videos
  136. result['page'] = 1
  137. result['pagecount'] = 1
  138. result['limit'] = 90
  139. result['total'] = 999999
  140. return result
  141. def get_zhui(self, pg, mode):
  142. result = {}
  143. if len(self.cookies) <= 0:
  144. self.getCookie()
  145. url = 'https://api.bilibili.com/x/space/bangumi/follow/list?type={2}&follow_status=0&pn={1}&ps=10&vmid={0}'.format(self.userid, pg, mode)
  146. rsp = self.fetch(url, cookies=self.cookies)
  147. content = rsp.text
  148. jo = json.loads(content)
  149. videos = []
  150. vodList = jo['data']['list']
  151. for vod in vodList:
  152. aid = str(vod['season_id']).strip()
  153. title = vod['title']
  154. img = vod['cover'].strip()
  155. remark = vod['new_ep']['index_show'].strip()
  156. videos.append({
  157. "vod_id": aid,
  158. "vod_name": title,
  159. "vod_pic": img,
  160. "vod_remarks": remark
  161. })
  162. result['list'] = videos
  163. result['page'] = pg
  164. result['pagecount'] = 9999
  165. result['limit'] = 90
  166. result['total'] = 999999
  167. return result
  168. def get_all(self, tid, pg, order, season_status, extend):
  169. result = {}
  170. if len(self.cookies) <= 0:
  171. self.getCookie()
  172. url = 'https://api.bilibili.com/pgc/season/index/result?order={2}&pagesize=20&type=1&season_type={0}&page={1}&season_status={3}'.format(tid, pg, order, season_status)
  173. rsp = self.fetch(url, cookies=self.cookies)
  174. content = rsp.text
  175. jo = json.loads(content)
  176. videos = []
  177. vodList = jo['data']['list']
  178. for vod in vodList:
  179. aid = str(vod['season_id']).strip()
  180. title = vod['title']
  181. img = vod['cover'].strip()
  182. remark = vod['index_show'].strip()
  183. videos.append({
  184. "vod_id": aid,
  185. "vod_name": title,
  186. "vod_pic": img,
  187. "vod_remarks": remark
  188. })
  189. result['list'] = videos
  190. result['page'] = pg
  191. result['pagecount'] = 9999
  192. result['limit'] = 90
  193. result['total'] = 999999
  194. return result
  195. def get_timeline(self, tid, pg):
  196. result = {}
  197. url = 'https://api.bilibili.com/pgc/web/timeline/v2?season_type={0}&day_before=2&day_after=4'.format(tid)
  198. rsp = self.fetch(url, cookies=self.cookies)
  199. content = rsp.text
  200. jo = json.loads(content)
  201. if jo['code'] == 0:
  202. videos1 = []
  203. vodList = jo['result']['latest']
  204. for vod in vodList:
  205. aid = str(vod['season_id']).strip()
  206. title = vod['title'].strip()
  207. img = vod['cover'].strip()
  208. remark = vod['pub_index'] + ' ' + vod['follows'].replace('系列', '')
  209. videos1.append({
  210. "vod_id": aid,
  211. "vod_name": title,
  212. "vod_pic": img,
  213. "vod_remarks": remark
  214. })
  215. videos2 = []
  216. for i in range(0, 7):
  217. vodList = jo['result']['timeline'][i]['episodes']
  218. for vod in vodList:
  219. if str(vod['published']) == "0":
  220. aid = str(vod['season_id']).strip()
  221. title = str(vod['title']).strip()
  222. img = str(vod['cover']).strip()
  223. date = str(time.strftime("%m-%d %H:%M", time.localtime(vod['pub_ts'])))
  224. remark = date + " " + vod['pub_index']
  225. videos2.append({
  226. "vod_id": aid,
  227. "vod_name": title,
  228. "vod_pic": img,
  229. "vod_remarks": remark
  230. })
  231. result['list'] = videos2 + videos1
  232. result['page'] = 1
  233. result['pagecount'] = 1
  234. result['limit'] = 90
  235. result['total'] = 999999
  236. return result
  237. def categoryContent(self, tid, pg, filter, extend):
  238. result = {}
  239. if len(self.cookies) <= 0:
  240. self.getCookie()
  241. if tid == "1":
  242. return self.get_rank(tid=tid)
  243. elif tid in {"2", "3", "4", "5", "7"}:
  244. return self.get_rank2(tid=tid)
  245. elif tid == "全部":
  246. tid = '1' # 全部界面默认展示最多播放的番剧
  247. order = '2'
  248. season_status = '-1'
  249. if 'tid' in extend:
  250. tid = extend['tid']
  251. if 'order' in extend:
  252. order = extend['order']
  253. if 'season_status' in extend:
  254. season_status = extend['season_status']
  255. return self.get_all(tid, pg, order, season_status, extend)
  256. elif tid == "追番":
  257. return self.get_zhui(pg, 1)
  258. elif tid == "追剧":
  259. return self.get_zhui(pg, 2)
  260. elif tid == "时间表":
  261. tid = 1
  262. if 'tid' in extend:
  263. tid = extend['tid']
  264. return self.get_timeline(tid, pg)
  265. else:
  266. result = self.searchContent(key=tid, quick="false")
  267. return result
  268. def cleanSpace(self, str):
  269. return str.replace('\n', '').replace('\t', '').replace('\r', '').replace(' ', '')
  270. def detailContent(self, array):
  271. aid = array[0]
  272. url = "https://api.bilibili.com/pgc/view/web/season?season_id={0}".format(aid)
  273. rsp = self.fetch(url, headers=self.header)
  274. jRoot = json.loads(rsp.text)
  275. jo = jRoot['result']
  276. id = jo['season_id']
  277. title = jo['title']
  278. pic = jo['cover']
  279. # areas = jo['areas']['name'] 改bilidanmu显示弹幕
  280. typeName = jo['share_sub_title']
  281. date = jo['publish']['pub_time'][0:4]
  282. dec = jo['evaluate']
  283. remark = jo['new_ep']['desc']
  284. stat = jo['stat']
  285. # 演员和导演框展示视频状态,包括以下内容:
  286. status = "弹幕: " + self.zh(stat['danmakus']) + " 点赞: " + self.zh(stat['likes']) + " 投币: " + self.zh(
  287. stat['coins']) + " 追番追剧: " + self.zh(stat['favorites'])
  288. if 'rating' in jo:
  289. score = "评分: " + str(jo['rating']['score']) + ' ' + jo['subtitle']
  290. else:
  291. score = "暂无评分" + ' ' + jo['subtitle']
  292. vod = {
  293. "vod_id": id,
  294. "vod_name": title,
  295. "vod_pic": pic,
  296. "type_name": typeName,
  297. "vod_year": date,
  298. "vod_area": "bilidanmu",
  299. "vod_remarks": remark,
  300. "vod_actor": status,
  301. "vod_director": score,
  302. "vod_content": dec
  303. }
  304. ja = jo['episodes']
  305. playUrl = ''
  306. for tmpJo in ja:
  307. eid = tmpJo['id']
  308. cid = tmpJo['cid']
  309. part = tmpJo['title'].replace("#", "-")
  310. playUrl = playUrl + '{0}${1}_{2}#'.format(part, eid, cid)
  311. vod['vod_play_from'] = 'B站'
  312. vod['vod_play_url'] = playUrl
  313. result = {
  314. 'list': [
  315. vod
  316. ]
  317. }
  318. return result
  319. def searchContent(self, key, quick):
  320. if len(self.cookies) <= 0:
  321. self.getCookie()
  322. url1 = 'https://api.bilibili.com/x/web-interface/search/type?search_type=media_bangumi&keyword={0}'.format(
  323. key) # 番剧搜索
  324. rsp1 = self.fetch(url1, cookies=self.cookies)
  325. content1 = rsp1.text
  326. jo1 = json.loads(content1)
  327. rs1 = jo1['data']
  328. url2 = 'https://api.bilibili.com/x/web-interface/search/type?search_type=media_ft&keyword={0}'.format(
  329. key) # 影视搜索
  330. rsp2 = self.fetch(url2, cookies=self.cookies)
  331. content2 = rsp2.text
  332. jo2 = json.loads(content2)
  333. rs2 = jo2['data']
  334. videos = []
  335. if rs1['numResults'] == 0:
  336. vodList = jo2['data']['result']
  337. elif rs2['numResults'] == 0:
  338. vodList = jo1['data']['result']
  339. else:
  340. vodList = jo1['data']['result'] + jo2['data']['result']
  341. for vod in vodList:
  342. aid = str(vod['season_id']).strip()
  343. title = key + '➢' + vod['title'].strip().replace("<em class=\"keyword\">", "").replace("</em>", "")
  344. img = vod['cover'].strip() # vod['eps'][0]['cover'].strip()原来的错误写法
  345. remark = vod['index_show']
  346. videos.append({
  347. "vod_id": aid,
  348. "vod_name": title,
  349. "vod_pic": img,
  350. "vod_remarks": remark
  351. })
  352. result = {
  353. 'list': videos
  354. }
  355. return result
  356. def playerContent(self, flag, id, vipFlags):
  357. result = {}
  358. ids = id.split("_")
  359. header = {
  360. "Referer": "https://www.bilibili.com",
  361. "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36"
  362. }
  363. url = 'https://api.bilibili.com/pgc/player/web/playurl?qn=116&ep_id={0}&cid={1}'.format(ids[0], ids[1])
  364. if len(self.cookies) <= 0:
  365. self.getCookie()
  366. rsp = self.fetch(url, cookies=self.cookies, headers=header)
  367. jRoot = json.loads(rsp.text)
  368. if jRoot['message'] != 'success':
  369. print("需要大会员权限才能观看")
  370. return {}
  371. jo = jRoot['result']
  372. ja = jo['durl']
  373. maxSize = -1
  374. position = -1
  375. for i in range(len(ja)):
  376. tmpJo = ja[i]
  377. if maxSize < int(tmpJo['size']):
  378. maxSize = int(tmpJo['size'])
  379. position = i
  380. url = ''
  381. if len(ja) > 0:
  382. if position == -1:
  383. position = 0
  384. url = ja[position]['url']
  385. result["parse"] = 0
  386. result["playUrl"] = ''
  387. result["url"] = url
  388. result["header"] = {
  389. "Referer": "https://www.bilibili.com",
  390. "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36"
  391. }
  392. result["contentType"] = 'video/x-flv'
  393. return result
  394. config = {
  395. "player": {},
  396. "filter": {
  397. "全部": [
  398. {
  399. "key": "tid",
  400. "name": "分类",
  401. "value": [{
  402. "n": "番剧",
  403. "v": "1"
  404. },
  405. {
  406. "n": "国创",
  407. "v": "4"
  408. },
  409. {
  410. "n": "电影",
  411. "v": "2"
  412. },
  413. {
  414. "n": "电视剧",
  415. "v": "5"
  416. },
  417. {
  418. "n": "记录片",
  419. "v": "3"
  420. },
  421. {
  422. "n": "综艺",
  423. "v": "7"
  424. }
  425. ]
  426. },
  427. {
  428. "key": "order",
  429. "name": "排序",
  430. "value": [
  431. {
  432. "n": "播放数量",
  433. "v": "2"
  434. },
  435. {
  436. "n": "更新时间",
  437. "v": "0"
  438. },
  439. {
  440. "n": "最高评分",
  441. "v": "4"
  442. },
  443. {
  444. "n": "弹幕数量",
  445. "v": "1"
  446. },
  447. {
  448. "n": "追看人数",
  449. "v": "3"
  450. },
  451. {
  452. "n": "开播时间",
  453. "v": "5"
  454. },
  455. {
  456. "n": "上映时间",
  457. "v": "6"
  458. },
  459. ]
  460. },
  461. {
  462. "key": "season_status",
  463. "name": "付费",
  464. "value": [
  465. {
  466. "n": "全部",
  467. "v": "-1"
  468. },
  469. {
  470. "n": "免费",
  471. "v": "1"
  472. },
  473. {
  474. "n": "付费",
  475. "v": "2%2C6"
  476. },
  477. {
  478. "n": "大会员",
  479. "v": "4%2C6"
  480. },
  481. ]
  482. },
  483. ],
  484. "时间表": [{
  485. "key": "tid",
  486. "name": "分类",
  487. "value": [
  488. {
  489. "n": "番剧",
  490. "v": "1"
  491. },
  492. {
  493. "n": "国创",
  494. "v": "4"
  495. },
  496. ]
  497. },
  498. ],
  499. }
  500. }
  501. header = {
  502. "Referer": "https://www.bilibili.com",
  503. "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'
  504. }
  505. def localProxy(self, param):
  506. return [200, "video/MP2T", action, ""]