最近想獲取幾首好聽(tīng)的網(wǎng)易云音樂(lè)文件毁菱,但是不是會(huì)員米死,只有緩存文件,而且經(jīng)過(guò)加工了的贮庞。
以前獲取過(guò)某k歌的緩存文件峦筒,直接修改后綴名就行了,但是網(wǎng)易云音樂(lè)不行窗慎,sigh
下面開(kāi)始探索網(wǎng)易云音樂(lè)之旅:D
目錄
- 解密緩存文件
- 獲得歌曲信息
- 獲取歌詞
- lyric文件
- 利用API獲取歌詞
- 成果
- 完整代碼
- 感想
- 注意
- And finally
解密緩存文件
在手機(jī)上的緩存文件在 netease/cloudmusic/Cache/Music1
里
觀察可以發(fā)現(xiàn)物喷,歌曲緩存文件包括兩個(gè),一個(gè)是index文件.idx!遮斥,另一個(gè)是歌曲文件峦失,index文件和歌詞文件(歌曲id命名)都是txt文件,可以直接打開(kāi)术吗,而歌曲文件.uc!打開(kāi)錯(cuò)誤氓涣。緩存文件是修改過(guò)的捞慌。如圖:
進(jìn)一步地胸哥,緩存文件和源文件大小一樣大紫岩,所以沒(méi)有經(jīng)過(guò)壓縮实幕,最簡(jiǎn)單的想法是異或運(yùn)算吝镣,這樣最簡(jiǎn)單,加密昆庇,解密一樣的操作末贾。逐個(gè)嘗試,發(fā)現(xiàn)每字節(jié)和0xa3異或即可整吆,得到正確的文件拱撵,可以播放,哈哈 :smiley: 下面是代碼表蝙,注意用bytearray修改bytes
with open (fileName,'rb') as f:
btay = bytearray(f.read())
with open(newFile,'wb') as out:
for i,j in enumerate(btay):
btay[i] = j ^ 0xa3
out.write(bytes(btay))
獲得歌曲信息
為了給歌曲文件正確命名拴测,我想獲得歌曲題目和歌手信息。雖然.idx!索引文件包含一些屬性府蛇,但是沒(méi)有歌曲標(biāo)題和歌手集索,不過(guò)重要的是musicId,這是歌曲的唯一標(biāo)識(shí)。然后發(fā)現(xiàn).idx! .uc!文件都是以id開(kāi)頭的务荆,且歌詞文件是id命名的妆距。
可以用這個(gè) api 來(lái)獲取信息
https://api.imjad.cn/cloudmusic/?type=detail&id=1234132
還有另一種方法,mp3等文件格式有一些metadata (元素?fù)?jù))函匕,mp3文件的 id3 tag里面就包含標(biāo)題娱据,歌手。這是wiki的介紹
然后找python模塊盅惜,網(wǎng)上說(shuō)eyeD3比較好用中剩,但是我安裝好后提示libmagic找不到,搜索問(wèn)題未能解決(如果你有解決辦法抒寂,請(qǐng)告訴我咽安,十分感謝), 然后用的mutagen模塊蓬推,這個(gè)模塊能操作很多格式的文件妆棒,這是效果
獲取歌詞
有兩種方法
lyric文件
這是歌詞文件內(nèi)容
從這個(gè)文件中讀取。 解析這個(gè)文件沸伏,由于沒(méi)有統(tǒng)一的鍵,所以可以用正則表達(dá)式r'(lyric|lrc|klyric|kalaokLyric|tlyric)\s*[\'\"]:\s*[\'\"]\s*\[')
來(lái)檢查是否有歌詞內(nèi)容
# self.hasLrcPt= re.compile(r'(lyric|lrc|klyric|kalaokLyric|tlyric)\s*[\'\"]:\s*[\'\"]\s*\[')
# self.lrcKey = 'lyric|lrc|klyric|kalaokLyric|tlyric'.split('|')
def noLrc(self,s):
'''judge if a dict or a string has lyrics'''
if isinstance(s,str):
return self.hasLrcPt.search(s) is None
else:
return not reduce(or_,[i in s and s[i]!='' for i in self.lrcKey])
檢查到有歌詞后糕珊,可以發(fā)現(xiàn)每句是這樣的
[0:09.000]平安夜,褻瀆的夜晚\n
最開(kāi)始用的r'\[\d+,\d+\](\(\d+,\d+\)(\w))+\n')
毅糟,然而總是匹配不到红选,在交互模式又匹配得很精確,在這里浪費(fèi)了很多時(shí)間姆另,最后發(fā)現(xiàn)是\n
的問(wèn)題喇肋,在正則表達(dá)式中要用\\n
,作為字符串在交互模式下打印出來(lái)只顯示了\n
, :weary: 迹辐, 心累 蝶防,改為r'\[\d+:\d+\.\d+\](.*?)\\n'
.
利用API獲取歌詞
利用上面的 api , 傳遞 lyric 參數(shù)即可
注意由于是緩存文件,有極少的音樂(lè)可能id3 tag以及 api 都沒(méi)有信息明吩,對(duì)于這些间学,我直接用的id命名
成果
- 展示
- 運(yùn)行輸出
-
歌詞
-
MP3
完整代碼
感想
:flushed: (羞澀
有時(shí)看書(shū)有點(diǎn)沒(méi)有耐心,想實(shí)踐印荔,然而如果沒(méi)有掌握好知識(shí)低葫,實(shí)踐的話就會(huì)踩很多坑,甚至可能還爬不起來(lái)有些坑仍律。 還差得遠(yuǎn)呢嘿悬,還得加油哦!
注意
- 有極少數(shù)的緩存文件 在 api 中沒(méi)有信息, 在 id3 tag 中也沒(méi)有, 這些歌曲我用的 id 來(lái)命令
- 最新更新都在github上, 博客很少更新, 所以使用前最好去讀一下 github 的 readme
And finally
(學(xué)習(xí)使用異或加密 :see_no_evil: