网易云音乐下载软件(上)

一. 创建软件界面

这里使用tkinter来实现前端界面:
导入库:

from tkinter import * 

实现前端界面:

# ****************************最底层画布相关设置***********************
# 创建画布界面
root = Tk()
# 创建界面标题
root.title('网易云下载器')
# 设置界面长和宽
root.geometry('560x450')

# *****************************Label标签******************************
# 添加标签控件,第一个参数表明将label控件安置在root画布界面上
label = Label(root, text='请输入下载歌曲:', font=('华文行楷', 20))
# grid函数用来定位控件,不指定参数时,默认row=0 column=0
label.grid() 

# *****************************entry输入框*******************************
entry = Entry(root, font=('隶书', 20))
entry.grid(row=0, column=1)


# *****************************text文本标签******************************
# 列表框
text = Listbox(root, font=('楷书', 20), width=40, height=12)
text.grid(row=1, columnspan=2)

# *****************************Label标签*********************************
# 按钮
button = Button(root, text='下载歌曲', font=('隶书', 15), command=get_music_name)
button.grid(row=2, column=0, sticky=W)

button = Button(root, text='退出歌曲', font=('隶书', 15), command=root.quit)
button.grid(row=2, column=1, sticky=E)

root.mainloop()

运行显示:
在这里插入图片描述

二. 后端实现

后端的实现借助于:selenium浏览器自动化测试工具 以及 urllib用于操作URL的库
导入库:

from selenium import webdriver
from urllib.request import urlretrieve

浏览器驱动安装:

选择浏览器并安装相应的驱动,这里我选择Chrome浏览器,所以安装相应的chromedriver:chromedriver官网网址

这里一定要注意Chrome版本与chromedriver版本的对应关系,下载相对应的版本

以上工作完成后,我们开始针对网站进行操作

1. 分析搜索网址

打开网易云官网:官网地址
在搜索框中搜索一首歌的名字,这里我选的歌曲:《绿色》
随后进入搜索结果页面,观察网址
在这里插入图片描述
这里可以找到规律,将s="绿色"中的绿色key值替换成其他任意歌曲,都可以得到相应歌曲搜索结果,那么可以将key值进行输入处理

s_name = '绿色'
url = 'https://music.163.com/#/search/m/?s={}&type=1'.format(s_name)

再设置浏览器驱动,并指明驱动路径,这里我的路径放在当前目录下:

path = r'../chromedriver.exe'
driver = webdriver.Chrome(executable_path=path)

启动驱动:

driver.get(url=url)

2. 分析搜索页面与歌曲链接

由于歌曲的链接嵌套在HTML页面中,所以想要获取该链接去下载歌曲,需要对页面进行分析与提取

对页面的内容进行分析与提取有很多种方法,可以使用XPath,正则,bs4等等,但我习惯使用XPath,后面使用XPath进行操作

使用谷歌开发者工具,对歌曲搜索页面的歌曲进行定位与分析
首先可以看到,该页面为HTML内联框架,即HTML中嵌套了一个HTML
在这里插入图片描述
对该形式,XPath语法无法直接定位到内部的HTML,所以需要进行文档转换

driver.switch_to.frame('g_iframe')

进入到内部HTML文档后,我们接着往后分析,可以找到,包含歌曲信息的根标签
在这里插入图片描述
扩展根标签,展开第二个直接子标签,可以看到包含歌曲的链接
在这里插入图片描述
但该链接并没有直接提供一个可以直接下载歌曲的mp3文件,所以,转换思路,进行抓包,利用谷歌开发者工具自带的抓包工具进行抓包。

打开谷歌开发者工具,刷新页面
点击一首歌,使浏览器自动请求歌曲URL,便于我们找寻歌曲链接
点搜索框中,输入mp3,进行匹配,随后获取到歌曲链接
在这里插入图片描述
页面点击打开,可以获取该歌曲的mp3文件:
在这里插入图片描述
但观察该链接,可以发现一个问题,该链接有时间参数,表明会随着时间而失效,如果使用该链接进行自动化爬取,可能下次爬取就会获取不到任何信息甚至报错,因为链接失效了。

3. 使用歌曲外链

外链的使用与概念:

由于直接获取的歌曲链接存在不稳定性,所以,我们需要一条稳定的,可以使用并且可以长期使用的链接,这里就引入了外链。

可查看百度经验关于外链的概念:外链

