Skip to content

Commit 93eeffb

Browse files
authored
Merge pull request #17 from lifegpc/dev
v1.1.4 dev
2 parents 246e088 + d39e7e4 commit 93eeffb

8 files changed

Lines changed: 751 additions & 31 deletions

File tree

JSONParser.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,3 +322,34 @@ def getsmi(d:dict)->dict :
322322
r['name']=x['name']
323323
r['uid']=x['uid']
324324
return r
325+
def getlr1(d:dict) -> dict :
326+
"获取直播回放信息"
327+
r={}
328+
t=d['data']
329+
r['dm']=t['dm_info']
330+
t=t['live_record_info']
331+
r['rid']=t['rid']
332+
r['roomid']=t['room_id']
333+
r['uid']=t['uid']
334+
r['title']=t['title']
335+
r['areaid']=t['area_id']
336+
r['pareaid']=t['parent_area_id']
337+
r['st']=t['start_timestamp']
338+
r['et']=t['end_timestamp']
339+
r['online']=t['online']
340+
r['danmunum']=t['danmu_num']
341+
return r
342+
def getlr2(d:dict,r:dict) :
343+
"获得房间信息(可能与当前回放信息不同)"
344+
t=d['data']
345+
r['des']=t['description']
346+
r['arean']=t['area_name']
347+
r['parean']=t['parent_area_name']
348+
r['tags']=t['tags']
349+
r['hotwords']=t['hot_words']
350+
def getlr3(d:dict,r:dict):
351+
"获得UP主信息"
352+
t=d['data']
353+
r['name']=t['name']
354+
r['sex']=t['sex']
355+
r['sign']=t['sign']

