现在的音乐APP有很多,为了不下载很多的APP,所以咱用python做了一个聚合的音乐下载器,现在聚合了咪咕音乐、QQ音乐,下面是效果图

安装

需要安装一个辅助模块 prettytable,用于美化控制台的表格输出

pip install prettytable

提取音乐链接

搜索音乐

以下载 QQ 音乐为例,在首页(https://y.qq.com/) 上的搜索框中搜索 «厚颜无耻», 打开 F12 的控制台面板,可以找到如下图的搜索链接,这个链接返回的是一个音乐列表的 json 串

def get_request(self, url):

try:

headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36'

}

response = requests.get(url, headers = headers)

if response.status_code == 200:

return response

except Exception as e:

print("请求出错:", e)

return None

def search_music(self, key):

# 20: 查询 20 条数据,key:关键字

url = 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp?p=1&n=%d&w=%s' % (20, key)

resp = self.get_request(url)

resp_json = json.loads(resp.text[9:][:-1])

data_song_list = resp_json['data']['song']['list']

song_list = []

for song in data_song_list:

singers = [s.get("name", "") for s in song.get("singer", "")]

song_list.append({'name': song['songname'], 'songmid': song['songmid'], 'singer': '|'.join(singers)})

return song_list

示例结果:

[{'name': '富士山下', 'songmid': '003dtkNk26WhJD', 'singer': '陈奕迅'}, {'name': '不要说话', 'songmid': '002B2EAA3brD5b', 'singer': '陈奕迅'}, ...., {'name': '最佳损友', 'songmid': '003hFxQh276Cv5', 'singer': '陈奕迅'}]

获取下载链接

把音乐列表页中的歌曲点击到播放音乐的页面,在控制面板找到多个以 m4a 结尾的音乐实际链接

它的参数部分有一个 vkey 的参数,把 vkey 当作关键字在 Network 面板中搜索,找到一个 musics.fcg 结尾的链接,vkey 的数据就在它返回的 json 串中,另外的 purl 的值就是上面的 m4a 链接,最后将 https://ws.stream.qqmusic.qq.com 和 purl 拼凑成音乐链接,musics.fcg 链接中 guid 参数是一个随机数,songmid 参数是上面单个音乐的 songmid,uin 参数是 QQ 号

def download_url(self, song):

guid = str(random.randrange(1000000000, 10000000000))

purl_url = 'https://u.y.qq.com/cgi-bin/musicu.fcg?' \

'&data={"req":{"param":{"guid":" %s"}},' \

'"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"%s","songmid":["%s"],"uin":"%s"}},"comm":{"uin":%s}}' \

% (guid, guid, song['songmid'], 0, 0)

resp = self.get_request(purl_url)

if resp is None:

return 'N', 'None', '.m4a'

resp_json = json.loads(resp.text)

purl = resp_json['req_0']['data']['midurlinfo'][0]['purl']

# 有些音乐在网站上不能听

if len(purl) < 1:

msg = 'N'

download_url = 'http://ws.stream.qqmusic.qq.com/' + purl

song_data = self.get_request(download_url)

if song_data:

msg = 'Y'

return msg, download_url, '.m4a'

示例结果:

只有一个域名的地址的下载链接表示这个音乐只能在客户端听,网页版听不了

