forked from GJCav/bilibiliDanmaku
/
danmaku.py
146 lines (122 loc) · 3.9 KB
/
danmaku.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import re as Regex
import requests as Request
import json as Json
import xml.etree.cElementTree as ET
import time as Time
__all__ = ['danmaku', 'danmakuParser']
# def getCookies():
# jsonStr = '';
# with open('bilibili.cookie', encoding='utf-8') as file:
# jsonStr = file.read()
# json = Json.loads(jsonStr, encoding='utf-8')
# global cookies
# for obj in json:
# cookies[obj['name']] = obj['value']
# getCookies()
bilibiliHeaders = {
'user-agent': 'fiddler',
'host': 'www.bilibili.com',
'accept-encoding': 'gzip, deflate, sdch'
}
bangumiHeaders = {
'user-agent': 'fiddler',
'host': 'bangumi.bilibili.com',
'accept-encoding': 'gzip, deflate, sdch'
}
danmakuHeaders = {
'host':'comment.bilibili.com',
'user-agent':'fiddler',
'origin':'https://www.bilibili.com',
'accept-encoding':'gzip, deflate, sdch'
}
def downloadDanmaku(cid:str) -> str:
"""
Download danmaku from cid
:param cid: str
:return: str
"""
url = 'https://comment.bilibili.com/%s.xml' % cid
r = Request.get(url, headers=danmakuHeaders)
return r.text
def fromBilibiliWebsite(url:str, cookies:dict = {}) -> str:
"""
Search cid from urls like "https://www.bilibili.com/video/"
:param url: str
:return: str
"""
r = Request.get(url, headers = bilibiliHeaders, cookies=cookies)
if not r.status_code == 200:
return None
groups = Regex.findall(r'.+?#page=(\d+)', url)
if not groups:
result = Regex.findall(r'cid=(.+?)&aid=', r.text)
if result:
return downloadDanmaku(result[0])
else:
page = int(groups[0])
groups = Regex.findall(r'cid=(.+?)&aid=', r.text)
if groups:
firstPageCid = int(groups[0])
curPageCid = str(firstPageCid + page - 1)
return downloadDanmaku(curPageCid)
def fromBangumiWebsite(url:str, cookies:dict = {}) -> str:
"""
Search cid from urls like "https://bangumi.bilibili.com/anime/{id}/play#{eid}".
:param url:
:return: str
"""
result = Regex.findall(r'play#(.+)', url)
if not result:
return None
eid = result[0]
infurl = 'https://bangumi.bilibili.com/web_api/episode/%s.json' % eid
r = Request.get(infurl, headers=bangumiHeaders, cookies=cookies)
json = Json.loads(r.text)
cid = json['result']['currentEpisode']['danmaku']
return downloadDanmaku(cid)
def danmaku(url:str, cookies:dict = {}) -> str:
"""
Download danmaku by giving url according to video you want.
This method will return str in xml format
:param url:
:return: str
"""
if url.find('//bangumi.bilibili.com/') != -1:
return fromBangumiWebsite(url, cookies)
elif url.find('//www.bilibili.com/') != -1:
return fromBilibiliWebsite(url, cookies)
def danmakuParser(xml:str) -> list:
"""
Parse xml from method `danmaku`.
The map in the returned list will contain keys,
which are "msg", "type", "fontsize", "color",
"date", "rawdate","pool", "userid" and "danmakuid" .
Especially, "userid" is special.
:param xml: str
:return: list
"""
tree = ET.fromstringlist(xml)
danmakulist = []
for tag in tree:
if tag.tag == 'd':
info = {}
info['msg'] = tag.text
params = tag.get('p').split(',')
info['time'] = float(params[0])
info['type'] = int(params[1])
info['fontsize'] = int(params[2])
info['color'] = hex(int(params[3]))
info['date'] = Time.strftime(
'%Y-%m-%d %H:%M:%S',
Time.localtime(
int(params[4])
)
)
info['timestamp'] = int(params[4])
info['pool'] = params[5]
info['userid'] = params[6]
info['danmuid'] = params[7]
danmakulist.append(info)
return danmakulist
if __name__ == '__main__':
pass