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