吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 16896|回复: 30
收起左侧

[Python 转载] 网易云歌单/歌曲下载

  [复制链接]
紫夜星辰 发表于 2020-4-18 13:55
本帖最后由 紫夜星辰 于 2020-4-28 10:01 编辑

界面化 可以根据歌单 / 歌曲ID 下载 歌单/歌曲。
eg: 歌单ID: https://music.163.com/#/playlist?id=3233380300 中的 3233380300
运行环境:   Python 3.7

编辑历史:
1、修复重置功能
2、移除音乐名字中的特殊字符
3、修改调用API接口, 灰色歌曲无法下载,已移除
4、修复路径创建顺序错误,导致提示歌单ID无效

[Python] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import os
import json
import requests
from tkinter import *
 
 
class couldmusic(object):
 
    def __init__(self, tk_root):
        """初始化"""
 
        self.root = tk_root
 
        self.playlist_id = StringVar()                                          # 歌单ID,可以通过网易云歌单详情页面获地址栏取
        self.song_id = StringVar()                                              # 歌曲ID,可以通过歌曲播放页面地址栏获取
        self.song_name = StringVar()                                            # 歌曲名字,用于显示下载信息
        self.song_name.set("")
        self.var = StringVar()                                                  # 下载进度值
        self.var.set("开始")
 
        self.index = 0
 
        self.song_list = {}
        self.save_path = os.path.abspath(".")                                   # 获取工作目录
        self.save_path = os.path.join(self.save_path, "网易云音乐")             # 生成网易云音乐文件夹路径
 
        # 浏览器Headers信息
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36",
            }
 
        # 绘制UI
        self.layout()
 
    def process(self):
        """下载进度条"""
 
        total_length = 260                                                      # 进度条总长度
        if len(self.song_list) > 0:                                             # 判断歌曲列表非空
            length = total_length * self.index / len(self.song_list)            # 计算下载进度长度
            self.canvas.coords(self.processbar, (0, 0, length,26))              # 创建进度条(起始X坐标,起始Y坐标, 长度,高度)
            self.var.set(f"{self.index}/{len(self.song_list)}")                 # 设定进度值
            if length == total_length:                                          # 判断是否下载完成
                self.song_name.set("下载完成")
        self.root.update()
 
    def reset(self):
        """重置"""
 
        self.song_id.set("")
        self.playlist_id.set("")
        self.song_list.clear()
        self.var.set("开始")
        self.index = 0
        self.save_path = os.path.abspath(".")
        self.save_path = os.path.join(self.save_path, "网易云音乐")
 
    def get_playlist(self, playlist_id):
 
        playlist_api = "http://music.163.com/api/playlist/detail?id="           # 歌单详情API
        playlist_url = playlist_api + playlist_id                               # 获取歌单详情地址
 
        r = requests.get(playlist_url, headers = self.headers)                  # 获取源码
        json_data = json.loads(r.text)                                          # 源码转换Json格式
         
        # 尝试提取指定信息
        try:
            song_list_name = json_data['result']['creator']['nickname']         # 提取歌单名字
            self.song_name.set(f"{song_list_name} 的歌单")
            self.save_path = os.path.join(self.save_path, song_list_name)       # 生成歌单文件路径
            if not os.path.isdir(self.save_path):                               # 判断路径是否存在
                os.mkdir(self.save_path)                                        # 创建歌单文件夹
        except:
            self.song_name.set("请输入有效的歌单ID或歌曲ID")
            return
 
        # 提取歌曲信息
        for i in json_data['result']['tracks']:
            song_name = i["name"].split("/")[0]                                 # 获取歌曲名字,并移除 "/"
            song_id = i['id']                                                   # 获取歌曲ID信息
            self.song_list[song_name] = song_id                                 # 将歌曲信息加入到字典备用
 
        return song_list_name
 
    def get_song_info(self, song_id):    
        """获取单首歌曲信息"""   
 
        song_detail_api = "http://music.163.com/api/song/detail/?id=song_id&ids=%5Bsong_id%5D"      # 歌曲信息API
        song_url = song_detail_api.replace("song_id", self.song_id.get())                           # 生成歌曲信息Url
 
        r = requests.get(song_url, headers = self.headers)                      # 获取源码
        json_data = json.loads(r.text)                                          # 源码转换Json格式
 
        # 尝试提取指定信息
        try:            
            for i in json_data['songs']:                                        # 获取Json_data中 ‘songs’内容
                self.song_list[i['name']] = self.song_id.get()                  # 将歌曲信息加入到字典备用
        except:
            self.song_name.set("请输入有效的歌单ID或歌曲ID_2")                                                  
 
    def download(self):
        """下载 "self.song_list" 中歌曲"""
 
        api = "http://music.163.com/song/media/outer/url?id=song_id.mp3"
        # api = "https://www.apicp.cn/API/wyy/api.php?id="                        # 网易云解析API, 第三方提供
        self.index = 0
         
        for item in self.song_list:                                             # 遍历歌曲列表
            self.index += 1                                                     # 歌曲次序
            song_url = api.replace("song_id", str(self.song_list[item]))             # 解析地址
            name = item + ".mp3"                                                # 歌曲名字
            split_list = ["<", ">", "/", "\\"]                                  # Windows名字机制,移除特殊字符
            for x in split_list:
                name = name.split(x)[0]                                          
            path = os.path.join(self.save_path, name)                           # 歌曲保存路径
            self.song_name.set(name)                                            # 更新UI信息
            content = requests.get(song_url, headers = self.headers).content    # 获取源码
            if content[0] != 0x49:                                              # 判断返回值是否属于音频文件
                self.song_name.set("灰色歌曲无法下载")                           # 灰色歌曲无法下载
                continue                                                        # 跳出本次循环
            if not os.path.isfile(path):                                        # 判断文件是否存在
                with open(path, "wb") as f:                                     # 保存文件
                    f.write(content)
            self.process()                                     
 
    def run(self):
        """获取输入信息, 并执行程序"""
 
        playlist_id = self.playlist_id.get()                                    # 获取页面输入歌单ID信息
        song_id = self.song_id.get()                                            # 获取页面输入歌曲ID信息
 
        if not os.path.isdir(self.save_path):                                   # 判断路径是否存在 
            os.mkdir(self.save_path)                                            # 创建文件夹
 
        # 判断输入歌单ID和歌曲ID有效
        if playlist_id == "" and song_id == "":                                 # 判断歌单/歌曲非空
            self.song_name.set("请输入有效的歌单ID或歌曲ID_1")                    
            return       
        elif playlist_id:                                                       # 歌单ID非空,执行歌单处理函数
            self.get_playlist(playlist_id)
        elif song_id:                                                           # 歌曲ID非空,执行歌曲处理函数
            self.get_song_info(song_id)
 
        self.download()                                                         # 执行歌曲下载函数
        self.reset()                                                            # 重置
 
    def layout(self):
        """绘制界面"""
 
        self.root.title("网易云下载器")                                          # 标题
        self.root.geometry("260x100+600+300")                                   # 位置
        self.root.bind("<Return>", lambda x:self.run())                         # 绑定回车键
 
        # 歌单ID
        Label(self.root, text = "歌单ID:").grid(row = 0, column = 0)
        Entry(self.root, textvariable = self.playlist_id).grid(row = 0, column =1, sticky=N+E+S+W)
         
        # 歌曲ID
        Label(self.root, text = "歌曲ID:").grid(row = 1, column =0)
        Entry(self.root, textvariable = self.song_id).grid(row = 1,column = 1, sticky=N+E+S+W)
 
        # 正在下载的歌曲信息
        Label(self.root, text = "正在下载:").grid(row = 2, column =0)
        Entry(self.root, textvariable = self.song_name).grid(row = 2,column = 1, sticky=N+E+S+W)
 
        # 进度条
        self.canvas = Canvas(self.root,height=26, bg="white")
        self.canvas.grid(row = 3,  column = 1)
        self.processbar = self.canvas.create_rectangle(0,0,0,0,width = 0,fill = "green")
 
        # 开始
        Button(self.root, textvariable = self.var, command = self.run).grid(row = 3, column = 0, sticky=N+E+S+W)
 
 
