前言:
最近點贊了一些文章,覺得有些東西是我還沒有接觸過的,于是打算復刻一次,但是用我的思路,加上一些新的想法,最后我也是成功實作了這些功能,
就和標題一樣,這次打算決議一下 網易云 請求的引數,然后把爬來的歌曲撰寫到前端html代碼里面,最后用代碼實作QQ郵箱的發送功能,嗯,沒錯,確實創新了一點,但是在撰寫代碼的框架思路上, 每個人都是有所不同, 找到自己的方法就可以了,
我本以為用python實作了它的加密演算法之后,可以決議(very import person) 歌曲, 但是根據我的實際操作上,是不可以的,后面也會講到,他們加密的引數是不一樣的,都有各自的播放渠道, 如果你熟悉 html 你都可以發現他有二個播放渠道, 分別對應一般和特殊,所以后面我直接就開了黑膠會員, 我就想知道引數到底有什么不同, 不幸的是,當我在網頁端登入賬號的時候, 我發現在我打斷點之后,我就不能啟動除錯功能了,相反的是debugger parse這樣的欄位,我嘗試去解決這個問題,根據網上各種方式,到后面還是無濟于事,索性放棄了,但是對于一般的 music , 是完全沒有問題的,都可以下載,發送,保存到本地,
后面當我把這代碼全部寫好,加上了一些例外處理,我想到我的憨憨女友,索性在加一點代碼實作,就把這些爬來的資料 寫道一個/<table>里面, 然后再用其他函式庫發送到她郵箱去了,單純覺得好玩,
這篇文章有點長,因為有點難懂, 我只是想講清楚一點,給她看,或者 給一些基礎不是很好的人看一下, 大佬可以親噴點,代碼用到了很多庫,但是我再后面也會一個個提到,不影響各位閱讀, 只要耐心的看,你就一定有識訓,
文章三天之后設定為粉絲可見,
歌曲著作權最終歸網易云所有!
我是沙漏,如果你喜歡我的文章,你可以點一個贊,收藏一次,關注下我,多謝,
有問題可以在評論區留言,我下課有時間就會回答你們,大三了有點小忙,
讀后有識訓,點贊,關注,加收藏,共勉!
點我,點我,點我呀!博主其他文章

- JS逆向, ASE加密, RES非對稱演算法,yagmail郵箱的發送,瀏覽器的debug,學到就是爽,
文章目錄
- 前言:
- 效果圖:
- 頁面分析:
- 引數加密:
- 函式function A:
- 函式function B:
- 函式function C:
- 連貫加密函式類:
- ID獲取:
- 獲取免費單首ID:
- 獲取id串列:
- 發送郵箱:
- 發送表格:
- 發送全部代碼:
- 下載單曲代碼:
- 關于__init__ :
效果圖:

就是一個 html 表格, 熟悉的應該就直接能看出來, 然后還有img標簽, a標簽之類的,
頁面分析:
當我們用chrome瀏覽器 (推薦用谷歌) 進入網易云官網,找到一首你喜歡的歌,

打開 f12 功能, 點擊 XHR 過濾, 這個時候,我們點擊播放, 在右側就會重新捕獲到新的網路請求,其中就包括我們需要的歌曲檔案鏈接,就像這樣,

v1?csrf … 這個網址就是剛刷的, 在回應中可以看到,有個url,你復制打開,就可以直接播放, 我們點擊一下headers看看怎么發送的,

請求了request url , 用post發送, 下面有2個引數表單 params 和 encSecKey 貌似我們有下面2個引數就可以直接發送請求了, 所以直接就嘗試了一下,
def spider(self):
"""
這是爬取一首歌的方式, 復制params就可以發送請求
"""
r = requests.post(self.params_url, params=self.params)
if r.status_code == 200:
mp3 = r.json().get("data")[0].get("url")
rmp3 = requests.get(mp3, headers={"user-agent": self.ua})
if rmp3.status_code == 200:
with open("像魚.mp3", 'wb') as fw:
fw.write(rmp3.content)
print("下載成功")
最后成功下載,

也就是說,我們只需要知道這二個引數怎么來的,就可以自己構造了,那就想怎么就怎么了,這個時候,我們就可以打開瀏覽器自帶的除錯功能了,要打斷點,要debug, 怎么打,怎么斷? 仔細點看我圖的注釋就可以了,

