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