用 Python 將歌單裡的歌詞儲存成圖片
網易雲音樂的手機客戶端有將歌詞儲存成圖片分享的功能,但是一次只能儲存一首歌。所以我用 Python 寫了個指令碼,可以將歌單裡面的所有歌曲都儲存成圖片。
還有缺陷需要彌補
GitHub - songzhi/Lrc2Img: 用Python將歌單裡的所有歌曲的歌詞儲存成圖片,使用了網易雲音樂API
使用了:
網易雲音樂的API
Pillow,requests 等模組
字型是 造字工房尚黑常規體,可以自己更改,在Img類裡的save方法的font變數裡
大概思路:
1。利用 API 獲取資訊,返回的是 Json 格式的資料,可以使用標準庫裡的 json 模組轉化成Python 內建的資料結構,其中 Json 中的 Object 轉化成了列表,所以對其進行迭代,找出其中的專輯圖片(url)、歌曲名字 id 和歌詞分別放入幾個列表中。
API 程式碼:
class
NetEase
():
cookies_filename
=
“netease_cookies。json”
def
__init__
(
self
):
super
()
。
__init__
()
self
。
headers
=
{
‘Host’
:
‘music。163。com’
,
‘Connection’
:
‘keep-alive’
,
‘Content-Type’
:
“application/x-www-form-urlencoded; charset=UTF-8”
,
‘Referer’
:
‘http://music。163。com/’
,
“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”
}
self
。
cookies
=
dict
(
appver
=
“1。2。1”
,
os
=
“osx”
)
def
show_progress
(
self
,
response
):
content
=
bytes
()
total_size
=
response
。
headers
。
get
(
‘content-length’
)
if
total_size
is
None
:
content
=
response
。
content
return
content
else
:
total_size
=
int
(
total_size
)
bytes_so_far
=
0
for
chunk
in
response
。
iter_content
():
content
+=
chunk
bytes_so_far
+=
len
(
chunk
)
progress
=
round
(
bytes_so_far
*
1。0
/
total_size
*
100
)
self
。
signal_load_progress
。
emit
(
progress
)
return
content
def
http_request
(
self
,
method
,
action
,
query
=
None
,
urlencoded
=
None
,
callback
=
None
,
timeout
=
1
):
headers
=
{
‘Host’
:
‘music。163。com’
,
‘Connection’
:
‘keep-alive’
,
‘Content-Type’
:
“application/x-www-form-urlencoded; charset=UTF-8”
,
‘Referer’
:
‘http://music。163。com/’
,
“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”
}
cookies
=
dict
(
appver
=
“1。2。1”
,
os
=
“osx”
)
res
=
None
if
method
==
“GET”
:
res
=
requests
。
get
(
action
,
headers
=
headers
,
cookies
=
cookies
,
timeout
=
timeout
)
elif
method
==
“POST”
:
res
=
requests
。
post
(
action
,
query
,
headers
=
self
。
headers
,
cookies
=
self
。
cookies
,
timeout
=
timeout
)
elif
method
==
“POST_UPDATE”
:
res
=
requests
。
post
(
action
,
query
,
headers
=
self
。
headers
,
cookies
=
self
。
cookies
,
timeout
=
timeout
)
self
。
cookies
。
update
(
res
。
cookies
。
get_dict
())
self
。
save_cookies
()
content
=
self
。
show_progress
(
res
)
content_str
=
content
。
decode
(
‘utf-8’
)
content_dict
=
json
。
loads
(
content_str
)
return
content_dict
def
user_playlist
(
self
,
uid
):
action
=
‘http://music。163。com/api/playlist/detail?id=’
+
str
(
uid
)
res_data
=
self
。
http_request
(
‘GET’
,
action
)
return
res_data
def
get_lyric_by_musicid
(
self
,
mid
):
url
=
‘http://music。163。com/api/song/lyric?’
+
‘id=’
+
str
(
mid
)
+
‘&lv=1&kv=1&tv=-1’
return
self
。
http_request
(
‘GET’
,
url
)
2。定義一個 Playlist 類:
class
Playlist
():
def
__init__
(
self
,
uid
):
self
。
id
=
uid
def
get
(
self
):
uid
=
self
。
id
import
re
music
=
NetEase
()
playlist
=
music
。
user_playlist
(
uid
=
uid
)
self
。
playlist
=
playlist
[
‘result’
][
‘tracks’
]
self
。
songName
=
[]
self
。
songId
=
[]
self
。
songImg
=
[]
self
。
songLrc
=
[]
for
song
in
self
。
playlist
:
self
。
songName
。
append
(
song
[
“name”
])
self
。
songId
。
append
(
song
[
“id”
])
self
。
songImg
。
append
(
song
[
“album”
][
“blurPicUrl”
])
for
songid
in
self
。
songId
:
lrc
=
music
。
get_lyric_by_musicid
(
mid
=
songid
)
lrc
=
lrc
[
‘lrc’
][
‘lyric’
]
pat
=
re
。
compile
(
r
‘\[。*\]’
)
lrc
=
re
。
sub
(
pat
,
“”
,
lrc
)
lrc
=
lrc
。
strip
()
self
。
songLrc
。
append
(
lrc
)
def
createImg
(
self
):
img
=
Img
()
for
songName
,
songLrc
,
songImg
in
zip
(
self
。
songName
,
self
。
songLrc
,
self
。
songImg
):
img
。
save
(
songName
,
songLrc
,
songImg
)
3。定義一個 Img 類來操作圖片:
class
Img
():
def
__init__
(
self
):
import
os
try
:
self
。
Path
=
r
‘C:\Img’
self
。
albumImgPath
=
self
。
Path
+
r
‘\albumImg’
os
。
mkdir
(
self
。
Path
)
os
。
mkdir
(
self
。
albumImgPath
)
except
:
pass
return
def
getsize
(
self
,
lrc
):
lrc
=
lrc
。
split
(
‘
\n
’
)
width
=
[]
for
line
in
lrc
:
width
。
append
(
len
(
line
))
width
=
max
(
width
)
self
。
fontSize
=
500
//
width
-
1
# 字型大小
fontSpace
=
10
# 每行間隔大小
length
=
len
(
lrc
)
*
(
self
。
fontSize
+
fontSpace
)
return
width
,
length
def
save
(
self
,
name
,
lrc
,
imgurl
):
from
io
import
BytesIO
import
requests
width
,
length
=
self
。
getsize
(
lrc
)
from
PIL
import
Image
,
ImageDraw
,
ImageFont
albumImgSize
=
500
#專輯縮圖大小
font
=
“MFShangHei_Noncommercial-Regular。otf”
fontSize
=
self
。
fontSize
#字型大小
fontSpace
=
10
#每行間隔大小
space
=
10
#留白
rImg
=
requests
。
get
(
imgurl
)
albumImg
=
Image
。
open
(
BytesIO
(
rImg
。
content
))
albumImg
。
save
(
self
。
albumImgPath
+
r
‘
\\
’
+
name
+
‘。bmp’
)
font
=
ImageFont
。
truetype
(
font
,
fontSize
)
rSizeImg
=
albumImg
。
resize
((
albumImgSize
,
albumImgSize
),
resample
=
3
)
x
=
albumImgSize
y
=
albumImgSize
+
length
+
space
*
4
outImg
=
Image
。
new
(
mode
=
‘RGB’
,
size
=
(
x
,
y
),
color
=
(
255
,
255
,
255
))
draw
=
ImageDraw
。
Draw
(
outImg
)
outImg
。
paste
(
rSizeImg
,(
0
,
0
))
draw
。
text
((
space
*
2
,
albumImgSize
+
space
*
2
),
lrc
,
font
=
font
,
fill
=
(
0
,
0
,
0
),
spacing
=
fontSpace
,
align
=
‘left’
)
draw
。
text
((
space
*
2
,
y
-
80
),
‘——’
+
name
,
fill
=
(
0
,
0
,
0
),
font
=
font
,
align
=
‘left’
)
outImg
。
save
(
self
。
Path
+
r
‘
\\
’
+
name
+
‘。bmp’
)
return
4。最後呼叫:
id
=
input
(
‘請輸入歌單ID:’
)
music
=
Playlist
(
id
)
music
。
get
()
music
。
createImg
()