如需快速使用,请直接前往:https://github.com/Rosyrain/BilibiliDownloadVedio
国内地址:BilibiliDownloadVedio: B站视频下载 (gitee.com)
直接点击releases进入进行下载(有配套使用教程,可跳过下面讲解)
如果有用请给仓库点个star~~
github下:
gitee下:
思路讲解:
1.使用前提(ffmpeg的下载)(ps;右键即可打开链接)
//可参考文献:(14条消息) Windows 10 安装 FFmpeg 并设置环境变量ffmpeg怎么设置Chanssl的博客-CSDN博客
①:找到FFmpeg的官网
②: 按下图所示点击
③: 寻找windows版本的下载,如下图(安装路径选择一个方便的如 C:/ ,后续需要用到)
④: 更改环境变量
找到之前安装ffmpeg的路径,输入进去,然后点击确定
先点击新建,然后将下图的文段输入进去(两条)
%FFMPEG_HOME%
%FFMPEG_HOME%\bin
更改环境变量成功后,一次点击确认即可
2.验证ffmpeg是否下载成功
①: win+R,cmd(win键就是形似
的按键),确定
②: 输入 ffmpeg -version
3.软件的使用
①:选择ffmpeg的路径(可手动输入也可点击按钮选择)
②:视频保存路径(选择文件夹,可手动输入,也可以按按钮选择)
③:输入视频网站(可手动复制,右边按钮可打开B站网页)
复制网址(快捷键ctrl+c复制,ctrl+v粘贴,也可右键)
粘贴至文本框中
④:视频昵称获取(可手动输入,也可以点击按钮自动获取标题,自动获取后可手动更改)
⑤:下载
点击确认后,开始下载
可以在后窗,即后台观察下载情况
如果出现下图情况,在黑窗下输入y,按下回车即可
⑥: 需要重复下载视频,重复③,④,⑤步骤即可(也可以根据②步骤更改视频的保存路径)
4.实现代码
GUI版本
#关于实现B站视频爬取功能实现利用到的库
import requests
import re
import json
import os
import time
from tqdm import tqdm
#关于功能GUI可视化用到的库
from tkinter import *
from tkinter.filedialog import *
from tkinter import messagebox
import webbrowser #用于打开网页
from tkinter import ttk #用于展示进度条
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.bgcolor = 'white'
self.fgcolor = 'black'
self.pack()
self.createWidget()
def createWidget(self):
#创建相应标签
self.label01 =Label(self,text = '文件ffmpeg的路径:',width=20,height=2,bg = self.bgcolor,fg = self.fgcolor,font = ('宋体',10))
self.label02 =Label(self,text = '视频保存路径:',width=20,height=2,bg = self.bgcolor,fg = self.fgcolor,font = ('宋体',10))
self.label03 =Label(self,text = '视频网址:',width=20,height=2,bg = self.bgcolor,fg = self.fgcolor,font = ('宋体',10))
self.label04 =Label(self,text = '视频昵称(可自动获取):',width=20,height=2,bg = self.bgcolor,fg = self.fgcolor,font = ('宋体',10))
self.label01.grid(row = 0,column=0,sticky= W)
self.label02.grid(row = 1,column=0,sticky= W)
self.label03.grid(row = 2,column=0,sticky= W)
self.label04.grid(row = 3,column=0,sticky= W)
#创建相应功能按钮
self.btn01 = Button(self,text = '选择路径',command = self.find_file01)
self.btn02 = Button(self,text = '选择路径',command = self.find_file02)
self.btn03 = Button(self,text = '打开bilibili网站',command = self.open_web)
self.btn04 = Button(self,text = '点击自动获取',command = self.find_names)
self.btn05 = Button(self,text = '开始下载',command = self.download)
self.progressone = ttk.Progressbar(self,name = '进度条',value = 0,mode='determinate', orient=HORIZONTAL)
self.btn01.grid(row = 0,column = 7,sticky=NSEW)
self.btn02.grid(row = 1,column = 7,sticky=NSEW)
self.btn03.grid(row = 2,column = 7,sticky=NSEW)
self.btn04.grid(row = 3,column = 7,sticky=NSEW)
self.btn05.grid(row = 4,column = 2,columnspan=3,sticky= NSEW)
self.progressone.grid(row = 5 ,column = 0,columnspan=8,sticky= NSEW )
#创建单行文本框
#1.创建变量并建立但文本行
self.ffmpeg_lujing = StringVar()
self.ffmpeg_lujing.set('请点击按钮选择ffmpeg.exe路径')
self.entry01 = Entry(self,textvariable=self.ffmpeg_lujing,width=40,exportselection=0,font = ('宋体',10))
self.keep_lujing = StringVar()
self.keep_lujing.set('请输入视频将保存的路径:')
self.entry02 = Entry(self,textvariable = self.keep_lujing,width=40,exportselection=0,font = ('宋体',10))
self.video_http = StringVar()
self.video_http.set('请输入视频地址,点击按钮打开B站')
self.entry03 = Entry(self,textvariable = self.video_http,width=40,exportselection=0,font = ('宋体',10))
self.video_names = StringVar()
self.video_names.set('可手动输入,也可以点击自动获取')
self.entry04 = Entry(self,textvariable= self.video_names,width=40,exportselection=0,font = ('宋体',10))
self.entry01.grid(row=0,column=1,columnspan=6)
self.entry02.grid(row=1,column=1,columnspan=6)
self.entry03.grid(row=2,column=1,columnspan=6)
self.entry04.grid(row=3,column=1,columnspan=6)
def find_file01(self): #实现选择ffmpeg.exe路径
filename = askopenfilename(filetypes = [('应用程序','.exe')])
self.ffmpeg_lujing.set(str(filename))
print('选择的ffmpeg的路径是: ',filename)
messagebox.askquestion('ffmpeg.exe路径','您选择的ffmpeg路径是: '+str(filename))
def find_file02(self): #实现选择保存路径
filename = askdirectory()
self.keep_lujing.set(str(filename))
print('选择的保存路径是: ',filename)
messagebox.askquestion('保存路径','您选择的保存路径是: '+str(filename))
def open_web(self): #实现打开bilibili网页
webbrowser.open('https://www.bilibili.com/')
def find_names(self): #实现自动获取视频名称
url = self.video_http.get()
print('获取视频昵称:'+str(url))
if url == '请输入视频地址,点击按钮打开B站' or url == '':
messagebox.showwarning('视频地址','您还未输入视频地址')
else :
name = 'none'
resp = requests.get(url)
page_content = resp.text
obj = re.compile(r'<title data-vue-meta="true">(?P<title>.*?)</title>', re.S)
result = obj.finditer(page_content)
for it in result:
name = it.group('title')
if name == 'none':
messagebox.showwarning('获取视频昵称','获取失败,请手动输入')
else:
self.video_names.set(name)
def download(self):
if self.ffmpeg_lujing.get() == '请点击按钮选择ffmpeg.exe路径' or self.ffmpeg_lujing.get() == '':
messagebox.showwarning('ffmpeg路径','您还未选择ffmpeg保存路径(PS:本程序需要下载ffmpeg)')
return
if self.keep_lujing.get() == '请输入视频将保存的路径:' or self.keep_lujing.get() == '':
messagebox.showwarning('保存路径','您还未选择视频需要保存的目录')
return
if self.video_http.get() == '请输入视频地址,点击按钮打开B站' or self.video_http.get() == '':
messagebox.showwarning('视频地址','您还输入B站视频地址')
return
if self.video_names.get() == '可手动输入,也可以点击自动获取' or self.video_names.get() == '':
messagebox.showwarning('视频地址','您还输入B站视频地址')
return
messagebox.showinfo('提示','此窗口可能会卡死,请勿关闭窗口,可在后台观察进度')
self.progressbar_start()
url = str(self.video_http.get())
_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76'
}
resp = requests.get(url, headers=_headers)
page_content = resp.text
obj = re.compile(r'<script>window.__playinfo__=(?P<data>.*?)</script>', re.S)
result = obj.finditer(page_content)
for it in result:
Data = it.group('data')
# print(Data)
data_json = json.loads(Data)
videosrcurl = data_json['data']['dash']['video'][0]['baseUrl']
audiosrcurl = data_json['data']['dash']['audio'][0]['baseUrl']
print('videosrcurl: '+str(videosrcurl))
print('audiosrcurl: '+str(audiosrcurl))
_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76',
'Referer': url
}
print('开始下载视频以及音频,请耐心等待')
video = requests.get(videosrcurl, headers=_headers, stream=True)
print('开始写入视频')
with open(self.keep_lujing.get() + '/video.mp4', mode='wb') as f:
for data in tqdm(video.iter_content(chunk_size=1024)):
f.write(data)
print('视频写入完成')
# print('休息5s')
# time.sleep(5)
audio = requests.get(audiosrcurl, headers=_headers, stream=True)
print('开始写入音频')
with open(self.keep_lujing.get() + '/audio.mp3', mode='wb') as f:
for data in tqdm(audio.iter_content(chunk_size=1024)):
f.write(data)
print('音频写入完成')
name = self.video_names.get()
print('开始合成最终视频')
# with open(self.keep_lujing.get() + f'/{name}.mp4', mode='wb') as f:
# 因为下文os.system写了合并后的文件,就不用提前创建了,提前创建的话,后面就需要在后台确认是否覆盖,不方便用户
Ffmpeg = self.ffmpeg_lujing.get().replace('.exe','')
os.system(
f'{Ffmpeg} -i {self.keep_lujing.get()}/video.mp4 -i {self.keep_lujing.get()}/audio.mp3 -acodec copy -vcodec copy {self.keep_lujing.get()}/"{name}".mp4')
print('合成成功!')
video.close()
audio.close()
os.remove(self.keep_lujing.get() + '/video.mp4')
os.remove(self.keep_lujing.get() + '/audio.mp3')
print('视频下载完成,请到文件夹中查询')
messagebox.showinfo('下载成功','视频下载完成,请到文件夹中查询')
self.progressbar_stop()
def progressbar_start(self):
self.progressone.start()
def progressbar_stop(self):
self.progressone.stop()
root = Tk()
root.geometry('600x200+500+200')
root.title('B站视频下载')
app = Application(master=root)
root.mainloop()
非GUI版本
实现爬取B站视频(非GUI版本)
def Name(url): # 获取视频的标题
name = 'none'
resp = requests.get(url)
page_content = resp.text
obj = re.compile(r'<title data-vue-meta="true">(?P<title>.*?)</title>', re.S)
result = obj.finditer(page_content)
for it in result:
name = it.group('title')
if name == 'none':
name = input('获取视频标题失败,请手动输入:')
return name
print('需要提前配置FFmpeg相关内容(可以参考此处:https://blog.csdn.net/pythonlaodi/article/details/109222790或者https://blog.csdn.net/Chanssl/article/details/83050959)')
print('配置完成后,在想要保存的磁盘中创建一个文件夹')
print('上述两步完成后,请重新打开此程序')
while True:
panduan = str(input('请确认上述两边是否完成(y/n): '))
if panduan == 'n' or panduan == 'N':
break
elif panduan == 'y' or panduan == 'Y':
while True:
ffmpeg_ = str(input('请输入您计算机中保存ffmpeg的路径(如C:/FFmpeg/bin)到bin即可 :'))
if os.path.exists(ffmpeg_):
while True:
dizhi = str(input("请输入视频想要保存到的文件夹路径(如E:/B站视频)(不是E:/B站视频/):"))
if os.path.exists(dizhi):
while True:
url = str(input('请输入B站视频地址: '))
_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76'
}
resp = requests.get(url,headers=_headers)
page_content = resp.text
#将页面源代码存入文件,方便后续的使用
# with open('B站页面源代码.html',mode='w',encoding = 'utf-8')as f:
# f.write(page_content)
obj = re.compile(r'<script>window.__playinfo__=(?P<data>.*?)</script>',re.S)
result = obj.finditer(page_content)
for it in result:
Data = it.group('data')
#print(Data)
data_json = json.loads(Data)
videosrcurl = data_json['data']['dash']['video'][0]['baseUrl']
audiosrcurl = data_json['data']['dash']['audio'][0]['baseUrl']
# print(videosrcurl)
# print(audiosrcurl)
_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76',
'Referer': url
}
print('开始下载视频以及音频,请耐心等待')
video = requests.get(videosrcurl,headers=_headers,stream = True)
print('开始写入视频')
with open(dizhi+'/video.mp4',mode = 'wb')as f:
for data in tqdm(video.iter_content(chunk_size=1024)):
f.write(data)
print('视频写入完成')
print('休息5s')
time.sleep(5)
audio = requests.get(audiosrcurl,headers=_headers,stream = True)
print('开始写入音频')
with open(dizhi+'/audio.mp3',mode = 'wb')as f:
for data in tqdm(audio.iter_content(chunk_size=1024)):
f.write(data)
print('音频写入完成')
name = Name(url)
print('开始合成最终视频')
with open(dizhi+f'/{name}.mp4',mode = 'wb')as f:
FFmpeg = ffmpeg_ + '/ffmpeg'
os.system(f'{FFmpeg} -i {dizhi}/video.mp4 -i {dizhi}/audio.mp3 -acodec copy -vcodec copy {dizhi}/"{name}".mp4')
print('合成成功!')
video.close()
audio.close()
os.remove(dizhi+'/video.mp4')
os.remove(dizhi+'/audio.mp3')
print('视频下载完成,请到文件夹中查询')
q = str(input('是否要继续下载视频y/n: '))
if q == 'y' or q == 'Y':
continue
else:
print('欢迎再次使用')
break
break
else:
print('您输入的文件夹路径不存在,请重新输入')
continue
break
else:
print('您输入的ffmpeg的路径不存在,请重新输入')
continue
break
else:
print('请重新输入')
continue
print('程序将在3分钟之后自动关闭,感谢使用')
time.sleep(180)
改进GUI版本窗口卡死的问题
参考文献:(14条消息) python tkinter界面卡死的解决办法_一颗小树x的博客-CSDN博客
tkinter界面卡死的解决办法 - 罗兵 - 博客园 (cnblogs.com)
说明
本文为个人学习记录笔记所用,如若侵权,请联系本人删文
本文章的所有内容仅供学习和参考之用,禁止用于商业用途。任何人或组织不得将本内容用于非法用途或侵犯他人合法权益。本仓库所涉及的爬虫技术仅用于学习和研究,不得用于对其他平台进行大规模爬虫或其他非法行为。对于因使用本仓库内容而引起的任何法律责任,本人不承担任何责任。使用本仓库的内容即表示您同意本免责声明的所有条款和条件。
有任何建议或其他需求可以私信我。
参考文献:(14条消息) Windows 10 安装 FFmpeg 并设置环境变量ffmpeg怎么设置Chanssl的博客-CSDN博客