還是之前的包, 你點擊第四個 initiator 就會重繪出很多和他有關系的檔案, 我們點擊第一個,


然后就來到這樣, 還記得之前的二個引數吧, 在這里我們直接 ctrl + f 找其中的一個引數,

這里可以看到 params , encSecKey 都是根據 bvz7s 來的, 而bvz7s 是根據 window.asrsea() 函式來的, 所以在這個 函式打一個斷點, 繼續看下一個搜索點

在這里,我們發現window.asrsea = d 所以就得看 d 函式,在d函式的語氣中,我們都可以打上斷點,以便觀察清楚, 打上斷電之后, 重繪頁面,等待一段時間,

之后就到第一個斷點處, 然后 f8 跳到下一個斷點

然后就可以發現 d 接受的4個引數是什么了, (d, e, f, g) 在右側我們也可以看到,多次測驗發現,后面三個是加密引數,固定值,所以復制拿過來用就可以了, 對于第一個d = {“csrf_token”:"…"} 這個是用來記錄你是否登入賬號, 如果你沒有登陸, 那就是空,
繼續f8 跳轉到最后

發現就是把最開始接受的4個引數,然后經過a, b, b, c 函式處理就可以了,那待會我們就要看看每個函式有什么作用,這就涉及到他們的加密方式了,但是在這里,就要思考一個問題了,關于最開始的4個引數, 就一個d會變, 其他都沒變化, 而且d還是一個慷訓者亂七八糟的的數字, 那他是怎么知道我是哪一首歌? 哪個歌手,所以這個引數一定有問題, (后面經過加密測驗,發現加密后引數長度少了很多) 所以在這里我就繼續 除錯了一下, 一樣的操作,

除錯一圈了,最后終于有一個靠譜的了,有歌曲的id 還有歌曲的音質, 其他的,如果不熟悉,可以每一個d都去試試,直到加密引數正確,
所以先確定d為
"{"ids":"[1459950258]","level":"standard","encodeType":"aac","csrf_token":"59098e191e8babbaef83f1b8bbbe5987"}"
姑且就用這個d引數去加密嘗試一次吧,
引數加密:
- 回到之前d函式的區域,就在d的上面,我們就可以看到a,b,c 函式的執行程序,

我們只需要一個個了解好,然后用python語言轉換一下就可以了,下面分模塊講這些,
函式function A:
function a(a) {
var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
for (d = 0; a > d; d += 1)
e = Math.random() * b.length,
e = Math.floor(e),
c += b.charAt(e);
return c
}
熟悉的一看就知道, a函式接受一個a引數, 然后再一次回圈中, 回圈一次為a次, 然后從 b中 隨機的挑選一些字符, 最后用字串的形式回傳, 對于Javascript來說,隨機沒那么容易,他需要用 random 生成 (0, 1) 的數,然后放大,取整,取值,累加,但對于python來說, 如下:
def SimulateFunctionA(self, length=None):
"""
@JavaScript
function a(a) {
var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
for (d = 0; a > d; d += 1)
e = Math.random() * b.length,
e = Math.floor(e),
c += b.charAt(e);
return c
}
length : 16
using the python get the c
"""
b = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
c = random.sample(b, length)
return "".join(c)
簡單.
函式function B:
function b(a, b) {
var c = CryptoJS.enc.Utf8.parse(b)
, d = CryptoJS.enc.Utf8.parse("0102030405060708")
, e = CryptoJS.enc.Utf8.parse(a)
, f = CryptoJS.AES.encrypt(e, c, {
iv: d,
mode: CryptoJS.mode.CBC
});
return f.toString()
}
這是一個 AES 加密, 模式 CBC, 其實剛開始我也不知道AES加密是什么東西, 后面我查看了官網檔案,參考了其他的辦法,實作了,
官網檔案
觀察這個函式, 接受了a,b, 其中a,b 是什么可以再函式d中看到到,

