]>
Commit | Line | Data |
---|---|---|
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 = 'http://www.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_lenth = len(origin) // n | |
58 | long_num = len(origin) - short_lenth * n | |
59 | l = tuple() | |
60 | for i in range(0, n): | |
61 | length = short_lenth | |
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_lenth + 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 | } |