Use tkinter + crawlers realize Netease cloud music downloader

Tkinter is Python's standard GUI library. Python using Tkinter can quickly create GUI applications.

Since python Tkinter is built into the installation package, then as long as you can import Tkinter installed Python libraries, but also with Tkinter IDLE written in, for simple graphical interface Tkinter still be able to cope.

Using Tkinter + reptile complete Netease cloud music downloader, a simple two-step process: Interface - Features

First, we have completed the Tkinter interface

First, the interface layout

#创建界面
root = Tk()
#标题
root.title("网易云音乐下载器")
#窗口大小
root.geometry('550x400')

#标签控件
label = Label(root,text='请输入歌曲名称:',font=("华文行楷",20))
#标签定位
label.grid()

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

#列表框
text = Listbox(root,font=("楷书",16),width=50,heigh=15)
text.grid(row=1,columnspan=2)

#开始按钮
button = Button(root,text="开始下载",font=("隶书",15))
button.grid(row=2,column=0,sticky=W)

#退出按钮
button1 = Button(root,text="退出程序",font=("隶书",15))
button1.grid(row=2,column=1,sticky=E)

#显示界面
root.mainloop()

By the above code can be obtained a simple interface, but also to add functionality, as follows
Here Insert Picture Description

Second, the function

Now we need to do is to add ginger reptile program button interface, implementation of functionality.

We need to download the music platform NetEase cloud music network
Here Insert Picture Description
by checking the page source code, view the search and download website, we can find the information on this page is url inside
https://music.163.com/weapi/cloudsearch/get / web? csrf_token = e87cd24a6de0c3c3b28727eaa8f2727b

This url need to post the request to get the data, which is encrypted parameters post request
params, encSecKey, we need to get these two parameters to decrypt the data.
Here Insert Picture Description

Continue to debug, to find a function block corresponding to the reduction in the python by way encryption,

import requests
import random
import base64
from Crypto.Cipher import AES
import json
import binascii


class Music_api():
    # 设置从JS文件提取的RSA的模数、协商的AES对称密钥、RSA的公钥等重要信息
    def __init__(self):
        self.modulus = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
        self.nonce = '0CoJUm6Qyw8W8jud'
        self.pubKey = '010001'
        self.url = "https://music.163.com/weapi/cloudsearch/get/web?csrf_token="
        self.HEADER = {}
        self.setHeader()
        self.secKey = self.getRandom()

    # 生成16字节即256位的随机数
    def getRandom(self):
        string = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        res = ""
        for i in range(16):
            res += string[int(random.random() * 62)]
        return res

    # AES加密,用seckey对text加密
    def aesEncrypt(self, text, secKey):
        pad = 16 - len(text) % 16
        text = text + pad * chr(pad)
        encryptor = AES.new(secKey.encode('utf-8'), 2, '0102030405060708'.encode('utf-8'))
        ciphertext = encryptor.encrypt(text.encode('utf-8'))
        ciphertext = base64.b64encode(ciphertext).decode("utf-8")
        return ciphertext

    # 快速模幂运算,求 x^y mod mo
    def quickpow(self, x, y, mo):
        res = 1
        while y:
            if y & 1:
                res = res * x % mo
            y = y // 2
            x = x * x % mo
        return res

        # rsa加密

    def rsaEncrypt(self, text, pubKey, modulus):
        text = text[::-1]
        a = int(binascii.hexlify(str.encode(text)), 16)
        b = int(pubKey, 16)
        c = int(modulus, 16)
        rs = self.quickpow(a, b, c)
        return format(rs, 'x').zfill(256)

    # 设置请求头
    def setHeader(self):
        self.HEADER = {
            'Accept': '*/*',
            'Accept-Encoding': 'gzip,deflate,sdch',
            'Accept-Language': 'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4',
            'Connection': 'keep-alive',
            'Content-Type': 'application/x-www-form-urlencoded',
            'Host': 'music.163.com',
            'Referer': 'https://music.163.com/search/',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36'
        }

    # 设置相应的请求参数,从而搜索列表
    # 总体的密码加密步骤为:
    # 首先用nonce对text加密生成密文1
    # 然后用随机数seckey加密密文1生成密文2
    # 随后,用公钥加密seckey生成密文3
    # 其中,密文2作为请求参数中的params,密文3作为encSeckey字段
    # 这样,接收方可以通过私钥解密密文3获得seckey(随机数)
    # 然后用seckey解密密文2获得密文1
    # 最终用统一协商的密钥nonce解密密文1最终获得text
    def search(self, s, offset, type="1"):
        text = {"hlpretag": "<span class=\"s-fc7\">",
                "hlposttag": "</span>",
                "#/discover": "",
                "s": s,
                "type": type,
                "offset": offset,
                "total": "true",
                "limit": "30",
                "csrf_token": ""}
        text = json.dumps(text)
        params = self.aesEncrypt(self.aesEncrypt(text, self.nonce), self.secKey)
        encSecKey = self.rsaEncrypt(self.secKey, self.pubKey, self.modulus)
        data = {
            'params': params,
            'encSecKey': encSecKey
        }
        result = requests.post(url=self.url,
                               data=data,
                               headers=self.HEADER).json()
        return result

    # 获取指定音乐列表(相当于主函数)
    def get_music_list(self, keywords):
        music_list = []
        for offset in range(1):
            result = Music_api().search(keywords, str(offset))
            result = result['result']['songs']
            for music in result:
                # if music['copyright'] == 1 and music['fee'] == 8:
                if (music['privilege']['fee'] == 0 or music['privilege']['payed']) and music['privilege']['pl'] > 0 and \
                        music['privilege']['dl'] == 0:
                    continue
                if music['privilege']['dl'] == 0 and music['privilege']['pl'] == 0:
                    continue
                    # if music['fee'] == 8:
                music_list.append(music)
        return music_list

