吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4566|回复: 18
收起左侧

[Python 转载] 用pyQt5写个B站下载器

  [复制链接]
cjs25 发表于 2021-7-19 10:57
上回写个无损音乐下载器,由于没用线程池,所以一次下多了会卡,后来自己再改了下,用到线程池控制一次的线程数,好多了。代码就不再发上来了。这回B站的就试着用了下。论坛里别人也有下载器的软件,比我好多了,我是自己刚学的,代码传上来大伙帮着指点指点下了。
[Python] 纯文本查看 复制代码
from B站下载0710 import Ui_MainWindow
import sys
from lxml import html
etree=html.etree
import os
import re

import subprocess
from PyQt5 import QtCore
from PyQt5.QtCore import  pyqtSignal,QCoreApplication,QThreadPool,QRunnable,QObject
import requests
import json

import random
import webbrowser
from PyQt5.QtWidgets import QDesktopWidget, QApplication, QFileDialog, QMessageBox, QTableWidgetItem,QProgressBar
from PyQt5 import QtWidgets

def random_user():
    user1 = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
    user2 = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"
    user3 = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"
    user4 = "Mozilla/5.0 (Windows NT 6.1; rv,2.0.1) Gecko/20100101 Firefox/4.0.1"
    user5 = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)"
    user6 = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)"
    user7 = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"
    user8 = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)"
    user = [user1, user2, user3, user4, user5, user6, user7, user8]
    user = random.choice(user)
    return user
class Tasks(QObject):

    updata_data = pyqtSignal(list)
    updata_data2 = pyqtSignal(str,int)
class BackendThread(QRunnable):
    def __init__(self,url,video_name,count):
        super().__init__()
        self.signal = Tasks()

        self.url = url
        self.video_name=video_name
        self.count = count
    def down_file(self,url,filename,file_row,count):                #这个函数不知用协程会不会更快些
        header = {"User-Agent": random_user(), "referer": "https://message.bilibili.com/"}
        file_data = requests.get(url, headers=header, stream=True)
        filesize = int(file_data.headers['Content-Length'])

        offset = 0
        fileobj = open(filename, 'wb')
        if file_data.status_code == 200:

            for chunk in file_data.iter_content(chunk_size=204800):
                if not chunk:

                    break


                fileobj.seek(offset)

                fileobj.write(chunk)

                offset += len(chunk)
                proess = (offset / filesize) * 100

                self.signal.updata_data.emit([int(proess), file_row, count])

            fileobj.close()

    def run(self):


        self.signal.updata_data.emit([0,1,self.count])
        self.signal.updata_data.emit([0, 2, self.count])
        header={"User-Agent": random_user(),"referer":"https://message.bilibili.com/"}
        resonpe=requests.get(self.url,headers=header)

        json_data = re.findall(r'<script>window.__playinfo__=(.*?)</script>', resonpe.text)[0]
        json_data = json.loads(json_data)
        audio_url = json_data["data"]["dash"]["audio"][0]["backupUrl"][0]
        video_url = json_data["data"]["dash"]["video"][0]["backupUrl"][0]
        video_bakname=self.video_name+'bak.mp4'
        audio_bakname = self.video_name + 'bak.mp3'
        video_fulname=self.video_name+'.mp4'


        self.down_file(video_url,video_bakname,1,self.count)
        self.down_file(audio_url, audio_bakname, 2, self.count)
        self.signal.updata_data2.emit('开始合并',self.count)

        word=r'ffmpeg -i '+video_bakname+' -i '+audio_bakname+' -c:v copy -c:a aac -strict experimental  '+video_fulname
        subprocess.call(word,shell=True)
        self.signal.updata_data2.emit('合并成功', self.count)
        os.remove(video_bakname)
        os.remove(audio_bakname)

