├── 1.jpg ├── 2.jpg ├── README.md ├── favicon.ico ├── python's homwork.py └── python大作业数据库.sql /1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ken-Chy129/Python_music/e7c2b1147ae82d02c2c4fe20837cea99f27e8c50/1.jpg -------------------------------------------------------------------------------- /2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ken-Chy129/Python_music/e7c2b1147ae82d02c2c4fe20837cea99f27e8c50/2.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > 介绍 2 | 3 | 基于**GUI界面**、**爬虫**、**数据处理**、**可视化展示**和**数据库存储**实现的可进行音乐搜索、音乐播放、音乐下载、音乐收藏、歌词下载、歌曲信息保存、当前热门歌曲查看、当前热门歌手、数据分析查看的一款软件 4 | 5 | > 环境说明 6 | 7 | 计算机系统版本:Windows10 8 | 9 | python版本:Python3.9 10 | 11 | 编辑器:Pycharm2021.1.2 12 | 13 | > 界面预览 14 | 15 | **登录页**:输入账号密码后点击Register进行注册,注册成功后数据会同步至数据库,随后即可输入该账号密码登录进入主界面 16 | 17 | ![登录](https://img-blog.csdnimg.cn/dafbf7008d364c5393064751f6012afa.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5b6X6L-H5LiU6L-H55qE5YuH6ICFeQ==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center) 18 | 19 | ![登录2](https://img-blog.csdnimg.cn/aa48c0704abb4c87955601287f70b82a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5b6X6L-H5LiU6L-H55qE5YuH6ICFeQ==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center) 20 | 21 | **主界面**: 22 | 23 | ![主界面](https://img-blog.csdnimg.cn/af83fc99068a4940bef91e4c1bc8b136.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5b6X6L-H5LiU6L-H55qE5YuH6ICFeQ==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center) 24 | 25 | **爬虫数据展示**: 26 | 27 | ![爬虫数据展示](https://img-blog.csdnimg.cn/e2e162ed20b34bcc9d234f024a610f1e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5b6X6L-H5LiU6L-H55qE5YuH6ICFeQ==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center) 28 | 29 | **数据分析展示**: 30 | 31 | ![image-20211217161817352](https://img-blog.csdnimg.cn/a44d346dccbe482bbfb3947d73f9a97b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5b6X6L-H5LiU6L-H55qE5YuH6ICFeQ==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center) 32 | 33 | ![热门歌手歌曲量占比饼图](https://img-blog.csdnimg.cn/7ae6a729860d426cbe56f95684c326b1.jpg?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5b6X6L-H5LiU6L-H55qE5YuH6ICFeQ==,size_14,color_FFFFFF,t_70,g_se,x_16#pic_center) 34 | 35 | **数据库展示:** 36 | 37 | ![数据库](https://img-blog.csdnimg.cn/7d5838b18073444bab0bfa6987faa9a2.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5b6X6L-H5LiU6L-H55qE5YuH6ICFeQ==,size_11,color_FFFFFF,t_70,g_se,x_16#pic_center) 38 | 39 | > 代码说明 40 | 41 | 具体代码功能与实现可以前往[我的博客](https://blog.csdn.net/qq_25046827/article/details/121829094)进行查看 42 | 43 | > 软件说明 44 | 45 | 1. 程序中分为两个类,分别对应两个GUI界面 46 | 2. 注册登录界面登录成功会传递当前登录的用户名以调用主界面 47 | 3. 进入主界面会自动调用search函数(默认search(“陈奕迅”))爬取歌曲信息并展示,可以通过在界面上的搜索框进行搜索其他歌手或歌曲 48 | 4. 点击搜索结果的歌名可以进行音乐播放,当播放结束会自动进入下一首,知道列表播放结束提示暂无下一首 49 | 5. 可以点击进度条上的按钮实现上一首,播放/暂停,下一首的功能 50 | 6. 点击右边执行操作即可实现相应的功能 51 | 7. 点击左侧我的下载和我的收藏可以查看当前用户收藏和下载过的歌曲 52 | 8. 点击左侧联系与帮助可以进入CSDN查看开发的流程,访问作者个人博客等 53 | 54 | >使用须知 55 | 56 | 1. 在使用之前得确保本地有相应的数据库和表,否则会出现数据库连接失败的情况 57 | - `host='localhost', user='root', password='129496', db='pyhomework'`(也可以更改数据库连接部分的代码为自己的用户名和密码) 58 | - 项目中已附带对应的建表的sql语句 59 | 2. 在进入主页面之前必须保证联网状态,因为进入主界面会自动触发爬虫搜索功能,需要联网否则会因连接超时而报错 60 | 3. 启动前需要先安装好依赖的包 61 | 62 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ken-Chy129/Python_music/e7c2b1147ae82d02c2c4fe20837cea99f27e8c50/favicon.ico -------------------------------------------------------------------------------- /python's homwork.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | import os 3 | import re 4 | import webbrowser 5 | from os.path import exists 6 | 7 | import jieba 8 | import matplotlib.pyplot as plt 9 | import numpy as np 10 | import pymysql 11 | import requests 12 | import xlsxwriter 13 | from PIL import Image 14 | from PyQt5 import QtCore, QtWidgets 15 | import sys 16 | import qtawesome 17 | from PyQt5.QtCore import QUrl, Qt 18 | from PyQt5.QtGui import QIcon, QPalette, QBrush, QPixmap, QFont 19 | from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer 20 | from PyQt5.QtWidgets import QFileDialog, QMessageBox, QDialog, QFrame, QVBoxLayout, QLineEdit, QGraphicsOpacityEffect, \ 21 | QPushButton 22 | from bs4 import BeautifulSoup 23 | from wordcloud import WordCloud 24 | 25 | class MainUi(QtWidgets.QMainWindow, QDialog): 26 | 27 | def __init__(self, username): 28 | super().__init__() 29 | self.username = username 30 | self.hot = [] 31 | self.player = QMediaPlayer(self) 32 | self.playing = False 33 | self.play_index_now = -1 34 | self.timer = QtCore.QTimer() 35 | self.timer.setInterval(1000) 36 | self.timer.start() 37 | self.timer.timeout.connect(self.check_music_status) 38 | self.init_ui() 39 | 40 | def init_ui(self): 41 | self.setFixedSize(960, 700) 42 | self.setWindowTitle('Ken-Chy') 43 | self.setWindowIcon(QIcon('favicon.ico')) # 设置窗体图标 44 | self.setWindowOpacity(0.9) # 设置窗口透明度 45 | self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # 设置窗口背景透明 46 | # self.setWindowFlags(QtCore.Qt.FramelessWindowHint) # 隐藏边框 47 | 48 | self.main_widget = QtWidgets.QWidget() # 创建窗口主部件 49 | self.main_layout = QtWidgets.QGridLayout() # 创建主部件的网格布局 50 | self.main_widget.setLayout(self.main_layout) # 设置窗口主部件布局为网格布局 51 | self.left_widget = QtWidgets.QWidget() # 创建左侧部件 52 | self.left_widget.setObjectName('left_widget') 53 | self.left_layout = QtWidgets.QGridLayout() # 创建左侧部件的网格布局层 54 | self.left_widget.setLayout(self.left_layout) # 设置左侧部件布局为网格 55 | self.right_widget = QtWidgets.QWidget() # 创建右侧部件 56 | self.right_widget.setObjectName('right_widget') 57 | self.right_layout = QtWidgets.QGridLayout() 58 | self.right_widget.setLayout(self.right_layout) # 设置右侧部件布局为网格 59 | self.setCentralWidget(self.main_widget) # 设置窗口主部件 60 | self.main_layout.addWidget(self.left_widget, 0, 0, 12, 2) # 左侧部件在第0行第0列 61 | self.main_layout.addWidget(self.right_widget, 0, 2, 12, 10) # 右侧部件在第0行第3列 62 | 63 | self.left_close = QtWidgets.QPushButton("") # 关闭按钮 64 | self.left_visit = QtWidgets.QPushButton("") # 空白按钮 65 | self.left_mini = QtWidgets.QPushButton("") # 最小化按钮 66 | 67 | self.left_label_1 = QtWidgets.QPushButton("每日推荐") 68 | self.left_label_1.setObjectName('left_label') 69 | self.left_label_2 = QtWidgets.QPushButton("我的音乐") 70 | self.left_label_2.setObjectName('left_label') 71 | self.left_label_3 = QtWidgets.QPushButton("联系与帮助") 72 | self.left_label_3.setObjectName('left_label') 73 | 74 | self.left_button_1 = QtWidgets.QPushButton(qtawesome.icon('fa.music', color='white'), "热门歌曲") 75 | self.left_button_1.setObjectName('left_button') 76 | self.left_button_2 = QtWidgets.QPushButton(qtawesome.icon('fa.sellsy', color='white'), "热门歌手") 77 | self.left_button_2.setObjectName('left_button') 78 | self.left_button_3 = QtWidgets.QPushButton(qtawesome.icon('fa.area-chart', color='white'), "数据分析") 79 | self.left_button_3.setObjectName('left_button') 80 | self.left_button_4 = QtWidgets.QPushButton(qtawesome.icon('fa.cloud-download', color='white'), "我的下载") 81 | self.left_button_4.setObjectName('left_button') 82 | self.left_button_5 = QtWidgets.QPushButton(qtawesome.icon('fa.star', color='white'), "我的收藏") 83 | self.left_button_5.setObjectName('left_button') 84 | self.left_button_6 = QtWidgets.QPushButton(qtawesome.icon('fa.exchange', color='white'), "切换账号") 85 | self.left_button_6.setObjectName('left_button') 86 | self.left_button_7 = QtWidgets.QPushButton(qtawesome.icon('fa.comment', color='white'), "开发流程") 87 | self.left_button_7.setObjectName('left_button') 88 | self.left_button_8 = QtWidgets.QPushButton(qtawesome.icon('fa.home', color='white'), "作者博客") 89 | self.left_button_8.setObjectName('left_button') 90 | self.left_button_9 = QtWidgets.QPushButton(qtawesome.icon('fa.comments', color='white'), "联系作者") 91 | self.left_button_9.setObjectName('left_button') 92 | 93 | self.left_layout.addWidget(self.left_mini, 0, 0, 1, 1) 94 | self.left_layout.addWidget(self.left_close, 0, 2, 1, 1) 95 | self.left_layout.addWidget(self.left_visit, 0, 1, 1, 1) 96 | self.left_layout.addWidget(self.left_label_1, 1, 0, 1, 3) 97 | self.left_layout.addWidget(self.left_button_1, 2, 0, 1, 3) 98 | self.left_layout.addWidget(self.left_button_2, 3, 0, 1, 3) 99 | self.left_layout.addWidget(self.left_button_3, 4, 0, 1, 3) 100 | self.left_layout.addWidget(self.left_label_2, 5, 0, 1, 3) 101 | self.left_layout.addWidget(self.left_button_4, 6, 0, 1, 3) 102 | self.left_layout.addWidget(self.left_button_5, 7, 0, 1, 3) 103 | self.left_layout.addWidget(self.left_button_6, 8, 0, 1, 3) 104 | self.left_layout.addWidget(self.left_label_3, 9, 0, 1, 3) 105 | self.left_layout.addWidget(self.left_button_7, 10, 0, 1, 3) 106 | self.left_layout.addWidget(self.left_button_8, 11, 0, 1, 3) 107 | self.left_layout.addWidget(self.left_button_9, 12, 0, 1, 3) 108 | 109 | self.right_bar_widget = QtWidgets.QWidget() # 右侧顶部搜索框部件 110 | self.right_bar_layout = QtWidgets.QGridLayout() # 右侧顶部搜索框网格布局 111 | self.right_bar_widget.setLayout(self.right_bar_layout) 112 | self.search_icon = QtWidgets.QLabel(chr(0xf002) + ' ' + '搜索 ') 113 | self.search_icon.setFont(qtawesome.font('fa', 20)) 114 | self.right_bar_widget_search_input = QtWidgets.QLineEdit() 115 | self.right_bar_widget_search_input.setPlaceholderText("输入歌手、歌曲或用户,回车进行搜索") 116 | 117 | self.right_bar_layout.addWidget(self.search_icon, 0, 0, 1, 1) 118 | self.right_bar_layout.addWidget(self.right_bar_widget_search_input, 0, 1, 1, 8) 119 | self.right_layout.addWidget(self.right_bar_widget, 0, 0, 1, 9) 120 | 121 | self.right_search_result_lable = QtWidgets.QLabel("搜索结果") 122 | self.right_search_result_lable.setObjectName('right_lable') 123 | self.right_operator_lable = QtWidgets.QLabel("执行操作") 124 | self.right_operator_lable.setObjectName('right_lable') 125 | 126 | self.right_search_result_widget = QtWidgets.QWidget() # 搜索歌曲部件 127 | self.right_search_result_layout = QtWidgets.QGridLayout() # 搜索歌曲部件网格布局 128 | self.right_search_result_widget.setLayout(self.right_search_result_layout) 129 | 130 | self.search_result_button_1 = QtWidgets.QPushButton() 131 | self.search_result_button_2 = QtWidgets.QPushButton() 132 | self.search_result_button_3 = QtWidgets.QPushButton() 133 | self.search_result_button_4 = QtWidgets.QPushButton() 134 | self.search_result_button_5 = QtWidgets.QPushButton() 135 | self.search_result_button_6 = QtWidgets.QPushButton() 136 | self.search_result_button_7 = QtWidgets.QPushButton() 137 | self.search_result_button_8 = QtWidgets.QPushButton() 138 | self.search_result_button_9 = QtWidgets.QPushButton() 139 | self.search_result_button_10 = QtWidgets.QPushButton() 140 | self.right_search_result_layout.addWidget(self.search_result_button_1, 0, 1, ) 141 | self.right_search_result_layout.addWidget(self.search_result_button_2, 1, 1, ) 142 | self.right_search_result_layout.addWidget(self.search_result_button_3, 2, 1, ) 143 | self.right_search_result_layout.addWidget(self.search_result_button_4, 3, 1, ) 144 | self.right_search_result_layout.addWidget(self.search_result_button_5, 4, 1, ) 145 | self.right_search_result_layout.addWidget(self.search_result_button_6, 5, 1, ) 146 | self.right_search_result_layout.addWidget(self.search_result_button_7, 6, 1, ) 147 | self.right_search_result_layout.addWidget(self.search_result_button_8, 7, 1, ) 148 | self.right_search_result_layout.addWidget(self.search_result_button_9, 8, 1, ) 149 | self.right_search_result_layout.addWidget(self.search_result_button_10, 9, 1, ) 150 | self.search("陈奕迅") 151 | 152 | self.right_operator_widget = QtWidgets.QWidget() # 播放歌单部件 153 | self.right_operator_layout = QtWidgets.QGridLayout() # 播放歌单网格布局 154 | self.right_operator_widget.setLayout(self.right_operator_layout) 155 | 156 | self.operator_button_1 = QtWidgets.QToolButton() 157 | self.operator_button_1.setText("导出所有歌曲信息") 158 | self.operator_button_1.setIcon(qtawesome.icon('fa.list', color='red')) 159 | self.operator_button_1.setIconSize(QtCore.QSize(50, 50)) 160 | self.operator_button_1.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) 161 | 162 | self.operator_button_2 = QtWidgets.QToolButton() 163 | self.operator_button_2.setText("导出所有歌曲歌词") 164 | self.operator_button_2.setIcon(qtawesome.icon('fa.file-text-o', color='red')) 165 | self.operator_button_2.setIconSize(QtCore.QSize(50, 50)) 166 | self.operator_button_2.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) 167 | 168 | self.operator_button_3 = QtWidgets.QToolButton() 169 | self.operator_button_3.setText("下载当前播放歌曲") 170 | self.operator_button_3.setIcon(qtawesome.icon('fa.download', color='red')) 171 | self.operator_button_3.setIconSize(QtCore.QSize(50, 50)) 172 | self.operator_button_3.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) 173 | 174 | self.operator_button_4 = QtWidgets.QToolButton() 175 | self.operator_button_4.setText("收藏当前播放歌曲") 176 | self.operator_button_4.setIcon(qtawesome.icon('fa.heart', color='red')) 177 | self.operator_button_4.setIconSize(QtCore.QSize(50, 50)) 178 | self.operator_button_4.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) 179 | 180 | self.operator_button_5 = QtWidgets.QToolButton() 181 | self.operator_button_5.setText("生成所有歌词词云") 182 | self.operator_button_5.setIcon(qtawesome.icon('fa.cloud', color='red')) 183 | self.operator_button_5.setIconSize(QtCore.QSize(50, 50)) 184 | self.operator_button_5.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) 185 | 186 | self.operator_button_6 = QtWidgets.QToolButton() 187 | self.operator_button_6.setText("热门歌手歌曲占比") 188 | self.operator_button_6.setIcon(qtawesome.icon('fa.pie-chart', color='red')) 189 | self.operator_button_6.setIconSize(QtCore.QSize(50, 50)) 190 | self.operator_button_6.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) 191 | 192 | self.right_operator_layout.addWidget(self.operator_button_1, 0, 0) 193 | self.right_operator_layout.addWidget(self.operator_button_2, 0, 1) 194 | self.right_operator_layout.addWidget(self.operator_button_3, 1, 0) 195 | self.right_operator_layout.addWidget(self.operator_button_4, 1, 1) 196 | self.right_operator_layout.addWidget(self.operator_button_5, 2, 0) 197 | self.right_operator_layout.addWidget(self.operator_button_6, 2, 1) 198 | 199 | self.right_layout.addWidget(self.right_search_result_lable, 2, 0, 1, 5) 200 | self.right_layout.addWidget(self.right_operator_lable, 2, 5, 1, 3) 201 | self.right_layout.addWidget(self.right_search_result_widget, 3, 0, 1, 5) 202 | self.right_layout.addWidget(self.right_operator_widget, 3, 5, 1, 3) 203 | 204 | self.right_process_bar = QtWidgets.QProgressBar() # 播放进度部件 205 | self.process_value = 0 206 | self.right_process_bar.setValue(self.process_value) 207 | self.right_process_bar.setFixedHeight(3) # 设置进度条高度 208 | self.right_process_bar.setTextVisible(False) # 不显示进度条文字 209 | 210 | self.right_playconsole_widget = QtWidgets.QWidget() # 播放控制部件 211 | self.right_playconsole_layout = QtWidgets.QGridLayout() # 播放控制部件网格布局层 212 | self.right_playconsole_widget.setLayout(self.right_playconsole_layout) 213 | 214 | self.console_button_1 = QtWidgets.QPushButton(qtawesome.icon('fa.backward', color='#F76677'), "") 215 | self.console_button_2 = QtWidgets.QPushButton(qtawesome.icon('fa.forward', color='#F76677'), "") 216 | self.console_button_3 = QtWidgets.QPushButton(qtawesome.icon('fa.play', color='#F76677', font=18), "") 217 | self.console_button_3.setIconSize(QtCore.QSize(30, 30)) 218 | 219 | self.right_playconsole_layout.addWidget(self.console_button_1, 0, 0) 220 | self.right_playconsole_layout.addWidget(self.console_button_2, 0, 2) 221 | self.right_playconsole_layout.addWidget(self.console_button_3, 0, 1) 222 | self.right_playconsole_layout.setAlignment(QtCore.Qt.AlignCenter) # 设置布局内部件居中显示 223 | 224 | self.right_layout.addWidget(self.right_process_bar, 9, 0, 1, 9) 225 | self.right_layout.addWidget(self.right_playconsole_widget, 10, 0, 1, 9) 226 | 227 | self.left_close.setFixedSize(15, 15) # 设置关闭按钮的大小 228 | self.left_visit.setFixedSize(15, 15) # 设置按钮大小 229 | self.left_mini.setFixedSize(15, 15) # 设置最小化按钮大小 230 | 231 | self.main_layout.setSpacing(0) # 设置内部控件间距 232 | 233 | self.left_close.setStyleSheet( 234 | '''QPushButton{background:#F76677;border-radius:5px;}QPushButton:hover{background:red;}''') 235 | self.left_visit.setStyleSheet( 236 | '''QPushButton{background:#F7D674;border-radius:5px;}QPushButton:hover{background:yellow;}''') 237 | self.left_mini.setStyleSheet( 238 | '''QPushButton{background:#6DDF6D;border-radius:5px;}QPushButton:hover{background:green;}''') 239 | 240 | self.left_widget.setStyleSheet("\ 241 | QPushButton{border:none;color:white;}\ 242 | QPushButton#left_label{\ 243 | border:none;\ 244 | border-bottom:1px solid white;\ 245 | font-size:18px;\ 246 | font-weight:700;\ 247 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\ 248 | }\ 249 | QPushButton#left_button:hover{border-left:4px solid red;font-weight:700;}\ 250 | QWidget#left_widget{\ 251 | background:gray;\ 252 | border-top:1px solid white;\ 253 | border-bottom:1px solid white;\ 254 | border-left:1px solid white;\ 255 | border-top-left-radius:10px;\ 256 | border-bottom-left-radius:10px;\ 257 | }") 258 | 259 | self.right_bar_widget_search_input.setStyleSheet( 260 | "QLineEdit{\ 261 | border:1px solid gray;\ 262 | width:300px;\ 263 | border-radius:10px;\ 264 | padding:8px 4px;\ 265 | }") 266 | 267 | self.right_widget.setStyleSheet(''' 268 | QWidget#right_widget{ 269 | color:#232C51; 270 | background:white; 271 | border-top:1px solid darkGray; 272 | border-bottom:1px solid darkGray; 273 | border-right:1px solid darkGray; 274 | border-top-right-radius:10px; 275 | border-bottom-right-radius:10px; 276 | } 277 | QLabel#right_lable{ 278 | border:none; 279 | font-size:20px; 280 | font-weight:700; 281 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 282 | text-align:center 283 | } 284 | ''') 285 | 286 | self.right_operator_widget.setStyleSheet( 287 | ''' 288 | QToolButton{border:none; margin-left:15px} 289 | QToolButton:hover{border-bottom:2px solid #F76677;} 290 | ''') 291 | 292 | self.right_search_result_widget.setStyleSheet(''' 293 | QPushButton{ 294 | border:none; 295 | color:gray; 296 | font-size:18px; 297 | height:36px; 298 | padding-left:5px; 299 | padding-right:10px; 300 | text-align:left; 301 | } 302 | QPushButton:hover{ 303 | color:black; 304 | border:1px solid #F3F3F5; 305 | border-radius:10px; 306 | background:LightGray; 307 | } 308 | ''') 309 | 310 | self.right_process_bar.setStyleSheet(''' 311 | QProgressBar::chunk { 312 | background-color: #F76677; 313 | } 314 | ''') 315 | 316 | self.right_playconsole_widget.setStyleSheet(''' 317 | QPushButton{ 318 | border:none; 319 | } 320 | ''') 321 | 322 | self.left_button_1.clicked.connect(self.pop_songs) 323 | self.left_button_2.clicked.connect(self.pop_singers) 324 | self.left_button_3.clicked.connect(self.analysis) 325 | self.left_button_4.clicked.connect(self.my_downloads) 326 | self.left_button_5.clicked.connect(self.my_collects) 327 | self.left_button_6.clicked.connect(self.change_account) 328 | self.left_button_7.clicked.connect(lambda: webbrowser.open('https://blog.csdn.net/qq_25046827')) 329 | self.left_button_8.clicked.connect(lambda: webbrowser.open('https://blog.csdn.net/qq_25046827')) 330 | self.left_button_9.clicked.connect(lambda: webbrowser.open('https://blog.csdn.net/qq_25046827')) 331 | self.right_bar_widget_search_input.returnPressed.connect( 332 | lambda: self.search(self.right_bar_widget_search_input.text())) 333 | self.search_result_button_1.clicked.connect(lambda: self.play_music(0)) 334 | self.search_result_button_2.clicked.connect(lambda: self.play_music(1)) 335 | self.search_result_button_3.clicked.connect(lambda: self.play_music(2)) 336 | self.search_result_button_4.clicked.connect(lambda: self.play_music(3)) 337 | self.search_result_button_5.clicked.connect(lambda: self.play_music(4)) 338 | self.search_result_button_6.clicked.connect(lambda: self.play_music(5)) 339 | self.search_result_button_7.clicked.connect(lambda: self.play_music(6)) 340 | self.search_result_button_8.clicked.connect(lambda: self.play_music(7)) 341 | self.search_result_button_9.clicked.connect(lambda: self.play_music(8)) 342 | self.search_result_button_10.clicked.connect(lambda: self.play_music(9)) 343 | self.operator_button_1.clicked.connect(lambda: self.export_songs_details()) 344 | self.operator_button_2.clicked.connect(lambda: self.export_songs_lyric()) 345 | self.operator_button_3.clicked.connect(lambda: self.download()) 346 | self.operator_button_4.clicked.connect(lambda: self.collect()) 347 | self.operator_button_5.clicked.connect(lambda: self.lyric_cloud()) 348 | self.operator_button_6.clicked.connect(lambda: self.hot_singer_song()) 349 | self.console_button_1.clicked.connect(self.pre_music) 350 | self.console_button_3.clicked.connect(self.play_music_by_button) 351 | self.console_button_2.clicked.connect(self.next_music) 352 | 353 | def search(self, keyword): 354 | self.play_index_now = -1 # 每次重新搜索都将当前播放序号设置为-1 355 | urlbase = r'https://www.8lrc.com/search' # 搜索的基础地址 356 | params = {'key': keyword} # 封装搜索的参数 357 | res_body = requests.get(urlbase, params) # 拼接url,发送请求 358 | soup_body = BeautifulSoup(res_body.text, 'html.parser') # html解析获得响应文本 359 | self.tags = soup_body.findAll(class_='tGequ') # 得到查询结果 360 | self.get_song_detail(keyword) 361 | 362 | def get_song_detail(self, keyword): # 呈现搜索结果于界面 363 | result = r'https://www.8lrc.com' # 搜索结果的基础地址 364 | pattern = r'(.*) - (.*)' # 得到歌名的正则表达式 365 | pattern1 = r'"url":"([^"]*)"' # 得到歌曲资源的正则表达式 366 | self.keyword = keyword 367 | self.names = [] 368 | self.musics = [] 369 | self.num = 0 370 | for tag in self.tags[0:]: 371 | if re.match(pattern, tag.text): 372 | res_body = requests.get(result + tag['href']) 373 | soup_body = BeautifulSoup(res_body.text, 'html.parser') 374 | if soup_body.text.__contains__("404"): continue 375 | script = soup_body.select("body script")[3].get_text() 376 | pre_music = re.search(pattern1, script).group(1) 377 | self.names.append(re.split(pattern, tag.text)[1]) # 获取歌名 378 | self.musics.append(pre_music.replace(r'\/', '/')) # 获取歌曲资源 379 | self.num = self.num+1 380 | self.song_show() 381 | 382 | def song_show(self): # 呈现"歌手-歌名"的形式 383 | num = self.num 384 | if self.num: 385 | self.search_result_button_1.setText(self.keyword + " - " + self.names[0]) 386 | self.num = self.num-1 387 | else: 388 | self.search_result_button_1.setText("") 389 | if self.num: 390 | self.search_result_button_2.setText(self.keyword + " - " + self.names[1]) 391 | self.num = self.num-1 392 | else: 393 | self.search_result_button_2.setText("") 394 | if self.num: 395 | self.search_result_button_3.setText(self.keyword + " - " + self.names[2]) 396 | self.num = self.num-1 397 | else: 398 | self.search_result_button_3.setText("") 399 | if self.num: 400 | self.search_result_button_4.setText(self.keyword + " - " + self.names[3]) 401 | self.num = self.num-1 402 | else: 403 | self.search_result_button_4.setText("") 404 | if self.num: 405 | self.search_result_button_5.setText(self.keyword + " - " + self.names[4]) 406 | self.num = self.num-1 407 | else: 408 | self.search_result_button_5.setText("") 409 | if self.num: 410 | self.search_result_button_6.setText(self.keyword + " - " + self.names[5]) 411 | self.num = self.num-1 412 | else: 413 | self.search_result_button_6.setText("") 414 | if self.num: 415 | self.search_result_button_7.setText(self.keyword + " - " + self.names[6]) 416 | self.num = self.num-1 417 | else: 418 | self.search_result_button_7.setText("") 419 | if self.num: 420 | self.search_result_button_8.setText(self.keyword + " - " + self.names[7]) 421 | self.num = self.num-1 422 | else: 423 | self.search_result_button_8.setText("") 424 | if self.num: 425 | self.search_result_button_9.setText(self.keyword + " - " + self.names[8]) 426 | self.num = self.num-1 427 | else: 428 | self.search_result_button_9.setText("") 429 | if self.num: 430 | self.search_result_button_10.setText(self.keyword + " - " + self.names[9]) 431 | else: 432 | self.search_result_button_10.setText("") 433 | self.num = num 434 | 435 | def process_timer_status(self): # 进度条进程百分比更新 436 | try: 437 | if self.playing is True: 438 | self.process_value += (100 / (self.duration / 1000)) 439 | # print("当前进度:", self.process_value) 440 | self.right_process_bar.setValue(self.process_value) 441 | except Exception as e: 442 | print(repr(e)) 443 | 444 | def check_music_status(self): # 确认播放咋黄台,播放结束则自动播放下一首 445 | player_status = self.player.mediaStatus() 446 | player_duration = self.player.duration() 447 | # print("音乐时间:",player_duration) 448 | # print("当前播放器状态",player_status) 449 | if player_status == 7: 450 | if not self.play_index_now >= 9: 451 | self.next_music() 452 | 453 | if player_duration > 0: 454 | self.duration = player_duration 455 | 456 | def play_music(self, num): # 播放歌曲 457 | if num >= self.num: 458 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '暂无该曲目') 459 | msg_box.exec_() 460 | return 461 | self.process_value = 0 462 | self.play_index_now = num 463 | self.playing = True 464 | self.console_button_3.setIcon(qtawesome.icon('fa.stop', color='#F76677', font=18)) 465 | self.player.setMedia(QMediaContent(QUrl(self.musics[num]))) 466 | self.player.setVolume(50) 467 | self.player.play() 468 | self.duration = self.player.duration() # 音乐的时长 469 | # print(self.duration) 470 | self.process_timer = QtCore.QTimer() 471 | self.process_timer.setInterval(1000) 472 | self.process_timer.start() 473 | self.process_timer.timeout.connect(self.process_timer_status) 474 | 475 | def play_music_by_button(self): # 播放器三个按钮功能设置 476 | if self.play_index_now == -1: 477 | if self.playing is False: 478 | self.process_value = 0 479 | self.play_music(0) 480 | self.console_button_3.setIcon(qtawesome.icon('fa.stop', color='#F76677', font=18)) 481 | elif self.playing is False: 482 | self.playing = True 483 | self.console_button_3.setIcon(qtawesome.icon('fa.stop', color='#F76677', font=18)) 484 | self.player.play() 485 | else: 486 | self.playing = False 487 | self.console_button_3.setIcon(qtawesome.icon('fa.play', color='#F76677', font=18)) 488 | self.player.pause() 489 | 490 | def pre_music(self): # 播放前一首 491 | if self.play_index_now <= 0: 492 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '已经是第一首了~') 493 | msg_box.exec_() 494 | else: 495 | self.play_music(self.play_index_now - 1) 496 | 497 | def next_music(self): # 播放后一首 498 | if self.play_index_now >= 9: 499 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '已经是最后一首了~') 500 | msg_box.exec_() 501 | else: 502 | self.play_music(self.play_index_now + 1) 503 | 504 | def export_songs_details(self): 505 | result = r'https://www.8lrc.com' 506 | row = 0 507 | if not exists('./songsdetails/'): 508 | os.makedirs('./songsdetails/') 509 | workbook = xlsxwriter.Workbook('./songsdetails/'+self.keyword+'.xlsx') 510 | worksheet = workbook.add_worksheet('music') 511 | worksheet.write_row(row, 0, ['歌名', '歌手', '歌曲url', '歌曲资源地址']) 512 | for name in self.names: 513 | row += 1 514 | worksheet.write_row(row, 0, [name.replace(' ', ''), self.keyword, result+self.tags[row-1]['href'], self.musics[row-1]]) 515 | workbook.close() 516 | if os.path.exists('./songsdetails/'+self.keyword+'.xlsx'): 517 | os.startfile('.\\songsdetails\\'+self.keyword+'.xlsx') 518 | else: 519 | msg_box = QMessageBox(QMessageBox.Warning, '提示', '出了点小问题~') 520 | msg_box.exec_() 521 | 522 | def export_songs_lyric(self): 523 | result = r'https://www.8lrc.com' 524 | pattern = r'"lrc":"(.*)","link"' 525 | num = 0 526 | if not exists('./lyric/'+self.keyword): 527 | os.makedirs('./lyric/'+self.keyword) 528 | for tag in self.tags[0:10]: 529 | res_body = requests.get(result + tag['href']) 530 | soup_body = BeautifulSoup(res_body.text, 'html.parser') 531 | if soup_body.text.__contains__("404"): continue 532 | script = soup_body.select("body script")[3].get_text() 533 | lyric = re.search(pattern, script).group(1) 534 | lyric = lyric.replace(r'\r\n', '\n') 535 | with open("lyric/"+self.keyword+'/'+self.names[num]+'.txt', 'w+', -1, 'utf-8') as fp: 536 | fp.write(lyric) 537 | fp.close() 538 | num += 1 539 | msg_box = QMessageBox(QMessageBox.Warning, '提示', '导出成功') 540 | msg_box.exec_() 541 | os.startfile(".\\lyric\\"+self.keyword) 542 | 543 | def download(self): 544 | if self.play_index_now == -1: 545 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '当前暂无播放歌曲') 546 | msg_box.exec_() 547 | return 548 | response = requests.get(self.musics[self.play_index_now]) 549 | filename = QFileDialog.getSaveFileName(self, '下载文件', '.', '音乐文件(*.MP3)') # 保存歌曲 550 | if filename[0] != '': 551 | try: 552 | conn = pymysql.connect(host='localhost', user='root', password='129496', db='pyhomework') 553 | cur = conn.cursor() 554 | except: 555 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '数据库连接错误') 556 | msg_box.exec_() 557 | return 558 | 559 | sql = 'insert into downloads values("%s","%s", "%s", "%s")' % ( 560 | self.username, self.keyword, self.names[self.play_index_now], self.musics[self.play_index_now]) 561 | try: 562 | cur.execute(sql) 563 | conn.commit() 564 | msg_box = QMessageBox(QMessageBox.Warning, '提示', '下载成功') 565 | msg_box.exec_() 566 | except: 567 | conn.rollback() 568 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '下载出错') 569 | msg_box.exec_() 570 | cur.close() 571 | conn.close() 572 | 573 | with open(filename[0], 'wb') as m: 574 | m.write(response.content) 575 | 576 | def collect(self): 577 | if self.play_index_now == -1: 578 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '当前暂无播放歌曲') 579 | msg_box.exec_() 580 | return 581 | try: 582 | conn = pymysql.connect(host='localhost', user='root', password='129496', db='pyhomework') 583 | cur = conn.cursor() 584 | except: 585 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '数据库连接错误') 586 | msg_box.exec_() 587 | return 588 | 589 | sql = 'insert into collects values("%s","%s", "%s", "%s")' % (self.username, self.keyword, self.names[self.play_index_now], self.musics[self.play_index_now]) 590 | try: 591 | cur.execute(sql) 592 | conn.commit() 593 | msg_box = QMessageBox(QMessageBox.Warning, '提示', '收藏成功') 594 | msg_box.exec_() 595 | except: 596 | conn.rollback() 597 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '收藏出错') 598 | msg_box.exec_() 599 | cur.close() 600 | conn.close() 601 | 602 | def lyric_cloud(self): 603 | result = r'https://www.8lrc.com' 604 | pattern = r'"lrc":"(.*)","link"' 605 | lyric = "" 606 | for tag in self.tags[0:10]: 607 | res_body = requests.get(result + tag['href']) 608 | soup_body = BeautifulSoup(res_body.text, 'html.parser') 609 | if soup_body.text.__contains__("404"): continue 610 | script = soup_body.select("body script")[3].get_text() 611 | lyric = lyric + re.search(pattern, script).group(1) 612 | text = re.findall('[\u4e00-\u9fa5]+', lyric, re.S) # 提取中文 613 | text = " ".join(text) 614 | word = jieba.cut(text, cut_all=True) # 分词 615 | new_word = [] 616 | for i in word: 617 | if len(i) >= 2: 618 | new_word.append(i) # 只添加长度大于2的词 619 | final_text = " ".join(new_word) 620 | mask = np.array(Image.open("2.jpg")) 621 | word_cloud = WordCloud(background_color="white", width=800, height=600, max_words=100, max_font_size=80, contour_width=1, contour_color='lightblue', font_path="C:/Windows/Fonts/simfang.ttf", mask=mask).generate(final_text) 622 | # image_color = ImageColorGenerator(mask) 623 | # plt.imshow(word_cloud, interpolation="bilinear") 624 | # plt.axis("off") 625 | # plt.show() 626 | word_cloud.to_file(self.keyword+'词云.png') 627 | os.startfile(self.keyword+'词云.png') 628 | 629 | def hot_singer_song(self): 630 | url = 'https://www.9ku.com/geshou/all-all-liuxing.htm' 631 | base = 'https://www.9ku.com' 632 | singers_url = [] 633 | songs_num = [] 634 | proportion = [] 635 | name = [] 636 | all_num = 0 637 | res_body = requests.get(url) 638 | soup_body = BeautifulSoup(res_body.text, 'html.parser') 639 | singers_body = soup_body.findAll(class_='t-i') 640 | for singer in singers_body[:10]: 641 | singers_url.append(base + singer['href']) 642 | for singer_url in singers_url: 643 | res_body = requests.get(singer_url) 644 | soup_body = BeautifulSoup(res_body.text, 'html.parser') 645 | name.append(soup_body.find(class_="t-t clearfix").h1.text) 646 | songs = soup_body.findAll(class_="songNameA") 647 | songs_num.append(len(songs)) 648 | all_num += len(songs) 649 | for i in songs_num: 650 | proportion.append(i/all_num) 651 | explode = [0.1, 0, 0, 0, 0, 0, 0, 0, 0, 0] 652 | plt.figure(figsize=(6, 9)) # 设置图形大小宽高 653 | plt.rcParams['font.sans-serif'] = ['SimHei'] # 解决中文乱码问题 654 | plt.axes(aspect=1) # 设置图形是圆的 655 | plt.pie(x=proportion, labels=name, explode=explode, autopct='%3.1f %%', 656 | shadow=True, labeldistance=1.2, startangle=0, pctdistance=0.8) 657 | plt.title("热门歌手歌曲量占比") 658 | # plt.show() 659 | plt.savefig("热门歌手歌曲量占比饼图.jpg") 660 | os.startfile("热门歌手歌曲量占比饼图.jpg") 661 | 662 | def pop_songs(self): 663 | row = 0 664 | base = 'http://m.yue365.com/' 665 | url = 'http://m.yue365.com/bang/box100_w.shtml' 666 | pattern = r'width:(.*)%' 667 | self.hot = [] 668 | self.songs = [] 669 | res_body = requests.get(url) 670 | res_body.encoding = 'gb2312' 671 | soup_body = BeautifulSoup(res_body.text, 'lxml') 672 | songs = soup_body.findAll(class_='name') 673 | hot = soup_body.findAll('span', class_='dib') 674 | workbook = xlsxwriter.Workbook('popsongs.xlsx') 675 | first_format = workbook.add_format({'align': 'center'}) 676 | second_format = workbook.add_format({'align': 'left'}) 677 | worksheet = workbook.add_worksheet('pop500') 678 | worksheet.set_column(0, 0, 6) 679 | worksheet.set_column(1, 1, 20) 680 | worksheet.set_column(2, 2, 46) 681 | worksheet.set_column(3, 3, 10) 682 | worksheet.write_row(row, 0, ['排名', '歌名', '歌曲url', '歌曲热度'], first_format) 683 | for song in songs: 684 | self.hot.append(int(re.split(pattern, hot[row*2+1]['style'])[1])) 685 | self.songs.append(song.a.text) 686 | row += 1 687 | song_url = base+song.a['href'] 688 | worksheet.write_row(row, 0, [row, song.a.text, song_url, self.hot[row-1]], second_format) 689 | workbook.close() 690 | os.startfile('popsongs.xlsx') 691 | 692 | def pop_singers(self): 693 | url = 'https://www.9ku.com/geshou/all-all-liuxing.htm' 694 | base = 'https://www.9ku.com' 695 | self.singers_url = [] 696 | res_body = requests.get(url) 697 | soup_body = BeautifulSoup(res_body.text, 'html.parser') 698 | singers_body = soup_body.findAll(class_='t-i') 699 | for singer in singers_body[:50]: 700 | self.singers_url.append(base + singer['href']) 701 | self.get_pop_singers_songs() 702 | 703 | def get_pop_singers_songs(self): 704 | workbook = xlsxwriter.Workbook('popsingers.xlsx') 705 | url_base = 'https://www.9ku.com' 706 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '数据量较大,请耐心等待!') 707 | msg_box.exec_() 708 | for singer_url in self.singers_url: 709 | res_body = requests.get(singer_url) 710 | soup_body = BeautifulSoup(res_body.text, 'html.parser') 711 | # self.singers_name.append(soup_body.find(class_="t-t clearfix").h1.text) 712 | name = soup_body.find(class_="t-t clearfix").h1.text 713 | worksheet = workbook.add_worksheet(name) 714 | worksheet.write_row(0, 0, ['歌名', '歌曲url', '歌词url']) 715 | worksheet.set_column(0, 0, 20) 716 | worksheet.set_column(1, 2, 40) 717 | songs = soup_body.findAll(class_="songNameA") 718 | lyrics = soup_body.findAll(class_="chi") 719 | row = 1 720 | for song in songs[:-18]: 721 | worksheet.write_row(row, 0, [song.text, url_base+song['href'], url_base+lyrics[row-1]['href']]) 722 | row += 1 723 | workbook.close() 724 | os.startfile('popsingers.xlsx') 725 | 726 | def analysis(self): 727 | plt.close() 728 | # 解决中文显示的问题 729 | plt.rcParams['font.sans-serif'] = ['SimHei'] 730 | plt.rcParams['axes.unicode_minus'] = False 731 | x = ('0-10', '10-20', '20-30', '30-40', '40-50', '>50') 732 | data = [0, 0, 0, 0, 0, 0] 733 | if len(self.hot) == 0: 734 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '正在获取热门歌曲') 735 | msg_box.exec_() 736 | self.pop_songs() 737 | for hot in self.hot: 738 | if int(hot) < 10: 739 | data[0] += 1 740 | elif int(hot) < 20: 741 | data[1] += 1 742 | elif int(hot) < 30: 743 | data[2] += 1 744 | elif int(hot) < 40: 745 | data[3] += 1 746 | elif int(hot) < 50: 747 | data[4] += 1 748 | else: 749 | data[5] += 1 750 | plt.bar(x, data, color='steelblue', alpha=0.8) 751 | plt.title("pop500歌曲热度") 752 | plt.xlabel("歌曲热度范围") 753 | plt.ylabel("歌曲数量") 754 | plt.show() 755 | 756 | def my_collects(self): 757 | try: 758 | conn = pymysql.connect(host='localhost', user='root', password='129496', db='pyhomework') 759 | cur = conn.cursor() 760 | except: 761 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '数据库连接错误') 762 | msg_box.exec_() 763 | return 764 | 765 | try: 766 | sql = 'select * from collects where user="%s"' % (self.username) 767 | cur.execute(sql) 768 | conn.commit() 769 | except: 770 | msg_box = QMessageBox(QMessageBox.Warning, '错误提示', '系统错误') 771 | msg_box.exec_() 772 | 773 | row = 0 774 | collects = cur.fetchall() 775 | cur.close() 776 | conn.close() 777 | workbook = xlsxwriter.Workbook(self.username+'\'s collects.xlsx') 778 | worksheet = workbook.add_worksheet('music') 779 | worksheet.write_row(row, 0, ['歌手', '歌名', '歌曲资源地址']) 780 | for collect in collects: 781 | row += 1 782 | worksheet.write_row(row, 0, [collect[1], collect[2], collect[3]]) 783 | workbook.close() 784 | os.startfile(self.username+'\'s collects.xlsx') 785 | 786 | def my_downloads(self): 787 | try: 788 | conn = pymysql.connect(host='localhost', user='root', password='129496', db='pyhomework') 789 | cur = conn.cursor() 790 | except: 791 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '数据库连接错误') 792 | msg_box.exec_() 793 | return 794 | 795 | try: 796 | sql = 'select * from downloads where user="%s"' % (self.username) 797 | cur.execute(sql) 798 | conn.commit() 799 | except: 800 | msg_box = QMessageBox(QMessageBox.Warning, '错误提示', '系统错误') 801 | msg_box.exec_() 802 | 803 | row = 0 804 | collects = cur.fetchall() 805 | cur.close() 806 | conn.close() 807 | workbook = xlsxwriter.Workbook(self.username + '\'s downloads.xlsx') 808 | worksheet = workbook.add_worksheet('music') 809 | worksheet.write_row(row, 0, ['歌手', '歌名', '歌曲资源地址']) 810 | for collect in collects: 811 | row += 1 812 | worksheet.write_row(row, 0, [collect[1], collect[2], collect[3]]) 813 | workbook.close() 814 | os.startfile(self.username + '\'s downloads.xlsx') 815 | 816 | def change_account(self): 817 | self.close() 818 | dialog = LoginDialog() 819 | if dialog.exec_() == QDialog.Accepted: 820 | gui = MainUi(dialog.get_username()) 821 | gui.show() 822 | 823 | 824 | class LoginDialog(QDialog): 825 | def __init__(self, *args, **kwargs): 826 | super().__init__(*args, **kwargs) 827 | self.setWindowTitle('登录') 828 | self.setWindowIcon(QIcon('favicon.ico')) 829 | self.setFixedSize(960, 700) 830 | self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint) 831 | 832 | palette = QPalette() 833 | palette.setBrush(QPalette.Background, QBrush(QPixmap('1.jpg'))) 834 | self.setPalette(palette) 835 | 836 | # 设置界面控件 837 | self.frame = QFrame(self) 838 | self.frame.move(260, 110) 839 | self.mainLayout = QVBoxLayout(self.frame) 840 | 841 | self.nameEd1 = QLineEdit(self) 842 | self.nameEd1.setPlaceholderText("Admin") 843 | self.nameEd1.setFont(QFont('微软雅黑', 22)) 844 | op2 = QGraphicsOpacityEffect() 845 | op2.setOpacity(0.5) 846 | self.nameEd1.setGraphicsEffect(op2) 847 | self.nameEd1.setStyleSheet('''QLineEdit{border-radius:5px; padding: 8px}''') 848 | 849 | self.nameEd2 = QLineEdit(self) 850 | self.nameEd2.setPlaceholderText("Password") 851 | self.nameEd2.setFont(QFont('微软雅黑', 22)) 852 | self.nameEd2.setEchoMode(QLineEdit.Password) 853 | op5 = QGraphicsOpacityEffect() 854 | op5.setOpacity(0.5) 855 | self.nameEd2.setGraphicsEffect(op5) 856 | self.nameEd2.setStyleSheet('''QLineEdit{border-radius:5px; padding: 8px}''') 857 | 858 | self.btnLG = QPushButton('Login') 859 | op3 = QGraphicsOpacityEffect() 860 | op3.setOpacity(0.5) 861 | self.btnLG.setGraphicsEffect(op3) 862 | self.btnLG.setStyleSheet( 863 | '''QPushButton{background:#1E90FF;border-radius:5px;}QPushButton:hover{background:#4169E1;}\ 864 | QPushButton{font-family:'Arial';color:#FFFFFF; padding:6px}''') 865 | 866 | self.btnRG = QPushButton('Register') 867 | op3 = QGraphicsOpacityEffect() 868 | op3.setOpacity(0.5) 869 | self.btnRG.setGraphicsEffect(op3) 870 | self.btnRG.setStyleSheet( 871 | '''QPushButton{background:#1E90FF;border-radius:5px;}QPushButton:hover{background:#4169E1;}\ 872 | QPushButton{font-family:'Arial';color:#FFFFFF; padding:6px}''') 873 | # 874 | self.btnLG.setFont(QFont('Microsoft YaHei', 22)) 875 | self.btnRG.setFont(QFont('Microsoft YaHei', 22)) 876 | 877 | self.mainLayout.addWidget(self.nameEd1) 878 | self.mainLayout.addWidget(self.nameEd2) 879 | self.mainLayout.addWidget(self.btnLG) 880 | self.mainLayout.addWidget(self.btnRG) 881 | 882 | self.mainLayout.setSpacing(60) 883 | 884 | # 绑定按钮事件 885 | self.btnLG.clicked.connect(self.login) 886 | self.btnRG.clicked.connect(self.register) 887 | 888 | def login(self, event): # 登录 889 | username = self.nameEd1.text() 890 | password = self.nameEd2.text() 891 | if username == "" or password == "": 892 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '请输入用户名和密码') 893 | msg_box.exec_() 894 | return 895 | 896 | try: 897 | conn = pymysql.connect(host='localhost', user='root', password='129496', db='pyhomework') 898 | cur = conn.cursor() 899 | except: 900 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '数据库连接错误') 901 | msg_box.exec_() 902 | return 903 | 904 | try: 905 | sql = 'select * from users where username="%s"' % (username) 906 | cur.execute(sql) 907 | conn.commit() 908 | except: 909 | msg_box = QMessageBox(QMessageBox.Warning, '错误提示', '系统错误') 910 | msg_box.exec_() 911 | cur.close() 912 | conn.close() 913 | return 914 | 915 | user = cur.fetchone() 916 | cur.close() 917 | conn.close() 918 | if user is None: 919 | msg_box = QMessageBox(QMessageBox.Warning, '错误提示', '该用户不存在') 920 | msg_box.exec_() 921 | self.nameEd1.setText("") 922 | self.nameEd2.setText("") 923 | return 924 | 925 | if username == user[0] and password == user[1]: 926 | msg_box = QMessageBox(QMessageBox.Warning, '恭喜', '登陆成功') 927 | msg_box.exec_() 928 | self.username = username 929 | self.accept() 930 | 931 | else: 932 | msg_box = QMessageBox(QMessageBox.Warning, '错误提示', '用户名或者密码错误') 933 | msg_box.exec_() 934 | self.nameEd1.setText("") 935 | self.nameEd2.setText("") 936 | return 937 | 938 | def register(self, event): # 注册 939 | username = self.nameEd1.text() 940 | password = self.nameEd2.text() 941 | if username == "" or password == "": 942 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '用户名和密码不能为空') 943 | msg_box.exec_() 944 | return 945 | 946 | if len(username) > 10 or len(password) > 16: 947 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '用户名或密码过长') 948 | msg_box.exec_() 949 | return 950 | 951 | try: 952 | conn = pymysql.connect(host='localhost', user='root', password='129496', db='pyhomework') 953 | cur = conn.cursor() 954 | except: 955 | msg_box = QMessageBox(QMessageBox.Warning, '错误提示', '数据库连接失败') 956 | msg_box.exec_() 957 | return 958 | 959 | sql = 'insert into users values("%s","%s")' % (username, password) 960 | try: 961 | cur.execute(sql) 962 | conn.commit() 963 | msg_box = QMessageBox(QMessageBox.Warning, '恭喜', '注册成功') 964 | msg_box.exec_() 965 | self.nameEd1.setText("") 966 | self.nameEd2.setText("") 967 | except: 968 | conn.rollback() 969 | msg_box = QMessageBox(QMessageBox.Warning, '温馨提示', '用户名已经存在') 970 | msg_box.exec_() 971 | self.nameEd1.setText("") 972 | self.nameEd2.setText("") 973 | cur.close() 974 | conn.close() 975 | 976 | def get_username(self): 977 | return self.username 978 | 979 | 980 | def main(): 981 | app = QtWidgets.QApplication(sys.argv) 982 | dialog = LoginDialog() 983 | if dialog.exec_() == QDialog.Accepted: 984 | gui = MainUi(dialog.get_username()) 985 | gui.show() 986 | sys.exit(app.exec_()) 987 | 988 | 989 | if __name__ == '__main__': 990 | main() 991 | -------------------------------------------------------------------------------- /python大作业数据库.sql: -------------------------------------------------------------------------------- 1 | /* 2 | SQLyog Community v13.1.7 (64 bit) 3 | MySQL - 8.0.26 : Database - pyhomework 4 | ********************************************************************* 5 | */ 6 | 7 | /*!40101 SET NAMES utf8 */; 8 | 9 | /*!40101 SET SQL_MODE=''*/; 10 | 11 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 12 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 13 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 14 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 15 | CREATE DATABASE /*!32312 IF NOT EXISTS*/`pyhomework` /*!40100 DEFAULT CHARACTER SET utf8 */ /*!80016 DEFAULT ENCRYPTION='N' */; 16 | 17 | USE `pyhomework`; 18 | 19 | /*Table structure for table `collects` */ 20 | 21 | DROP TABLE IF EXISTS `collects`; 22 | 23 | CREATE TABLE `collects` ( 24 | `user` varchar(50) NOT NULL, 25 | `singer_name` varchar(50) DEFAULT NULL, 26 | `song_name` varchar(50) DEFAULT NULL, 27 | `song_url` varchar(200) DEFAULT NULL 28 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 29 | 30 | /*Data for the table `collects` */ 31 | 32 | insert into `collects`(`user`,`singer_name`,`song_name`,`song_url`) values 33 | ('129496','陈奕迅','2001太空漫游','https://mp3.haoge500.com/hot/2004/07-13/26373.mp3'), 34 | ('129496','陈奕迅','冤家','https://mp3.haoge500.com/hot/2004/07-13/140.mp3'), 35 | ('129496','陈奕迅','防不胜防','https://mp3.haoge500.com/mp3/20/19819.mp3'), 36 | ('129496','陈奕迅','2001太空漫游','https://mp3.haoge500.com/hot/2004/07-13/26373.mp3'), 37 | ('129496','陈奕迅','防不胜防','https://mp3.haoge500.com/mp3/20/19819.mp3'); 38 | 39 | /*Table structure for table `downloads` */ 40 | 41 | DROP TABLE IF EXISTS `downloads`; 42 | 43 | CREATE TABLE `downloads` ( 44 | `user` varchar(50) NOT NULL, 45 | `singer_name` varchar(50) DEFAULT NULL, 46 | `song_name` varchar(50) DEFAULT NULL, 47 | `song_url` varchar(200) DEFAULT NULL 48 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 49 | 50 | /*Data for the table `downloads` */ 51 | 52 | insert into `downloads`(`user`,`singer_name`,`song_name`,`song_url`) values 53 | ('129496','陈奕迅','防不胜防','https://mp3.haoge500.com/mp3/20/19819.mp3'); 54 | 55 | /*Table structure for table `users` */ 56 | 57 | DROP TABLE IF EXISTS `users`; 58 | 59 | CREATE TABLE `users` ( 60 | `username` varchar(50) COLLATE utf8_bin NOT NULL, 61 | `password` varchar(100) COLLATE utf8_bin DEFAULT NULL, 62 | PRIMARY KEY (`username`) 63 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin; 64 | 65 | /*Data for the table `users` */ 66 | 67 | insert into `users`(`username`,`password`) values 68 | ('123456789','123456789'), 69 | ('129496','123456'), 70 | ('Linno','123456'), 71 | ('xxx','129496'); 72 | 73 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 74 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 75 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 76 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 77 | --------------------------------------------------------------------------------