当前位置:   article > 正文

小工具(for朗读软件) ,用python获取bilibili字幕,并清洗序号和时间戳_哔站字幕爬取

哔站字幕爬取

用python获取B站字幕

1、手动方法获取字幕


ubuntu 的浏览器

    1  F12,进入后台资源
    2  网络tab-标签栏
    3  另外的页面打开 io.json


windows 的chrome浏览器
    打开bilibili视频窗口
    检查,切换到网络
    不开字幕,清除所有文件,打开字幕(刷新页面?)

    新窗口中,打开体积较大的一个文件(文件类型排序,xlr文件中找到 .json 结尾的文件。属性是磁盘缓存)

2、自动方法获取字幕

先要准备视频号,在弹窗输入

  1. # from https://gitee.com/KGDKL/BiliCC-Srt/tree/master/Python
  2. # 使用代理软件时报错,例如连接 翻==墙 软件
  3. import gzip
  4. import requests
  5. import json
  6. import time
  7. import urllib
  8. txtCode = 'utf-8'
  9. he = {
  10. "Host": 'api.bilibili.com',
  11. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0',
  12. 'Accept': '*/*',
  13. 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
  14. 'Accept-Encoding': 'gzip,deflate',
  15. 'Connection': 'keep-alive',
  16. }
  17. def downAll(bv):
  18. '''
  19. 传入BV号,下载该BV号下的全部字幕
  20. '''
  21. videoList = getVideoList(bv)
  22. p = 1
  23. for i in videoList:
  24. cid = i['cid']
  25. downSolo(cid, bv, p, i['part']) # 下载该P视频的字幕,part是单P视频名。
  26. print ('【任务总进度:%s/%sP】\n'%(p,len(videoList)))
  27. p += 1
  28. print ('\n\n*** 任务完成 ***\n')
  29. def getVideoList(bv):
  30. '''
  31. 传入BV号,返回该BV号的视频列表
  32. '''
  33. url = 'https://api.bilibili.com/x/player/pagelist?bvid=%s' % bv # 创建URL
  34. response = requests.get(url,headers=he) # 获取Json
  35. videoList = json.loads(response.text)['data'] # Json转换
  36. print ('请求URL:', url)
  37. print ('视频目录获取成功!共%sP。\n'%len(videoList)) #汇报
  38. return videoList
  39. def downSolo(cid, bv, p, part=''):
  40. '''
  41. 根据cid,下载单P里的全部语言字幕
  42. '''
  43. url = 'https://api.bilibili.com/x/player/v2?bvid=%s&cid=%s'%(bv,cid)
  44. response = requests.get(url,headers=he)
  45. data = json.loads(response.text)
  46. subList = data['data']['subtitle']['subtitles'] # 字幕信息列表
  47. if len(subList) == 0:print('【警告】P%s无字幕!' % p)
  48. i = 1
  49. for d in subList:
  50. lan = d['lan'] # 字幕的语言编号(ZH JP EN之类)
  51. name = bv + ' - P' + str(p) + ':' + rep(part) + ' - ' + lan # 根据BV号、P数、语言,生成字幕文件名
  52. subUrl = 'http:' + d['subtitle_url'] # 字幕的URL
  53. # urllib.request.urlretrieve(subUrl,'%s.json' % name) # 下载json字幕文件
  54. response = urllib.request.urlopen(subUrl) # 不下载了,直接获取内容
  55. if response.info().get('Content-Encoding') == 'gzip': # 在响应头中获取编码格式
  56. j = gzip.decompress(response.read())
  57. else:
  58. j = response.read()
  59. jsonToSrt (name, j)
  60. print ('P%s 第%s种语言下载完成,进度:%s/%s'%(p,i,i,len(subList))) #报告任务进度(以该P视频的字幕语言数算)
  61. i += 1
  62. time.sleep(0.2)
  63. def jsonToSrt(fileName,j):
  64. '''
  65. 传入文件名和json字幕内容,将json输出为Srt字幕文件
  66. '''
  67. data = json.loads(j)['body']
  68. file = open('%s.srt'%fileName,'w',encoding=txtCode) # 创建srt字幕文件
  69. i = 1 # Srt字幕的序号计数器
  70. for d in data:
  71. f = round(d['from'],3) # 开始时间 (round(n,3)四舍五入为三位小数)
  72. t = round(d['to'],3) # 结束时间
  73. c = d['content'] # 字幕内容
  74. ff = time.strftime("%H:%M:%S",time.gmtime(f)) + ',' + miao(f) # 开始时间,秒数转 时:分:秒 格式,加逗号、毫秒修正为三位
  75. tt = time.strftime("%H:%M:%S",time.gmtime(t)) + ',' + miao(t) # 结束时间,处理方式同上
  76. srt = str(i) + '\n' + ff + ' ' + '-->' + ' ' + tt + '\n' + c + '\n\n' # 格式化为Srt字幕
  77. file.write(srt) # 写入文件
  78. i += 1 # 计数器+1
  79. file.close()
  80. print ('%s OK.' % fileName)
  81. li = [
  82. ['/','、'],
  83. ['\\','、'],
  84. ['|','、'],
  85. ['*','X'],
  86. [':',':'],
  87. ['?','?'],
  88. ['<','《'],
  89. ['>','》'],
  90. ['\"','“'],
  91. ['\"','”'],
  92. ]
  93. def rep(s=''):
  94. '''
  95. 根据列表li,去除特殊符号(不能用于文件名的)
  96. '''
  97. for i in li:
  98. s.replace(i[0],i[1])
  99. return s
  100. def miao(m):
  101. '''
  102. 修正毫秒为三位
  103. '''
  104. m = str(m).partition('.')[2] #取小数部分
  105. if len(m)==0:m = '000' #补齐三位小数
  106. if len(m)==1:m = m + '00'
  107. if len(m)==2:m = m + '0'
  108. return m #返回标准三位的毫秒数
  109. #########################################################
  110. import tkinter #载入模块
  111. import threading
  112. # BV1m3411P7TG gzip
  113. # BV13f4y1G7sA 无压缩
  114. # BV18a4y1H73s 很多P
  115. def xc():
  116. thread1 = threading.Thread(target=zzz) # 定义线程,运行抓取程序
  117. thread1.start() # 让线程开始工作
  118. def zzz():
  119. downAll(avID.get())
  120. # 单选按钮回调函数,就是当单选按钮被点击会执行该函数
  121. def radCall():
  122. radSel = radVar.get()
  123. if radSel == 1:
  124. txtCode = 'utf-8'
  125. print ('编码输出变更为:UTF-8')
  126. elif radSel == 2:
  127. txtCode = 'utf-16'
  128. print ('编码输出变更为:UTF-16')
  129. ### Tk GUI窗口 ###
  130. windowsInput = tkinter.Tk()
  131. windowsInput.title('BLIBILI CC字幕下载器 V4.1')
  132. windowsInput.geometry('400x220')
  133. group1 = tkinter.Frame(windowsInput) #第一节
  134. group2 = tkinter.Frame(windowsInput) #第二节
  135. group3 = tkinter.Frame(windowsInput) #第三节
  136. tag = tkinter.Label(windowsInput,text='BLIBILI CC字幕下载器 V4.1',width=20,height=2,font=("微软雅黑",22)) #标签
  137. tag.pack()
  138. group1.pack() #显示一二三节
  139. group2.pack()
  140. group3.pack()
  141. tkinter.Label(group1,text='目标BV号:',width=8,height=1,font=("微软雅黑",15)).pack(side='left') #标签
  142. avID = tkinter.Entry(group1) #AV号输入框
  143. avID.pack(side='right')
  144. radVar = tkinter.IntVar() # 通过tk.IntVar() 获取单选按钮value参数对应的值
  145. rad1 = tkinter.Radiobutton(group2,text='UTF-8 ',variable=radVar,value=1,command=radCall,font=("微软雅黑",15)) #单选框
  146. rad1.pack(side='left')
  147. rad2 = tkinter.Radiobutton(group2,text='UTF-16',variable=radVar,value=2,command=radCall,font=("微软雅黑",15))
  148. rad2.pack(side='right')
  149. button1 = tkinter.Button(group3,text='抓取',command=xc,width=15,height=1,font=("微软雅黑",18)) #按钮
  150. button1.pack(side='right')
  151. print ('### 编码默认输出:UTF-8。\n### 如果字幕乱码,可尝试选择UTF-16编码。\n')
  152. windowsInput.mainloop()

