From a0b9a8086e215f7e6643d0ad5bcf65b7efb1e1da Mon Sep 17 00:00:00 2001 From: hjdhnx Date: Mon, 21 Nov 2022 10:28:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=B8=BF=E9=80=94=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=93=94=E5=93=A9=E7=9B=B4?= =?UTF-8?q?=E6=92=AD=E7=9A=84py=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "jiexi/\351\270\277\351\200\224.js" | 59 ++- txt/py/py_bilimd.py | 744 ++++++++++++++++++++-------- txt/py/py_bilizb.py | 684 +++++++++++++++++++++++++ 3 files changed, 1277 insertions(+), 210 deletions(-) create mode 100644 txt/py/py_bilizb.py diff --git "a/jiexi/\351\270\277\351\200\224.js" "b/jiexi/\351\270\277\351\200\224.js" index cabb6f3..47db2db 100644 --- "a/jiexi/\351\270\277\351\200\224.js" +++ "b/jiexi/\351\270\277\351\200\224.js" @@ -1,12 +1,57 @@ -let jxUrl = 'https://h5.freejson.xyz/player/analysis.php?v='; +// let jxUrl = 'https://h5.freejson.xyz/player/analysis.php?v='; +// fetch_params.headers.Referer = jxUrl; +// try { +// // realUrl = null; +// let html = request(jxUrl+vipUrl); +// log(html); +// //realUrl = jsp.pjfh(html,'$..url'); +// realUrl=html.match(/var urls = "(.*?)"/)[1]; +// log('解析到真实播放地址:'+realUrl); +// }catch (e) { +// log('解析发生错误:'+e.message); +// realUrl = vipUrl; +// } +// 虾米免嗅 +let jxUrl = 'https://jx.xmflv.com/?url='; fetch_params.headers.Referer = jxUrl; +eval(getCryptoJS()); +function encrypt(_0x5cf953) { + var _0x5efb07 = CryptoJS.enc.Utf8.parse(vkey); + var _0x45c0ea = CryptoJS.enc.Utf8.parse('ash3omcjsoajh1ur'); + var _0x268682 = CryptoJS.AES.encrypt(_0x5cf953, _0x5efb07, { + 'iv': _0x45c0ea, + 'mode': CryptoJS.mode.CBC, + 'padding': CryptoJS.pad.ZeroPadding + }); + return _0x268682.toString(); +} + +function jsdecrypt(_0x1a43fe) { + var _0x10ab4d = CryptoJS.enc.Utf8.parse(vkey); + var _0x291247 = CryptoJS.enc.Utf8.parse('contentDocuments'); + var _0x5abb12 = CryptoJS.AES.decrypt(_0x1a43fe, _0x10ab4d, { + 'iv': _0x291247, + 'mode': CryptoJS.mode.CBC, + 'padding': CryptoJS.pad.ZeroPadding + }).toString(CryptoJS.enc.Utf8); + return _0x5abb12.toString(); +} try { - // realUrl = null; - let html = request(jxUrl+vipUrl); - log(html); - //realUrl = jsp.pjfh(html,'$..url'); - realUrl=html.match(/var urls = "(.*?)"/)[1]; - log('解析到真实播放地址:'+realUrl); +let html = request(jxUrl+vipUrl); +let time = html.match(/var time = '(.*?)'/)[1]; +let ua = html.match(/var ua = '(.*?)'/)[1]; +let vkey = html.match(/var vkey = '(.*?)'/)[1]; +// log(encrypt(vkey)); +let phtml = request("https://jx.xmflv.com/favicon.ico", { + headers: { + "origin": "https://jx.xmflv.com" + }, + body: "url=" + vipUrl + "&time=" + time + "&ua=" + ua + "&vkey=" + encrypt(vkey), + method: "post" +}); +// log(phtml); +realUrl = jsdecrypt(JSON.parse(phtml).url); +log('解析到真实播放地址:'+realUrl); }catch (e) { log('解析发生错误:'+e.message); realUrl = vipUrl; diff --git a/txt/py/py_bilimd.py b/txt/py/py_bilimd.py index ba4fd95..78f2e06 100644 --- a/txt/py/py_bilimd.py +++ b/txt/py/py_bilimd.py @@ -1,6 +1,7 @@ -#coding=utf-8 -#!/usr/bin/python +# coding=utf-8 +# !/usr/bin/python import sys + sys.path.append('..') from base.spider import Spider import json @@ -9,205 +10,542 @@ import os import time import base64 + class Spider(Spider): # 元类 默认的元类 type - def getName(self): - return "B站影视" - def init(self,extend=""): - print("============{0}============".format(extend)) - pass - def isVideoFormat(self,url): - pass - def manualVideoCheck(self): - pass - def homeContent(self,filter): - result = {} - cateManual = { - "番剧": "1", - "国创": "4", - "电影": "2", - "综艺": "7", - "电视剧": "5", - "纪录片": "3" - } - classes = [] - for k in cateManual: - classes.append({ - 'type_name':k, - 'type_id':cateManual[k] - }) - result['class'] = classes - if(filter): - result['filters'] = self.config['filter'] - return result - def homeVideoContent(self): - result = { - 'list':[] - } - return result - cookies = '' - def getCookie(self): - cookies_str = "" # 填B站Cookies - cookies_dic = dict([co.strip().split('=') for co in cookies_str.split(';')]) - rsp = session() - cookies_jar = utils.cookiejar_from_dict(cookies_dic) - rsp.cookies = cookies_jar - content = self.fetch("http://api.bilibili.com/x/web-interface/nav", cookies=rsp.cookies) - res = json.loads(content.text) - if res["code"] == 0: - self.cookies = rsp.cookies - else: - rsp = self.fetch("https://www.bilibili.com/") - self.cookies = rsp.cookies - return rsp.cookies - - def categoryContent(self,tid,pg,filter,extend): - result = {} - url = 'https://api.bilibili.com/pgc/season/index/result?order=2&season_status=-1&style_id=-1&sort=0&area=-1&pagesize=20&type=1&st={0}&season_type={0}&page={1}'.format(tid,pg) - if len(self.cookies) <= 0: - self.getCookie() - rsp = self.fetch(url, cookies=self.cookies) - content = rsp.text - jo = json.loads(content) - videos = [] - vodList = jo['data']['list'] - for vod in vodList: - aid = str(vod['season_id']).strip() - title = vod['title'].strip() - img = vod['cover'].strip() - remark = vod['index_show'].strip() - videos.append({ - "vod_id":aid, - "vod_name":title, - "vod_pic":img, - "vod_remarks":remark - }) - result['list'] = videos - result['page'] = pg - result['pagecount'] = 9999 - result['limit'] = 90 - result['total'] = 999999 - return result - def cleanSpace(self,str): - return str.replace('\n','').replace('\t','').replace('\r','').replace(' ','') - def detailContent(self,array): - aid = array[0] - url = "http://api.bilibili.com/pgc/view/web/season?season_id={0}".format(aid) - rsp = self.fetch(url,headers=self.header) - jRoot = json.loads(rsp.text) - jo = jRoot['result'] - id = jo['season_id'] - title = jo['title'] - pic = jo['cover'] - areas = jo['areas'][0]['name'] - typeName = jo['share_sub_title'] - dec = jo['evaluate'] - remark = jo['new_ep']['desc'] - vod = { - "vod_id":id, - "vod_name":title, - "vod_pic":pic, - "type_name":typeName, - "vod_year":"", - "vod_area":areas, - "vod_remarks":remark, - "vod_actor":"", - "vod_director":"", - "vod_content":dec - } - ja = jo['episodes'] - playUrl = '' - for tmpJo in ja: - eid = tmpJo['id'] - cid = tmpJo['cid'] - part = tmpJo['title'].replace("#", "-") - playUrl = playUrl + '{0}${1}_{2}#'.format(part, eid, cid) - - vod['vod_play_from'] = 'B站影视' - vod['vod_play_url'] = playUrl - - result = { - 'list':[ - vod - ] - } - return result - def searchContent(self,key,quick): - url = 'https://api.bilibili.com/x/web-interface/search/type?search_type=media_bangumi&keyword={0}'.format(key) # 番剧搜索 - if len(self.cookies) <= 0: - self.getCookie() - rsp = self.fetch(url, cookies=self.cookies) - content = rsp.text - jo = json.loads(content) - rs = jo['data'] - if rs['numResults'] == 0: - url = 'https://api.bilibili.com/x/web-interface/search/type?search_type=media_ft&keyword={0}'.format(key) # 影视搜索 - rspRetry = self.fetch(url, cookies=self.cookies) - content = rspRetry.text - jo = json.loads(content) - videos = [] - vodList = jo['data']['result'] - for vod in vodList: - aid = str(vod['season_id']).strip() - title = vod['title'].strip().replace("", "").replace("", "") - img = vod['eps'][0]['cover'].strip() - remark = vod['index_show'] - videos.append({ - "vod_id": aid, - "vod_name": title, - "vod_pic": img, - "vod_remarks": remark - }) - result = { - 'list': videos - } - return result - - def playerContent(self,flag,id,vipFlags): - result = {} - ids = id.split("_") - header = { - "Referer": "https://www.bilibili.com", - "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" - } - url = 'https://api.bilibili.com/pgc/player/web/playurl?qn=116&ep_id={0}&cid={1}'.format(ids[0],ids[1]) - if len(self.cookies) <= 0: - self.getCookie() - rsp = self.fetch(url,cookies=self.cookies,headers=header) - jRoot = json.loads(rsp.text) - if jRoot['message'] != 'success': - print("需要大会员权限才能观看") - return {} - jo = jRoot['result'] - ja = jo['durl'] - maxSize = -1 - position = -1 - for i in range(len(ja)): - tmpJo = ja[i] - if maxSize < int(tmpJo['size']): - maxSize = int(tmpJo['size']) - position = i - - url = '' - if len(ja) > 0: - if position == -1: - position = 0 - url = ja[position]['url'] - - result["parse"] = 0 - result["playUrl"] = '' - result["url"] = url - result["header"] = { - "Referer":"https://www.bilibili.com", - "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" - } - result["contentType"] = 'video/x-flv' - return result - - config = { - "player": {}, - "filter": {} - } - header = {} - - def localProxy(self,param): - return [200, "video/MP2T", action, ""] + def getName(self): + return "哔哩影视" + + def init(self, extend=""): + print("============{0}============".format(extend)) + pass + + def isVideoFormat(self, url): + pass + + def manualVideoCheck(self): + pass + + def homeContent(self, filter): + result = {} + cateManual = { + "番剧": "1", + "国创": "4", + "电影": "2", + "电视剧": "5", + "纪录片": "3", + "综艺": "7", + "全部": "全部", + "追番": "追番", + "追剧": "追剧", + "时间表": "时间表", + + } + classes = [] + for k in cateManual: + classes.append({ + 'type_name': k, + 'type_id': cateManual[k] + }) + result['class'] = classes + if (filter): + result['filters'] = self.config['filter'] + return result + + cookies = '' + userid = '' + + def getCookie(self): + # --------↓↓↓↓↓↓↓------在下方cookies_str后的双引号内填写-------↓↓↓↓↓↓↓-------- + cookies_str = "" + if cookies_str: + cookies = dict([co.strip().split('=', 1) for co in cookies_str.split(';')]) + bili_jct = cookies['bili_jct'] + SESSDATA = cookies['SESSDATA'] + DedeUserID = cookies['DedeUserID'] + cookies_jar = {"bili_jct": bili_jct, + 'SESSDATA': SESSDATA, + 'DedeUserID': DedeUserID + } + rsp = session() + rsp.cookies = cookies_jar + content = self.fetch("https://api.bilibili.com/x/web-interface/nav", cookies=rsp.cookies) + res = json.loads(content.text) + if res["code"] == 0: + self.cookies = rsp.cookies + self.userid = res["data"].get('mid') + return rsp.cookies + rsp = self.fetch("https://www.bilibili.com/") + self.cookies = rsp.cookies + return rsp.cookies + + # 将超过10000的数字换成成以万和亿为单位 + def zh(self, num): + if int(num) >= 100000000: + p = round(float(num) / float(100000000), 1) + p = str(p) + '亿' + else: + if int(num) >= 10000: + p = round(float(num) / float(10000), 1) + p = str(p) + '万' + else: + p = str(num) + return p + + def homeVideoContent(self): + result = {} + videos = self.get_rank(1)['list'][0:5] + for i in [4, 2, 5, 3, 7]: + videos += self.get_rank2(i)['list'][0:5] + result['list'] = videos + return result + + def get_rank(self, tid): + result = {} + url = 'https://api.bilibili.com/pgc/web/rank/list?season_type={0}&day=3'.format(tid) + rsp = self.fetch(url, cookies=self.cookies) + content = rsp.text + jo = json.loads(content) + if jo['code'] == 0: + videos = [] + vodList = jo['result']['list'] + for vod in vodList: + aid = str(vod['season_id']).strip() + title = vod['title'].strip() + img = vod['cover'].strip() + remark = vod['new_ep']['index_show'] + videos.append({ + "vod_id": aid, + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + result['list'] = videos + result['page'] = 1 + result['pagecount'] = 1 + result['limit'] = 90 + result['total'] = 999999 + return result + + def get_rank2(self, tid): + result = {} + url = 'https://api.bilibili.com/pgc/season/rank/web/list?season_type={0}&day=3'.format(tid) + rsp = self.fetch(url, cookies=self.cookies) + content = rsp.text + jo = json.loads(content) + if jo['code'] == 0: + videos = [] + vodList = jo['data']['list'] + for vod in vodList: + aid = str(vod['season_id']).strip() + title = vod['title'].strip() + img = vod['cover'].strip() + remark = vod['new_ep']['index_show'] + videos.append({ + "vod_id": aid, + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + result['list'] = videos + result['page'] = 1 + result['pagecount'] = 1 + result['limit'] = 90 + result['total'] = 999999 + return result + + def get_zhui(self, pg, mode): + result = {} + if len(self.cookies) <= 0: + self.getCookie() + 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) + rsp = self.fetch(url, cookies=self.cookies) + content = rsp.text + jo = json.loads(content) + videos = [] + vodList = jo['data']['list'] + for vod in vodList: + aid = str(vod['season_id']).strip() + title = vod['title'] + img = vod['cover'].strip() + remark = vod['new_ep']['index_show'].strip() + videos.append({ + "vod_id": aid, + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + result['list'] = videos + result['page'] = pg + result['pagecount'] = 9999 + result['limit'] = 90 + result['total'] = 999999 + return result + + def get_all(self, tid, pg, order, season_status, extend): + result = {} + if len(self.cookies) <= 0: + self.getCookie() + 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) + rsp = self.fetch(url, cookies=self.cookies) + content = rsp.text + jo = json.loads(content) + videos = [] + vodList = jo['data']['list'] + for vod in vodList: + aid = str(vod['season_id']).strip() + title = vod['title'] + img = vod['cover'].strip() + remark = vod['index_show'].strip() + videos.append({ + "vod_id": aid, + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + result['list'] = videos + result['page'] = pg + result['pagecount'] = 9999 + result['limit'] = 90 + result['total'] = 999999 + return result + + def get_timeline(self, tid, pg): + result = {} + url = 'https://api.bilibili.com/pgc/web/timeline/v2?season_type={0}&day_before=2&day_after=4'.format(tid) + rsp = self.fetch(url, cookies=self.cookies) + content = rsp.text + jo = json.loads(content) + if jo['code'] == 0: + videos1 = [] + vodList = jo['result']['latest'] + for vod in vodList: + aid = str(vod['season_id']).strip() + title = vod['title'].strip() + img = vod['cover'].strip() + remark = vod['pub_index'] + ' ' + vod['follows'].replace('系列', '') + videos1.append({ + "vod_id": aid, + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + videos2 = [] + for i in range(0, 7): + vodList = jo['result']['timeline'][i]['episodes'] + for vod in vodList: + if str(vod['published']) == "0": + aid = str(vod['season_id']).strip() + title = str(vod['title']).strip() + img = str(vod['cover']).strip() + date = str(time.strftime("%m-%d %H:%M", time.localtime(vod['pub_ts']))) + remark = date + " " + vod['pub_index'] + videos2.append({ + "vod_id": aid, + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + result['list'] = videos2 + videos1 + result['page'] = 1 + result['pagecount'] = 1 + result['limit'] = 90 + result['total'] = 999999 + return result + + def categoryContent(self, tid, pg, filter, extend): + result = {} + if len(self.cookies) <= 0: + self.getCookie() + if tid == "1": + return self.get_rank(tid=tid) + elif tid in {"2", "3", "4", "5", "7"}: + return self.get_rank2(tid=tid) + elif tid == "全部": + tid = '1' # 全部界面默认展示最多播放的番剧 + order = '2' + season_status = '-1' + if 'tid' in extend: + tid = extend['tid'] + if 'order' in extend: + order = extend['order'] + if 'season_status' in extend: + season_status = extend['season_status'] + return self.get_all(tid, pg, order, season_status, extend) + elif tid == "追番": + return self.get_zhui(pg, 1) + elif tid == "追剧": + return self.get_zhui(pg, 2) + elif tid == "时间表": + tid = 1 + if 'tid' in extend: + tid = extend['tid'] + return self.get_timeline(tid, pg) + else: + result = self.searchContent(key=tid, quick="false") + return result + + def cleanSpace(self, str): + return str.replace('\n', '').replace('\t', '').replace('\r', '').replace(' ', '') + + def detailContent(self, array): + aid = array[0] + url = "https://api.bilibili.com/pgc/view/web/season?season_id={0}".format(aid) + rsp = self.fetch(url, headers=self.header) + jRoot = json.loads(rsp.text) + jo = jRoot['result'] + id = jo['season_id'] + title = jo['title'] + pic = jo['cover'] + # areas = jo['areas']['name'] 改bilidanmu显示弹幕 + typeName = jo['share_sub_title'] + date = jo['publish']['pub_time'][0:4] + dec = jo['evaluate'] + remark = jo['new_ep']['desc'] + stat = jo['stat'] + # 演员和导演框展示视频状态,包括以下内容: + status = "弹幕: " + self.zh(stat['danmakus']) + " 点赞: " + self.zh(stat['likes']) + " 投币: " + self.zh( + stat['coins']) + " 追番追剧: " + self.zh(stat['favorites']) + if 'rating' in jo: + score = "评分: " + str(jo['rating']['score']) + ' ' + jo['subtitle'] + else: + score = "暂无评分" + ' ' + jo['subtitle'] + vod = { + "vod_id": id, + "vod_name": title, + "vod_pic": pic, + "type_name": typeName, + "vod_year": date, + "vod_area": "bilidanmu", + "vod_remarks": remark, + "vod_actor": status, + "vod_director": score, + "vod_content": dec + } + ja = jo['episodes'] + playUrl = '' + for tmpJo in ja: + eid = tmpJo['id'] + cid = tmpJo['cid'] + part = tmpJo['title'].replace("#", "-") + playUrl = playUrl + '{0}${1}_{2}#'.format(part, eid, cid) + + vod['vod_play_from'] = 'B站' + vod['vod_play_url'] = playUrl + + result = { + 'list': [ + vod + ] + } + return result + + def searchContent(self, key, quick): + if len(self.cookies) <= 0: + self.getCookie() + url1 = 'https://api.bilibili.com/x/web-interface/search/type?search_type=media_bangumi&keyword={0}'.format( + key) # 番剧搜索 + rsp1 = self.fetch(url1, cookies=self.cookies) + content1 = rsp1.text + jo1 = json.loads(content1) + rs1 = jo1['data'] + url2 = 'https://api.bilibili.com/x/web-interface/search/type?search_type=media_ft&keyword={0}'.format( + key) # 影视搜索 + rsp2 = self.fetch(url2, cookies=self.cookies) + content2 = rsp2.text + jo2 = json.loads(content2) + rs2 = jo2['data'] + videos = [] + if rs1['numResults'] == 0: + vodList = jo2['data']['result'] + elif rs2['numResults'] == 0: + vodList = jo1['data']['result'] + else: + vodList = jo1['data']['result'] + jo2['data']['result'] + for vod in vodList: + aid = str(vod['season_id']).strip() + title = key + '➢' + vod['title'].strip().replace("", "").replace("", "") + img = vod['cover'].strip() # vod['eps'][0]['cover'].strip()原来的错误写法 + remark = vod['index_show'] + videos.append({ + "vod_id": aid, + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + result = { + 'list': videos + } + return result + + def playerContent(self, flag, id, vipFlags): + result = {} + ids = id.split("_") + header = { + "Referer": "https://www.bilibili.com", + "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" + } + url = 'https://api.bilibili.com/pgc/player/web/playurl?qn=116&ep_id={0}&cid={1}'.format(ids[0], ids[1]) + if len(self.cookies) <= 0: + self.getCookie() + rsp = self.fetch(url, cookies=self.cookies, headers=header) + jRoot = json.loads(rsp.text) + if jRoot['message'] != 'success': + print("需要大会员权限才能观看") + return {} + jo = jRoot['result'] + ja = jo['durl'] + maxSize = -1 + position = -1 + for i in range(len(ja)): + tmpJo = ja[i] + if maxSize < int(tmpJo['size']): + maxSize = int(tmpJo['size']) + position = i + + url = '' + if len(ja) > 0: + if position == -1: + position = 0 + url = ja[position]['url'] + + result["parse"] = 0 + result["playUrl"] = '' + result["url"] = url + result["header"] = { + "Referer": "https://www.bilibili.com", + "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" + } + result["contentType"] = 'video/x-flv' + return result + + config = { + "player": {}, + "filter": { + "全部": [ + { + "key": "tid", + "name": "分类", + "value": [{ + "n": "番剧", + "v": "1" + }, + { + "n": "国创", + "v": "4" + }, + + { + "n": "电影", + "v": "2" + }, + { + "n": "电视剧", + "v": "5" + }, + { + "n": "记录片", + "v": "3" + }, + { + "n": "综艺", + "v": "7" + } + + ] + }, + { + "key": "order", + "name": "排序", + "value": [ + + { + "n": "播放数量", + "v": "2" + }, + + { + "n": "更新时间", + "v": "0" + }, + + { + "n": "最高评分", + "v": "4" + }, + { + "n": "弹幕数量", + "v": "1" + }, + { + "n": "追看人数", + "v": "3" + }, + + { + "n": "开播时间", + "v": "5" + }, + { + "n": "上映时间", + "v": "6" + }, + + ] + }, + { + "key": "season_status", + "name": "付费", + "value": [ + { + "n": "全部", + "v": "-1" + }, + { + "n": "免费", + "v": "1" + }, + + { + "n": "付费", + "v": "2%2C6" + }, + + { + "n": "大会员", + "v": "4%2C6" + }, + + ] + }, + ], + + + "时间表": [{ + "key": "tid", + "name": "分类", + "value": [ + + { + "n": "番剧", + "v": "1" + }, + + { + "n": "国创", + "v": "4" + }, + + ] + }, + ], + } + } + + + header = { + "Referer": "https://www.bilibili.com", + "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' + } + + def localProxy(self, param): + return [200, "video/MP2T", action, ""] diff --git a/txt/py/py_bilizb.py b/txt/py/py_bilizb.py new file mode 100644 index 0000000..44b73fc --- /dev/null +++ b/txt/py/py_bilizb.py @@ -0,0 +1,684 @@ +# coding=utf-8 +# !/usr/bin/python +import sys + +sys.path.append('..') +from base.spider import Spider +import json +import requests +from requests import session, utils +import time +import base64 + + +class Spider(Spider): # 元类 默认的元类 type + + def getName(self): + return "哔哩直播" + + def homeContent(self, filter): + result = {} + cateManual = { + "推荐": "推荐", + "网游": "2", + "手游": "3", + "单机": "6", + "娱乐": "1", + "生活": "10", + "知识": "11", + "赛事": "13", + "电台": "5", + "虚拟": "9", + "我的关注": "我的关注", + "观看记录": "观看记录", + + } + classes = [] + for k in cateManual: + classes.append({ + 'type_name': k, + 'type_id': cateManual[k] + }) + result['class'] = classes + if (filter): + result['filters'] = self.config['filter'] + return result + + # 用户cookies + cookies = '' + userid = '' + + def getCookie(self): + # --------↓↓↓↓↓↓↓------在下方cookies_str后的双引号内填写-------↓↓↓↓↓↓↓-------- + cookies_str = "" + if cookies_str: + cookies = dict([co.strip().split('=', 1) for co in cookies_str.split(';')]) + bili_jct = cookies['bili_jct'] + SESSDATA = cookies['SESSDATA'] + DedeUserID = cookies['DedeUserID'] + + cookies_jar = {"bili_jct": bili_jct, + 'SESSDATA': SESSDATA, + 'DedeUserID': DedeUserID + } + rsp = session() + rsp.cookies = cookies_jar + content = self.fetch("https://api.bilibili.com/x/web-interface/nav", cookies=rsp.cookies) + res = json.loads(content.text) + if res["code"] == 0: + self.cookies = rsp.cookies + self.userid = res["data"].get('mid') + return rsp.cookies + rsp = self.fetch("https://www.bilibili.com/") + self.cookies = rsp.cookies + return rsp.cookies + + def init(self, extend=""): + print("============{0}============".format(extend)) + pass + + def isVideoFormat(self, url): + pass + + def manualVideoCheck(self): + pass + + # 将超过10000的数字换成成以万和亿为单位 + def zh(self, num): + if int(num) >= 100000000: + p = round(float(num) / float(100000000), 1) + p = str(p) + '亿' + else: + if int(num) >= 10000: + p = round(float(num) / float(10000), 1) + p = str(p) + '万' + else: + p = str(num) + return p + + # 获取主播用户名 + uname = '' + + def get_live_userInfo(self, uid): + url = 'https://api.live.bilibili.com/live_user/v1/Master/info?uid=%s' % uid + rsp = self.fetch(url, cookies=self.cookies) + content = rsp.text + jo = json.loads(content) + if jo['code'] == 0: + return jo['data']["info"]["uname"] + + def homeVideoContent(self): + return self.get_hot(1) + + def get_recommend(self, pg): + result = {} + url = 'https://api.live.bilibili.com/xlive/web-interface/v1/webMain/getList?platform=web&page=%s' % pg + rsp = self.fetch(url, cookies=self.cookies) + content = rsp.text + jo = json.loads(content) + if jo['code'] == 0: + videos = [] + vodList = jo['data']['recommend_room_list'] + for vod in vodList: + aid = str(vod['roomid']).strip() + title = vod['title'].replace("", "").replace("", "").replace(""", '"') + img = vod['keyframe'].strip() + remark = vod['watched_show']['text_small'].strip() + " " + vod['uname'].strip() + videos.append({ + "vod_id": aid + '&live', + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + result['list'] = videos + result['page'] = pg + result['pagecount'] = 9999 + result['limit'] = 90 + result['total'] = 999999 + return result + + def get_hot(self, pg): + result = {} + url = 'https://api.live.bilibili.com/room/v1/room/get_user_recommend?page=%s' % pg + rsp = self.fetch(url, cookies=self.cookies) + content = rsp.text + jo = json.loads(content) + if jo['code'] == 0: + videos = [] + vodList = jo['data'] + for vod in vodList: + aid = str(vod['roomid']).strip() + title = vod['title'].replace("", "").replace("", "").replace(""", '"') + img = vod['user_cover'].strip() + remark = vod['watched_show']['text_small'].strip() + " " + vod['uname'].strip() + videos.append({ + "vod_id": aid + '&live', + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + result['list'] = videos + result['page'] = pg + result['pagecount'] = 9999 + result['limit'] = 90 + result['total'] = 999999 + return result + + def get_live(self, pg, parent_area_id, area_id): + result = {} + url = 'https://api.live.bilibili.com/xlive/web-interface/v1/second/getList?platform=web&parent_area_id=%s&area_id=%s&sort_type=online&page=%s' % ( + parent_area_id, area_id, pg) + rsp = self.fetch(url, cookies=self.cookies) + content = rsp.text + jo = json.loads(content) + if jo['code'] == 0: + videos = [] + vodList = jo['data']['list'] + for vod in vodList: + aid = str(vod['roomid']).strip() + title = vod['title'].replace("", "").replace("", "").replace(""", '"') + img = vod.get('cover').strip() + remark = vod['watched_show']['text_small'].strip() + " " + vod['uname'].strip() + videos.append({ + "vod_id": aid + '&live', + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + result['list'] = videos + result['page'] = pg + result['pagecount'] = 9999 + result['limit'] = 90 + result['total'] = 999999 + return result + + def get_fav(self, pg): + result = {} + url = 'https://api.live.bilibili.com/xlive/web-ucenter/v1/xfetter/GetWebList?page=%s&page_size=10' % pg + rsp = self.fetch(url, cookies=self.cookies) + content = rsp.text + jo = json.loads(content) + videos = [] + vodList = jo['data']['rooms'] + for vod in vodList: + aid = str(vod['room_id']).strip() + title = vod['title'].replace("", "").replace("", "").replace(""", '"') + img = vod['cover_from_user'].strip() + remark = vod['uname'].strip() + videos.append({ + "vod_id": aid + '&live', + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + result['list'] = videos + result['page'] = pg + result['pagecount'] = 9999 + result['limit'] = 90 + result['total'] = 999999 + return result + + def get_history(self): + result = {} + url = 'https://api.bilibili.com/x/web-interface/history/cursor?ps=30&type=live' + rsp = self.fetch(url, cookies=self.cookies) + content = rsp.text + jo = json.loads(content) + if jo['code'] == 0: + videos = [] + vodList = jo['data']['list'] + for vod in vodList: + aid = str(vod['history']['oid']).strip() + title = vod['title'].replace("", "").replace("", "").replace(""", '"') + img = vod['cover'].strip() + remark = str(vod['live_status']).replace("0", "未开播").replace("1", "") +" " + vod['author_name'].strip() + videos.append({ + "vod_id": aid + '&live', + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + result['list'] = videos + result['page'] = 1 + result['pagecount'] = 1 + result['limit'] = 90 + result['total'] = 999999 + return result + + def categoryContent(self, tid, pg, filter, extend): + result = {} + if len(self.cookies) <= 0: + self.getCookie() + if tid.isdigit(): + parent_area_id = tid + area_id = 0 + if 'area_id' in extend: + area_id = extend['area_id'] + return self.get_live(pg=pg, parent_area_id=parent_area_id, area_id=area_id) + if tid == "推荐": + return self.get_recommend(pg) + if tid == "我的关注": + return self.get_fav(pg) + if tid == "观看记录": + return self.get_history() + return result + + def cleanSpace(self, str): + return str.replace('\n', '').replace('\t', '').replace('\r', '').replace(' ', '') + + def detailContent(self, array): + arrays = array[0].split("&") + aid = arrays[0] + url = "https://api.live.bilibili.com/room/v1/Room/get_info?room_id=%s" % aid + rsp = self.fetch(url, headers=self.header, cookies=self.cookies) + jRoot = json.loads(rsp.text) + if jRoot.get('code') == 0: + jo = jRoot['data'] + title = jo['title'].replace("", "").replace("", "") + pic = jo.get("user_cover") + desc = jo.get('description') + dire = self.get_live_userInfo(jo["uid"]) + typeName = jo.get("area_name") + live_status = str(jo.get('live_status')).replace("0", "未开播").replace("1", "").replace("2", "") + live_time = str(jo.get('live_time'))[5: 16] + remark = '在线人数:' + str(jo['online']).strip() + vod = { + "vod_id": aid, + "vod_name": title, + "vod_pic": pic, + "type_name": typeName, + "vod_year": "", + "vod_area": "bilidanmu", + "vod_remarks": remark, + "vod_actor": "主播:" + dire + "  " + "房间号:" + aid + "  " + live_status, + "vod_director": "关注:" + self.zh(jo.get('attention')) + "  " + "开播时间:" + live_time, + "vod_content": desc, + } + playUrl = 'flv线路原画$platform=web&quality=4_' + aid + '#flv线路高清$platform=web&quality=3_' + aid + '#h5线路原画$platform=h5&quality=4_' + aid + '#h5线路高清$platform=h5&quality=3_' + aid + + vod['vod_play_from'] = 'B站' + vod['vod_play_url'] = playUrl + result = { + 'list': [ + vod + ] + } + return result + + def searchContent(self, key, quick): + url = 'https://api.bilibili.com/x/web-interface/search/type?search_type=live&keyword={0}&page=1'.format(key) + if len(self.cookies) <= 0: + self.getCookie() + rsp = self.fetch(url, cookies=self.cookies, headers=self.header) + content = rsp.text + jo = json.loads(content) + if jo['code'] != 0: + rspRetry = self.fetch(url, cookies=self.cookies, headers=self.header) + content = rspRetry.text + jo = json.loads(content) + videos1 = [] + if jo['data']['pageinfo']['live_room']['numResults'] != 0: + vodList = jo['data']['result']['live_room'] + for vod in vodList: + aid = str(vod['roomid']).strip() + title = vod['title'].strip() + "⇦" + key + img = 'https:' + vod['user_cover'].strip() + remark = vod['watched_show']['text_small'].strip() + " " + vod['uname'].strip() + videos1.append({ + "vod_id": aid, + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + videos2 = [] + if jo['data']['pageinfo']['live_user']['numResults'] != 0: + vodList = jo['data']['result']['live_user'] + for vod in vodList: + aid = str(vod['roomid']).strip() + title = vod['uname'].strip().replace("", "").replace("", "") + "⇦" + key + img = 'https:' + vod['uface'].strip() + remark = str(vod['live_status']).replace("0", "未开播").replace("1", "") + " 关注:" + self.zh(vod['attentions']) + videos2.append({ + "vod_id": aid, + "vod_name": title, + "vod_pic": img, + "vod_remarks": remark + }) + videos = videos1 + videos2 + result = { + 'list': videos + } + return result + + def playerContent(self, flag, id, vipFlags): + result = {} + ids = id.split("_") + + url = 'https://api.live.bilibili.com/room/v1/Room/playUrl?cid=%s&%s' % (ids[1], ids[0]) + + # raise Exception(url) + if len(self.cookies) <= 0: + self.getCookie() + rsp = self.fetch(url, cookies=self.cookies) + jRoot = json.loads(rsp.text) + if jRoot['code'] == 0: + + jo = jRoot['data'] + ja = jo['durl'] + + url = '' + if len(ja) > 0: + url = ja[0]['url'] + + result["parse"] = 0 + # result['type'] ="m3u8" + result["playUrl"] = '' + result["url"] = url + result["header"] = { + "Referer": "https://live.bilibili.com", + "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' + } + + if "h5" in ids[0]: + result["contentType"] = '' + else: + result["contentType"] = 'video/x-flv' + return result + + config = { + "player": {}, + "filter": { + "1": [ + { + "key": "area_id", + "name": "全部分类", + "value": [ + { + "n": "舞见", + "v": "207" + }, + { + "n": "视频唱见", + "v": "21" + }, + { + "n": "萌宅领域", + "v": "530" + }, + + { + "n": "视频聊天", + "v": "145" + }, + + { + "n": "情感", + "v": "706" + }, + { + "n": "户外", + "v": "123" + }, + { + "n": "日常", + "v": "399" + }, + ] + }, + ], + "2": [ + { + "key": "area_id", + "name": "热门分类", + "value": [ + { + "n": "英雄联盟", + "v": "86" + }, + { + "n": "DOTA2", + "v": "92" + }, + { + "n": "CS:GO", + "v": "89" + }, + + { + "n": "APEX英雄", + "v": "240" + }, + + { + "n": "永劫无间", + "v": "666" + }, + { + "n": "穿越火线", + "v": "88" + }, + { + "n": "守望先锋", + "v": "87" + }, + ] + }, + ], + "3": [ + { + "key": "area_id", + "name": "热门分类", + "value": [ + { + "n": "王者荣耀", + "v": "35" + }, + { + "n": "和平精英", + "v": "256" + }, + { + "n": "LOL手游", + "v": "395" + }, + + { + "n": "原神", + "v": "321" + }, + + { + "n": "第五人格", + "v": "163" + }, + { + "n": "明日方舟", + "v": "255" + }, + { + "n": "哈利波特:魔法觉醒", + "v": "474" + }, + ] + }, + ], + "6": [ + { + "key": "area_id", + "name": "热门分类", + "value": [ + { + "n": "主机游戏", + "v": "236" + }, + { + "n": "战神", + "v": "579" + }, + { + "n": "我的世界", + "v": "216" + }, + + { + "n": "独立游戏", + "v": "283" + }, + + { + "n": "怀旧游戏", + "v": "237" + }, + { + "n": "大多数", + "v": "726" + }, + { + "n": "弹幕互动玩法", + "v": "460" + }, + ] + }, + ], + "5": [ + { + "key": "area_id", + "name": "全部分类", + "value": [ + { + "n": "唱见电台", + "v": "190" + }, + { + "n": "聊天电台", + "v": "192" + }, + { + "n": "配音", + "v": "193" + }, + ] + }, + ], + "9": [ + { + "key": "area_id", + "name": "全部分类", + "value": [ + { + "n": "虚拟主播", + "v": "371" + }, + { + "n": "3D虚拟主播", + "v": "697" + }, + ] + }, + ], + "10": [ + { + "key": "area_id", + "name": "全部分类", + "value": [ + { + "n": "生活分享", + "v": "646" + }, + { + "n": "运动", + "v": "628" + }, + { + "n": "搞笑", + "v": "624" + }, + + { + "n": "手工绘画", + "v": "627" + }, + + { + "n": "萌宠", + "v": "369" + }, + { + "n": "美食", + "v": "367" + }, + { + "n": "时尚", + "v": "378" + }, + { + "n": "影音馆", + "v": "33" + }, + ] + }, + ], + "11": [ + { + "key": "area_id", + "name": "全部分类", + "value": [ + { + "n": "社科法律心理", + "v": "376" + }, + { + "n": "人文历史", + "v": "702" + }, + { + "n": "校园学习", + "v": "372" + }, + + { + "n": "职场·技能", + "v": "377" + }, + + { + "n": "科技", + "v": "375" + }, + { + "n": "科学科普", + "v": "710" + }, + ] + }, + ], + "13": [ + { + "key": "area_id", + "name": "全部分类", + "value": [ + { + "n": "游戏赛事", + "v": "561" + }, + { + "n": "体育赛事", + "v": "562" + }, + { + "n": "赛事综合", + "v": "563" + }, + ] + }, + ], + } + } + header = { + "Referer": "https://www.bilibili.com", + "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' + } + + def localProxy(self, param): + + return [200, "video/MP2T", action, ""] -- GitLab