zoukankan      html  css  js  c++  java
  • 第十八篇 -- QTreeWidget应用篇 -- kuwo

    效果图:

    最近学习QTreeWidget,总想着做些什么,正好学习过一点简单的爬虫,就做了一个简易的“酷我音乐下载器”,界面可能不太好看,以后继续优化。

     ui_kuwo.py

    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'ui_kuwo.ui'
    #
    # Created by: PyQt5 UI code generator 5.13.0
    #
    # WARNING! All changes made in this file will be lost!
    
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.resize(800, 624)
            font = QtGui.QFont()
            font.setPointSize(10)
            MainWindow.setFont(font)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
            self.lineEdit.setGeometry(QtCore.QRect(60, 20, 681, 41))
            font = QtGui.QFont()
            font.setPointSize(12)
            self.lineEdit.setFont(font)
            self.lineEdit.setStyleSheet("border:2px groove gray;border-radius:10px;padding:2px 4px")
            self.lineEdit.setInputMask("")
            self.lineEdit.setText("")
            self.lineEdit.setObjectName("lineEdit")
            self.treeWidget = QtWidgets.QTreeWidget(self.centralwidget)
            self.treeWidget.setGeometry(QtCore.QRect(60, 110, 681, 411))
            self.treeWidget.setObjectName("treeWidget")
            self.treeWidget.headerItem().setTextAlignment(0, QtCore.Qt.AlignCenter)
            font = QtGui.QFont()
            font.setPointSize(10)
            font.setBold(True)
            font.setWeight(75)
            self.treeWidget.headerItem().setFont(0, font)
            self.treeWidget.headerItem().setTextAlignment(1, QtCore.Qt.AlignCenter)
            font = QtGui.QFont()
            font.setPointSize(10)
            font.setBold(True)
            font.setWeight(75)
            self.treeWidget.headerItem().setFont(1, font)
            self.treeWidget.headerItem().setTextAlignment(2, QtCore.Qt.AlignCenter)
            font = QtGui.QFont()
            font.setPointSize(10)
            font.setBold(True)
            font.setWeight(75)
            self.treeWidget.headerItem().setFont(2, font)
            self.treeWidget.headerItem().setTextAlignment(3, QtCore.Qt.AlignCenter)
            font = QtGui.QFont()
            font.setPointSize(10)
            font.setBold(True)
            font.setWeight(75)
            self.treeWidget.headerItem().setFont(3, font)
            self.treeWidget.headerItem().setTextAlignment(4, QtCore.Qt.AlignCenter)
            font = QtGui.QFont()
            font.setPointSize(10)
            font.setBold(True)
            font.setWeight(75)
            self.treeWidget.headerItem().setFont(4, font)
            self.treeWidget.header().setDefaultSectionSize(130)
            self.btnSel_ALL = QtWidgets.QPushButton(self.centralwidget)
            self.btnSel_ALL.setGeometry(QtCore.QRect(210, 80, 75, 23))
            self.btnSel_ALL.setObjectName("btnSel_ALL")
            self.btnSel_None = QtWidgets.QPushButton(self.centralwidget)
            self.btnSel_None.setGeometry(QtCore.QRect(340, 80, 75, 23))
            self.btnSel_None.setObjectName("btnSel_None")
            self.btnSel_Invs = QtWidgets.QPushButton(self.centralwidget)
            self.btnSel_Invs.setGeometry(QtCore.QRect(470, 80, 75, 23))
            self.btnSel_Invs.setObjectName("btnSel_Invs")
            self.label = QtWidgets.QLabel(self.centralwidget)
            self.label.setGeometry(QtCore.QRect(60, 530, 681, 16))
            self.label.setText("")
            self.label.setObjectName("label")
            MainWindow.setCentralWidget(self.centralwidget)
            self.menubar = QtWidgets.QMenuBar(MainWindow)
            self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
            self.menubar.setObjectName("menubar")
            MainWindow.setMenuBar(self.menubar)
            self.toolBar = QtWidgets.QToolBar(MainWindow)
            self.toolBar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
            self.toolBar.setObjectName("toolBar")
            MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
            self.actSong_Download = QtWidgets.QAction(MainWindow)
            icon = QtGui.QIcon()
            icon.addPixmap(QtGui.QPixmap("Image/icon/download.jpg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actSong_Download.setIcon(icon)
            self.actSong_Download.setObjectName("actSong_Download")
            self.actSong_Search = QtWidgets.QAction(MainWindow)
            icon1 = QtGui.QIcon()
            icon1.addPixmap(QtGui.QPixmap("Image/icon/search.jpg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actSong_Search.setIcon(icon1)
            self.actSong_Search.setObjectName("actSong_Search")
            self.toolBar.addAction(self.actSong_Download)
    
            self.retranslateUi(MainWindow)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "酷我音乐下载器"))
            self.lineEdit.setPlaceholderText(_translate("MainWindow", "请输入歌手名/歌曲名"))
            self.treeWidget.headerItem().setText(0, _translate("MainWindow", "序号"))
            self.treeWidget.headerItem().setText(1, _translate("MainWindow", "歌曲"))
            self.treeWidget.headerItem().setText(2, _translate("MainWindow", "歌手"))
            self.treeWidget.headerItem().setText(3, _translate("MainWindow", "专辑"))
            self.treeWidget.headerItem().setText(4, _translate("MainWindow", "时长"))
            self.btnSel_ALL.setText(_translate("MainWindow", "全选"))
            self.btnSel_None.setText(_translate("MainWindow", "全不选"))
            self.btnSel_Invs.setText(_translate("MainWindow", "反选"))
            self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))
            self.actSong_Download.setText(_translate("MainWindow", "下载歌曲"))
            self.actSong_Download.setToolTip(_translate("MainWindow", "下载歌曲"))
            self.actSong_Search.setText(_translate("MainWindow", "搜索"))
            self.actSong_Search.setToolTip(_translate("MainWindow", "搜索"))
    View Code

    myMainWindow_kuwo.py

    #!/usr/bin/env python
    # _*_ coding: UTF-8 _*_
    """=================================================
    @Project -> File    : Operate-system -> myMainWindow_kuwo_download.py
    @IDE     : PyCharm
    @Author  : zihan
    @Date    : 2020/4/21 10:26
    @Desc    :
    ================================================="""
    
    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow, QTreeWidgetItem, QLineEdit
    from enum import Enum
    from PyQt5.QtCore import Qt, QThread, pyqtSignal
    from ui_kuwo import Ui_MainWindow
    import requests
    import os
    
    
    def create_folder(path):
        if os.path.exists(path):
            pass
        else:
            os.mkdir(path)
    
    
    # 节点类型的枚举类型
    class TreeItemType(Enum):
        itTopItem = 1001  # 顶层节点
        itGroupItem = 1002  # 分组节点
        itImageItem = 1003  # 图片文件节点
    
    
    class TreeColNum(Enum):  # 目录树的列号的枚举类型
        col_order = 0  # 序号列
        col_song_name = 1   # 歌曲名列
        col_singer_name = 2  # 歌手列
        col_singer_album = 3  # 专辑列
        col_song_time = 4  # 时长列
        col_song_rid = 5  # rid
    
    
    class SongDownload(QThread):
        label_str = pyqtSignal(str)
    
        def __init__(self, path, song_url, song_name):
            super(SongDownload, self).__init__()
            self.__path = path
            self.__url = song_url
            self.__songname = song_name
    
        def run(self):
            self.label_str.emit("正在请求响应...请耐心等待")
            # self.label_str.emit("正在下载{}".format(self.__songname))
            # print("正在下载{}".format(self.__songname))
            data = requests.get(self.__url).content
    
            with open(self.__path + "/" + self.__songname + ".mp3", "wb") as f:
                f.write(data)
            self.label_str.emit(self.__songname + " 成功下载到" + self.__path)
            print(self.__songname + " 成功下载到" + self.__path)
    
    
    class QmyMainWindow(QMainWindow):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.ui = Ui_MainWindow()
            self.ui.setupUi(self)
            self.thread = None
    
            self.itemFlags = Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsAutoTristate
    
            self.ui.lineEdit.addAction(self.ui.actSong_Search, QLineEdit.TrailingPosition)
    
            self.ui.treeWidget.hideColumn(5)
    
            # 当点击搜索时
            self.ui.actSong_Search.triggered.connect(self.do_act_song_search_triggered)
            # 全选
            self.ui.btnSel_ALL.clicked.connect(self.do_btn_sel_all_clicked)
            # 全不选
            self.ui.btnSel_None.clicked.connect(self.do_btn_sel_none_clicked)
            # 反选
            self.ui.btnSel_Invs.clicked.connect(self.do_btn_sel_invs_clicked)
            # 当点击下载歌曲时
            self.ui.actSong_Download.triggered.connect(self.do_act_song_download_triggered)
    
        # 全选
        def do_btn_sel_all_clicked(self):
            for i in range(self.ui.treeWidget.topLevelItemCount()):
                aItem = self.ui.treeWidget.topLevelItem(i)
                aItem.setCheckState(TreeColNum.col_order.value, Qt.Checked)
    
        # 全不选
        def do_btn_sel_none_clicked(self):
            for i in range(self.ui.treeWidget.topLevelItemCount()):
                aItem = self.ui.treeWidget.topLevelItem(i)
                aItem.setCheckState(TreeColNum.col_order.value, Qt.Unchecked)
    
        # 反选
        def do_btn_sel_invs_clicked(self):
            for i in range(self.ui.treeWidget.topLevelItemCount()):
                aItem = self.ui.treeWidget.topLevelItem(i)
                if aItem.checkState(TreeColNum.col_order.value) != Qt.Checked:
                    aItem.setCheckState(TreeColNum.col_order.value, Qt.Checked)
                else:
                    aItem.setCheckState(TreeColNum.col_order.value, Qt.Unchecked)
    
        # 当点击搜索按钮时
        def do_act_song_search_triggered(self):
            # 获取歌手名或者歌曲名
            search_text = self.ui.lineEdit.text()
            self.ui.treeWidget.clear()
            self.get_kuwo_songs(search_text)
    
        # 搜索之后列出歌单
        def show_songs_tree(self, order, song_name, singer_name, singer_album, song_time, song_rid):
            # 创建节点
            item = QTreeWidgetItem(TreeItemType.itTopItem.value)
            item.setText(TreeColNum.col_order.value, str(order+1))
            item.setText(TreeColNum.col_song_name.value, song_name)
            item.setText(TreeColNum.col_singer_name.value, singer_name)
            item.setText(TreeColNum.col_singer_album.value, singer_album)
            item.setText(TreeColNum.col_song_time.value, song_time)
            item.setText(TreeColNum.col_song_rid.value, str(song_rid))
    
            item.setFlags(self.itemFlags)
            item.setCheckState(TreeColNum.col_order.value, Qt.Checked)
            item.setData(TreeColNum.col_order.value, Qt.UserRole, "")
    
            # 设置文字居中
            item.setTextAlignment(TreeColNum.col_order.value, Qt.AlignCenter)
            item.setTextAlignment(TreeColNum.col_song_name.value, Qt.AlignCenter)
            item.setTextAlignment(TreeColNum.col_singer_name.value, Qt.AlignCenter)
            item.setTextAlignment(TreeColNum.col_singer_album.value, Qt.AlignCenter)
            item.setTextAlignment(TreeColNum.col_song_time.value, Qt.AlignCenter)
            item.setTextAlignment(TreeColNum.col_song_rid.value, Qt.AlignCenter)
            self.ui.treeWidget.addTopLevelItem(item)
    
        # 获取歌曲,默认5页
        def get_kuwo_songs(self, key, page=5):
            # 右键检查-->network-->在Name找到searchMusicBykeyWord?点开,在右侧可以看到请求头和url信息
            headers = {
                'User-Agent': "agent信息",
                'Referer': "refer信息",
                'csrf': "csrf信息",
                'Cookie': "cookie信息"
            }
            order = 0
            for i in range(1, page + 1):
                url = "http://www.kuwo.cn/api/www/search/searchMusicBykeyWord?key={}&pn={}".format(key, i)
                html = requests.get(url, headers=headers).json()
                data = html["data"]["list"]
                for dic_songs_info in data:
                    song_rid = dic_songs_info["rid"]
                    song_name = dic_songs_info["name"]
                    singer_name = dic_songs_info["artist"]
                    song_time = dic_songs_info["songTimeMinutes"]
                    singer_album = dic_songs_info["album"]
                    path_singer = "./酷我音乐/" + self.ui.lineEdit.text()
                    create_folder(path_singer)
                    self.show_songs_tree(order, song_name, singer_name, singer_album, song_time, song_rid)
                    order = order + 1
    
        def start_thread(self, path_singer, song_url, song_name):
            # 创建线程
            self.thread = SongDownload(path_singer, song_url, song_name)
            # 连接信号
            self.thread.label_str[str].connect(self.do_label_change)
            # 开启线程
            self.thread.start()
    
        # 当点击下载
        def do_act_song_download_triggered(self):
            for i in range(self.ui.treeWidget.topLevelItemCount()):
                aItem = self.ui.treeWidget.topLevelItem(i)
                if aItem.checkState(TreeColNum.col_order.value) != Qt.Checked:
                    pass
                else:
                    song_name = aItem.text(1)
                    song_rid = int(aItem.text(5))
                    song_url = self.get_one_song_url(song_rid)
                    path_singer = "./酷我音乐/" + self.ui.lineEdit.text()
                    self.start_thread(path_singer, song_url, song_name)
    
        # 获取一首歌的url
        def get_one_song_url(self, rid):
            # 点开一首免费歌曲,找到url格式url?format,点开找到头信息
            url = "http://www.kuwo.cn/url?format=mp3&rid={}&response=url&type=convert_url3&br=128kmp3&from=web&t=1587429921873&reqId=617f0321-8369-11ea-80b3-bbd056ce88a1".format(
                rid)
            headers = {
                'Cookie': "",
                'Referer': "",
                'User-Agent': "",
                'csrf': ""
            }
            data = requests.get(url, headers=headers).json()
            # {'code': 200, 'msg': 'success', 'url': 'https://win-web-ra01-sycdn.kuwo.cn/e9cbd04a0602f9f82c40e0f1800fa696/5e9e44a1/resource/n3/128/43/28/1310690697.mp3'}
            song_url = data["url"]
            return song_url
    
        def do_label_change(self, str_label):
            self.ui.label.setText(str_label)
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)  # 创建app,用QApplication类
        form = QmyMainWindow()
        form.show()
        sys.exit(app.exec_())
    View Code

    下面说一些值得注意的点。

    一、搜索歌曲时请求头信息

    初学者容易在这个地方就卡住,我用的google浏览器,现在就这个跟大家分享一下。

    首先,打开酷我音乐网页,随便搜索一个歌手名,比如周杰伦。

    可以看到他的歌单,此时鼠标右击打开Inspect-->NetWork

    在左边找到searchMusicByKeyWord这种样式单击鼠标左键,可以在右边看到url以及请求头信息。

    二、下载歌曲时,url格式的获取

    这是第二个值得注意的地方,这时,需要找到一个可以免费播放的歌曲,然后在network左侧找到url?format这种样式的单击鼠标左键,在右侧找到url链接(我个人是这样找的,但是我觉得原理可能并不是这样,如果没有免费歌曲的话,那岂不是下载不了,如果有谁知道正确简单的查找方法,欢迎在评论区分享给大家,谢谢。)

  • 相关阅读:
    Nginx中工作进程(work-process)为多少合适?
    Ubuntu中安装启动Nginx
    怎么获得类加载器?
    XML解析方式有哪些?
    HashMap常见面试题
    IO流分类
    集合之间的区别
    css布局2
    css布局1
    css3 总结01
  • 原文地址:https://www.cnblogs.com/smart-zihan/p/12745679.html
Copyright © 2011-2022 走看看