class firstfrom(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.pushButton.clicked.connect(self.page_find)
        self.ui.pushButton_5.clicked.connect(self.change_dir)
        self.ui.pushButton_4.clicked.connect(QCoreApplication.instance().quit)
        self.ui.pushButton_2.clicked.connect(self.start_find)
        self.ui.pushButton_3.clicked.connect(self.start_down)
        self.pool = QThreadPool()
        self.pool.globalInstance()
        self.pool.setMaxThreadCount(int(self.ui.comboBox.currentText()))
        self.ui.checkBox.clicked.connect(self.check)
        self.ui.pushButton_6.clicked.connect(self.opendir)
    def opendir(self):
        if not os.path.exists(self.ui.label_5.text()):
            os.mkdir(self.ui.label_5.text())
        if self.ui.label_5.text()=='./B站下载/':
            os.startfile(os.getcwd()+'/B站下载/')
        else:
            os.startfile(str(self.ui.label_5.text()))
    def check(self):
        if self.ui.tableWidget.rowCount() != 0:
            for i in range(0, self.ui.tableWidget.rowCount()):
                self.ui.tableWidget.item(i, 0).setCheckState(self.ui.checkBox.checkState())
    def start_down(self):  #开始下载的函数,用了线程池。可以控制同时下载几个
        self.pool.setMaxThreadCount(int(self.ui.comboBox.currentText()))

        if self.ui.tableWidget.rowCount() == 0:
            msg_box = QMessageBox(QMessageBox.Warning, '警告', '请先搜索歌曲!')
            msg_box.exec_()
        else:
            if not os.path.exists(self.ui.label_5.text()):
                os.mkdir(self.ui.label_5.text())
            row = self.ui.tableWidget.rowCount()

            for num in range(0, row):
                if self.ui.tableWidget.item(num, 0).checkState() == 2:
                    down_url=self.ui.lineEdit_2.text().split('?')[0]+'?p='+str(num+1)
                    print(down_url)
                    viedio_name=self.ui.label_5.text()+'/'+self.ui.tableWidget.item(num,0).text()
                    self.backend = BackendThread(down_url,viedio_name,num)
                    self.backend.signal.updata_data.connect(self.text_write)
                    self.backend.signal.updata_data2.connect(self.text_write2)
                    self.pool.start(self.backend)
                    QApplication.processEvents()
    def text_write2(self,word,cont):        #用一个字符串跟行数来表示音视频的合并状态
        new_item1 = QTableWidgetItem(word)
        new_item1.setTextAlignment(QtCore.Qt.AlignCenter)

        self.ui.tableWidget.setItem(cont, 3, QTableWidgetItem(new_item1))
    def text_write(self,word):                 #用一个列表来接收信息显示进度条状态,1值进度条值,2进度条的列数,3进度条的行
        if word[0]==0:

            banber=QProgressBar(self)
            self.ui.tableWidget.setCellWidget(word[2],word[1],banber)

        else:

            self.ui.tableWidget.cellWidget(word[2],word[1]).setValue(word[0])



    def start_find(self):                               #根据链接搜索
        if self.ui.lineEdit_2.text()=='':
            msg_box = QMessageBox(QMessageBox.Warning, '警告', '请先输入要解析的地址')
            msg_box.exec_()
        else:
            self.ui.tableWidget.clear()
            self.ui.tableWidget.setColumnCount(4)

            self.ui.tableWidget.setColumnWidth(0, 250)
            self.ui.tableWidget.setColumnWidth(1, 250)
            self.ui.tableWidget.setColumnWidth(2, 250)
            self.ui.tableWidget.setColumnWidth(3, 250)



            self.ui.tableWidget.setHorizontalHeaderLabels(['视频名', '视频下载状态', '音频下载状态', '音视合并状态'])
            page_url=self.ui.lineEdit_2.text().split('?')[0]

            header = {"User-Agent": random_user(),"referer":"https://message.bilibili.com/"}
            try:
                reponse = requests.get(page_url, headers=header)
                if reponse.status_code==200:

                    json_data = re.findall(r'"no_cache":false,"pages":(.*?),"subtitle"', reponse.text)[0]
                    json_data = json.loads(json_data)
                    self.ui.tableWidget.setRowCount(len(json_data))
                    for i in range(len(json_data)):
                       # page = json_data[i]["page"]
                        title1 = json_data[i]["part"]
                        pattern = re.compile(r"[\/\\\:\*\?\"\<\>\|\&\ \/]")
                        title = re.sub(pattern, "", title1)
                        new_item1 = QTableWidgetItem(title)
                        new_item1.setTextAlignment(QtCore.Qt.AlignCenter)

                        self.ui.tableWidget.setItem(i, 0, QTableWidgetItem(new_item1))
                        self.ui.tableWidget.item(i, 0).setCheckState(0)
                    QApplication.processEvents()
            except:
                msg_box = QMessageBox(QMessageBox.Warning, '警告', '请输入正确的网址!')
                msg_box.exec_()



    def page_find(self):                     #调用浏览器打开B站的关键词搜索结果网页
        if self.ui.lineEdit.text()!='':
            url ='https://search.bilibili.com/all?keyword='+self.ui.lineEdit.text()
        else:
            url='https://www.bilibili.com/'
        webbrowser.open(url, new=0, autoraise=True)
    def change_dir(self):
        dir_ = QFileDialog.getExistingDirectory(self, '选择文件夹', '/')
        if dir_ != '':
            self.ui.label_5.setText(dir_)
        else:
            self.ui.label_5.setText('./B站下载/')
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = firstfrom()
    screen = QDesktopWidget().screenGeometry()
    size = w.geometry()
    w.setWindowTitle('B站下载器')
    left = (screen.width() - size.width()) / 2
    hight = (screen.height() - size.height()) / 2
    w.move(left, hight)
    w.show()
    sys.exit(app.exec_())

下面这个是界面的代码
[Python] 纯文本查看 复制代码
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'B站下载0710.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1014, 671)

        MainWindow.setFixedSize(MainWindow.width(), MainWindow.height())
        MainWindow.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setGeometry(QtCore.QRect(690, 10, 91, 22))
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(530, 10, 161, 20))
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        self.label_4.setFont(font)
        self.label_4.setObjectName("label_4")
        self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
        self.checkBox.setGeometry(QtCore.QRect(840, 0, 171, 41))
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        self.checkBox.setFont(font)
        self.checkBox.setObjectName("checkBox")
        self.layoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.layoutWidget.setGeometry(QtCore.QRect(10, 0, 491, 71))
        self.layoutWidget.setObjectName("layoutWidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.layoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label = QtWidgets.QLabel(self.layoutWidget)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)
        self.lineEdit = QtWidgets.QLineEdit(self.layoutWidget)
        self.lineEdit.setObjectName("lineEdit")
        self.horizontalLayout.addWidget(self.lineEdit)
        self.pushButton = QtWidgets.QPushButton(self.layoutWidget)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        self.layoutWidget1 = QtWidgets.QWidget(self.centralwidget)
        self.layoutWidget1.setGeometry(QtCore.QRect(10, 70, 491, 61))
        self.layoutWidget1.setObjectName("layoutWidget1")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.layoutWidget1)
        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.label_2 = QtWidgets.QLabel(self.layoutWidget1)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout_2.addWidget(self.label_2)
        self.lineEdit_2 = QtWidgets.QLineEdit(self.layoutWidget1)
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.horizontalLayout_2.addWidget(self.lineEdit_2)
        self.pushButton_2 = QtWidgets.QPushButton(self.layoutWidget1)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        self.pushButton_2.setFont(font)
        self.pushButton_2.setObjectName("pushButton_2")
        self.horizontalLayout_2.addWidget(self.pushButton_2)
        self.pushButton_5 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_5.setGeometry(QtCore.QRect(530, 50, 171, 31))
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        self.pushButton_5.setFont(font)
        self.pushButton_5.setObjectName("pushButton_5")
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(750, 50, 231, 31))
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        self.label_5.setFont(font)
        self.label_5.setObjectName("label_5")
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setGeometry(QtCore.QRect(10, 140, 1000, 520))
        self.tableWidget.setMaximumSize(QtCore.QSize(1000, 520))
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)
        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(530, 80, 461, 51))
        self.widget.setObjectName("widget")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget)
        self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.pushButton_3 = QtWidgets.QPushButton(self.widget)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        self.pushButton_3.setFont(font)
        self.pushButton_3.setObjectName("pushButton_3")
        self.horizontalLayout_3.addWidget(self.pushButton_3)
        self.pushButton_6 = QtWidgets.QPushButton(self.widget)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        self.pushButton_6.setFont(font)
        self.pushButton_6.setObjectName("pushButton_6")
        self.horizontalLayout_3.addWidget(self.pushButton_6)
        self.pushButton_4 = QtWidgets.QPushButton(self.widget)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        self.pushButton_4.setFont(font)
        self.pushButton_4.setObjectName("pushButton_4")
        self.horizontalLayout_3.addWidget(self.pushButton_4)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.comboBox.setItemText(0, _translate("MainWindow", "5"))
        self.comboBox.setItemText(1, _translate("MainWindow", "6"))
        self.comboBox.setItemText(2, _translate("MainWindow", "7"))
        self.comboBox.setItemText(3, _translate("MainWindow", "8"))
        self.comboBox.setItemText(4, _translate("MainWindow", "9"))
        self.comboBox.setItemText(5, _translate("MainWindow", "10"))
        self.label_4.setText(_translate("MainWindow", "选择下载线程数"))
        self.checkBox.setText(_translate("MainWindow", "全选/全不选"))
        self.label.setText(_translate("MainWindow", "请输入要搜索的关键词"))
        self.pushButton.setText(_translate("MainWindow", "打开网站"))
        self.label_2.setText(_translate("MainWindow", "请复制要解析的地址"))
        self.pushButton_2.setText(_translate("MainWindow", "开始解析"))
        self.pushButton_5.setText(_translate("MainWindow", "请选择保存地址"))
        self.label_5.setText(_translate("MainWindow", "./B站下载/"))
        self.pushButton_3.setText(_translate("MainWindow", "开始下载"))
        self.pushButton_6.setText(_translate("MainWindow", "打开下载目录"))
        self.pushButton_4.setText(_translate("MainWindow", "退出程序"))

