python实现某网站的音乐下载

写在前面:首先,理论上讲,如果歌曲可以在网页上播放,那么一定有网址(source src)保存着歌曲的源文件。那么利用火狐(或者谷歌)浏览器的F12功能,就可以快速提取出该source src,进而完成歌曲下载了。基于上述操作,我就想到了用python把如前所述封装起来,输入歌曲名称进行选择进而完成下载。

1. 前期准备

  • 开发环境:win10 + py3.5(即windows + py3.x)

  • 需要安装的库:requests 和 selenium(具体安装方法网上有很多,这里不再赘述。其中关于selenium的教程建议参考虫师的《selenium2 python自动化测试》)

  • ps. 这里的某网站指的是QQ音乐,当然酷狗音乐原理相同。网易云会涉及到更加复杂的跳转,由于没有学过前端,暂时无法处理。。。

2. 具体步骤

2.1 网址定位

打开QQ音乐,使用“搜索”按钮进行搜索后(以搜索-崇拜-为例),得到的结果为:

搜索网址

从图中复制可以得到歌曲搜索网址如下:

https://y.qq.com/portal/search.html#page=1&searchid=1&remoteplace=txt.yqq.top&t=song&w=%E5%B4%87%E6%8B%9C

注意:上述网址中的%E5%B4%87%E6%8B%9C是“崇拜”的HTML可识别编码形式。

接下来我们使用requests.get(url)就可以得到页面内容了,让我们看一下结果:

# coding:utf-8
# 测试返回结果

import requests
import urllib.request

headers = {
        'Host': 'y.qq.com',
        'User-Agent': '', # 这个大家用自己的就好
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
        'Accept-Encoding': 'gzip, deflate, br',
        'Referer': 'http://y.qq.com/',
        'Connection': 'keep-alive',
        'Cache-Control': 'max-age=0',
    }
MusicName = "崇拜"  # 测试用例
urlMusicName = urllib.parse.quote(MusicName)  # 转换成url可以读取的字符串

url = "https://y.qq.com/portal/search.html#page=1&searchid=1&remoteplace=txt.yqq.top&t=song&w=" + urlMusicName
response = requests.get(url, headers = headers)
print(response.text)

运行上述代码,打印结果如下所示:

第一次打印结果图

由于结果太长,这里我们截取一部分观察。发现结果中出现很多乱码,原来是缺失对response编码的结果。在上述代码中进行修改:

    response = requests.get(url, headers = headers)
    response.encoding = 'utf-8'   # 对结果进行utf-8编码

此时再重新打印,就可以显示中文了!

但是我们会发现,在返回的结果中,并没有显示出歌曲列表,这是为什么呢?

对比一下原网页的F12结果和返回结果我们发现,在原网页中,歌曲列表是存在在这个div里的:

<div class="js_search_tab_cont" id="song_box" style="display: block;">

但是在返回结果中,该div标签的显示为:

<div class="js_search_tab_cont" id="song_box"></div>

内容为空!这也就解释了为什么我们无法得到歌曲列表了,因为根本没有加载出来。

为了进一步解释这个问题,我们需要做以下几件事:

  1. 打开火狐浏览器(因为我selenium用的火狐,所以这里都是使用火狐浏览器,当然使用谷歌也完全没有问题~~),在地址栏中输入about:config,进入浏览器设置页面。

  2. 在页面中输入javascript.enabled,找到后 鼠标右键-切换。

  3. 这样我们就将浏览器的javascript关掉了。

  4. 关掉之后再重新加载原搜索网页,可以发现歌曲列表不见了。

通过上述操作,我们已经弄明白原因,那就是该歌曲列表是通过JavaScript进行加载,而非静态网页,也因此,我们使用静态网页方法进行获取时,是得不到加载后的歌曲列表的。

为了解决上述问题,也查看了不少方法,觉得说的比较全面在这里:传送门-知乎

最后,我选择了一种最不智能的方法,就是—暗中观察。

继续F12,网络–JS–“clint_search”找到了js跳转的真正网址,具体如图:

暗中观察

这样就完成了请求网址的定位,万里长征走完第一步~

2.2 歌曲列表打印

可能有同学要问了,为什么我们要去定位上述网址呢,上述网址打开之后是什么样子呢?

网址打开

乱乱的,像json。为了方便阅读,这里直接使用火狐自带的阅读模式,就是上图中红色框中的button,点击,继续观察:

阅读模式

注意图中红色框出的部分,“media_mid”,“name”,“title”。后面两个很好解释,那么第一个是做什么用的呢?

在歌曲列表网页中随便点击一首歌曲,可以发现其跳转后的URL为:

https://y.qq.com/n/yqq/song/003JlYgD1SvCYe.html

后面这一长串就是media_mid,原来它是用来定位歌曲的。

具体如何从json中查找出全部有用信息,这就涉及到了python 正则匹配的问题,建议大家自行学习,这里匹配不难,注意细节即可!

将全部有用信息提取出来后,存入字典,并打印在屏幕上,这样就可以自己选择想下载的歌曲了。