如何获取到歌曲的外链?
外链制作网站有很多,有免费的也有收费的;也有网站上通过其他渠道获得的。
这里提供一个制作外链的免费网站:HHTJim’s部落格 Web App
在这里插入图片描述
支持网易云音乐,QQ音乐、百度音乐三种外链转换,输入歌曲页面的链接即可
在这里插入图片描述
但这里我使用一种较普遍的、大众化的外链链接:

http://music.163.com/song/media/outer/url?id=1345848098.mp3

该id为《绿色》歌曲的id,将该链接输入浏览器进行搜索,可以获得歌曲的mp3文件,即可下载

同样,将链接进行改写

song_id = 1345848098
song_url = 'http://music.163.com/song/media/outer/url?id={}.mp3'.format(song_id)

4. 获取歌曲链接、下载歌曲完整实现

通过上面的外链获取歌曲可以看到,只需获得歌曲的id即可得到歌曲的下载链接,而歌曲的id通过搜索页面定位相应的歌曲而得到。

网易云音乐 ---(搜歌)---> 搜索页面 ---(定位目标歌曲)---> 获取歌曲id
                                                       +
歌曲页面网址 ------(外链网站)---(其他途径)------------> 外链 
                                                       |
                                                       ----> 歌曲mp3文件

这里有获取歌曲链接和下载歌曲两个功能,所以封装成两个函数
获取歌曲链接:

def get_music_name():
	# 获取搜索页面URL
	s_name = '绿色'
	url = 'https://music.163.com/#/search/m/?s={}&type=1'.format(s_name)
	
	# 设置浏览器驱动,定位路径
	path = r'../chromedriver.exe'
    driver = webdriver.Chrome(executable_path=path)
    driver.get(url=url)

	# 浏览器内容进行分析
	# 进入内嵌HTML
	driver.switch_to.frame('g_iframe')

	# 获取歌曲id与歌手名(可自行定位,可定位到结果即可)
	se = driver.find_element_by_id('m-search')
	mu_id = se.find_element_by_xpath('.//div[@class="item f-cb h-flag  "]//div[2]//a').get_attribute('href')
	singer_id = se.find_element_by_xpath('.//div[@class="item f-cb h-flag  "]//div[4]//a').text
	# 取出id那一部分
	song_id = m_id.split('=')[1]
	# 定位歌曲名字
    song_name = req.find_element_by_xpath('.//div[@class="item f-cb h-flag  "]//div[2]//b').get_attribute('title')
	
	# 定义一个字典存储:歌曲id、歌曲名字、歌手
    item = {}
    item["song_id"] = song_id
    item["song_name"] = song_name
    item["singer_name"] = singer_name

    song_load(item=item)

下载歌曲:

def song_load(item):
    song_id = item['song_id']
    song_name = item['song_name']
    singer_name = item['singer_name']

    song_url = 'http://music.163.com/song/media/outer/url?id={}.mp3'.format(song_id)
    # 歌曲路径
    os.makedirs('music', exist_ok=True)  # 如果文件夹存在,不会报错,不会继续创建
    path = 'music/{}-{}.mp3'.format(song_name, singer_name)

    # 下载提示文本
    text.insert(END, '歌曲:{},正在下载......'.format(song_name))
    # 文本框滚动
    text.see(END)
    # 更新
    text.update()

    # 计时start
    start = time.clock()
    # 下载
    urlretrieve(song_url, path)
    # 计时end
    end = time.clock()
    # 结果
    cost = end-start

    # 下载完毕
    # 完毕提示文本
    text.insert(END, '歌曲:{},演唱:{},下载完毕, 共花费{:.2f}s!'.format(song_name, singer_name, cost))
    # 文本框滚动
    text.see(END)
    # 更新
    text.update()

三. 前后端整合

前面的前端代码与后端代码可以分别运行,但是如何整合到一起,根据用户输入的歌名和歌手,自动下载歌曲呢?

只需要在get_music_name()函数内部进行更改:
s_name = '绿色'改为s_name=entry1.get()
更改url变量为url = 'https://music.163.com/#/search/m/?s={}&type=1'.format(s_name, s_singer)

四. 实现chromeless无头浏览器

至此,已经基本完成了软件的代码设计,但是,每次运行时,总会弹出浏览器,会影响使用体验,那么需要对chrome进行配置

