└── Lrc2Img.py /Lrc2Img.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import json 3 | import requests 4 | class NetEase(): 5 | 6 | cookies_filename = "netease_cookies.json" 7 | 8 | def __init__(self): 9 | # super().__init__() 10 | self.headers = { 11 | 'Host': 'music.163.com', 12 | 'Connection': 'keep-alive', 13 | 'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8", 14 | 'Referer': 'http://music.163.com/', 15 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36" 16 | " (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36" 17 | } 18 | self.cookies = dict(appver="1.2.1", os="osx") 19 | 20 | def show_progress(self, response): 21 | content = bytes() 22 | total_size = response.headers.get('content-length') 23 | if total_size is None: 24 | 25 | content = response.content 26 | return content 27 | else: 28 | total_size = int(total_size) 29 | bytes_so_far = 0 30 | 31 | for chunk in response.iter_content(): 32 | content += chunk 33 | bytes_so_far += len(chunk) 34 | progress = round(bytes_so_far * 1.0 / total_size * 100) 35 | self.signal_load_progress.emit(progress) 36 | return content 37 | 38 | def http_request(self, method, action, query=None, urlencoded=None, callback=None, timeout=1): 39 | headers={ 40 | 'Host': 'music.163.com', 41 | 'Connection': 'keep-alive', 42 | 'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8", 43 | 'Referer': 'http://music.163.com/', 44 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36" 45 | " (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36" 46 | } 47 | cookies = dict(appver="1.2.1", os="osx") 48 | res = None 49 | if method == "GET": 50 | res = requests.get(action, headers=headers, cookies=cookies, timeout=timeout) 51 | elif method == "POST": 52 | res = requests.post(action, query, headers=self.headers, cookies=self.cookies, timeout=timeout) 53 | elif method == "POST_UPDATE": 54 | res = requests.post(action, query, headers=self.headers, cookies=self.cookies, timeout=timeout) 55 | self.cookies.update(res.cookies.get_dict()) 56 | self.save_cookies() 57 | content = self.show_progress(res) 58 | content_str = content.decode('utf-8') 59 | content_dict = json.loads(content_str) 60 | return content_dict 61 | 62 | def user_playlist(self, uid): 63 | action = 'http://music.163.com/api/playlist/detail?id=' + str(uid) 64 | res_data = self.http_request('GET', action) 65 | return res_data 66 | 67 | 68 | 69 | def get_lyric_by_musicid(self, mid): 70 | 71 | url = 'http://music.163.com/api/song/lyric?' + 'id=' + str(mid) + '&lv=1&kv=1&tv=-1' 72 | return self.http_request('POST', url) #此API必须使用POST方式才能正确返回,否则提示“illegal request” 73 | 74 | class Playlist(): 75 | def __init__(self,uid): 76 | self.id=uid 77 | def get(self): 78 | uid=self.id 79 | import re 80 | music=NetEase() 81 | playlist = music.user_playlist(uid=uid) 82 | self.playlist = playlist['result']['tracks'] 83 | self.songName = [] 84 | self.songId = [] 85 | self.songImg = [] 86 | self.songLrc = [] 87 | for song in self.playlist: 88 | self.songName.append(song["name"]) 89 | self.songId.append(song["id"]) 90 | self.songImg.append(song["album"]["blurPicUrl"]) 91 | for songid in self.songId: 92 | lrc = music.get_lyric_by_musicid(mid=songid) 93 | lrc=lrc['lrc']['lyric'] 94 | pat = re.compile(r'\[.*\]') 95 | lrc = re.sub(pat, "", lrc) 96 | lrc=lrc.strip() 97 | self.songLrc.append(lrc) 98 | def createImg(self): 99 | img=Img() 100 | for songName,songLrc,songImg in zip(self.songName,self.songLrc,self.songImg): 101 | img.save(songName,songLrc,songImg) 102 | class Img(): 103 | def __init__(self): 104 | 105 | import os 106 | try: 107 | self.Path = r'C:\Img' 108 | self.albumImgPath = self.Path + r'\albumImg' 109 | os.mkdir(self.Path) 110 | os.mkdir(self.albumImgPath) 111 | except: 112 | pass 113 | 114 | 115 | 116 | 117 | return 118 | 119 | def is_chinese(self,uchar): 120 | """判断一个unicode是否是汉字""" 121 | if uchar >= u'\u4e00' and uchar <= u'\u9fa5': 122 | return True 123 | else: 124 | return False 125 | def getsize(self,lrc): 126 | 127 | lrc=lrc.split('\n') 128 | width = [] 129 | for line in lrc: 130 | width.append(len(line)) 131 | width = max(width) 132 | 133 | self.fontSize = 500//width-1 # 字体大小 134 | fontSpace = 10 # 每行间隔大小 135 | 136 | length=len(lrc)*(self.fontSize+fontSpace) 137 | 138 | 139 | return width,length 140 | 141 | 142 | 143 | 144 | def save(self,name,lrc,imgurl): 145 | from io import BytesIO 146 | width,length = self.getsize(lrc) 147 | from PIL import Image, ImageDraw, ImageFont 148 | isChinese=False 149 | for char in name: 150 | if self.is_chinese(char): 151 | isChinese=True 152 | if not isChinese: 153 | self.fontSize=int(self.fontSize*2.5) 154 | length*=2 155 | albumImgSize=500#专辑缩略图大小 156 | font="C:\\MFShangHei_Noncommercial-Regular.otf" #需要把字体下载到本地,并且提供其路径 157 | 158 | 159 | fontSize=self.fontSize#字体大小 160 | fontSpace=10#每行间隔大小 161 | space=10#留白 162 | rImg= requests.get(imgurl) 163 | albumImg = Image.open(BytesIO(rImg.content)) 164 | albumImg.save(self.albumImgPath+r'\\'+name + '.bmp') 165 | font=ImageFont.truetype(font, fontSize) 166 | rSizeImg=albumImg.resize((albumImgSize,albumImgSize),resample=3) 167 | 168 | x=albumImgSize 169 | y=albumImgSize+length+space*8 170 | outImg=Image.new(mode='RGB', size=(x, y), color=(255, 255, 255)) 171 | draw= ImageDraw.Draw(outImg) 172 | outImg.paste(rSizeImg,(0,0)) 173 | 174 | draw.text((space*2,albumImgSize+space*2),lrc,font=font,fill=(0,0,0),spacing=fontSpace,align='left') 175 | # Python中字符串类型分为byte string 和 unicode string两种,'——'为中文标点byte string,需转换为unicode string 176 | draw.text((space*2, y-60),unicode('——', "utf-8")+name,fill=(0,0,0),font=font,align="left") 177 | outImg.save(self.Path+r'\\'+name+'.bmp') 178 | 179 | return 180 | id=input('请输入歌单ID:') 181 | music=Playlist(id) 182 | music.get() 183 | music.createImg() 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | --------------------------------------------------------------------------------