# print(Music_api().get_music_list("山海"))#测试

Here Insert Picture Description
Data is no problem, it is worth noting that,
Python under Windows when using AES module to be installed is pycryptodome pip install pycryptodome

python in Linux when using AES module to be installed is pycrypto pip install pycrypto

When importing from Crypto.Cipher import AES, there will be an error, the crypto change the uppercase lowercase c C.
Here Insert Picture Description

Third, the combination of functions and interfaces

Here Insert Picture Description
By adding parameters in the command button, a reference function (be careful not to add (), only the function name)

#下载歌曲
def download_song(item):
    name = item['name']
    id = item['id']

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

    os.makedirs("music",exist_ok=True)
    path = "music\{}.mp3".format(name)
    #文本框
    text.insert(END,"歌曲:{},正在下载......".format(name))
    #文本框滚动
    text.see(END)
    #更新
    text.update()
    # 下载
    urlretrieve(url, path)
    #文本框
    text.insert(END,"下载完毕,{},请试听......".format(name))
    #文本框滚动
    text.see(END)
    #更新
    text.update()

#搜索歌曲名称
def get_music_name():

    name = entry.get()  #获取输入的歌曲名称
    music_list_id = Music_api().get_music_list(name)

    
    name = music_list_id[0]['name']
    id = music_list_id[0]['id']
    item = {}
    item['name'] = name
    item['id'] = id
    download_song(item)

Achieved from urllib.request import urlretrieve, a line of code download mp3, left to go to the redundant code with open, and
Here Insert Picture Description
create folders through the os module, save the file
Here Insert Picture Description
exist_ok = True representation when you create a folder is not created, there is no error also covering created.

So far, functionality and interface is complete, look at the results
Here Insert Picture Description
and then look at whether there is a folder
Here Insert Picture Description

ok, above completed using Tkinter + crawlers realize Netease cloud music downloader.

Published 73 original articles · won praise 47 · views 70000 +

Guess you like

Origin blog.csdn.net/weixin_43870646/article/details/104609873