if __name__ == "__main__":
    root = Tk()
    couldmusic(root)
    root.mainloop()

免费评分

参与人数 13吾爱币 +12 热心值 +12 收起 理由
风吹烛影乱 + 1 + 1 学会了 谢谢大神
Coptis_china + 1 谢谢@Thanks!
StevenK + 1 + 1 我很赞同!
geniusrot + 1 大佬牛逼啊
klidopic + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
EliauK + 1 + 1 用心讨论,共获提升!
454503684 + 1 + 1 热心回复!
许诗 + 1 + 1 好像没用了哈
chxchxkkk + 1 + 1 热心回复!
隋戈子 + 2 我很赞同!
frommemory + 1 + 1 谢谢@Thanks!
xenoscrt + 1 + 1 谢谢@Thanks!
taozididi + 1 + 1 先试一试 感谢大佬

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 紫夜星辰 发表于 2020-4-18 17:24
taozididi 发表于 2020-4-18 17:06
好像有Bug       https://music.163.com/#/playlist?id=2025127775
Exception in Tkinter ca ...

Win10的命名机制,不允许<  > / 特殊字符出现,已修复
taozididi 发表于 2020-4-18 17:06
好像有Bug       https://music.163.com/#/playlist?id=2025127775
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\taozi\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1705, in __call__
    return self.func(*args)
  File "C:\Users\taozi\Desktop\a\新网易云歌单下载.py", line 137, in run
    self.download()                                                         # 执行歌曲下载函数
  File "C:\Users\taozi\Desktop\a\新网易云歌单下载.py", line 115, in download
    with open(path, "wb") as f:                                     # 保存文件
OSError: [Errno 22] Invalid argument: 'C:\\Users\\taozi\\Desktop\\a\\网易云音乐\\acgnfans\\Perfect Time <再arr>.mp3'
lsy1980 发表于 2020-4-18 14:24
845xyz 发表于 2020-4-18 14:31
实测可以下载 感谢分享代码
taozididi 发表于 2020-4-18 14:33
已使用 但是每次重复使用都要重新打开一次  有重置就好了
 楼主| 紫夜星辰 发表于 2020-4-18 14:35
taozididi 发表于 2020-4-18 14:33
已使用 但是每次重复使用都要重新打开一次  有重置就好了

不需要吧,还真没试过。
unixcs 发表于 2020-4-18 14:36
vip歌曲可以下载码
冷诗烟 发表于 2020-4-18 14:36
求问大佬,Python应该怎么学
 楼主| 紫夜星辰 发表于 2020-4-18 14:45
taozididi 发表于 2020-4-18 14:33
已使用 但是每次重复使用都要重新打开一次  有重置就好了

谢谢反馈,已加入重置功能
 楼主| 紫夜星辰 发表于 2020-4-18 14:47
unixcs 发表于 2020-4-18 14:36
vip歌曲可以下载码

使用的是网站的API,目前来看是可以下载VIP和灰色歌曲的
友谊少年sss 发表于 2020-4-18 14:49
bat几行就ok了
@echo off
title 网易云音乐外链获取
Set var=0
Set choice=
Set /p choice=请输入网易云音乐ID:
Set "choice=%choice:"=%"
explorer "http://music.163.com/song/media/outer/url?id=%choice%.mp3"
pause
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-23 16:18

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表