Skip to content
This repository has been archived by the owner on Mar 8, 2023. It is now read-only.

extractors/bilibili: new api #90

Merged
merged 1 commit into from
Mar 15, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 35 additions & 37 deletions lulu/extractors/bilibili.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import hashlib
import urllib.parse
import urllib.request
from xml.dom.minidom import parseString

from lulu.common import (
match1,
Expand All @@ -29,16 +28,16 @@ class Bilibili(VideoExtractor):
name = '哔哩哔哩 bilibili.com'
live_api = 'https://live.bilibili.com/api/playurl?cid={}&otype=json'
api_url = 'https://interface.bilibili.com/v2/playurl?'
bangumi_api_url = 'https://bangumi.bilibili.com/player/web_api/playurl?'
bangumi_api_url = 'https://bangumi.bilibili.com/player/web_api/v2/playurl?'
live_room_init_api_url = (
'https://api.live.bilibili.com/room/v1/Room/room_init?id={}'
)
live_room_info_api_url = (
'https://api.live.bilibili.com/room/v1/Room/get_info?room_id={}'
)

SEC1 = '1c15888dc316e05a15fdd0a02ed6584f'
SEC2 = '9b288147e5474dd2aa67085f716c560d'
APPKEY = "84956560bc028eb7"
SECKEY = "94aba54af9065f71de72f5508f1cd42e"
stream_types = [
{'id': 'flv_p60'},
{'id': 'flv720_p60'},
Expand Down Expand Up @@ -75,46 +74,46 @@ def bilibili_stream_type(urls):
return 'mp4', 'mp4'
raise Exception('Unknown stream type')

def api_req(self, cid, quality, bangumi, bangumi_movie=False, **kwargs):
ts = str(int(time.time()))
if not bangumi:
params_str = 'cid={}&player=1&qn={}&quality={}&ts={}'.format(
cid, quality, quality, ts
def api_req(self, cid, quality, bangumi, **kwargs):
if bangumi:
api = self.bangumi_api_url
params_str = (
'appkey={}&cid={}&module=bangumi&otype=json&qn={}&quality={}'
'&season_type=4&type='.format(
self.APPKEY, cid, quality, quality
)
)
chksum = hashlib.md5(
bytes(params_str+self.SEC1, 'utf8')
).hexdigest()
api_url = self.api_url + params_str + '&sign=' + chksum
else:
mod = 'movie' if bangumi_movie else 'bangumi'
api = self.api_url
params_str = (
'cid={}&module={}&player=1&qn={}&quality={}&ts={}'.format(
cid, mod, quality, quality, ts
'appkey={}&cid={}&otype=json&qn={}&quality={}&type='.format(
self.APPKEY, cid, quality, quality
)
)
chksum = hashlib.md5(
bytes(params_str+self.SEC2, 'utf8')
).hexdigest()
api_url = self.bangumi_api_url + params_str + '&sign=' + chksum

xml_str = get_content(api_url, headers={
chksum = hashlib.md5(
bytes(params_str+self.SECKEY, 'utf8')
).hexdigest()
api_url = api + params_str + '&sign=' + chksum

# Add Referer to fix HTTP error code 403
# and User-Agent to fix HTTP error code 466
data = json.loads(get_content(api_url, headers={
'Referer': self.url,
'User-Agent': FAKE_HEADERS['User-Agent'],
})
return xml_str
}))
return data

def parse_bili_xml(self, xml_str):
def parse_bilibili_data(self, data):
# {'code': -404, 'message': '结果为空或者已被删除'}
if data.get('result') != 'suee':
return
urls_list = []
total_size = 0
doc = parseString(xml_str.encode('utf8'))
durls = doc.getElementsByTagName('durl')
for durl in durls:
size = durl.getElementsByTagName('size')[0]
total_size += int(size.firstChild.nodeValue)
url = durl.getElementsByTagName('url')[0]
urls_list.append(url.firstChild.nodeValue)
if not urls_list:
return
for durl in data['durl']:
size = durl['size']
total_size += int(size)
url = durl['url']
urls_list.append(url)
stream_type, container = self.bilibili_stream_type(urls_list)
if stream_type not in self.streams:
self.streams[stream_type] = {}
Expand All @@ -127,9 +126,8 @@ def download_by_vid(self, cid, bangumi, **kwargs):
# guard here. if stream_id invalid, fallback as not stream_id

info_only = kwargs.get('info_only')
for qlt in [116, 74, 80, 64, 32, 15]:
api_xml = self.api_req(cid, qlt, bangumi, **kwargs)
self.parse_bili_xml(api_xml)
for qlt in [116, 74, 112, 80, 64, 32, 15]:
self.parse_bilibili_data(self.api_req(cid, qlt, bangumi, **kwargs))
if not info_only or stream_id:
self.danmuku = get_danmuku_xml(cid)

Expand Down