# -*- coding: utf-8 -*-
# @Time : 2020/12/2 19:00
# @Software : Sublime Text3
# @Author : 公众号 DGX杂学
import requests
import parsel
import re
from PyQt5.QtGui import QIcon
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
import os
from PyQt5.QtWidgets import *
import time
import threading
class Ui_MainWindow(QtWidgets.QMainWindow):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(710, 458)
MainWindow.setWindowIcon(QIcon('C:\\Users\\Administrator\\Desktop\\Python项目集\\3.0版本\\logo.ico'))#页面窗口左上角的图标,这里自定义图片路径
self.cwd = os.getcwd()
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
self.groupBox_2.setGeometry(QtCore.QRect(20, 60, 671, 141))
self.groupBox_2.setObjectName("groupBox_2")
self.label = QtWidgets.QLabel(self.groupBox_2)
self.label.setGeometry(QtCore.QRect(30, 30, 61, 16))
self.label.setObjectName("label")
self.lineEdit = QtWidgets.QLineEdit(self.groupBox_2)
self.lineEdit.setGeometry(QtCore.QRect(90, 30, 271, 20))
self.lineEdit.setObjectName("lineEdit")
self.groupBox = QtWidgets.QGroupBox(self.groupBox_2)
self.groupBox.setGeometry(QtCore.QRect(520, 30, 111, 61))
self.groupBox.setObjectName("groupBox")
self.comboBox = QtWidgets.QComboBox(self.groupBox)
self.comboBox.setGeometry(QtCore.QRect(20, 20, 69, 22))
self.comboBox.setObjectName("comboBox")
self.comboBox.addItem("1080p")
self.comboBox.addItem("720p")
self.comboBox.addItem("420p")
self.comboBox.addItem("360p")
self.comboBox.currentIndexChanged.connect(self.selectionchange)
self.label_2 = QtWidgets.QLabel(self.groupBox_2)
self.label_2.setGeometry(QtCore.QRect(10, 70, 81, 20))
self.label_2.setObjectName("label_2")
layout=QVBoxLayout()
self.btn1=QLabel('')
layout.addWidget(self.btn1)
self.fileT = QtWidgets.QLineEdit(self.centralwidget)
self.fileT.setGeometry(QtCore.QRect(109, 130, 272, 22))
self.fileT.setObjectName("file")
self.pushButton = QtWidgets.QPushButton(self.groupBox_2)
self.pushButton.setGeometry(QtCore.QRect(370, 70, 81, 21))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.groupBox_2)
self.pushButton_2.setGeometry(QtCore.QRect(370, 30, 81, 23))
self.pushButton_2.setStyleSheet("background-color: rgb(85, 255, 0);")
self.pushButton_2.setObjectName("pushButton_2")
self.groupBox_3 = QtWidgets.QGroupBox(self.centralwidget)
self.groupBox_3.setGeometry(QtCore.QRect(20, 210, 671, 71))
self.groupBox_3.setObjectName("groupBox_3")
#有textEdit这个键,但是没有显示在GUI页面(即隐藏了,这里主要起到全局传参的作用)
self.textEdit = QtWidgets.QTextEdit()
self.textEdit.setObjectName("textEdit")
self.textEdit_2 = QtWidgets.QTextEdit()
self.textEdit_2.setObjectName("textEdit_2")
self.progressBar = QtWidgets.QProgressBar(self.groupBox_3)
self.progressBar.setGeometry(QtCore.QRect(70, 20, 531, 16))
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
# self.label_3 = QtWidgets.QLabel(self.groupBox_3)
# self.label_3.setGeometry(QtCore.QRect(260, 40, 71, 20))
# self.label_3.setObjectName("label_3")
self.label_11 = QtWidgets.QLabel(self.centralwidget)
self.label_11.setGeometry(QtCore.QRect(300, 250, 71, 20))
self.label_11.setObjectName("label_11")
self.label_12 = QtWidgets.QLabel(self.centralwidget)
self.label_12.setGeometry(QtCore.QRect(250, 200, 71, 20))
self.label_12.setObjectName("label_12")
# self.label_12 = QtWidgets.QLabel(self.centralwidget)
# self.label_12.setObjectName("label_12")
self.groupBox_4 = QtWidgets.QGroupBox(self.centralwidget)
self.groupBox_4.setGeometry(QtCore.QRect(20, 300, 371, 101))
self.groupBox_4.setObjectName("groupBox_4")
self.label_4 = QtWidgets.QLabel(self.groupBox_4)
self.label_4.setGeometry(QtCore.QRect(20, 30, 331, 16))
self.label_4.setObjectName("label_4")
self.label_5 = QtWidgets.QLabel(self.groupBox_4)
self.label_5.setGeometry(QtCore.QRect(20, 50, 271, 16))
self.label_5.setObjectName("label_5")
self.groupBox_5 = QtWidgets.QGroupBox(self.centralwidget)
self.groupBox_5.setGeometry(QtCore.QRect(430, 300, 261, 101))
self.groupBox_5.setObjectName("groupBox_5")
self.label_6 = QtWidgets.QLabel(self.groupBox_5)
self.label_6.setGeometry(QtCore.QRect(20, 20, 61, 16))
self.label_6.setObjectName("label_6")
self.label_7 = QtWidgets.QLabel(self.groupBox_5)
self.label_7.setGeometry(QtCore.QRect(20, 40, 121, 16))
self.label_7.setObjectName("label_7")
self.label_8 = QtWidgets.QLabel(self.groupBox_5)
self.label_8.setGeometry(QtCore.QRect(20, 60, 81, 16))
self.label_8.setObjectName("label_8")
self.label_9 = QtWidgets.QLabel(self.groupBox_5)
self.label_9.setGeometry(QtCore.QRect(20, 80, 141, 16))
self.label_9.setObjectName("label_9")
self.label_10 = QtWidgets.QLabel(self.centralwidget)
self.label_10.setGeometry(QtCore.QRect(240, 20, 211, 41))
self.label_10.setObjectName("label_10")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 710, 23))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.pushButton_2.clicked.connect(self.download)
self.pushButton_2.clicked.connect(self.ProgressBar)
self.pushButton.clicked.connect(self.savepath)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def selectionchange(self):
#self.label_12.setText(self.comboBox.currentText())
if self.comboBox.currentText() == "1080p":
definition = "80"
self.textEdit_2.append(definition)
elif self.comboBox.currentText() == "720p":
definition = "64"
self.textEdit_2.append(definition)
elif self.comboBox.currentText() == "480p":
definition = "32"
self.textEdit_2.append(definition)
elif self.comboBox.currentText() == "360p":
definition = "16"
self.textEdit_2.append(definition)
def savepath(self):
fileName_choose, filetype = QFileDialog.getSaveFileName(self,
"文件保存",
self.cwd, # 起始路径 Mp4 Files (*.mp4)
"Mp4 Files (*.mp4);;FLV Files (*.flv)")
if fileName_choose == "":
return
self.fileT.setText(fileName_choose)
self.textEdit.append(fileName_choose)#这里主要是让download()调用这里的保存地址
#进度条目前是假的,即不管下载哪个视频,都是一样的;后期会完善这个问题
def ProgressBar(self):
def bar():
self.label_11.setText("下载中...")
ur3_1 = self.lineEdit.text()+'2'
ur3_2 = re.compile('/video/(.*?)2').findall(ur3_1) #这里可能有问题,加斜杠
ur3_3 = ur3_2[0] #获取bvid
ur3_5 = "https://api.bilibili.com/x/player/pagelist?bvid={}&jsonp=jsonp".format(ur3_3)
r = requests.get(ur3_5)
r.encoding="utf-8"
scid = str(r.text)
duration = re.compile('"duration":(.*?),"vid"').findall(scid) #获取cid
duration2 = int(duration[0])
#0.3M/s
mp_flux = duration2*0.3 #视频流量大小取整,这里是估计1080p视频大小
#估计视频下载速度为4m/s
numtime = int(mp_flux/0.3)
h=numtime//3600
m=(numtime-(h*3600))//60
s=numtime-(3600*h)-(60*m)
val = 0
for i in range(1,100):
val =val + 1
self.progressBar.setProperty("value",val)
time.sleep(numtime/99)
st = self.textEdit_2.toPlainText()
if st == "下载完成!":
self.progressBar.setProperty("value",100)
self.label_11.setText("下载完成!")
break
#self.label_12.setText("预计下载时间")
#time.sleep(5)
#self.label_12.setText("")
thread = threading.Thread(target=bar)
thread.start()
#这里设置子线程以减少主线程(即你看到的UI页面)的压力,防止页面假死(即“未响应”的字样)
def download(self):
#这里用到B站官方的两个API接口,本人通过Fiddler抓包工具获取到官方接口
self.label_11.setText("下载中...")
url_1 = self.lineEdit.text()+'2'
url_2 = re.compile('/video/(.*?)2').findall(url_1) #这里可能有问题,加斜杠
url_3 = url_2[0] #获取bvid
url_5 = "https://api.bilibili.com/x/player/pagelist?bvid={}&jsonp=jsonp".format(url_3)
r = requests.get(url_5)
r.encoding="utf-8"
scid = str(r.text)
cid = re.compile('"cid":(.*?),"page"').findall(scid) #获取cid
cid2 = str(cid[0])
url_4 = "https://api.bilibili.com/x/player/playurl?bvid={}&cid={}&fourk=1&qn={}&type=&otype=json&fnver=0".format(url_3,cid2,self.textEdit_2.toPlainText()) #清晰度暂时不设置
headers2 = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0",
"accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"accept-encoding":"gzip, deflate, br",
"accept-language":"zh-CN,zh;q=0.9",
"referer":"https://api.bilibili.com/",
"sec-ch-ua-mobile":"?0",
"sec-fetch-dest":"document",
"sec-fetch-mode":"navigate",
"sec-fetch-site":"cross-site",
"sec-fetch-user":"?1",
"upgrade-insecure-requests":"1",
"cookie":"_uuid=0204C263-C8A7-3E5A-37E0-5952386448CD00423infoc; buvid3=6411E1BB-31BD-44E0-80F0-45EE889CC85953929infoc; sid=kv3d3l2z; rpdid=|(k|k)mY~RJR0J'ulm|lYRlRk; LIVE_BUVID=AUTO5615922228199699; blackside_state=1; CURRENT_FNVAL=80; LNG=zh-CN; _ga=GA1.2.352663241.1602946601; CURRENT_QUALITY=80; DedeUserID=449154488; DedeUserID__ckMd5=1b8a0cef25efa62f; SESSDATA=5ca42809%2C1619341696%2Cfdbdd*a1; bili_jct=b0e59804d632d8c93a8a98d1dd9430d6; bp_video_offset_449154488=458577167186968738; bp_t_offset_449154488=458937875718173787; PVID=2; bfe_id=0c3a1998eda2972db3dbce4811a80de6"
}#加入cookie可以下载更高画质的视频,这里的cookie为本人的,你可以换成你自己的
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0",
"cookie":"_uuid=0204C263-C8A7-3E5A-37E0-5952386448CD00423infoc; buvid3=6411E1BB-31BD-44E0-80F0-45EE889CC85953929infoc; sid=kv3d3l2z; rpdid=|(k|k)mY~RJR0J'ulm|lYRlRk; LIVE_BUVID=AUTO5615922228199699; blackside_state=1; CURRENT_FNVAL=80; LNG=zh-CN; _ga=GA1.2.352663241.1602946601; CURRENT_QUALITY=80; DedeUserID=449154488; DedeUserID__ckMd5=1b8a0cef25efa62f; SESSDATA=5ca42809%2C1619341696%2Cfdbdd*a1; bili_jct=b0e59804d632d8c93a8a98d1dd9430d6; bp_video_offset_449154488=458577167186968738; bp_t_offset_449154488=458937875718173787; PVID=2; bfe_id=0c3a1998eda2972db3dbce4811a80de6"
}
#添加cookie可以下载1080p及更高的清晰度
get_url = requests.get(url_4,headers = headers)
get_url_2 = str(get_url.text)
get_url_3 = re.compile('"url":"(.*?)","backup_url"').findall(get_url_2)
URL = str(get_url_3[0])
URL2 = URL.replace("\\u0026","&")#把下载的url转化为json格式
def file():
r = requests.get(URL2,headers = headers2)
c = r.content
#变为byte流数据
#save_mov=open('{}'.format(self.savepath()),'wb')
f=open(self.textEdit.toPlainText(),'wb')
f.write(c)
f.close()
#self.progressBar.setProperty("value",100)
self.textEdit_2.append("下载完成!")
self.btn1.setText(self.textEdit.toPlainText())
thread = threading.Thread(target=file)
thread.start()
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "B站视频下载(DGX)"))
self.lineEdit.setPlaceholderText(_translate("MainWindow", "请输入视频的URL"))
self.groupBox_2.setTitle(_translate("MainWindow", "填写数据"))
self.fileT.setText(_translate("MainWindow", ""))
self.label.setText(_translate("MainWindow", "视频地址:"))
self.groupBox.setTitle(_translate("MainWindow", "清晰度"))
self.label_2.setText(_translate("MainWindow", "保存视频位置:"))
self.pushButton.setText(_translate("MainWindow", "选择保存路径"))
self.pushButton_2.setText(_translate("MainWindow", "点击下载视频"))
self.groupBox_3.setTitle(_translate("MainWindow", "运行状态"))
#self.label_3.setText(_translate("MainWindow", "下载进度..."))
self.groupBox_4.setTitle(_translate("MainWindow", "说明"))
self.label_4.setText(_translate("MainWindow", "1.软件暂时不支持下载视频选集,后期更新后会解决这个问题"))
self.label_5.setText(_translate("MainWindow", "2.此软件仅供学习和娱乐,禁止商用和非法用途!"))
self.groupBox_5.setTitle(_translate("MainWindow", "关于"))
self.label_6.setText(_translate("MainWindow", "作者:DGX"))
self.label_7.setText(_translate("MainWindow", "微信公众号:DGX杂学"))
self.label_8.setText(_translate("MainWindow", "B站:DGX杂学"))
self.label_9.setText(_translate("MainWindow", "开发时间:2020/11/19"))
self.label_10.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-size:26pt; font-weight:600;\">B站视频下载</span></p></body></html>"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())