根據之前的分析, g是固定值,我們已經復制下來, d 認為是一個字符字典
"{"ids":"[1459950258]","level":"standard","encodeType":"aac","csrf_token":"59098e191e8babbaef83f1b8bbbe5987"}"
這樣,我們用python語言加入這些引數,試著模擬一下,
def SimulateFunctionB(self, d, key):
"""
function b(a, b) {
var c = CryptoJS.enc.Utf8.parse(b)
, d = CryptoJS.enc.Utf8.parse("0102030405060708")
, e = CryptoJS.enc.Utf8.parse(a)
, f = CryptoJS.AES.encrypt(e, c, {
iv: d,
mode: CryptoJS.mode.CBC
});
return f.toString()
}
a = `"{"ids":"[1459950258]","level":"standard","encodeType":"aac","csrf_token":"59098e191e8babbaef83f1b8bbbe5987"}"`
b = key = self.g(first) = SimulateFunctionA()(second)
"""
key = key.encode()
iv = self.iv.encode()
aes = AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
text = pad(data_to_pad=d.encode(), block_size=AES.block_size)
aes_text = aes.encrypt(plaintext=text)
aes_texts = base64.b64encode(aes_text).decode()
return aes_texts
SimulateFunticonB(d=" `"{"ids":"[1459950258]","level":"standard","encodeType":"aac","csrf_token":"59098e191e8babbaef83f1b8bbbe5987"}"`", key=self.g)
這里也是成功實作了,截圖我忘記截了, 關于如何AES加密,可以直接看我的,有時間有興趣的也可以和我一樣看官網檔案, 都行, 實作就可以了,
函式function C:
function c(a, b, c) {
var d, e;
return setMaxDigits(131),
d = new RSAKeyPair(b,"",c),
e = encryptedString(d, a)
}
一看很簡單,其實復雜, 用到了RSA加密演算法,關于RSA加密演算法,我找了一些資料,

大致原理如圖:
參考檔案
我們用python這樣實作;
def SimulateFunctionC(self, random16):
"""
a = 131
RSA加密原理
# num = pow(x, y) % z
# 加密C=M^e mod n
"""
e = self.e
f = self.f
text = random16[::-1]
num = pow(int(text.encode().hex(), 16), int(e, 16), int(f, 16))
return format(num, 'x').zfill(131) # TODO: last the num change the hex digit and left fill (131)
pow() 其實是可以接受三個引數的, 如果有第三個, 第三個就為取余值, 用上int(a, 16) 就可以直接將16進制轉換為10進制, 最后的format(num, ‘x’) 將值用16進制形式輸出, 然后zfill() 填充131 位數,, (根據函式C得知 位數為131)
連貫加密函式類:
分析了上面三個函式, 其實我們就可以直接撰寫程式加密了, 我們把程式連起來,
# -*- coding : utf-8 -*-
# @Time : 2020/9/15 15:45
# @author : 沙漏在下雨
# @Software : PyCharm
# @CSDN : https://me.csdn.net/qq_45906219
import requests
from get_useragent import GetUserAgentCS
import random
from Crypto.Util.Padding import pad
from Crypto.Cipher import AES
import base64
class GetParams(object):
def __init__(self):
self.ua = GetUserAgentCS().get_user()
self.params_url = 'https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token='
self.e = "010001"
self.g = "0CoJUm6Qyw8W8jud"
self.iv = '0102030405060708'
self.f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a" \
"876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9" \
"d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e28" \
"9dc6935b3ece0462db0a22b8e7"
self.params = None
def SimulateFunctionA(self, length=None):
"""
@JavaScript
function a(a) {
var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
for (d = 0; a > d; d += 1)
e = Math.random() * b.length,
e = Math.floor(e),
c += b.charAt(e);
return c
}
length : 16
using the python get the c
"""
b = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
c = random.sample(b, length)
return "".join(c)
def SimulateFunctionB(self, d, key):
"""
function b(a, b) {
var c = CryptoJS.enc.Utf8.parse(b)
, d = CryptoJS.enc.Utf8.parse("0102030405060708")
, e = CryptoJS.enc.Utf8.parse(a)
, f = CryptoJS.AES.encrypt(e, c, {
iv: d,
mode: CryptoJS.mode.CBC
});
return f.toString()
}
a = "{"csrf_token":""}"
b = key = self.g(first) = SimulateFunctionA()(second)
"""
key = key.encode()
iv = self.iv.encode()
aes = AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
text = pad(data_to_pad=d.encode(), block_size=AES.block_size)
aes_text = aes.encrypt(plaintext=text)
aes_texts = base64.b64encode(aes_text).decode()
return aes_texts
def SimulateFunctionC(self, random16):
"""
a = 131
RSA加密原理
# num = pow(x, y) % z
# 加密C=M^e mod n
"""
e = self.e
f = self.f
text = random16[::-1]
num = pow(int(text.encode().hex(), 16), int(e, 16), int(f, 16))
return format(num, 'x').zfill(131) # TODO: last the num change the hex digit and left fill (131)
def spider(self):
"""
這是爬取一首歌的方式, 復制params就可以發送請求
"""
r = requests.post(self.params_url, params=self.params)
if r.status_code == 200:
mp3 = r.json().get("data")[0].get("url")
rmp3 = requests.get(mp3, headers={"user-agent": self.ua})
if rmp3.status_code == 200:
with open("像魚.mp3", 'wb') as fw:
fw.write(rmp3.content)
print("下載成功")
def get_encrypt_params(self, d=None):
"""
The function can encrypt your params if you give me a d
@params: d debug your chrome browser
"""
i = self.SimulateFunctionA(length=16)
encText = self.SimulateFunctionB(d, self.g)
encText = self.SimulateFunctionB(encText, i)
encSecKey = self.SimulateFunctionC(random16=i)
return {
"params": encText,
"encSecKey": encSecKey
}
# a = GetParams()
# a.spider()
- 說到底,我們還是要歌曲的id, 怎么來的,就需要繼續看下去了,
ID獲取:
獲取免費單首ID:

直接這樣就可以了,
獲取id串列:

如果你是進入歌手表單在這個界面,你是找不到需要的id表單資料的,在這里就要用selenium 去爬取然后分析了,
如果你在下面的情況下,就可以找到id表單資料,

還有一樣的,在這個包,我們看到引數還是params 和 encSerKey 然后重復上面操作, 打斷點除錯,甚至加密方式都是一樣,不斷的打斷點,最后發現d是這樣的
{"hlpretag":"<span class=\"s-fc7\">","hlposttag":"</span>","s":"許嵩","type":"1","offset":"0","total":"true","limit":"30","csrf_token":""}
我們更改一下s的值, 歌曲名稱 歌手 都可以, 構建好這個字典, 發送這個網址,就可以得到id了, 然后拿著id去繼續構造上面的d值, 就可以拿到歌曲url了,
如下:
# -*- coding : utf-8 -*-
# @Time : 2020/9/17 14:59
# @author : 沙漏在下雨
# @Software : PyCharm
# @CSDN : https://me.csdn.net/qq_45906219
from GetParams import GetParams
import requests
from get_useragent import GetUserAgentCS
import random
import keyring
import yagmail
class DownMp3(object):
def __init__(self):
self.GetIdUrl = "https://music.163.com/weapi/cloudsearch/get/web?csrf_token="
self.GetMP3Url = 'https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token='
self.ua = GetUserAgentCS().get_user()
self.headers = {"User-Agent": self.ua}
self.MUSIC_LIST = [] # The singer music demo list
self.Sented_qq_email = self.get_email()
def get_email(self):
email_list = input("輸入QQ郵箱 如果你有多個 請用空格隔開:").split()
if len(email_list) == 1:
if "@qq.com" not in email_list[0]:
raise Exception("郵箱規格好像不合適,你輸入的是 ", email_list[0])
else:
return email_list[0]
elif len(email_list) >= 2:
for i in email_list:
if "@qq.com" not in i:
raise Exception("郵箱規格好像不合適,你輸入的是 ", i)
else:
pass
return email_list
def my_request(self, url, model="get", params=None):
if model == 'post':
r = requests.post(url, headers=self.headers, params=params)
if r.status_code == 200:
r.encoding = r.apparent_encoding
s = r.json()
return s
elif model == 'get':
r = requests.get(url, headers=self.headers, params=params)
if r.status_code == 200:
return r.content
else:
raise Exception("method is error !")
def get_mp3_id_demo(self, start=None):
"""
get the mp3 id
{"hlpretag":"<span class=\"s-fc7\">","hlposttag":"</span>","s":"本兮","type":"1","offset":"0","total":"true","limit":"30","csrf_token":""}
"""
if start is None:
raise Exception("You should enter a start name, but you enter start =", start)
d = {
"hlpretag": "<span class=\"s-fc7\">",
"hlposttag": "</span>",
"s": str(start),
"type": "1",
"offset": "0",
"total": "true",
"limit": "30",
"csrf_token": ""
}
params = GetParams().get_encrypt_params(str(d))
return self.my_request(self.GetIdUrl, model="post", params=params)["result"]["songs"]
def get_mp3_url(self, id):
"""
params: id the music of id
fix the id into "{"ids":"[35440198]","level":"standard","encodeType":"aac","csrf_token":""}"
so we can get the music the downpath
"""
d = {"ids": str([id]), "level": "standard", "encodeType": "aac", "csrf_token": ""}
params = GetParams().get_encrypt_params(str(d))
context = self.my_request(self.GetMP3Url, model="post", params=params)
mp3_path_url = context.get("data")[0]["url"]
return mp3_path_url
def print_id_list(self, id_list):
"""
params: id_list print the singer about 30s musics
"""
a = {}
for index, value in enumerate(id_list):
a['count'] = (index + 1)
a["singer_name"] = value.get("name")
a["id"] = value.get("id")
a["album"] = value.get("al").get("name")
a["image"] = value.get("al").get("picUrl")
self.MUSIC_LIST.append(a.copy())
def random_get_mp3(self):
mp3Ten = random.sample(self.MUSIC_LIST, 10) # 提出十首歌
content = "" # 把資料寫入html中 方便發送
content += '<p><font size="20" color="Tan">Happy day for you !</font></p>'
content += '<table border="1" style="border-collapse: collapse;">\n<caption>Today music demo </caption>\n<tr><th>序號</th><th>歌曲名</th><th>歌曲鏈接</th><th>歌曲所屬</th><th>美圖</th></tr>'
count = 1
for j in mp3Ten:
s = f"\n<tr><th>{count}</th><th>{j['singer_name']}</th>" \
f"<th><a href='{self.get_mp3_url(j['id'])}'>點擊播放</a></th><th>{j['album']}</th>" \
f"<th><img src='{j['image']}' alt='美圖' height='400' width='400' /></th></tr>"
content += s
count += 1
content += "</table>"
return content
def sent_email(self, content):
"""
sent the music demo list for you like one
"""
pwd = keyring.get_password("qqemail", "884427640")
yag = yagmail.SMTP("884427640@qq.com", pwd, host="smtp.qq.com")
# test qq 2817634007@qq.com
yag.send(self.Sented_qq_email, '網易云專屬推送', content)
yag.close()
print("Today music already sent ok!")
def start_demo(self):
try:
start_name = input("input a music singer or music name "
"if you like it:")
id_list = self.get_mp3_id_demo(start=start_name)
self.print_id_list(id_list)
print(self.MUSIC_LIST)
self.sent_email(self.random_get_mp3())
except Exception as e:
print("出現error", e, "再試一次!")
self.start_demo()
# 如果要運行此程式 請打開下面的注釋
# a = DownMp3()
# a.start_demo()
發送郵箱:
- 函式庫用到
import keyringimport yagmail
下載一下就可以了,
-
關于keyring 這是一個保存密碼的庫, 對于一些密碼來說,我們可以這樣
keyring set qq 88442764
然后就會讓你輸入密碼 ,當你輸入要獲得就這樣
keyring get qq 884427640 就可以了
前提你的keyring.exe 在環境變數中, 當然在python中,這個也是很簡單使用的, -
關于yagmail 這是一個發送郵箱的函式庫
def sent_email(self, content):
"""
sent the music demo list for you like one
"""
pwd = keyring.get_password("qqemail", "884427640")
yag = yagmail.SMTP("884427640@qq.com", pwd, host="smtp.qq.com")
# test qq 2817634007@qq.com
yag.send(self.Sented_qq_email, '網易云專屬推送', content)
yag.close()
print("Today music already sent ok!")
pwd 這個是郵箱的QQ郵箱的授權碼, 很長的字串,要去QQ郵箱里面開啟服務,所以我就放到密碼庫里面了,然后用SMTP鏈接一下郵箱, 就這樣發送就可以了,
發送表格:
懂點html的都應該會撰寫這個,
def random_get_mp3(self):
mp3Ten = random.sample(self.MUSIC_LIST, 10) # 提出十首歌
content = "" # 把資料寫入html中 方便發送
content += '<p><font size="20" color="Tan">Happy day for you !</font></p>'
content += '<table border="1" style="border-collapse: collapse;">\n<caption>Today music demo </caption>\n<tr><th>序號</th><th>歌曲名</th><th>歌曲鏈接</th><th>歌曲所屬</th><th>美圖</th></tr>'
count = 1
for j in mp3Ten:
s = f"\n<tr><th>{count}</th><th>{j['singer_name']}</th>" \
f"<th><a href='{self.get_mp3_url(j['id'])}'>點擊播放</a></th><th>{j['album']}</th>" \
f"<th><img src='{j['image']}' alt='美圖' height='400' width='400' /></th></tr>"
content += s
count += 1
content += "</table>"
return content
就這樣寫一下就可以了,
發送全部代碼:
# -*- coding : utf-8 -*-
# @Time : 2020/9/17 14:59
# @author : 沙漏在下雨
# @Software : PyCharm
# @CSDN : https://me.csdn.net/qq_45906219
from GetParams import GetParams
import requests
from get_useragent import GetUserAgentCS
import random
import keyring
import yagmail
class DownMp3(object):
def __init__(self):
self.GetIdUrl = "https://music.163.com/weapi/cloudsearch/get/web?csrf_token="
self.GetMP3Url = 'https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token='
self.ua = GetUserAgentCS().get_user()
self.headers = {"User-Agent": self.ua}
self.MUSIC_LIST = [] # The singer music demo list
self.Sented_qq_email = self.get_email()
def get_email(self):
email_list = input("輸入QQ郵箱 如果你有多個 請用空格隔開:").split()
if len(email_list) == 1:
if "@qq.com" not in email_list[0]:
raise Exception("郵箱規格好像不合適,你輸入的是 ", email_list[0])
else:
return email_list[0]
elif len(email_list) >= 2:
for i in email_list:
if "@qq.com" not in i:
raise Exception("郵箱規格好像不合適,你輸入的是 ", i)
else:
pass
return email_list
def my_request(self, url, model="get", params=None):
if model == 'post':
r = requests.post(url, headers=self.headers, params=params)
if r.status_code == 200:
r.encoding = r.apparent_encoding
s = r.json()
return s
elif model == 'get':
r = requests.get(url, headers=self.headers, params=params)
if r.status_code == 200:
return r.content
else:
raise Exception("method is error !")
def get_mp3_id_demo(self, start=None):
"""
get the mp3 id
{"hlpretag":"<span class=\"s-fc7\">","hlposttag":"</span>","s":"本兮","type":"1","offset":"0","total":"true","limit":"30","csrf_token":""}
"""
if start is None:
raise Exception("You should enter a start name, but you enter start =", start)
d = {
"hlpretag": "<span class=\"s-fc7\">",
"hlposttag": "</span>",
"s": str(start),
"type": "1",
"offset": "0",
"total": "true",
"limit": "30",
"csrf_token": ""
}
params = GetParams().get_encrypt_params(str(d))
return self.my_request(self.GetIdUrl, model="post", params=params)["result"]["songs"]
def get_mp3_url(self, id):
"""
params: id the music of id
fix the id into "{"ids":"[35440198]","level":"standard","encodeType":"aac","csrf_token":""}"
so we can get the music the downpath
"""
d = {"ids": str([id]), "level": "standard", "encodeType": "aac", "csrf_token": ""}
params = GetParams().get_encrypt_params(str(d))
context = self.my_request(self.GetMP3Url, model="post", params=params)
mp3_path_url = context.get("data")[0]["url"]
return mp3_path_url
def print_id_list(self, id_list):
"""
params: id_list print the singer about 30s musics
"""
a = {}
for index, value in enumerate(id_list):
a['count'] = (index + 1)
a["singer_name"] = value.get("name")
a["id"] = value.get("id")
a["album"] = value.get("al").get("name")
a["image"] = value.get("al").get("picUrl")
self.MUSIC_LIST.append(a.copy())
def random_get_mp3(self):
mp3Ten = random.sample(self.MUSIC_LIST, 10) # 提出十首歌
content = "" # 把資料寫入html中 方便發送
content += '<p><font size="20" color="Tan">Happy day for you !</font></p>'
content += '<table border="1" style="border-collapse: collapse;">\n<caption>Today music demo </caption>\n<tr><th>序號</th><th>歌曲名</th><th>歌曲鏈接</th><th>歌曲所屬</th><th>美圖</th></tr>'
count = 1
for j in mp3Ten:
s = f"\n<tr><th>{count}</th><th>{j['singer_name']}</th>" \
f"<th><a href='{self.get_mp3_url(j['id'])}'>點擊播放</a></th><th>{j['album']}</th>" \
f"<th><img src='{j['image']}' alt='美圖' height='400' width='400' /></th></tr>"
content += s
count += 1
content += "</table>"
return content
def sent_email(self, content):
"""
sent the music demo list for you like one
"""
pwd = keyring.get_password("qqemail", "884427640")
yag = yagmail.SMTP("884427640@qq.com", pwd, host="smtp.qq.com")
# test qq 2817634007@qq.com
yag.send(self.Sented_qq_email, '網易云專屬推送', content)
yag.close()
print("Today music already sent ok!")
def start_demo(self):
try:
start_name = input("input a music singer or music name "
"if you like it:")
id_list = self.get_mp3_id_demo(start=start_name)
self.print_id_list(id_list)
print(self.MUSIC_LIST)
self.sent_email(self.random_get_mp3())
except Exception as e:
print("出現error", e, "再試一次!")
self.start_demo()
# 如果要運行此程式 請打開下面的注釋
# a = DownMp3()
# a.start_demo()
下載單曲代碼:
擴展了一個下載一首歌的代碼,如果你需要,
# -*- coding : utf-8 -*-
# @Time : 2020/9/17 21:35
# @author : 沙漏在下雨
# @Software : PyCharm
# @CSDN : https://me.csdn.net/qq_45906219
import requests
from get_useragent import GetUserAgentCS
from GetParams import GetParams
from DownMp3 import DownMp3
class DownOneMp3(DownMp3):
def __init__(self):
super().__init__()
self.GetIdUrl = "https://music.163.com/weapi/cloudsearch/get/web?csrf_token="
self.params_url = "https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token="
self.headers = {"user-agent": GetUserAgentCS().get_user()}
self.start = input("Please input the music name:")
ids = self.get_id()
self.params = self.get_params(id=ids)
self.mp3_name = self.start + ".mp3"
def my_request(self, url, model="get", params=None):
"""
繼承父類的一個方法
"""
return super().my_request(url, model, params)
def get_params(self, id):
"""給出id 回傳加密引數"""
d = {"ids": str([id]), "level": "standard", "encodeType": "aac", "csrf_token": ""}
params = GetParams().get_encrypt_params(str(d))
return params
def get_id(self):
"""
根據歌曲名稱獲取id
"""
start = self.start
d = {
"hlpretag": "<span class=\"s-fc7\">",
"hlposttag": "</span>",
"s": str(start),
"type": "1",
"offset": "0",
"total": "true",
"limit": "30",
"csrf_token": ""
}
params = GetParams().get_encrypt_params(str(d))
return self.my_request(self.GetIdUrl, model="post", params=params)["result"]["songs"][0].get("id")
def spider(self):
"""
這是爬取一首歌的方式, 你只需要輸入歌曲名稱就可以 會自動呼叫其他類實作引數加密 id獲取等
"""
import os
r = requests.post(self.params_url, params=self.params)
if r.status_code == 200:
print(r.json())
mp3 = r.json().get("data")[0].get("url")
print("music link is ", mp3)
rmp3 = requests.get(mp3, headers=self.headers)
if rmp3.status_code == 200:
with open(self.mp3_name, 'wb') as fw:
fw.write(rmp3.content)
print("Down Successful! ", "file path is ", os.path.dirname(__file__))
# 如果要運行此程式 請打開下面的注釋
# a = DownOneMp3()
# a.spider()
關于__init__ :
"""
如果你僅僅只是想下載一首歌 跳轉到DownOneMp3模塊啟動模塊運行
如果你想多首歌發送某人郵箱 跳轉到DownMp3模塊啟動模塊運行
"""
JS逆向, ASE加密, RES非對稱演算法,yagmail郵箱的發送,瀏覽器的debug,學到就是爽,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/81610.html
標籤:其他
上一篇:Python—海龜作圖