添加一个函数

    def share_browser(self):
        chrome_options = Options()
        chrome_options.add_argument('--headless')
        chrome_options.add_argument('--disable-gpu')

        # 本机google浏览器路径
        path = r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
        chrome_options.binary_location = path
        # 路径自定义,这里是我电脑的路径
        driver_path = r'D:\PyCharm 2018\3WebSpiders\网易云音乐下载\chromedriver.exe'
        browser = webdriver.Chrome(chrome_options=chrome_options, executable_path=driver_path)
        return browser

由于上面的函数实现了chrome驱动,那么更改get_music_name函数中的驱动变量

# path = r'D:\PyCharm 2018\3WebSpiders\网易云音乐下载\chromedriver.exe'
# driver = webdriver.Chrome(executable_path=path)

driver = self.share_browser()
driver.get(url=url)

五. 整体代码

# -*- coding:utf-8 -*-
from tkinter import *

import os
from urllib.request import urlretrieve
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

import time
# https://music.163.com/#/search/m/?s=绿色&type=1


def get_music_name():
    s_name = entry1.get()
    url = 'https://music.163.com/#/search/m/?s={}&type=1'.format(s_name)
    "https://music.163.com/#/search/m/?s=%E7%BB%BF%E8%89%B2%20%E6%A2%A6%E9%80%B8%E9%A3%9E&type=1"


    # path = r'D:\PyCharm 2018\3WebSpiders\网易云音乐下载\chromedriver.exe'
    # driver = webdriver.Chrome(executable_path=path)

    driver = share_browser()
    driver.get(url=url)

    driver.switch_to.frame('g_iframe')

    # 获取歌曲id
    req = driver.find_element_by_id('m-search')
    m_id = req.find_element_by_xpath('.//div[starts-with(@class,"item f-cb h-flag  ")]//div[2]//a').get_attribute('href')
    singer_name = req.find_element_by_xpath('.//div[starts-with(@class,"item f-cb h-flag  ")]//div[4]//a').text

    song_id = m_id.split('=')[1]
    song_name = req.find_element_by_xpath('.//div[@class="item f-cb h-flag  "]//div[2]//b').get_attribute('title')

    item = {}
    item["song_id"] = song_id
    item["song_name"] = song_name
    item["singer_name"] = singer_name

    song_load(item=item)

def song_load(item):
    song_id = item['song_id']
    song_name = item['song_name']
    singer_name = item['singer_name']

    song_url = 'http://music.163.com/song/media/outer/url?id={}.mp3'.format(song_id)
    # 歌曲路径
    os.makedirs('music', exist_ok=True)  # 如果文件夹存在,不会报错,不会继续创建
    path = 'music/{}-{}.mp3'.format(song_name, singer_name)

    # 下载提示文本
    text.insert(END, '歌曲:{},正在下载.......Loading......'.format(song_name))
    # 文本框滚动
    text.see(END)
    # 更新
    text.update()

    # 计时start
    start = time.clock()
    # 下载
    urlretrieve(song_url, path)
    # 计时end
    end = time.clock()
    # 结果
    cost = end - start

    # 下载完毕
    # 完毕提示文本
    text.insert(END, '歌曲:{},演唱:{},下载完毕!共花费{:.2f}s!'.format(song_name, singer_name, cost))
    # 文本框滚动
    text.see(END)
    # 更新
    text.update()

# 构建浏览器静默模式
def share_browser():
    chrome_options = Options()
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--disable-gpu')

    # 本机google浏览器路径
    path = r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
    chrome_options.binary_location = path
    browser = webdriver.Chrome(chrome_options=chrome_options)
    return browser

# 创建界面
root = Tk()
# 界面标题
root.title('网易云下载器')
# 界面长和宽
root.geometry('620x450')
# 标签控件
label = Label(root, text='请输入下载歌曲:', font=('华文行楷', 20))
# 标签定位
label.grid(row=0, column=0)  # 默认row=0 column=0

entry1 = Entry(root, font=('隶书', 20), width=22)
entry1.grid(row=0, column=1)


# 列表框
text = Listbox(root, font=('楷书', 20), width=44, height=12)
text.grid(row=1, columnspan=2)
# 按钮
button = Button(root, text='下载歌曲', font=('隶书', 15), command=get_music_name)
button.grid(row=2, column=0, sticky=W)

button = Button(root, text='退出歌曲', font=('隶书', 15), command=root.quit)
button.grid(row=2, column=1, sticky=E)

root.mainloop()


# pyinstaller -F -w(去除命令行窗口) -i 图片路径 py文件

六. 运行演示

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值