]>
Commit | Line | Data |
---|---|---|
dcdb292f | 1 | # coding: utf-8 |
efb1bb90 JMF |
2 | from __future__ import unicode_literals |
3 | ||
2563bcc8 | 4 | import re |
2563bcc8 JMF |
5 | |
6 | from .common import InfoExtractor | |
6b820a23 | 7 | from ..utils import ( |
8 | ExtractorError, | |
9 | int_or_none, | |
10 | parse_iso8601, | |
2563bcc8 JMF |
11 | ) |
12 | ||
13 | ||
14 | class MySpaceIE(InfoExtractor): | |
3166b1f0 S |
15 | _VALID_URL = r'''(?x) |
16 | https?:// | |
17 | myspace\.com/[^/]+/ | |
18 | (?P<mediatype> | |
19 | video/[^/]+/(?P<video_id>\d+)| | |
20 | music/song/[^/?#&]+-(?P<song_id>\d+)-\d+(?:[/?#&]|$) | |
21 | ) | |
22 | ''' | |
efb1bb90 | 23 | |
3166b1f0 S |
24 | _TESTS = [{ |
25 | 'url': 'https://myspace.com/fiveminutestothestage/video/little-big-town/109594919', | |
26 | 'md5': '9c1483c106f4a695c47d2911feed50a7', | |
27 | 'info_dict': { | |
28 | 'id': '109594919', | |
29 | 'ext': 'mp4', | |
30 | 'title': 'Little Big Town', | |
31 | 'description': 'This country quartet was all smiles while playing a sold out show at the Pacific Amphitheatre in Orange County, California.', | |
32 | 'uploader': 'Five Minutes to the Stage', | |
33 | 'uploader_id': 'fiveminutestothestage', | |
34 | 'timestamp': 1414108751, | |
35 | 'upload_date': '20141023', | |
2563bcc8 | 36 | }, |
3166b1f0 | 37 | }, { |
a196a532 | 38 | # songs |
3166b1f0 S |
39 | 'url': 'https://myspace.com/killsorrow/music/song/of-weakened-soul...-93388656-103880681', |
40 | 'md5': '1d7ee4604a3da226dd69a123f748b262', | |
41 | 'info_dict': { | |
42 | 'id': '93388656', | |
43 | 'ext': 'm4a', | |
44 | 'title': 'Of weakened soul...', | |
45 | 'uploader': 'Killsorrow', | |
46 | 'uploader_id': 'killsorrow', | |
2563bcc8 | 47 | }, |
3166b1f0 S |
48 | }, { |
49 | 'url': 'https://myspace.com/starset2/music/song/first-light-95799905-106964426', | |
50 | 'only_matching': True, | |
51 | }, { | |
52 | 'url': 'https://myspace.com/thelargemouthbassband/music/song/02-pure-eyes.mp3-94422330-105113388', | |
53 | 'only_matching': True, | |
54 | }] | |
2563bcc8 JMF |
55 | |
56 | def _real_extract(self, url): | |
5ad28e7f | 57 | mobj = self._match_valid_url(url) |
3166b1f0 | 58 | video_id = mobj.group('video_id') or mobj.group('song_id') |
f65dba7c | 59 | is_song = mobj.group('mediatype').startswith('music/song') |
2563bcc8 | 60 | webpage = self._download_webpage(url, video_id) |
f2b44a25 | 61 | player_url = self._search_regex( |
f65dba7c | 62 | r'videoSwf":"([^"?]*)', webpage, 'player URL', fatal=False) |
efb1bb90 | 63 | |
f65dba7c RA |
64 | def formats_from_stream_urls(stream_url, hls_stream_url, http_stream_url, width=None, height=None): |
65 | formats = [] | |
66 | vcodec = 'none' if is_song else None | |
67 | if hls_stream_url: | |
68 | formats.append({ | |
69 | 'format_id': 'hls', | |
70 | 'url': hls_stream_url, | |
71 | 'protocol': 'm3u8_native', | |
72 | 'ext': 'm4a' if is_song else 'mp4', | |
73 | 'vcodec': vcodec, | |
74 | }) | |
75 | if stream_url and player_url: | |
76 | rtmp_url, play_path = stream_url.split(';', 1) | |
77 | formats.append({ | |
78 | 'format_id': 'rtmp', | |
79 | 'url': rtmp_url, | |
80 | 'play_path': play_path, | |
81 | 'player_url': player_url, | |
82 | 'protocol': 'rtmp', | |
83 | 'ext': 'flv', | |
84 | 'width': width, | |
85 | 'height': height, | |
86 | 'vcodec': vcodec, | |
87 | }) | |
88 | if http_stream_url: | |
89 | formats.append({ | |
90 | 'format_id': 'http', | |
91 | 'url': http_stream_url, | |
92 | 'width': width, | |
93 | 'height': height, | |
94 | 'vcodec': vcodec, | |
95 | }) | |
96 | return formats | |
6b820a23 | 97 | |
f65dba7c | 98 | if is_song: |
efb1bb90 | 99 | # songs don't store any useful info in the 'context' variable |
1940fadd TF |
100 | song_data = self._search_regex( |
101 | r'''<button.*data-song-id=(["\'])%s\1.*''' % video_id, | |
102 | webpage, 'song_data', default=None, group=0) | |
103 | if song_data is None: | |
954f36f8 JMF |
104 | # some songs in an album are not playable |
105 | self.report_warning( | |
1940fadd TF |
106 | '%s: No downloadable song on this page' % video_id) |
107 | return | |
810fb84d | 108 | |
efb1bb90 | 109 | def search_data(name): |
b66e6998 | 110 | return self._search_regex( |
954f36f8 JMF |
111 | r'''data-%s=([\'"])(?P<data>.*?)\1''' % name, |
112 | song_data, name, default='', group='data') | |
f65dba7c RA |
113 | formats = formats_from_stream_urls( |
114 | search_data('stream-url'), search_data('hls-stream-url'), | |
115 | search_data('http-stream-url')) | |
116 | if not formats: | |
3266f0c6 TF |
117 | vevo_id = search_data('vevo-id') |
118 | youtube_id = search_data('youtube-id') | |
119 | if vevo_id: | |
120 | self.to_screen('Vevo video detected: %s' % vevo_id) | |
121 | return self.url_result('vevo:%s' % vevo_id, ie='Vevo') | |
122 | elif youtube_id: | |
123 | self.to_screen('Youtube video detected: %s' % youtube_id) | |
124 | return self.url_result(youtube_id, ie='Youtube') | |
125 | else: | |
126 | raise ExtractorError( | |
127 | 'Found song but don\'t know how to download it') | |
f65dba7c | 128 | self._sort_formats(formats) |
6b820a23 | 129 | return { |
efb1bb90 JMF |
130 | 'id': video_id, |
131 | 'title': self._og_search_title(webpage), | |
03fd72d9 | 132 | 'uploader': search_data('artist-name'), |
efb1bb90 JMF |
133 | 'uploader_id': search_data('artist-username'), |
134 | 'thumbnail': self._og_search_thumbnail(webpage), | |
6b820a23 | 135 | 'duration': int_or_none(search_data('duration')), |
f65dba7c | 136 | 'formats': formats, |
efb1bb90 JMF |
137 | } |
138 | else: | |
6b820a23 | 139 | video = self._parse_json(self._search_regex( |
140 | r'context = ({.*?});', webpage, 'context'), | |
141 | video_id)['video'] | |
f65dba7c RA |
142 | formats = formats_from_stream_urls( |
143 | video.get('streamUrl'), video.get('hlsStreamUrl'), | |
144 | video.get('mp4StreamUrl'), int_or_none(video.get('width')), | |
145 | int_or_none(video.get('height'))) | |
6b820a23 | 146 | self._sort_formats(formats) |
147 | return { | |
148 | 'id': video_id, | |
efb1bb90 | 149 | 'title': video['title'], |
6b820a23 | 150 | 'description': video.get('description'), |
151 | 'thumbnail': video.get('imageUrl'), | |
152 | 'uploader': video.get('artistName'), | |
153 | 'uploader_id': video.get('artistUsername'), | |
154 | 'duration': int_or_none(video.get('duration')), | |
155 | 'timestamp': parse_iso8601(video.get('dateAdded')), | |
156 | 'formats': formats, | |
efb1bb90 JMF |
157 | } |
158 | ||
95c673a1 TF |
159 | |
160 | class MySpaceAlbumIE(InfoExtractor): | |
161 | IE_NAME = 'MySpace:album' | |
162 | _VALID_URL = r'https?://myspace\.com/([^/]+)/music/album/(?P<title>.*-)(?P<id>\d+)' | |
163 | ||
164 | _TESTS = [{ | |
165 | 'url': 'https://myspace.com/starset2/music/album/transmissions-19455773', | |
166 | 'info_dict': { | |
167 | 'title': 'Transmissions', | |
168 | 'id': '19455773', | |
169 | }, | |
170 | 'playlist_count': 14, | |
171 | 'skip': 'this album is only available in some countries', | |
172 | }, { | |
173 | 'url': 'https://myspace.com/killsorrow/music/album/the-demo-18596029', | |
174 | 'info_dict': { | |
175 | 'title': 'The Demo', | |
176 | 'id': '18596029', | |
177 | }, | |
178 | 'playlist_count': 5, | |
179 | }] | |
180 | ||
181 | def _real_extract(self, url): | |
5ad28e7f | 182 | mobj = self._match_valid_url(url) |
95c673a1 TF |
183 | playlist_id = mobj.group('id') |
184 | display_id = mobj.group('title') + playlist_id | |
185 | webpage = self._download_webpage(url, display_id) | |
186 | tracks_paths = re.findall(r'"music:song" content="(.*?)"', webpage) | |
187 | if not tracks_paths: | |
954f36f8 JMF |
188 | raise ExtractorError( |
189 | '%s: No songs found, try using proxy' % display_id, | |
190 | expected=True) | |
95c673a1 TF |
191 | entries = [ |
192 | self.url_result(t_path, ie=MySpaceIE.ie_key()) | |
193 | for t_path in tracks_paths] | |
95c673a1 TF |
194 | return { |
195 | '_type': 'playlist', | |
196 | 'id': playlist_id, | |
197 | 'display_id': display_id, | |
954f36f8 | 198 | 'title': self._og_search_title(webpage), |
95c673a1 TF |
199 | 'entries': entries, |
200 | } |