]>
Raphaƫl G. Git Repositories - youtubedl/blob - youtube_dl/extractor/bandcamp.py
   1 from __future__ 
import unicode_literals
 
   8 from .common 
import InfoExtractor
 
  23 class BandcampIE(InfoExtractor
): 
  24     _VALID_URL 
= r
'https?://.*?\.bandcamp\.com/track/(?P<title>.*)' 
  26         'url': 'http://youtube-dl.bandcamp.com/track/youtube-dl-test-song', 
  27         'md5': 'c557841d5e50261777a6585648adf439', 
  31             'title': "youtube-dl  \"'/\\\u00e4\u21ad - youtube-dl test song \"'/\\\u00e4\u21ad", 
  34         '_skip': 'There is a limit of 200 free downloads / month for the test song' 
  36         'url': 'http://benprunty.bandcamp.com/track/lanius-battle', 
  37         'md5': '73d0b3171568232574e45652f8720b5c', 
  41             'title': 'Lanius (Battle)', 
  42             'uploader': 'Ben Prunty Music', 
  46     def _real_extract(self
, url
): 
  47         mobj 
= re
.match(self
._VALID
_URL
, url
) 
  48         title 
= mobj
.group('title') 
  49         webpage 
= self
._download
_webpage
(url
, title
) 
  50         m_download 
= re
.search(r
'freeDownloadPage: "(.*?)"', webpage
) 
  52             m_trackinfo 
= re
.search(r
'trackinfo: (.+),\s*?\n', webpage
) 
  54                 json_code 
= m_trackinfo
.group(1) 
  55                 data 
= json
.loads(json_code
)[0] 
  56                 track_id 
= compat_str(data
['id']) 
  58                 if not data
.get('file'): 
  59                     raise ExtractorError('Not streamable', video_id
=track_id
, expected
=True) 
  62                 for format_id
, format_url 
in data
['file'].items(): 
  63                     ext
, abr_str 
= format_id
.split('-', 1) 
  65                         'format_id': format_id
, 
  66                         'url': self
._proto
_relative
_url
(format_url
, 'http:'), 
  70                         'abr': int_or_none(abr_str
), 
  73                 self
._sort
_formats
(formats
) 
  77                     'title': data
['title'], 
  79                     'duration': float_or_none(data
.get('duration')), 
  82                 raise ExtractorError('No free songs found') 
  84         download_link 
= m_download
.group(1) 
  85         video_id 
= self
._search
_regex
( 
  86             r
'(?ms)var TralbumData = .*?[{,]\s*id: (?P<id>\d+),?$', 
  89         download_webpage 
= self
._download
_webpage
( 
  90             download_link
, video_id
, 'Downloading free downloads page') 
  92         blob 
= self
._parse
_json
( 
  94                 r
'data-blob=(["\'])(?P
<blob
>{.+?
})\
1', download_webpage, 
  95                 'blob
', group='blob
'), 
  96             video_id, transform_source=unescapeHTML) 
  98         info = blob['digital_items
'][0] 
 100         downloads = info['downloads
'] 
 101         track = info['title
'] 
 103         artist = info.get('artist
') 
 104         title = '%s - %s' % (artist, track) if artist else track 
 106         download_formats = {} 
 107         for f in blob['download_formats
']: 
 108             name, ext = f.get('name
'), f.get('file_extension
') 
 109             if all(isinstance(x, compat_str) for x in (name, ext)): 
 110                 download_formats[name] = ext.strip('.') 
 113         for format_id, f in downloads.items(): 
 114             format_url = f.get('url
') 
 117             # Stat URL generation algorithm is reverse engineered from 
 118             # download_*_bundle_*.js 
 119             stat_url = update_url_query( 
 120                 format_url.replace('/download
/', '/statdownload
/'), { 
 121                     '.rand
': int(time.time() * 1000 * random.random()), 
 123             format_id = f.get('encoding_name
') or format_id 
 124             stat = self._download_json( 
 125                 stat_url, video_id, 'Downloading 
%s JSON
' % format_id, 
 126                 transform_source=lambda s: s[s.index('{'):s.rindex('}') + 1], 
 130             retry_url = stat.get('retry_url
') 
 131             if not isinstance(retry_url, compat_str): 
 134                 'url
': self._proto_relative_url(retry_url, 'http
:'), 
 135                 'ext
': download_formats.get(format_id), 
 136                 'format_id
': format_id, 
 137                 'format_note
': f.get('description
'), 
 138                 'filesize
': parse_filesize(f.get('size_mb
')), 
 141         self._sort_formats(formats) 
 146             'thumbnail
': info.get('thumb_url
'), 
 147             'uploader
': info.get('artist
'), 
 154 class BandcampAlbumIE(InfoExtractor): 
 155     IE_NAME = 'Bandcamp
:album
' 
 156     _VALID_URL = r'https?
://(?
:(?P
<subdomain
>[^
.]+)\
.)?bandcamp\
.com(?
:/album
/(?P
<album_id
>[^?
#]+)|/?(?:$|[?#]))' 
 159         'url': 'http://blazo.bandcamp.com/album/jazz-format-mixtape-vol-1', 
 162                 'md5': '39bc1eded3476e927c724321ddf116cf', 
 170                 'md5': '1a2c32e2691474643e912cc6cd4bffaa', 
 174                     'title': 'Kero One - Keep It Alive (Blazo remix)', 
 179             'title': 'Jazz Format Mixtape vol.1', 
 180             'id': 'jazz-format-mixtape-vol-1', 
 181             'uploader_id': 'blazo', 
 186         'skip': 'Bandcamp imposes download limits.' 
 188         'url': 'http://nightbringer.bandcamp.com/album/hierophany-of-the-open-grave', 
 190             'title': 'Hierophany of the Open Grave', 
 191             'uploader_id': 'nightbringer', 
 192             'id': 'hierophany-of-the-open-grave', 
 194         'playlist_mincount': 9, 
 196         'url': 'http://dotscale.bandcamp.com', 
 200             'uploader_id': 'dotscale', 
 202         'playlist_mincount': 7, 
 204         # with escaped quote in title 
 205         'url': 'https://jstrecords.bandcamp.com/album/entropy-ep', 
 207             'title': '"Entropy" EP', 
 208             'uploader_id': 'jstrecords', 
 211         'playlist_mincount': 3, 
 214     def _real_extract(self
, url
): 
 215         mobj 
= re
.match(self
._VALID
_URL
, url
) 
 216         uploader_id 
= mobj
.group('subdomain') 
 217         album_id 
= mobj
.group('album_id') 
 218         playlist_id 
= album_id 
or uploader_id
 
 219         webpage 
= self
._download
_webpage
(url
, playlist_id
) 
 220         tracks_paths 
= re
.findall(r
'<a href="(.*?)" itemprop="url">', webpage
) 
 222             raise ExtractorError('The page doesn\'t contain any tracks') 
 224             self
.url_result(compat_urlparse
.urljoin(url
, t_path
), ie
=BandcampIE
.ie_key()) 
 225             for t_path 
in tracks_paths
] 
 226         title 
= self
._html
_search
_regex
( 
 227             r
'album_title\s*:\s*"((?:\\.|[^"\\])+?)"', 
 228             webpage
, 'title', fatal
=False) 
 230             title 
= title
.replace(r
'\"', '"') 
 233             'uploader_id': uploader_id
,