PrintInfo.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1616
from time import localtime,strftime
1717
from biliTime import tostr2
18-
from bstr import gettags
18+
from bstr import gettags,rhtml
1919
def printInfo(data) :
2020
"输出普通AV号获取的信息"
2121
print("视频av号:"+str(data['aid']))
@@ -156,6 +156,20 @@ def printcho(cho) :
156156
for i in cho :
157157
print('%s,' %(i['titleFormat']),end='')
158158
print()
159+
def printlr(d:dict):
160+
print('直播回放id:%s'%(d['rid']))
161+
print('房间id:%s'%(d['roomid']))
162+
print('UP主:%s'%(d['name']))
163+
print('UP主UID:%s'%(d['uid']))
164+
print('UP主性别:%s'%(d['sex']))
165+
print('UP主个性签名:%s'%(d['sign']))
166+
print('直播名称:%s'%(d['title']))
167+
print('开始时间:%s'%(tostr2(d['st'])))
168+
print('结束时间:%s'%(tostr2(d['et'])))
169+
print('简介(去HTML化):%s'%(rhtml(d['des'])))
170+
print('区域:%s-%s'%(d['parean'],d['arean']))
171+
print('房间标签:%s'%(d['tags']))
172+
print('房间热词:%s'%(gettags(d['hotwords'])))
159173
def pr() :
160174
print(""" bili 版权所有 (C) 2019-2020 lifegpc
161175
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.

biliLiveDanmu.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# (C) 2019-2020 lifegpc
2+
# This file is part of bili.
3+
#
4+
# This program is free software: you can redistribute it and/or modify
5+
# it under the terms of the GNU General Public License as published by
6+
# the Free Software Foundation, either version 3 of the License, or
7+
# (at your option) any later version.
8+
#
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU General Public License
15+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
from requests import Session
17+
from JSONParser import getset
18+
from file import mkdir
19+
import os
20+
from biliDanmuXmlFilter import Filter
21+
from biliDanmuCreate import objtoxml
22+
import file
23+
def lrdownload(data:dict,r:Session,ip:dict,se:dict,xml,xmlc:list) :
24+
"""下载直播回放弹幕
25+
-1 文件夹创建失败
26+
-2 API解析失败
27+
-3 打开文件失败"""
28+
ns=True
29+
if 's' in ip :
30+
ns=False
31+
o="Download/"
32+
read=getset(se,'o')
33+
if read!=None :
34+
o=read
35+
if 'o' in ip:
36+
o=ip['o']
37+
try :
38+
if not os.path.exists(o) :
39+
mkdir(o)
40+
except :
41+
print("创建%s文件夹失败"%(o))
42+
return -1
43+
filen='%s%s.xml'%(o,file.filtern('%s(%s,%s)'%(data['title'],data['rid'],data['roomid'])))
44+
if os.path.exists(filen) :
45+
fg=False
46+
bs=True
47+
if not ns:
48+
fg=True
49+
bs=False
50+
if 'y' in ip :
51+
if ip['y'] :
52+
fg=True
53+
bs=False
54+
else :
55+
fg=False
56+
bs=False
57+
while bs:
58+
inp=input('"%s"文件已存在,是否覆盖?(y/n)'%(filen))
59+
if len(inp)>0 :
60+
if inp[0].lower()=='y' :
61+
fg=True
62+
bs=False
63+
elif inp[0].lower()=='n' :
64+
bs=False
65+
if fg:
66+
os.remove(filen)
67+
else :
68+
return 0
69+
dm=[]
70+
ot={'chatserver':'api.live.bilibili.com','chatid':data['rid'],'mission':0,'maxlimit':8000,'state':0,'real_name':0,'source':'k-v'}
71+
ot['list']=[]
72+
for i in data['dm']['index_info']:
73+
re=r.get('https://api.live.bilibili.com/xlive/web-room/v1/dM/getDMMsgByPlayBackID?rid=%s&index=%s'%(data['rid'],i['index']))
74+
re=re.json()
75+
if re['code']!=0 :
76+
print('%s %s'%(re['code'],re['message']))
77+
return -2
78+
for j in re['data']['dm']['dm_info'] :
79+
dm.append(j)
80+
if ns:
81+
print('解析完毕,共获得%s条弹幕。\n将转换格式为XML'%(len(dm)))
82+
for i in dm :
83+
t={}
84+
t['ti']='%.5f'%(i['ts']/1000)
85+
t['mod']=i['dm_mode']
86+
t['fs']=i['dm_fontsize']
87+
t['fc']=i['dm_color']
88+
t['ut']=round(i['check_info']['ts']/1000)
89+
t['dp']=i['dm_type']
90+
t['si']=i['user_hash']
91+
t['ri']=0
92+
t['t']=i['text']
93+
ot['list'].append(t)
94+
try :
95+
f=open(filen,mode='w',encoding='utf8')
96+
f.write('<?xml version="1.0" encoding="UTF-8"?>')
97+
f.write('<i><chatserver>%s</chatserver><chatid>%s</chatid><mission>%s</mission><maxlimit>%s</maxlimit><state>%s</state><real_name>%s</real_name><source>%s</source>' % (ot['chatserver'],ot['chatid'],ot['mission'],ot['maxlimit'],ot['state'],ot['real_name'],ot['source']))
98+
except:
99+
print('打开文件失败'+filen)
100+
return -3
101+
if xml==1 :
102+
l=0 #过滤数量
103+
z=len(dm) #总数量
104+
for i in ot['list'] :
105+
read=Filter(i,xmlc)
106+
if read :
107+
l=l+1
108+
else :
109+
try :
110+
f.write(objtoxml(i))
111+
except :
112+
print('保存文件失败'+filen)
113+
return -3
114+
if ns:
115+
print('共计过滤%s条' % (l))
116+
print('实际输出%s条' % (z-l))
117+
else :
118+
for i in ot['list'] :
119+
f.write(objtoxml(i))
120+
try :
121+
f.write('</i>')
122+
f.close()
123+
except :
124+
print('保存文件失败'+filen)
125+
return -3
126+
print('弹幕下载完毕!')
127+
return 0

bstr.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#
1414
# You should have received a copy of the GNU General Public License
1515
# along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
from re import search,I
17+
from html.parser import HTMLParser
1618
def f(i:str):
1719
s=i.replace('\r','\\r')
1820
s=s.replace('\n','\\n')
@@ -29,3 +31,30 @@ def gettags(t:list) -> str:
2931
else :
3032
s=s+","+i
3133
return s
34+
def rhtml(s:str)-> str:
35+
"去HTML化"
36+
r=s.replace('\n','')
37+
r=r.replace('<br>','\n')
38+
r=r.replace('<br/>','\n')
39+
r=r.replace('</p>','\n')
40+
t=search(r'<[^>]+>',r,I)
41+
while t!=None:
42+
t=t.span()
43+
if t[0]==0 :
44+
r=r[t[1]:]
45+
elif t[1]==len(s) :
46+
r=r[:t[0]]
47+
else :
48+
r=r[:t[0]]+r[t[1]:]
49+
t=search(r'<[^>]+>',r,I)
50+
r=HTMLParser().unescape(r)
51+
return r
52+
def getv(l:list) -> (list,list) :
53+
"""将合并在一起的画质id和画质描述分开
54+
返回值为id,画质描述"""
55+
q=[]
56+
d=[]
57+
for i in l:
58+
q.append(i['qn'])
59+
d.append(i['desc'])
60+
return q,d

command.py

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,27 @@
2121
def ph() :
2222
h='''命令行帮助:
2323
start.py -h/-?/--help 显示命令行帮助信息
24-
start.py [-i <输入>] [-d <下载方式>] [-p <p数>] [-m <boolean>] [--ac <boolean>] [--dm <boolean>] [--ad <boolean>] [-r <boolean>] [-y/-n] [--yf/--nf] [--mc avc/hev] [--ar/--nar] [--ax <number>] [--as <number>] [--ak <number>] [--ab/--nab] [--fa none/prealloc/trunc/falloc] [--sv <boolean>] [--ma <boolean>] [--ms <speed>] [--da <boolean>] [--httpproxy <URI>] [--httpsproxy <URI>] [--jt <number>|a|b] [--jts <date>] [-F] [-v <id>] [-a <id>] [-o <dir>] [--af/--naf] [--afp <序号>] [-s] [--slt/--nslt] [--te/--nte] [--bd/--nbd]
24+
start.py [-i <输入>] [-d <下载方式>] [-p <p数>] [-m <boolean>/--ym/--nm] [--ac <boolean>/--yac/--nac] [--dm <boolean>/--ydm/--ndm] [--ad <boolean>/--yad/--nad] [-r <boolean>/--yr/--nr] [-y/-n] [--yf/--nf] [--mc avc/hev] [--ar/--nar] [--ax <number>] [--as <number>] [--ak <number>] [--ab/--nab] [--fa none/prealloc/trunc/falloc] [--sv <boolean>/--ysv/--nsv] [--ma <boolean>/--yma/--nma] [--ms <speed>] [--da <boolean>/--yda/--nda] [--httpproxy <URI>] [--httpsproxy <URI>] [--jt <number>|a|b] [--jts <date>] [-F] [-v <id>] [-a <id>] [-o <dir>] [--af/--naf] [--afp <序号>] [-s] [--slt/--nslt] [--te/--nte] [--bd/--nbd] [--cad/--ncad] [--lrh/--nlrh] [--ahttpproxy <PROXY>] [--ahttpsproxy <PROXY>]
2525
start.py show c/w 显示许可证
2626
-i <输入> av/bv/ep/ss号或者视频链接
2727
-d <下载方式> 下载方式:1.当前弹幕2.全弹幕3.视频4.当前弹幕+视频5.全弹幕+视频6.仅字幕下载(番剧除外)
28+
直播回放下载方式:1.视频2.弹幕3.视频+弹幕
2829
-p <p数> 要下载的P数(两个p数可用,连接),使用a全选,输入为ep号时可用b选择该ep号,下载上次观看的视频可输入l(仅限番剧)
2930
-m <boolean> 是否默认下载最高画质
31+
--ym 相当于-m true
32+
--nm 相当于-m false
3033
--ac <boolean> 是否开启继续下载功能
34+
--yac 相当于--ac true
35+
--nac 相当于--ac false
3136
--dm <boolean> 是否启用弹幕过滤
37+
--ydm 相当于--dm true
38+
--ndm 相当于--dm false
3239
--ad <boolean> 是否在合并完成后删除文件
40+
--yad 相当于--ad true
41+
--nad 相当于--ad false
3342
-r <boolean> 是否在下载失败后重新下载
43+
--yr 相当于-r true
44+
--nr 相当于-r false
3445
-y 覆盖所有重复文件
3546
-n 不覆盖重复文件
3647
--yf 使用ffmpeg
@@ -45,9 +56,15 @@ def ph() :
4556
--nab 在使用aria2c下载时不使用备用网址
4657
--fa none/prealloc/trunc/falloc 在使用arai2c下载时预分配方式即--file-allocation的参数
4758
--sv <boolean> 文件名中是否输出视频画质信息
59+
--ysv 相当于--sv true
60+
--nsv 相当于--sv false
4861
--ma <boolean> 是否强制增加视频元数据(这会导致原本不需要转码的视频被转码,转码不会影响画质)
62+
--yma 相当于--ma true
63+
--nma 相当于--ma false
4964
--ms <speed> 在使用aria2c下载时最大总体速度,即--max-overall-download-limit的参数,默认单位为B,可以使用K和M为单位
5065
--da <boolean> 收藏夹是否自动下载每一个视频的所有分P
66+
--yda 相当于--da true
67+
--nda 相当于--da false
5168
--httpproxy <URI> 使用HTTP代理
5269
--httpsproxy <URI> 使用HTTPS代理
5370
--jt <number>|a|b 下载全弹幕时两次抓取之间的天数,范围为1-365,a会启用自动模式(推荐自动模式),番剧模式下b修改抓取起始日期
@@ -66,13 +83,19 @@ def ph() :
6683
--nte requests不使用环境变量中的代理设置
6784
--bd 合并完成后删除文件时保留字幕文件
6885
--nbd 合并完成后删除文件时删除字幕文件
86+
--cad 使用aria2c时关闭异步DNS(关闭后在Windows系统下可以解决Timeout while contacting DNS servers问题)
87+
--ncad 使用aria2c时启用异步DNS
88+
--lrh 直播回放简介写入元数据时进行去HTML化
89+
--nlrh 直播回放简介写入元数据时不进行去HTML化
90+
--ahttpproxy <PROXY> 指定aria2c使用的http代理,即aria2c的--http-proxy参数
91+
--ahttpsproxy <PROXY> 指定aria2c使用的https代理,即aria2c的--https-proxy参数
6992
注1:如出现相同的选项,只有第一个会生效
7093
注2:命令行参数的优先级高于settings.json里的设置
7194
注3:ffmpeg和aria2c需要自行下载并确保放入当前文件夹或者放入环境变量PATH指定的目录中
7295
注4:当下载收藏夹/频道,除了-i和-p参数外,其他参数将被沿用至收藏夹/频道视频的下载设置,-i和-p参数只对收藏夹/频道起作用'''
7396
print(h)
7497
def gopt(args,d:bool=False) :
75-
re=getopt(args,'h?i:d:p:m:r:ynFv:a:o:s',['help','ac=','dm=','ad=','yf','nf','mc=','ar','nar','ax=','as=','ak=','ab','nab','fa=','sv=','ma=','ms=','da=','httpproxy=','httpsproxy=','jt=','jts=','af','naf','afp=','slt','nslt','te','nte','bd','nbd'])
98+
re=getopt(args,'h?i:d:p:m:r:ynFv:a:o:s',['help','ac=','dm=','ad=','yf','nf','mc=','ar','nar','ax=','as=','ak=','ab','nab','fa=','sv=','ma=','ms=','da=','httpproxy=','httpsproxy=','jt=','jts=','af','naf','afp=','slt','nslt','te','nte','bd','nbd','cad','ncad','lrh','nlrh','ym','nm','yac','nac','ydm','ndm','yad','nad','yr','nr','ysv','nsv','yma','nma','yda','nda','ahttpproxy=','ahttpsproxy='])
7699
if d:
77100
print(re)
78101
rr=re[0]
@@ -92,26 +115,46 @@ def gopt(args,d:bool=False) :
92115
r['m']=True
93116
elif i[1].lower()=='false' :
94117
r['m']=False
118+
if i[0]=='--ym' and not 'm' in r:
119+
r['m']=True
120+
if i[0]=='--nm' and not 'm' in r:
121+
r['m']=False
95122
if i[0]=='--ac' and not 'ac' in r:
96123
if i[1].lower()=='true' :
97124
r['ac']=True
98125
elif i[1].lower()=='false' :
99126
r['ac']=False
127+
if i[0]=='--yac' and not 'ac' in r:
128+
r['ac']=True
129+
if i[0]=='--nac' and not 'ac' in r:
130+
r['ac']=False
100131
if i[0]=='--dm' and not 'dm' in r:
101132
if i[1].lower()=='true' :
102133
r['dm']=True
103134
elif i[1].lower()=='false' :
104135
r['dm']=False
136+
if i[0]=='--ydm' and not 'dm' in r:
137+
r['dm']=True
138+
if i[0]=='--ndm' and not 'dm' in r:
139+
r['dm']=False
105140
if i[0]=='--ad' and not 'ad' in r:
106141
if i[1].lower()=='true' :
107142
r['ad']=True
108143
elif i[1].lower()=='false' :
109144
r['ad']=False
145+
if i[0]=='--yad' and not 'ad' in r:
146+
r['ad']=True
147+
if i[0]=='--nad' and not 'ad' in r:
148+
r['ad']=False
110149
if i[0]=='-r' and not 'r' in r:
111150
if i[1].lower()=='true' :
112151
r['r']=True
113152
elif i[1].lower()=='false' :
114153
r['r']=False
154+
if i[0]=='--yr' and not 'r' in r:
155+
r['r']=True
156+
if i[0]=='--nr' and not 'r' in r:
157+
r['r']=False
115158
if i[0]=='-y' and not 'y' in r:
116159
r['y']=True
117160
if i[0]=='-n' and not 'y' in r:
@@ -156,11 +199,19 @@ def gopt(args,d:bool=False) :
156199
r['sv']=True
157200
elif i[1].lower()=='false' :
158201
r['sv']=False
202+
if i[0]=='--ysv' and not 'sv' in r:
203+
r['sv']=True
204+
if i[0]=='--nsv' and not 'sv' in r:
205+
r['sv']=False
159206
if i[0]=='--ma' and not 'ma' in r:
160207
if i[1].lower()=='true' :
161208
r['ma']=True
162209
elif i[1].lower()=='false' :
163210
r['ma']=False
211+
if i[0]=='--yma' and not 'ma' in r:
212+
r['ma']=True
213+
if i[0]=='--nma' and not 'ma' in r:
214+
r['ma']=False
164215
if i[0]=='--ms' and not 'ms' in r:
165216
t=search("^[0-9]+[MK]?$",i[1])
166217
if t!=None :
@@ -170,6 +221,10 @@ def gopt(args,d:bool=False) :
170221
r['da']=True
171222
elif i[1].lower()=='false' :
172223
r['da']=False
224+
if i[0]=='--yda' and not 'da' in r:
225+
r['da']=True
226+
if i[0]=='--nda' and not 'da' in r:
227+
r['da']=False
173228
if i[0]=='--httpproxy' and not 'httpproxy' in r:
174229
r['httpproxy']=i[1]
175230
if i[0]=='--httpsproxy' and not 'httpsproxy' in r:
@@ -212,6 +267,18 @@ def gopt(args,d:bool=False) :
212267
r['bd']=True
213268
if i[0]=='--nbd' and not 'bd' in r:
214269
r['bd']=False
270+
if i[0]=='--cad' and not 'cad' in r:
271+
r['cad']=True
272+
if i[0]=='--ncad' and not 'cad' in r:
273+
r['cad']=False
274+
if i[0]=='--lrh' and not 'lrh' in r:
275+
r['lrh']=True
276+
if i[0]=='--nlrh' and not 'lrh' in r:
277+
r['lrh']=False
278+
if i[0]=='--ahttpproxy' and not 'ahttpproxy' in r:
279+
r['ahttpproxy']=i[1]
280+
if i[0]=='--ahttpsproxy' and not 'ahttpsproxy' in r:
281+
r['ahttpsproxy']=i[1]
215282
for i in re[1] :
216283
if i.lower()=="show":
217284
prc()

0 commit comments

Comments
 (0)