2.1  获取字幕后,清洗字幕,去除序号和时间戳。

下面的程序一次性将文件夹中的字幕.txt文件全部清洗,需要对下面程序中的地址做修改:

filenames=os.listdir(r'/home/x220/depthai-python/字幕到音频/trans')   ##存储原始字幕文件路径,绝对路径

inputfile = open('./trans/'+filename ,'r')  ##存储原始字幕文件路径,相对路径,与下面的程序保存地点有关

  1. # for ubuntu system
  2. import os # 文件夹、文件
  3. import re # 通配符搜索
  4. filenames=os.listdir(r'/home/x220/depthai-python/字幕到音频/trans')
  5. print(filenames)
  6. for filename in filenames:
  7. # 读取
  8. inputfile = open('./trans/'+filename ,'r')
  9. datalist=inputfile.readlines()
  10. print(inputfile) # 打印 <_io.TextIOWrapper name='test.txt' mode='r' encoding='UTF-8'>
  11. a = []
  12. # 将数据进行格式化处理
  13. for data in datalist:
  14. if re.search(r'\A\d*', data ).group() : # 如果是数字跳过此次循环
  15. continue
  16. a.append(data )
  17. testoutputfile = open(filename+'OutPut.txt' ,"w")
  18. testoutputfile.writelines(a)
  19. testoutputfile.close()
  20. inputfile.close()
  21. '''
  22. \d 的含义是 [0-9]
  23. \D 的含义是 [^0-9]
  24. \w 任何一个字母数字字符(大小写均可)或下划线,等价于 [A-Za-z0-9_]
  25. \W 表示[^A-Za-z0-9_]
  26. + 表示匹配一个或多个字符(至少一个,不匹配零个字符的情况)
  27. 邮箱中是允许出现下划线和 . 的
  28. * 表示含有零个或者多个指定的字符
  29. ? 表示匹配零个或者一个字符
  30. \A 只在字符串开始进行匹配
  31. \Z 只在字符串结尾进行匹配
  32. \b 匹配位于开始或结尾的空字符串
  33. \B 匹配不位于开始或结尾的空字符串
  34. \d 相当于[0-9]
  35. \D 相当于[^0-9]
  36. \s 匹配任意空白字符:[\t\n\r\r\v]
  37. \S 匹配任意非空白字符:[^\t\n\r\r\v]
  38. \w 匹配任意数字和字母:[a-zA-Z0-9]
  39. \W 匹配任意非数字和字母:[^a-zA-Z0-9]
  40. '''

  1. # for windows system ,jupyter lab
  2. import os # 文件夹、文件
  3. import re # 通配符搜索
  4. filenames=os.listdir(r'C:\Users\Administrator.ZX-202202281837\temp\trans')
  5. print(filenames)
  6. for filename in filenames:
  7. # 读取
  8. inputfile = open('C:\\Users\\Administrator.ZX-202202281837\\temp\\trans\\'+filename ,'r', encoding='utf-8-sig')
  9. #
  10. # debug <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< , UnicodeEncodeError: 'gbk' codec can't encode character '\ufeff' in position 0: illegal multibyte sequence
  11. # debug <<<<<<<<<<<<<<< encoding='utf-8-sig' 可以, encoding='utf-8-sig'
  12. # filename 无论是 srt. 还是txt 都行
  13. # debug <<<<<<<<<<<<<<<<<<<<<<<<<<<< SyntaxError: EOL while scanning string literal
  14. # 为何 字符串不能 以 \ (反斜杠) 结束 https://blog.csdn.net/u012065954/article/details/126641698
  15. datalist=inputfile.readlines()
  16. print(inputfile) # 打印 <_io.TextIOWrapper name='test.txt' mode='r' encoding='UTF-8'>
  17. a = []
  18. # 将数据进行格式化处理
  19. for data in datalist:
  20. if re.search(r'\A\d*', data ).group() : # 如果是数字跳过此次循环
  21. continue
  22. a.append(data )
  23. testoutputfile = open(filename+'OutPut.txt' ,"w")
  24. testoutputfile.writelines( a )
  25. testoutputfile.close()
  26. inputfile.close()

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/966989
推荐阅读
相关标签
  

闽ICP备14008679号