歌曲列表打印

其中,字符串的对齐需要注意一下。因为包含中文和标点符号,因此直接使用`”%-10s”等python自带的对齐方式是不行的,需要重新写对齐函数,我参考了这里中文字符对齐-传送门,并进行了部分修改,得到字符对齐函数如下:

# ================中文检测函数====================
# 参考网址:http://lib.csdn.net/article/python/66507?knId=160
def findChinese(source):
    # text = source.decode('utf8')   # python3 默认为unicode
    r = re.findall('[\u4e00-\u9fa5]', source)
    # 去除空格影响
    condition = lambda t: t != ' '
    results = list(filter(condition, r))
    return results


# ===============填充字符函数======================
# 参考网址:http://lib.csdn.net/article/python/66507?knId=160
# 输入变量说明:
# un_align_str: 输入字符串
# lenh: 半角字符个数;自己设置;默认为0
# lenf: 全角字符个数;自己设置;默认为0
# addh: 半角字符空格
# addf: 全角字符空格
def myAlign(un_align_str, lenh = 0, lenf = 0, addh = ' ', addf = u' '):
    assert isinstance(lenh, int)   # 断言半角长度为整形变量
    assert isinstance(lenf, int)   # 断言全角长度为整形变量
    slen = len(un_align_str)
    # 中文在默认的utf-8编码下显示占用约2个字符
    chn = findChinese(un_align_str)
    numchn = len(chn)
    numspn = slen - numchn
    str = addh * (lenh - numspn) + addf * (lenf - 2 * numchn)
    return str

OK,完成歌曲列表打印!

2.3 链接跳转与歌曲下载

我们发现,当我们点击歌曲的-播放-按钮时,实际上完成的是一次网页跳转(jump~jump~)

跳转

对于这种类似于人的操作,我们可以使用selenium来进行模拟。

具体过程也可以描述成如下步骤:

  1. 定位“播放”按钮

  2. 模拟鼠标左键单击操作

  3. 读取跳转后的网页,查找source src

由于页面加载需要时间,这里我直接使用的是time.sleep()函数来进行等待,另外针对多窗口之间的跳转,selenium也给出了API,那就是driver.window_handles

在这里,需要利用time.sleep()等待句柄加载完成,否则会出现无法读取的情况,因此我用了如下判断语句进行处理

    count = 0
    allhandles = driver.window_handles
    for handle in allhandles:
        count += 1
    if count == 2:
        driver.switch_to_window(driver.window_handles[1])
    else:
        time.sleep(5)
        driver.switch_to_window(driver.window_handles[1])

有了当前driver,我们就可以读取driver.page_source,正则匹配出source src,然后利用requests.get(url).content完成歌曲下载啦!

3. 相关源码

源码已经上传,大家可以自行下载:QQ音乐下载器源码

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现在线音乐播放器需要前端和后端的技术。前端技术可以使用HTML、CSS和JavaScript,后端技术可以使用Python。 下面是一个基于Python Flask框架实现的在线音乐播放器的示例代码: ```python from flask import Flask, render_template, url_for, request import os app = Flask(__name__) @app.route("/") def index(): music_list = os.listdir("static/music") return render_template("index.html", music_list=music_list) @app.route("/play", methods=["POST"]) def play(): music_name = request.form["music_name"] return render_template("play.html", music_name=music_name) if __name__ == "__main__": app.run(debug=True) ``` 这是一个简单的后端代码,我们需要在`static/music`文件夹下放置音乐文件,然后通过前端页面来实现在线播放。下面是HTML代码: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>在线音乐播放器</title> </head> <body> <h1>在线音乐播放器</h1> <ul> {% for music in music_list %} <li> <form action="{{ url_for('play') }}" method="post"> <input type="hidden" name="music_name" value="{{ music }}" /> <button type="submit">{{ music }}</button> </form> </li> {% endfor %} </ul> </body> </html> ``` 这是主页的HTML代码,我们通过Python代码中的`music_list = os.listdir("static/music")`获取`static/music`文件夹下的所有音乐文件,然后通过循环展示在页面上。当用户点击某个音乐文件时,会提交一个POST请求到`/play`路由,Python代码中的`play()`函数会接收到这个请求,然后渲染一个新的页面。 下面是播放页面的HTML代码: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>{{ music_name }}</title> </head> <body> <h1>{{ music_name }}</h1> <audio controls src="{{ url_for('static', filename='music/' + music_name) }}"></audio> </body> </html> ``` 这是播放页面的HTML代码,我们通过Python代码中的`music_name = request.form["music_name"]`获取用户选择的音乐文件名称,然后在页面上渲染出音乐名称和播放器。由于音乐文件在`static/music`文件夹下,因此我们使用`url_for('static', filename='music/' + music_name)`来获取音乐文件的URL。 这样,我们就完成了一个简单的在线音乐播放器的实现。当用户访问`http://127.0.0.1:5000/`时,会展示出音乐列表,用户选择某个音乐文件后,会跳转到播放页面,自动播放该音乐文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值