xiami.py (6816B)
1 # coding: utf-8 2 from __future__ import unicode_literals 3 4 from .common import InfoExtractor 5 from ..compat import compat_urllib_parse_unquote 6 from ..utils import int_or_none 7 8 9 class XiamiBaseIE(InfoExtractor): 10 _API_BASE_URL = 'https://emumo.xiami.com/song/playlist/cat/json/id' 11 12 def _download_webpage_handle(self, *args, **kwargs): 13 webpage = super(XiamiBaseIE, self)._download_webpage_handle(*args, **kwargs) 14 if '>Xiami is currently not available in your country.<' in webpage: 15 self.raise_geo_restricted('Xiami is currently not available in your country') 16 return webpage 17 18 def _extract_track(self, track, track_id=None): 19 track_name = track.get('songName') or track.get('name') or track['subName'] 20 artist = track.get('artist') or track.get('artist_name') or track.get('singers') 21 title = '%s - %s' % (artist, track_name) if artist else track_name 22 track_url = self._decrypt(track['location']) 23 24 subtitles = {} 25 lyrics_url = track.get('lyric_url') or track.get('lyric') 26 if lyrics_url and lyrics_url.startswith('http'): 27 subtitles['origin'] = [{'url': lyrics_url}] 28 29 return { 30 'id': track.get('song_id') or track_id, 31 'url': track_url, 32 'title': title, 33 'thumbnail': track.get('pic') or track.get('album_pic'), 34 'duration': int_or_none(track.get('length')), 35 'creator': track.get('artist', '').split(';')[0], 36 'track': track_name, 37 'track_number': int_or_none(track.get('track')), 38 'album': track.get('album_name') or track.get('title'), 39 'artist': artist, 40 'subtitles': subtitles, 41 } 42 43 def _extract_tracks(self, item_id, referer, typ=None): 44 playlist = self._download_json( 45 '%s/%s%s' % (self._API_BASE_URL, item_id, '/type/%s' % typ if typ else ''), 46 item_id, headers={ 47 'Referer': referer, 48 }) 49 return [ 50 self._extract_track(track, item_id) 51 for track in playlist['data']['trackList']] 52 53 @staticmethod 54 def _decrypt(origin): 55 n = int(origin[0]) 56 origin = origin[1:] 57 short_length = len(origin) // n 58 long_num = len(origin) - short_length * n 59 l = tuple() 60 for i in range(0, n): 61 length = short_length 62 if i < long_num: 63 length += 1 64 l += (origin[0:length], ) 65 origin = origin[length:] 66 ans = '' 67 for i in range(0, short_length + 1): 68 for j in range(0, n): 69 if len(l[j]) > i: 70 ans += l[j][i] 71 return compat_urllib_parse_unquote(ans).replace('^', '0') 72 73 74 class XiamiSongIE(XiamiBaseIE): 75 IE_NAME = 'xiami:song' 76 IE_DESC = '虾米音乐' 77 _VALID_URL = r'https?://(?:www\.)?xiami\.com/song/(?P<id>[^/?#&]+)' 78 _TESTS = [{ 79 'url': 'http://www.xiami.com/song/1775610518', 80 'md5': '521dd6bea40fd5c9c69f913c232cb57e', 81 'info_dict': { 82 'id': '1775610518', 83 'ext': 'mp3', 84 'title': 'HONNE - Woman', 85 'thumbnail': r're:http://img\.xiami\.net/images/album/.*\.jpg', 86 'duration': 265, 87 'creator': 'HONNE', 88 'track': 'Woman', 89 'album': 'Woman', 90 'artist': 'HONNE', 91 'subtitles': { 92 'origin': [{ 93 'ext': 'lrc', 94 }], 95 }, 96 }, 97 'skip': 'Georestricted', 98 }, { 99 'url': 'http://www.xiami.com/song/1775256504', 100 'md5': '932a3abd45c6aa2b1fdbe028fcb4c4fc', 101 'info_dict': { 102 'id': '1775256504', 103 'ext': 'mp3', 104 'title': '戴荃 - 悟空', 105 'thumbnail': r're:http://img\.xiami\.net/images/album/.*\.jpg', 106 'duration': 200, 107 'creator': '戴荃', 108 'track': '悟空', 109 'album': '悟空', 110 'artist': '戴荃', 111 'subtitles': { 112 'origin': [{ 113 'ext': 'lrc', 114 }], 115 }, 116 }, 117 'skip': 'Georestricted', 118 }, { 119 'url': 'http://www.xiami.com/song/1775953850', 120 'info_dict': { 121 'id': '1775953850', 122 'ext': 'mp3', 123 'title': 'До Скону - Чума Пожирает Землю', 124 'thumbnail': r're:http://img\.xiami\.net/images/album/.*\.jpg', 125 'duration': 683, 126 'creator': 'До Скону', 127 'track': 'Чума Пожирает Землю', 128 'track_number': 7, 129 'album': 'Ад', 130 'artist': 'До Скону', 131 }, 132 'params': { 133 'skip_download': True, 134 }, 135 }, { 136 'url': 'http://www.xiami.com/song/xLHGwgd07a1', 137 'only_matching': True, 138 }] 139 140 def _real_extract(self, url): 141 return self._extract_tracks(self._match_id(url), url)[0] 142 143 144 class XiamiPlaylistBaseIE(XiamiBaseIE): 145 def _real_extract(self, url): 146 item_id = self._match_id(url) 147 return self.playlist_result(self._extract_tracks(item_id, url, self._TYPE), item_id) 148 149 150 class XiamiAlbumIE(XiamiPlaylistBaseIE): 151 IE_NAME = 'xiami:album' 152 IE_DESC = '虾米音乐 - 专辑' 153 _VALID_URL = r'https?://(?:www\.)?xiami\.com/album/(?P<id>[^/?#&]+)' 154 _TYPE = '1' 155 _TESTS = [{ 156 'url': 'http://www.xiami.com/album/2100300444', 157 'info_dict': { 158 'id': '2100300444', 159 }, 160 'playlist_count': 10, 161 'skip': 'Georestricted', 162 }, { 163 'url': 'http://www.xiami.com/album/512288?spm=a1z1s.6843761.1110925389.6.hhE9p9', 164 'only_matching': True, 165 }, { 166 'url': 'http://www.xiami.com/album/URVDji2a506', 167 'only_matching': True, 168 }] 169 170 171 class XiamiArtistIE(XiamiPlaylistBaseIE): 172 IE_NAME = 'xiami:artist' 173 IE_DESC = '虾米音乐 - 歌手' 174 _VALID_URL = r'https?://(?:www\.)?xiami\.com/artist/(?P<id>[^/?#&]+)' 175 _TYPE = '2' 176 _TESTS = [{ 177 'url': 'http://www.xiami.com/artist/2132?spm=0.0.0.0.dKaScp', 178 'info_dict': { 179 'id': '2132', 180 }, 181 'playlist_count': 20, 182 'skip': 'Georestricted', 183 }, { 184 'url': 'http://www.xiami.com/artist/bC5Tk2K6eb99', 185 'only_matching': True, 186 }] 187 188 189 class XiamiCollectionIE(XiamiPlaylistBaseIE): 190 IE_NAME = 'xiami:collection' 191 IE_DESC = '虾米音乐 - 精选集' 192 _VALID_URL = r'https?://(?:www\.)?xiami\.com/collect/(?P<id>[^/?#&]+)' 193 _TYPE = '3' 194 _TEST = { 195 'url': 'http://www.xiami.com/collect/156527391?spm=a1z1s.2943601.6856193.12.4jpBnr', 196 'info_dict': { 197 'id': '156527391', 198 }, 199 'playlist_mincount': 29, 200 'skip': 'Georestricted', 201 }