打包好程序链接在下面,ffmpeg跟主程序要放同一目录,音视频合并时要用到这个程序
链接:https://wws.lanzoui.com/iFXHyrlmq3e密码:3544

免费评分

参与人数 8吾爱币 +8 热心值 +4 收起 理由
zhaochun1219 + 1 用不了呀
angel_5173 + 1 用心讨论,共获提升!
l0rraine + 1 + 1 谢谢@Thanks!
18269055653 + 1 + 1 热心回复!
qq63 + 1 + 1 谢谢@Thanks!
GXW1693 + 1 热心回复!
江男 + 1 + 1 谢谢@Thanks!
谷小白 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

kk159 发表于 2021-7-19 12:33
random_user()很优秀,可以考虑下fake_useragent
asynico会不会比pool好呢?
楼上的伙伴的you-get确实神器,,
 楼主| cjs25 发表于 2021-7-19 12:44
kk159 发表于 2021-7-19 12:33
random_user()很优秀,可以考虑下fake_useragent
asynico会不会比pool好呢?
楼上的伙伴的you-get确实神 ...

谢谢了,没想到还有这个随机生成的库,以后看来就用这个了,you-get下载的这个库,我还不知道下载进度什么在界面上实时更新显示出来啊。我也是刚学的,第三方库知道的不多
江男 发表于 2021-7-19 11:20
MOEYU_VANILLA 发表于 2021-7-19 11:34
感谢分享
Loker 发表于 2021-7-19 11:42
截几个运行的图吧。。
三滑稽甲苯 发表于 2021-7-19 12:05
lz可以只做界面,下载的工作交给you-get
飘零星夜 发表于 2021-7-19 14:05
这个,我也在学python ,就是感觉,视频讲的都好简单,实战都好难
ofo 发表于 2021-7-19 15:47
很少见到PY写UI
 楼主| cjs25 发表于 2021-7-19 16:14
飘零星夜 发表于 2021-7-19 14:05
这个,我也在学python ,就是感觉,视频讲的都好简单,实战都好难

多实践啊,比如爬虫先找个简单的美女壁纸网来下,可以养颜,还能学东西,论坛里别人发的也多,可以参考学习啊。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 11:34

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表