PyQt5-B站视频下载器

*此程序仅为学习python所写。

程序功能:通过链接下载b站(www.bilibili.com)视频保存到本地指定目录。

一、PyQt设计界面

二、编写代码 

  • 下载按钮
res = requests.get(self.txtLink.text()) #获取网页数据
self.downloadProgress(1)
bf = BeautifulSoup(res.text,features = "html.parser")
fileName = bf.find_all("span",class_ = "tit") #提取视频标题
fileName = fileName[0].text.replace('\xa0'*8,'\n\n') #去除文字标签
for i in "/\\*:?<>|\"":
    fileName = fileName.replace(i,"") #去除标题中不能用作文件名的特殊字符

此部分代码用作获取目标视频的标题,作为保存至本地后的文件名。

这里关于Beautifulsoup4的用法参考:《基于Python3的网络爬虫脚本》 

bvid = self.txtLink.text()
bvid = bvid[bvid.find("BV"):len(bvid)] #获取视频BV号
url = "https://api.bilibili.com/x/player/pagelist?bvid=%s&jsonp=jsonp" % bvid
cid = str(requests.get(url,headers=headers).json()["data"][0]["cid"])
downloadUrl = "https://api.bilibili.com/x/player/playurl?cid=%s&bvid=%s&qn=64&type=&otype=json" % (cid,bvid)
contents = requests.get(downloadUrl).json()
dataUrl = contents["data"]["durl"][0]["url"]
dataSize = contents["data"]["durl"][0]["size"]
flv_host = re.findall("https://(.*)com",dataUrl,re.I)
head["Host"] = flv_host[0] + "com"
head["Range"] = "bytes=0-%s" % dataSize

此部分代码用于获取视频下载链接。由于b站视频不能直接获取下载链接,这里参考 https://www.bilibili.com/read/cv9898845 的方法获取视频下载链接。 

这里我使用find()方法和[ : ]运算符提取链接中视频BV号。

res = requests.get(dataUrl, headers=head, stream=True, verify=False)
chunk_size = 1024
count = 1
f = open(self.txtFileSaveAdd.text() + "/" + fileName + ".flv","wb") #下载视频
for i in res.iter_content(chunk_size):
    f.write(i)
    self.downloadProgress(int((count/(dataSize/chunk_size))*100)+1)
    count += 1
f.close()
self.downloadProgress(100)

此部分代码用于下载视频,通过open()在指定的目录下创建以视频标题命名的文件,每次写入1024字节数据来逐步下载视频,并通过进度条实时更新下载进度。

整段下载程序可用try...except进行异常的处理,比如当下载链接或保存地址未填写时,下载状态显示对应提示。

  • 清空按钮
def init(self): 
        self.txtFileSaveAdd.setText("")
        self.txtLink.setText("")
        self.progressBar.setValue(0)
        self.labState.setText("准备下载。")

此段程序用于在点击清空按钮后,所有控件恢复到程序初始状态,方便下一次下载。

  • 选择目录按钮 
def getFileAdd(self): 
        self.txtFileSaveAdd.setText(QFileDialog.getExistingDirectory())

此段程序用于点击“…”按钮后,弹出选择目标文件夹的窗口,然后将目标路径存入地址文本框。 

  • 下载状态与进度条 
def downloadProgress (self,progress): 
        if progress < 100: 
            self.labState.setText("Downloading...")
        elif progress == 100:
            self.labState.setText("下载完成!")
        self.progressBar.setValue(progress)

此段程序用于同步下载状态与进度条。 

三、完整代码 

import re
import sys
import requests
from PyQt5 import QtCore, QtGui, QtWidgets
from bs4 import BeautifulSoup  
from PyQt5.QtWidgets import QFileDialog
from Ui_MainWindow import Ui_MainWindow
requests.packages.urllib3.disable_warnings()

class CMainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent = None):
        super(CMainWindow, self).__init__(parent)
        self.setupUi(self)

        # 主窗体设置
        self.show()

    def download(self): #下载
        headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36 SLBrowser/7.0.0.4071 SLBChan/21'}
        head = {
            "Host" : "",
            "Range":"",
            "Origin":"https://www.bilibili.com/",
            "Referer":"https://www.bilibili.com/",
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36 SLBrowser/7.0.0.4071 SLBChan/21'
        }
        try:
            #### 获取视频标题 ####
            res = requests.get(self.txtLink.text()) #获取网页数据
            self.downloadProgress(1) #启动进度条 提示爬虫开始运行
            bf = BeautifulSoup(res.text,features = "html.parser")
            fileName = bf.find_all("span",class_ = "tit") #提取视频标题
            fileName = fileName[0].text.replace('\xa0'*8,'\n\n') #去除标签
            for i in "/\\*:?<>|\"":
               fileName = fileName.replace(i,"") #去除标题中不能用作文件名的特殊字符

            #### 获取下载链接 ####      --参考https://www.bilibili.com/read/cv9898845
            bvid = self.txtLink.text()
            bvid = bvid[bvid.find("BV"):len(bvid)] #获取视频BV号
            url = "https://api.bilibili.com/x/player/pagelist?bvid=%s&jsonp=jsonp" % bvid
            cid = str(requests.get(url,headers=headers).json()["data"][0]["cid"])
            downloadUrl = "https://api.bilibili.com/x/player/playurl?cid=%s&bvid=%s&qn=64&type=&otype=json" % (cid,bvid)
            contents = requests.get(downloadUrl).json()
            dataUrl = contents["data"]["durl"][0]["url"]
            dataSize = contents["data"]["durl"][0]["size"]
            flv_host = re.findall("https://(.*)com",dataUrl,re.I)
            head["Host"] = flv_host[0] + "com"
            head["Range"] = "bytes=0-%s" % dataSize

            #### 下载视频 ####
            res = requests.get(dataUrl, headers=head, stream=True, verify=False)
            chunk_size = 1024
            count = 1
            f = open(self.txtFileSaveAdd.text() + "/" + fileName + ".flv","wb") #下载视频到指定目录
            for i in res.iter_content(chunk_size):
                f.write(i) 
                self.downloadProgress(int((count/(dataSize/chunk_size))*100)+1)
                count += 1
            f.close()
            self.downloadProgress(100)
            
        #异常处理
        except requests.exceptions.MissingSchema: 
            self.labState.setText("无效的下载连接!")
            self.progressBar.setValue(0)
        except (FileNotFoundError,PermissionError): 
            self.labState.setText("无效的保存目录!")
            self.progressBar.setValue(0)
        except: 
            self.labState.setText("未知错误!")
            self.progressBar.setValue(0)

    def init(self): #清空文本框
        self.txtFileSaveAdd.setText("")
        self.txtLink.setText("")
        self.progressBar.setValue(0)
        self.labState.setText("准备下载。")

    def getFileAdd(self): #获取保存路径
        self.txtFileSaveAdd.setText(QFileDialog.getExistingDirectory())

    def downloadProgress (self,progress): #同步下载状态与进度条
        if progress < 100: 
            self.labState.setText("Downloading...")
        elif progress == 100:
            self.labState.setText("下载完成!")
        self.progressBar.setValue(progress) 

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = CMainWindow()
    sys.exit(app.exec_())

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值