到这里已经完了 QQ 音乐的搜索、抓取脚本,用同样的方式抓取咪咕音乐(http://m.music.migu.cn)做成咪咕音乐脚本,咪咕音乐更容易爬取

命令行主界面

主界面的主要功能就是以表格的方式显示搜索到的音乐和以序号的方式下载音乐

import os

from qqMusic import QQMusic

from miguMusic import MiGuMusic

from prettytable import PrettyTable

class MusicBox(object):

def __init__(self):

pass

def download(self, data, songName, type):

save_path = 'music/' + songName + '.' + type

file = 'music'

if os.path.exists(file):

pass

else:

os.mkdir('music')

try:

print("{}下载中.....".format(songName), end='')

with open(save_path, 'wb') as f:

f.write(data)

print("已下载完成")

except Exception as err:

print("文件写入出错:", err)

return None

def main(self):

print('请输入需要下载的歌曲或者歌手:')

key = input()

print('正在查询..import os

from qqMusic import QQMusic

from miguMusic import MiGuMusic

from prettytable import PrettyTable

class MusicBox(object):

def __init__(self):

pass

def download(self, data, songName, type):

save_path = 'music/' + songName + '.' + type

file = 'music'

if os.path.exists(file):

pass

else:

os.mkdir('music')

try:

print("{}下载中.....".format(songName), end='')

with open(save_path, 'wb') as f:

f.write(data)

print("已下载完成")

except Exception as err:

print("文件写入出错:", err)

return None

def main(self):

print('请输入需要下载的歌曲或者歌手:')

key = input()

print('正在查询..\033[32mQQ音乐\033[0m', end='')

qqMusic = QQMusic()

qq_song_list = qqMusic.main(key)

print('...\033[31m咪咕音乐\033[0m')

miguMusic = MiGuMusic()

migu_song_list = miguMusic.main(key)

qq_song_list.extend(migu_song_list)

song_dict = {}

for song in qq_song_list:

key = song['name'] + '\\' + song['singer']

s = song_dict.get(key)

if s:

if s['msg'] != 'Y':

song_dict[key] = song

else:

song_dict[key] = song

i = 0

table = PrettyTable(['序号', '歌手', '下载', '歌名'])

table.border = 0

table.align = 'l'

for song in list(song_dict.values()):

i = i + 1

table.add_row([str(i), song['singer'], song['msg'], song['name']])

print(table)

while 1:

print('\n请输入需要下载,按 q 退出:')

index = input()

if index == 'q':

return

song = list(song_dict.values())[int(index) - 1]

data = qqMusic.get_request(song['downloadUrl'])

if song['msg'] == 'Y':

self.download(data.content, song['name'], song['type'])

else:

print('该歌曲不允许下载')

if __name__ == '__main__':

musicBox = MusicBox()

musicBox.main()

33[32mQQ音乐import os

from qqMusic import QQMusic

from miguMusic import MiGuMusic

from prettytable import PrettyTable

class MusicBox(object):

def __init__(self):

pass

def download(self, data, songName, type):

save_path = 'music/' + songName + '.' + type

file = 'music'

if os.path.exists(file):

pass

else:

os.mkdir('music')

try:

print("{}下载中.....".format(songName), end='')

with open(save_path, 'wb') as f:

f.write(data)

print("已下载完成")

except Exception as err:

print("文件写入出错:", err)

return None

def main(self):

print('请输入需要下载的歌曲或者歌手:')

key = input()

print('正在查询..\033[32mQQ音乐\033[0m', end='')

qqMusic = QQMusic()

qq_song_list = qqMusic.main(key)

print('...\033[31m咪咕音乐\033[0m')

miguMusic = MiGuMusic()

migu_song_list = miguMusic.main(key)

qq_song_list.extend(migu_song_list)

song_dict = {}

for song in qq_song_list:

key = song['name'] + '\\' + song['singer']

s = song_dict.get(key)

if s:

if s['msg'] != 'Y':

song_dict[key] = song

else:

song_dict[key] = song

i = 0

table = PrettyTable(['序号', '歌手', '下载', '歌名'])

table.border = 0

table.align = 'l'

for song in list(song_dict.values()):

i = i + 1

table.add_row([str(i), song['singer'], song['msg'], song['name']])

print(table)

while 1:

print('\n请输入需要下载,按 q 退出:')

index = input()

if index == 'q':

return

song = list(song_dict.values())[int(index) - 1]

data = qqMusic.get_request(song['downloadUrl'])

if song['msg'] == 'Y':

self.download(data.content, song['name'], song['type'])

else:

print('该歌曲不允许下载')

if __name__ == '__main__':

musicBox = MusicBox()

musicBox.main()

33[0m', end='')

qqMusic = QQMusic()

qq_song_list = qqMusic.main(key)

print('...import os

from qqMusic import QQMusic

from miguMusic import MiGuMusic

from prettytable import PrettyTable

class MusicBox(object):

def __init__(self):

pass

def download(self, data, songName, type):

save_path = 'music/' + songName + '.' + type

file = 'music'

if os.path.exists(file):

pass

else:

os.mkdir('music')

try:

print("{}下载中.....".format(songName), end='')

with open(save_path, 'wb') as f:

f.write(data)

print("已下载完成")

except Exception as err:

print("文件写入出错:", err)

return None

def main(self):

print('请输入需要下载的歌曲或者歌手:')

key = input()

print('正在查询..\033[32mQQ音乐\033[0m', end='')

qqMusic = QQMusic()

qq_song_list = qqMusic.main(key)

print('...\033[31m咪咕音乐\033[0m')

miguMusic = MiGuMusic()

migu_song_list = miguMusic.main(key)

qq_song_list.extend(migu_song_list)

song_dict = {}

for song in qq_song_list:

key = song['name'] + '\\' + song['singer']

s = song_dict.get(key)

if s:

if s['msg'] != 'Y':

song_dict[key] = song

else:

song_dict[key] = song

i = 0

table = PrettyTable(['序号', '歌手', '下载', '歌名'])

table.border = 0

table.align = 'l'

for song in list(song_dict.values()):

i = i + 1

table.add_row([str(i), song['singer'], song['msg'], song['name']])

print(table)

while 1:

print('\n请输入需要下载,按 q 退出:')

index = input()

if index == 'q':

return

song = list(song_dict.values())[int(index) - 1]

data = qqMusic.get_request(song['downloadUrl'])

if song['msg'] == 'Y':

self.download(data.content, song['name'], song['type'])

else:

print('该歌曲不允许下载')

if __name__ == '__main__':

musicBox = MusicBox()

musicBox.main()

33[31m咪咕音乐import os

from qqMusic import QQMusic

from miguMusic import MiGuMusic

from prettytable import PrettyTable

class MusicBox(object):

def __init__(self):

pass

def download(self, data, songName, type):

save_path = 'music/' + songName + '.' + type

file = 'music'

if os.path.exists(file):

pass

else:

os.mkdir('music')

try:

print("{}下载中.....".format(songName), end='')

with open(save_path, 'wb') as f:

f.write(data)

print("已下载完成")

except Exception as err:

print("文件写入出错:", err)

return None

def main(self):

print('请输入需要下载的歌曲或者歌手:')

key = input()

print('正在查询..\033[32mQQ音乐\033[0m', end='')

qqMusic = QQMusic()

qq_song_list = qqMusic.main(key)

print('...\033[31m咪咕音乐\033[0m')

miguMusic = MiGuMusic()

migu_song_list = miguMusic.main(key)

qq_song_list.extend(migu_song_list)

song_dict = {}

for song in qq_song_list:

key = song['name'] + '\\' + song['singer']

s = song_dict.get(key)

if s:

if s['msg'] != 'Y':

song_dict[key] = song

else:

song_dict[key] = song

i = 0

table = PrettyTable(['序号', '歌手', '下载', '歌名'])

table.border = 0

table.align = 'l'

for song in list(song_dict.values()):

i = i + 1

table.add_row([str(i), song['singer'], song['msg'], song['name']])

print(table)

while 1:

print('\n请输入需要下载,按 q 退出:')

index = input()

if index == 'q':

return

song = list(song_dict.values())[int(index) - 1]

data = qqMusic.get_request(song['downloadUrl'])

if song['msg'] == 'Y':

self.download(data.content, song['name'], song['type'])

else:

print('该歌曲不允许下载')

if __name__ == '__main__':

musicBox = MusicBox()

musicBox.main()

33[0m')

miguMusic = MiGuMusic()

migu_song_list = miguMusic.main(key)

qq_song_list.extend(migu_song_list)

song_dict = {}

for song in qq_song_list:

key = song['name'] + '\' + song['singer']

s = song_dict.get(key)

if s:

if s['msg'] != 'Y':

song_dict[key] = song

else:

song_dict[key] = song

i = 0

table = PrettyTable(['序号', '歌手', '下载', '歌名'])

table.border = 0

table.align = 'l'

for song in list(song_dict.values()):

i = i + 1

table.add_row([str(i), song['singer'], song['msg'], song['name']])

print(table)

while 1:

print('\n请输入需要下载,按 q 退出:')

index = input()

if index == 'q':

return

song = list(song_dict.values())[int(index) - 1]

data = qqMusic.get_request(song['downloadUrl'])

if song['msg'] == 'Y':

self.download(data.content, song['name'], song['type'])

else:

print('该歌曲不允许下载')

if __name__ == '__main__':

musicBox = MusicBox()

musicBox.main()

总结

音乐聚合下载器最重要的部分还是爬虫抓取各个音乐网站的数据,命令行的方式则省去了画 GUI 的工作

代码都在上面了,需要打包好的工具或者视频教程点击蓝字获取

python爬取付费音乐包有什么用_用Python制作音乐聚合下载器!付费的好像也能下载哦!...相关推荐

  1. 用python爬取指定数据流量是几点_使用python进行微信宜出行人流量数据爬取

    写在前面 由于宜出行的登录策略更新,导致无法使用qq登录直接爬取人流量的问题,近期进行了代码升级,已经解决了该问题,并且能顺利爬取数据,示例如下.目前暂不提供源代码,如有需要宜出行数据,可联系:917 ...

  2. python爬取饿了么外卖商家数据_用python抓取饿了么无证店铺

    一.前言 饿了么平台上很多店铺都无营业执照,只能借用他人的营业执照上传开店.那就想看看附近有多少这样无证共用营业执照的店铺. 先看一下抓取的截图,竟然有这么多店没有营业执照. mongodb3.png ...

  3. python爬取京东商品数据要先登录_手把手教你用python 爬取京东评论

    本次python实战,主要目标是利用 Python爬取京东商品评论数,如上图所示:爬取"Python之父"推荐的小蓝书,这些信息主要包括用户名.书名.评论等信息. 爬取的网址url ...

  4. python怎么爬取一个网页图片显示不出来_使用python爬取网页,获取不到图片地址【python 爬取图片教程】...

    python 网络爬虫,怎么自动保存图片 f12找啊 使用python爬取网页,获取不到图片地址 大图片是在点击之后用 JS 控制加载的. 你可以看看 js/js.js 这个文件,253 行:func ...

  5. Python爬取20w+表情包,微信斗图谁怕谁!

    源 / python教程       文 / 小雨 有一次想要斗图 就在网上搜索表情包 然后发现了一个表情巨多的网站 不小心动起了邪念 产生了兴趣 那就 把它们存下来吧 用 requests 请求了一 ...

  6. python爬取cctalk视频_python爬虫urllib使用和进阶 | Python爬虫实战二

    python爬虫urllib使用和进阶 上节课已经介绍了爬虫的基本概念和基础内容,接下来就要开始内容的爬取了. 其实爬虫就是浏览器,只不过它是一个特殊的浏览器.爬取网页就是通过HTTP协议访问相应的网 ...

  7. python爬取京东商品数据要先登录_京东商品评论情感分析|文本数据预处理

    本文爬取了十款热销手机的文本评论数据后,首先对文本评论数据做文本预处理,文本评论数据中存在大量的无价值信息,引入无用的文本数据,对其作情感分析,显然没有价值,得出的文本挖掘结果也不尽人意.所以对于文本 ...

  8. python爬取贴吧所有标题的评论_用BS4爬取贴吧文章的作者信息时,如何兼顾爬取高亮的作者信息?...

    百度贴吧上的文章信息中,一般的作者信息代码,如下所示: 别让依靠成 而有部分作者信息是橙色的.如下所示: 冰缘瑞雪... # -*-coding:utf-8-*- """ ...

  9. python爬取公交车站数据_Python爬虫实例_城市公交网络站点数据的爬取方法

    爬取的站点:http://beijing.8684.cn/ (1)环境配置,直接上代码: # -*- coding: utf-8 -*- import requests ##导入requests fr ...

最新文章

  1. sql-case when 条件1 then 取值1 when 条件2 then 取值2 else 取值3 end
  2. sendEmail实现邮件报警
  3. 五年了,别再把务虚会开 “虚” 了
  4. vue 跨域问题 - 总结篇
  5. Kubernetes 1.13 版本发布:Kubeadm简化群集管理、容器存储接口(CSI)和CoreDNS作为默认DNS现已普遍可用
  6. html中高与行高的区别,CSS中line-height与height有什么区别
  7. 三大特性--多态和多态性
  8. python tkinter界面 控件位置随窗体自动调整适应_如何实现python tkinter控件随窗口变化?...
  9. qss 样式不生效--注释不能嵌套
  10. Single Number III
  11. window下搭建qt开发环境编译、引用ace
  12. sama5做linux的sd卡启动u盘,windows中service.msc与regedit
  13. slot的使用方法详解
  14. Python游戏开发,pygame模块,Python实现记忆翻牌小游戏
  15. 如何用私钥登陆linux服务器和cyberduck登陆配置
  16. 一起学JAVA之【基础篇】4种默认线程池介绍
  17. webdriver和火狐浏览器历史版本下载
  18. 《Java并发编程的艺术》——Java并发的前置知识(笔记)
  19. Redis 存储List对象
  20. 自动化测试到底该怎么学?

热门文章

  1. 【SFND_Lidar_Obstacle_Detection】代码笔记
  2. opencv Mser的用法
  3. 开放平台:新浪微博 for iOS
  4. 2007年在职攻读硕士学位全国联考答案
  5. S/HIC 系列软件:partialS/HIC 利用 CNN 识别 不完全软/硬 清扫
  6. 海天酱油新模式发展,让品牌形象深入人心
  7. 剪映电脑版超简单使用教程Mac
  8. 分子量(ACM/ICPC)详细解答
  9. (工厂供电)无限大容量电力系统中短路电流的计算
  10. Spring IOC的理解