X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=youtube_dl%2FInfoExtractors.py;h=139173016a9f7139e9e3caae11dc563cf066f499;hb=2f58b12dad1b5e19f2daf338cdba958be0b0a87c;hp=d5876ad3463b71a841b00552f0b97737b4264996;hpb=7b670a4483d589af822e7fc061d1d3d3aafd36f0;p=youtube-dl diff --git a/youtube_dl/InfoExtractors.py b/youtube_dl/InfoExtractors.py index d5876ad34..139173016 100755 --- a/youtube_dl/InfoExtractors.py +++ b/youtube_dl/InfoExtractors.py @@ -114,8 +114,8 @@ class InfoExtractor(object): def _request_webpage(self, url_or_request, video_id, note=None, errnote=None): """ Returns the response handle """ if note is None: - note = u'Downloading video webpage' - if note is not False: + self.report_download_webpage(video_id) + elif note is not False: self.to_screen(u'%s: %s' % (video_id, note)) try: return compat_urllib_request.urlopen(url_or_request) @@ -124,8 +124,8 @@ class InfoExtractor(object): errnote = u'Unable to download webpage' raise ExtractorError(u'%s: %s' % (errnote, compat_str(err)), sys.exc_info()[2]) - def _download_webpage(self, url_or_request, video_id, note=None, errnote=None): - """ Returns the data of the page as a string """ + def _download_webpage_handle(self, url_or_request, video_id, note=None, errnote=None): + """ Returns a tuple (page content as string, URL handle) """ urlh = self._request_webpage(url_or_request, video_id, note, errnote) content_type = urlh.headers.get('Content-Type', '') m = re.match(r'[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+\s*;\s*charset=(.+)', content_type) @@ -142,7 +142,12 @@ class InfoExtractor(object): self.to_screen(u'Dumping request to ' + url) dump = base64.b64encode(webpage_bytes).decode('ascii') self._downloader.to_screen(dump) - return webpage_bytes.decode(encoding, 'replace') + content = webpage_bytes.decode(encoding, 'replace') + return (content, urlh) + + def _download_webpage(self, url_or_request, video_id, note=None, errnote=None): + """ Returns the data of the page as a string """ + return self._download_webpage_handle(url_or_request, video_id, note, errnote)[0] def to_screen(self, msg): """Print msg to screen, prefixing it with '[ie_name]'""" @@ -152,6 +157,10 @@ class InfoExtractor(object): """Report information extraction.""" self.to_screen(u'%s: Extracting information' % id_or_name) + def report_download_webpage(self, video_id): + """Report webpage download.""" + self.to_screen(u'%s: Downloading webpage' % video_id) + def report_age_confirmation(self): """Report attempt to confirm age.""" self.to_screen(u'Confirming age') @@ -202,7 +211,7 @@ class YoutubeIE(InfoExtractor): ([0-9A-Za-z_-]+) # here is it! the YouTube video ID (?(1).+)? # if we found the ID, everything can follow $""" - _LANG_URL = r'http://www.youtube.com/?hl=en&persist_hl=1&gl=US&persist_gl=1&opt_out_ackd=1' + _LANG_URL = r'https://www.youtube.com/?hl=en&persist_hl=1&gl=US&persist_gl=1&opt_out_ackd=1' _LOGIN_URL = 'https://accounts.google.com/ServiceLogin' _AGE_URL = 'http://www.youtube.com/verify_age?next_url=/&gl=US&hl=en' _NEXT_URL_RE = r'[\?&]next_url=([^&]+)' @@ -418,7 +427,7 @@ class YoutubeIE(InfoExtractor): # Log in login_form_strs = { - u'continue': u'http://www.youtube.com/signin?action_handle_signin=true&feature=sign_in_button&hl=en_US&nomobiletemp=1', + u'continue': u'https://www.youtube.com/signin?action_handle_signin=true&feature=sign_in_button&hl=en_US&nomobiletemp=1', u'Email': username, u'GALX': galx, u'Passwd': password, @@ -463,14 +472,12 @@ class YoutubeIE(InfoExtractor): self.report_age_confirmation() age_results = compat_urllib_request.urlopen(request).read().decode('utf-8') except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to confirm age: %s' % compat_str(err)) - return + raise ExtractorError(u'Unable to confirm age: %s' % compat_str(err)) def _extract_id(self, url): mobj = re.match(self._VALID_URL, url, re.VERBOSE) if mobj is None: - self._downloader.report_error(u'invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) video_id = mobj.group(2) return video_id @@ -478,18 +485,17 @@ class YoutubeIE(InfoExtractor): # Extract original video URL from URL with redirection, like age verification, using next_url parameter mobj = re.search(self._NEXT_URL_RE, url) if mobj: - url = 'http://www.youtube.com/' + compat_urllib_parse.unquote(mobj.group(1)).lstrip('/') + url = 'https://www.youtube.com/' + compat_urllib_parse.unquote(mobj.group(1)).lstrip('/') video_id = self._extract_id(url) # Get video webpage self.report_video_webpage_download(video_id) - url = 'http://www.youtube.com/watch?v=%s&gl=US&hl=en&has_verified=1' % video_id + url = 'https://www.youtube.com/watch?v=%s&gl=US&hl=en&has_verified=1' % video_id request = compat_urllib_request.Request(url) try: video_webpage_bytes = compat_urllib_request.urlopen(request).read() except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download video webpage: %s' % compat_str(err)) - return + raise ExtractorError(u'Unable to download video webpage: %s' % compat_str(err)) video_webpage = video_webpage_bytes.decode('utf-8', 'ignore') @@ -513,23 +519,20 @@ class YoutubeIE(InfoExtractor): break if 'token' not in video_info: if 'reason' in video_info: - self._downloader.report_error(u'YouTube said: %s' % video_info['reason'][0]) + raise ExtractorError(u'YouTube said: %s' % video_info['reason'][0]) else: - self._downloader.report_error(u'"token" parameter not in video info for unknown reason') - return + raise ExtractorError(u'"token" parameter not in video info for unknown reason') # Check for "rental" videos if 'ypc_video_rental_bar_text' in video_info and 'author' not in video_info: - self._downloader.report_error(u'"rental" videos not supported') - return + raise ExtractorError(u'"rental" videos not supported') # Start extracting information self.report_information_extraction(video_id) # uploader if 'author' not in video_info: - self._downloader.report_error(u'unable to extract uploader name') - return + raise ExtractorError(u'Unable to extract uploader name') video_uploader = compat_urllib_parse.unquote_plus(video_info['author'][0]) # uploader_id @@ -542,8 +545,7 @@ class YoutubeIE(InfoExtractor): # title if 'title' not in video_info: - self._downloader.report_error(u'unable to extract video title') - return + raise ExtractorError(u'Unable to extract video title') video_title = compat_urllib_parse.unquote_plus(video_info['title'][0]) # thumbnail image @@ -558,12 +560,7 @@ class YoutubeIE(InfoExtractor): mobj = re.search(r'id="eow-date.*?>(.*?)', video_webpage, re.DOTALL) if mobj is not None: upload_date = ' '.join(re.sub(r'[/,-]', r' ', mobj.group(1)).split()) - format_expressions = ['%d %B %Y', '%B %d %Y', '%b %d %Y'] - for expression in format_expressions: - try: - upload_date = datetime.datetime.strptime(upload_date, expression).strftime('%Y%m%d') - except: - pass + upload_date = unified_strdate(upload_date) # description video_description = get_element_by_id("eow-description", video_webpage) @@ -613,10 +610,13 @@ class YoutubeIE(InfoExtractor): self.report_rtmp_download() video_url_list = [(None, video_info['conn'][0])] elif 'url_encoded_fmt_stream_map' in video_info and len(video_info['url_encoded_fmt_stream_map']) >= 1: - url_data_strs = video_info['url_encoded_fmt_stream_map'][0].split(',') - url_data = [compat_parse_qs(uds) for uds in url_data_strs] - url_data = [ud for ud in url_data if 'itag' in ud and 'url' in ud] - url_map = dict((ud['itag'][0], ud['url'][0] + '&signature=' + ud['sig'][0]) for ud in url_data) + url_map = {} + for url_data_str in video_info['url_encoded_fmt_stream_map'][0].split(','): + url_data = compat_parse_qs(url_data_str) + if 'itag' in url_data and 'url' in url_data: + url = url_data['url'][0] + '&signature=' + url_data['sig'][0] + if not 'ratebypass' in url: url += '&ratebypass=yes' + url_map[url_data['itag'][0]] = url format_limit = self._downloader.params.get('format_limit', None) available_formats = self._available_formats_prefer_free if self._downloader.params.get('prefer_free_formats', False) else self._available_formats @@ -684,17 +684,10 @@ class MetacafeIE(InfoExtractor): _FILTER_POST = 'http://www.metacafe.com/f/index.php?inputType=filter&controllerGroup=user' IE_NAME = u'metacafe' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - def report_disclaimer(self): """Report disclaimer retrieval.""" self.to_screen(u'Retrieving disclaimer') - def report_download_webpage(self, video_id): - """Report webpage download.""" - self.to_screen(u'%s: Downloading webpage' % video_id) - def _real_initialize(self): # Retrieve disclaimer request = compat_urllib_request.Request(self._DISCLAIMER) @@ -702,8 +695,7 @@ class MetacafeIE(InfoExtractor): self.report_disclaimer() disclaimer = compat_urllib_request.urlopen(request).read() except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to retrieve disclaimer: %s' % compat_str(err)) - return + raise ExtractorError(u'Unable to retrieve disclaimer: %s' % compat_str(err)) # Confirm age disclaimer_form = { @@ -715,15 +707,13 @@ class MetacafeIE(InfoExtractor): self.report_age_confirmation() disclaimer = compat_urllib_request.urlopen(request).read() except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to confirm age: %s' % compat_str(err)) - return + raise ExtractorError(u'Unable to confirm age: %s' % compat_str(err)) def _real_extract(self, url): # Extract id and simplified title from URL mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) video_id = mobj.group(1) @@ -752,30 +742,25 @@ class MetacafeIE(InfoExtractor): else: mobj = re.search(r' name="flashvars" value="(.*?)"', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract media URL') - return + raise ExtractorError(u'Unable to extract media URL') vardict = compat_parse_qs(mobj.group(1)) if 'mediaData' not in vardict: - self._downloader.report_error(u'unable to extract media URL') - return + raise ExtractorError(u'Unable to extract media URL') mobj = re.search(r'"mediaURL":"(?Phttp.*?)",(.*?)"key":"(?P.*?)"', vardict['mediaData'][0]) if mobj is None: - self._downloader.report_error(u'unable to extract media URL') - return + raise ExtractorError(u'Unable to extract media URL') mediaURL = mobj.group('mediaURL').replace('\\/', '/') video_extension = mediaURL[-3:] video_url = '%s?__gda__=%s' % (mediaURL, mobj.group('key')) mobj = re.search(r'(?im)(.*) - Video', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract title') - return + raise ExtractorError(u'Unable to extract title') video_title = mobj.group(1).decode('utf-8') mobj = re.search(r'submitter=(.*?);', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract uploader nickname') - return + raise ExtractorError(u'Unable to extract uploader nickname') video_uploader = mobj.group(1) return [{ @@ -787,23 +772,17 @@ class MetacafeIE(InfoExtractor): 'ext': video_extension.decode('utf-8'), }] - class DailymotionIE(InfoExtractor): """Information Extractor for Dailymotion""" _VALID_URL = r'(?i)(?:https?://)?(?:www\.)?dailymotion\.[a-z]{2,3}/video/([^/]+)' IE_NAME = u'dailymotion' - _WORKING = False - - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) def _real_extract(self, url): # Extract id and simplified title from URL mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) video_id = mobj.group(1).split('_')[0].split('?')[0] @@ -818,8 +797,7 @@ class DailymotionIE(InfoExtractor): self.report_extraction(video_id) mobj = re.search(r'\s*var flashvars = (.*)', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract media URL') - return + raise ExtractorError(u'Unable to extract media URL') flashvars = compat_urllib_parse.unquote(mobj.group(1)) for key in ['hd1080URL', 'hd720URL', 'hqURL', 'sdURL', 'ldURL', 'video_url']: @@ -828,13 +806,11 @@ class DailymotionIE(InfoExtractor): self.to_screen(u'Using %s' % key) break else: - self._downloader.report_error(u'unable to extract video URL') - return + raise ExtractorError(u'Unable to extract video URL') mobj = re.search(r'"' + max_quality + r'":"(.+?)"', flashvars) if mobj is None: - self._downloader.report_error(u'unable to extract video URL') - return + raise ExtractorError(u'Unable to extract video URL') video_url = compat_urllib_parse.unquote(mobj.group(1)).replace('\\/', '/') @@ -842,8 +818,7 @@ class DailymotionIE(InfoExtractor): mobj = re.search(r'', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract title') - return + raise ExtractorError(u'Unable to extract title') video_title = unescapeHTML(mobj.group('title')) video_uploader = None @@ -876,50 +851,52 @@ class DailymotionIE(InfoExtractor): class PhotobucketIE(InfoExtractor): """Information extractor for photobucket.com.""" - _VALID_URL = r'(?:http://)?(?:[a-z0-9]+\.)?photobucket\.com/.*[\?\&]current=(.*\.flv)' + # TODO: the original _VALID_URL was: + # r'(?:http://)?(?:[a-z0-9]+\.)?photobucket\.com/.*[\?\&]current=(.*\.flv)' + # Check if it's necessary to keep the old extracion process + _VALID_URL = r'(?:http://)?(?:[a-z0-9]+\.)?photobucket\.com/.*(([\?\&]current=)|_)(?P.*)\.(?P(flv)|(mp4))' IE_NAME = u'photobucket' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - - def report_download_webpage(self, video_id): - """Report webpage download.""" - self.to_screen(u'%s: Downloading webpage' % video_id) - def _real_extract(self, url): # Extract id from URL mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'Invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) - video_id = mobj.group(1) + video_id = mobj.group('id') - video_extension = 'flv' + video_extension = mobj.group('ext') # Retrieve video webpage to extract further information - request = compat_urllib_request.Request(url) - try: - self.report_download_webpage(video_id) - webpage = compat_urllib_request.urlopen(request).read() - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'Unable to retrieve video webpage: %s' % compat_str(err)) - return + webpage = self._download_webpage(url, video_id) # Extract URL, uploader, and title from webpage self.report_extraction(video_id) + # We try first by looking the javascript code: + mobj = re.search(r'Pb\.Data\.Shared\.put\(Pb\.Data\.Shared\.MEDIA, (?P.*?)\);', webpage) + if mobj is not None: + info = json.loads(mobj.group('json')) + return [{ + 'id': video_id, + 'url': info[u'downloadUrl'], + 'uploader': info[u'username'], + 'upload_date': datetime.date.fromtimestamp(info[u'creationDate']).strftime('%Y%m%d'), + 'title': info[u'title'], + 'ext': video_extension, + 'thumbnail': info[u'thumbUrl'], + }] + + # We try looking in other parts of the webpage mobj = re.search(r'', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract media URL') - return + raise ExtractorError(u'Unable to extract media URL') mediaURL = compat_urllib_parse.unquote(mobj.group(1)) video_url = mediaURL mobj = re.search(r'(.*) video by (.*) - Photobucket', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract title') - return + raise ExtractorError(u'Unable to extract title') video_title = mobj.group(1).decode('utf-8') video_uploader = mobj.group(2).decode('utf-8') @@ -935,143 +912,72 @@ class PhotobucketIE(InfoExtractor): class YahooIE(InfoExtractor): - """Information extractor for video.yahoo.com.""" + """Information extractor for screen.yahoo.com.""" + _VALID_URL = r'http://screen\.yahoo\.com/.*?-(?P\d*?)\.html' - _WORKING = False - # _VALID_URL matches all Yahoo! Video URLs - # _VPAGE_URL matches only the extractable '/watch/' URLs - _VALID_URL = r'(?:http://)?(?:[a-z]+\.)?video\.yahoo\.com/(?:watch|network)/([0-9]+)(?:/|\?v=)([0-9]+)(?:[#\?].*)?' - _VPAGE_URL = r'(?:http://)?video\.yahoo\.com/watch/([0-9]+)/([0-9]+)(?:[#\?].*)?' - IE_NAME = u'video.yahoo' - - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - - def report_download_webpage(self, video_id): - """Report webpage download.""" - self.to_screen(u'%s: Downloading webpage' % video_id) - - def _real_extract(self, url, new_video=True): - # Extract ID from URL + def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'Invalid URL: %s' % url) - return - - video_id = mobj.group(2) - video_extension = 'flv' - - # Rewrite valid but non-extractable URLs as - # extractable English language /watch/ URLs - if re.match(self._VPAGE_URL, url) is None: - request = compat_urllib_request.Request(url) - try: - webpage = compat_urllib_request.urlopen(request).read() - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'Unable to retrieve video webpage: %s' % compat_str(err)) - return - - mobj = re.search(r'\("id", "([0-9]+)"\);', webpage) - if mobj is None: - self._downloader.report_error(u'Unable to extract id field') - return - yahoo_id = mobj.group(1) - - mobj = re.search(r'\("vid", "([0-9]+)"\);', webpage) - if mobj is None: - self._downloader.report_error(u'Unable to extract vid field') - return - yahoo_vid = mobj.group(1) - - url = 'http://video.yahoo.com/watch/%s/%s' % (yahoo_vid, yahoo_id) - return self._real_extract(url, new_video=False) - - # Retrieve video webpage to extract further information - request = compat_urllib_request.Request(url) - try: - self.report_download_webpage(video_id) - webpage = compat_urllib_request.urlopen(request).read() - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'Unable to retrieve video webpage: %s' % compat_str(err)) - return - - # Extract uploader and title from webpage - self.report_extraction(video_id) - mobj = re.search(r'', webpage) - if mobj is None: - self._downloader.report_error(u'unable to extract video title') - return - video_title = mobj.group(1).decode('utf-8') - - mobj = re.search(r'

(.*)

', webpage) - if mobj is None: - self._downloader.report_error(u'unable to extract video uploader') - return - video_uploader = mobj.group(1).decode('utf-8') - - # Extract video thumbnail - mobj = re.search(r'', webpage) - if mobj is None: - self._downloader.report_error(u'unable to extract video thumbnail') - return - video_thumbnail = mobj.group(1).decode('utf-8') - - # Extract video description - mobj = re.search(r'', webpage) - if mobj is None: - self._downloader.report_error(u'unable to extract video description') - return - video_description = mobj.group(1).decode('utf-8') - if not video_description: - video_description = 'No description available.' - - # Extract video height and width - mobj = re.search(r'', webpage) - if mobj is None: - self._downloader.report_error(u'unable to extract video height') - return - yv_video_height = mobj.group(1) - - mobj = re.search(r'', webpage) - if mobj is None: - self._downloader.report_error(u'unable to extract video width') - return - yv_video_width = mobj.group(1) - - # Retrieve video playlist to extract media URL - # I'm not completely sure what all these options are, but we - # seem to need most of them, otherwise the server sends a 401. - yv_lg = 'R0xx6idZnW2zlrKP8xxAIR' # not sure what this represents - yv_bitrate = '700' # according to Wikipedia this is hard-coded - request = compat_urllib_request.Request('http://cosmos.bcst.yahoo.com/up/yep/process/getPlaylistFOP.php?node_id=' + video_id + - '&tech=flash&mode=playlist&lg=' + yv_lg + '&bitrate=' + yv_bitrate + '&vidH=' + yv_video_height + - '&vidW=' + yv_video_width + '&swf=as3&rd=video.yahoo.com&tk=null&adsupported=v1,v2,&eventid=1301797') - try: - self.report_download_webpage(video_id) - webpage = compat_urllib_request.urlopen(request).read() - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'Unable to retrieve video webpage: %s' % compat_str(err)) - return - - # Extract media URL from playlist XML - mobj = re.search(r'.+?)";', webpage) + + if m_id is None: + # TODO: Check which url parameters are required + info_url = 'http://cosmos.bcst.yahoo.com/rest/v2/pops;lmsoverride=1;outputformat=mrss;cb=974419660;id=%s;rd=news.yahoo.com;datacontext=mdb;lg=KCa2IihxG3qE60vQ7HtyUy' % video_id + webpage = self._download_webpage(info_url, video_id, u'Downloading info webpage') + info_re = r'''<!\[CDATA\[(?P<title>.*?)\]\]>.* + .*?)\]\]>.* + .*?)\ .*\]\]>.* + https?://)?(?:(?:www|player)\.)?vimeo\.com/(?:(?:groups|album)/[^/]+/)?(?Pplay_redirect_hls\?clip_id=)?(?:videos?/)?(?P[0-9]+)' IE_NAME = u'vimeo' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - - def report_download_webpage(self, video_id): - """Report webpage download.""" - self.to_screen(u'%s: Downloading webpage' % video_id) - def _real_extract(self, url, new_video=True): # Extract ID from URL mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'Invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) video_id = mobj.group('id') if not mobj.group('proto'): @@ -1102,13 +1000,7 @@ class VimeoIE(InfoExtractor): # Retrieve video webpage to extract further information request = compat_urllib_request.Request(url, None, std_headers) - try: - self.report_download_webpage(video_id) - webpage_bytes = compat_urllib_request.urlopen(request).read() - webpage = webpage_bytes.decode('utf-8') - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'Unable to retrieve video webpage: %s' % compat_str(err)) - return + webpage = self._download_webpage(request, video_id) # Now we begin extracting as much information as we can from what we # retrieved. First we extract the information common to all extractors, @@ -1120,8 +1012,10 @@ class VimeoIE(InfoExtractor): config = webpage.split(' = {config:')[1].split(',assets:')[0] config = json.loads(config) except: - self._downloader.report_error(u'unable to extract info section') - return + if re.search('The creator of this video has not given you permission to embed it on this domain.', webpage): + raise ExtractorError(u'The author has restricted the access to this video, try with the "--referer" option') + else: + raise ExtractorError(u'Unable to extract info section') # Extract title video_title = config["video"]["title"] @@ -1170,8 +1064,7 @@ class VimeoIE(InfoExtractor): self.to_screen(u'%s: Downloading %s file at %s quality' % (video_id, video_codec.upper(), video_quality)) break else: - self._downloader.report_error(u'no known codec found') - return + raise ExtractorError(u'No known codec found') video_url = "http://player.vimeo.com/play_redirect?clip_id=%s&sig=%s&time=%s&quality=%s&codecs=%s&type=moogaloop_local&embed_location=" \ %(video_id, sig, timestamp, video_quality, video_codec.upper()) @@ -1197,24 +1090,15 @@ class ArteTvIE(InfoExtractor): IE_NAME = u'arte.tv' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - - def report_download_webpage(self, video_id): - """Report webpage download.""" - self.to_screen(u'%s: Downloading webpage' % video_id) - def fetch_webpage(self, url): request = compat_urllib_request.Request(url) try: self.report_download_webpage(url) webpage = compat_urllib_request.urlopen(request).read() except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'Unable to retrieve video webpage: %s' % compat_str(err)) - return + raise ExtractorError(u'Unable to retrieve video webpage: %s' % compat_str(err)) except ValueError as err: - self._downloader.report_error(u'Invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) return webpage def grep_webpage(self, url, regex, regexFlags, matchTuples): @@ -1223,13 +1107,11 @@ class ArteTvIE(InfoExtractor): info = {} if mobj is None: - self._downloader.report_error(u'Invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) for (i, key, err) in matchTuples: if mobj.group(i) is None: - self._downloader.report_error(err) - return + raise ExtractorError(err) else: info[key] = mobj.group(i) @@ -1301,7 +1183,7 @@ class ArteTvIE(InfoExtractor): 'id': info.get('id'), 'url': compat_urllib_parse.unquote(info.get('url')), 'uploader': u'arte.tv', - 'upload_date': info.get('date'), + 'upload_date': unified_strdate(info.get('date')), 'title': info.get('title').decode('utf-8'), 'ext': u'mp4', 'format': u'NA', @@ -1327,14 +1209,11 @@ class GenericIE(InfoExtractor): _VALID_URL = r'.*' IE_NAME = u'generic' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - def report_download_webpage(self, video_id): """Report webpage download.""" if not self._downloader.params.get('test', False): self._downloader.report_warning(u'Falling back on generic information extractor.') - self.to_screen(u'%s: Downloading webpage' % video_id) + super(GenericIE, self).report_download_webpage(video_id) def report_following_redirect(self, new_url): """Report information extraction.""" @@ -1404,8 +1283,7 @@ class GenericIE(InfoExtractor): except ValueError as err: # since this is the last-resort InfoExtractor, if # this error is thrown, it'll be thrown here - self._downloader.report_error(u'Invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) self.report_extraction(video_id) # Start with something easy: JW Player in SWFObject @@ -1417,14 +1295,12 @@ class GenericIE(InfoExtractor): # Broaden the search a little bit: JWPlayer JS loader mobj = re.search(r'[^A-Za-z0-9]?file:\s*["\'](http[^\'"&]*)', webpage) if mobj is None: - self._downloader.report_error(u'Invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) # It's possible that one of the regexes # matched, but returned an empty group: if mobj.group(1) is None: - self._downloader.report_error(u'Invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) video_url = compat_urllib_parse.unquote(mobj.group(1)) video_id = os.path.basename(video_url) @@ -1441,15 +1317,13 @@ class GenericIE(InfoExtractor): # and so on and so forth; it's just not practical mobj = re.search(r'(.*)', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract title') - return + raise ExtractorError(u'Unable to extract title') video_title = mobj.group(1) # video uploader is domain name mobj = re.match(r'(?:https?://)?([^/]*)/.*', url) if mobj is None: - self._downloader.report_error(u'unable to extract title') - return + raise ExtractorError(u'Unable to extract title') video_uploader = mobj.group(1) return [{ @@ -1469,9 +1343,6 @@ class YoutubeSearchIE(InfoExtractor): _max_youtube_results = 1000 IE_NAME = u'youtube:search' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - def report_download_page(self, query, pagenum): """Report attempt to download search page with given number.""" query = query.decode(preferredencoding()) @@ -1480,8 +1351,7 @@ class YoutubeSearchIE(InfoExtractor): def _real_extract(self, query): mobj = re.match(self._VALID_URL, query) if mobj is None: - self._downloader.report_error(u'invalid search query "%s"' % query) - return + raise ExtractorError(u'Invalid search query "%s"' % query) prefix, query = query.split(':') prefix = prefix[8:] @@ -1494,8 +1364,7 @@ class YoutubeSearchIE(InfoExtractor): try: n = int(prefix) if n <= 0: - self._downloader.report_error(u'invalid download number %s for query "%s"' % (n, query)) - return + raise ExtractorError(u'Invalid download number %s for query "%s"' % (n, query)) elif n > self._max_youtube_results: self._downloader.report_warning(u'ytsearch returns max %i results (you requested %i)' % (self._max_youtube_results, n)) n = self._max_youtube_results @@ -1517,13 +1386,11 @@ class YoutubeSearchIE(InfoExtractor): try: data = compat_urllib_request.urlopen(request).read().decode('utf-8') except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download API page: %s' % compat_str(err)) - return + raise ExtractorError(u'Unable to download API page: %s' % compat_str(err)) api_response = json.loads(data)['data'] if not 'items' in api_response: - self._downloader.report_error(u'[youtube] No video results') - return + raise ExtractorError(u'[youtube] No video results') new_ids = list(video['id'] for video in api_response['items']) video_ids += new_ids @@ -1539,85 +1406,52 @@ class YoutubeSearchIE(InfoExtractor): class GoogleSearchIE(InfoExtractor): """Information Extractor for Google Video search queries.""" - _VALID_URL = r'gvsearch(\d+|all)?:[\s\S]+' - _TEMPLATE_URL = 'http://video.google.com/videosearch?q=%s+site:video.google.com&start=%s&hl=en' - _VIDEO_INDICATOR = r'|\d+|all):(?P[\s\S]+)' _MORE_PAGES_INDICATOR = r'class="pn" id="pnnext"' _max_google_results = 1000 IE_NAME = u'video.google:search' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - - def report_download_page(self, query, pagenum): - """Report attempt to download playlist page with given number.""" - query = query.decode(preferredencoding()) - self.to_screen(u'query "%s": Downloading page %s' % (query, pagenum)) - def _real_extract(self, query): mobj = re.match(self._VALID_URL, query) - if mobj is None: - self._downloader.report_error(u'invalid search query "%s"' % query) - return - prefix, query = query.split(':') - prefix = prefix[8:] - query = query.encode('utf-8') + prefix = mobj.group('prefix') + query = mobj.group('query') if prefix == '': - self._download_n_results(query, 1) - return + return self._get_n_results(query, 1) elif prefix == 'all': - self._download_n_results(query, self._max_google_results) - return + return self._get_n_results(query, self._max_google_results) else: - try: - n = int(prefix) - if n <= 0: - self._downloader.report_error(u'invalid download number %s for query "%s"' % (n, query)) - return - elif n > self._max_google_results: - self._downloader.report_warning(u'gvsearch returns max %i results (you requested %i)' % (self._max_google_results, n)) - n = self._max_google_results - self._download_n_results(query, n) - return - except ValueError: # parsing prefix as integer fails - self._download_n_results(query, 1) - return + n = int(prefix) + if n <= 0: + raise ExtractorError(u'invalid download number %s for query "%s"' % (n, query)) + elif n > self._max_google_results: + self._downloader.report_warning(u'gvsearch returns max %i results (you requested %i)' % (self._max_google_results, n)) + n = self._max_google_results + return self._get_n_results(query, n) - def _download_n_results(self, query, n): - """Downloads a specified number of results for a query""" - - video_ids = [] - pagenum = 0 - - while True: - self.report_download_page(query, pagenum) - result_url = self._TEMPLATE_URL % (compat_urllib_parse.quote_plus(query), pagenum*10) - request = compat_urllib_request.Request(result_url) - try: - page = compat_urllib_request.urlopen(request).read() - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download webpage: %s' % compat_str(err)) - return + def _get_n_results(self, query, n): + """Get a specified number of results for a query""" - # Extract video identifiers - for mobj in re.finditer(self._VIDEO_INDICATOR, page): - video_id = mobj.group(1) - if video_id not in video_ids: - video_ids.append(video_id) - if len(video_ids) == n: - # Specified n videos reached - for id in video_ids: - self._downloader.download(['http://video.google.com/videoplay?docid=%s' % id]) - return + res = { + '_type': 'playlist', + 'id': query, + 'entries': [] + } - if re.search(self._MORE_PAGES_INDICATOR, page) is None: - for id in video_ids: - self._downloader.download(['http://video.google.com/videoplay?docid=%s' % id]) - return + for pagenum in itertools.count(1): + result_url = u'http://video.google.com/videosearch?q=%s&start=%s&hl=en' % (compat_urllib_parse.quote_plus(query), pagenum*10) + webpage = self._download_webpage(result_url, u'gvsearch:' + query, + note='Downloading result page ' + str(pagenum)) - pagenum = pagenum + 1 + for mobj in re.finditer(r'

n) or not re.search(self._MORE_PAGES_INDICATOR, webpage): + return res class YahooSearchIE(InfoExtractor): """Information Extractor for Yahoo! Video search queries.""" @@ -1630,9 +1464,6 @@ class YahooSearchIE(InfoExtractor): _max_yahoo_results = 1000 IE_NAME = u'video.yahoo:search' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - def report_download_page(self, query, pagenum): """Report attempt to download playlist page with given number.""" query = query.decode(preferredencoding()) @@ -1641,8 +1472,7 @@ class YahooSearchIE(InfoExtractor): def _real_extract(self, query): mobj = re.match(self._VALID_URL, query) if mobj is None: - self._downloader.report_error(u'invalid search query "%s"' % query) - return + raise ExtractorError(u'Invalid search query "%s"' % query) prefix, query = query.split(':') prefix = prefix[8:] @@ -1657,8 +1487,7 @@ class YahooSearchIE(InfoExtractor): try: n = int(prefix) if n <= 0: - self._downloader.report_error(u'invalid download number %s for query "%s"' % (n, query)) - return + raise ExtractorError(u'Invalid download number %s for query "%s"' % (n, query)) elif n > self._max_yahoo_results: self._downloader.report_warning(u'yvsearch returns max %i results (you requested %i)' % (self._max_yahoo_results, n)) n = self._max_yahoo_results @@ -1682,8 +1511,7 @@ class YahooSearchIE(InfoExtractor): try: page = compat_urllib_request.urlopen(request).read() except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download webpage: %s' % compat_str(err)) - return + raise ExtractorError(u'Unable to download webpage: %s' % compat_str(err)) # Extract video identifiers for mobj in re.finditer(self._VIDEO_INDICATOR, page): @@ -1726,24 +1554,16 @@ class YoutubePlaylistIE(InfoExtractor): _MAX_RESULTS = 50 IE_NAME = u'youtube:playlist' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - @classmethod def suitable(cls, url): """Receives a URL and returns True if suitable for this IE.""" return re.match(cls._VALID_URL, url, re.VERBOSE) is not None - def report_download_page(self, playlist_id, pagenum): - """Report attempt to download playlist page with given number.""" - self._downloader.to_screen(u'[youtube] PL %s: Downloading page #%s' % (playlist_id, pagenum)) - def _real_extract(self, url): # Extract playlist id mobj = re.match(self._VALID_URL, url, re.VERBOSE) if mobj is None: - self._downloader.report_error(u'invalid url: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) # Download playlist videos from API playlist_id = mobj.group(1) or mobj.group(2) @@ -1751,30 +1571,21 @@ class YoutubePlaylistIE(InfoExtractor): videos = [] while True: - self.report_download_page(playlist_id, page_num) - url = self._TEMPLATE_URL % (playlist_id, self._MAX_RESULTS, self._MAX_RESULTS * (page_num - 1) + 1) - try: - page = compat_urllib_request.urlopen(url).read().decode('utf8') - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download webpage: %s' % compat_str(err)) - return + page = self._download_webpage(url, playlist_id, u'Downloading page #%s' % page_num) try: response = json.loads(page) except ValueError as err: - self._downloader.report_error(u'Invalid JSON in API response: ' + compat_str(err)) - return + raise ExtractorError(u'Invalid JSON in API response: ' + compat_str(err)) if 'feed' not in response: - self._downloader.report_error(u'Got a malformed response from YouTube API') - return + raise ExtractorError(u'Got a malformed response from YouTube API') + playlist_title = response['feed']['title']['$t'] if 'entry' not in response['feed']: # Number of videos is a multiple of self._MAX_RESULTS break - playlist_title = response['feed']['title']['$t'] - videos += [ (entry['yt$position']['$t'], entry['content']['src']) for entry in response['feed']['entry'] if 'content' in entry ] @@ -1798,10 +1609,6 @@ class YoutubeChannelIE(InfoExtractor): _MORE_PAGES_URL = 'http://www.youtube.com/channel_ajax?action_load_more_videos=1&flow=list&paging=%s&view=0&sort=da&channel_id=%s' IE_NAME = u'youtube:channel' - def report_download_page(self, channel_id, pagenum): - """Report attempt to download channel page with given number.""" - self._downloader.to_screen(u'[youtube] Channel %s: Downloading page #%s' % (channel_id, pagenum)) - def extract_videos_from_page(self, page): ids_in_page = [] for mobj in re.finditer(r'href="/watch\?v=([0-9A-Za-z_-]+)&?', page): @@ -1813,22 +1620,16 @@ class YoutubeChannelIE(InfoExtractor): # Extract channel id mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'invalid url: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) # Download channel page channel_id = mobj.group(1) video_ids = [] pagenum = 1 - self.report_download_page(channel_id, pagenum) url = self._TEMPLATE_URL % (channel_id, pagenum) - request = compat_urllib_request.Request(url) - try: - page = compat_urllib_request.urlopen(request).read().decode('utf8') - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download webpage: %s' % compat_str(err)) - return + page = self._download_webpage(url, channel_id, + u'Downloading page #%s' % pagenum) # Extract video identifiers ids_in_page = self.extract_videos_from_page(page) @@ -1839,14 +1640,9 @@ class YoutubeChannelIE(InfoExtractor): while True: pagenum = pagenum + 1 - self.report_download_page(channel_id, pagenum) url = self._MORE_PAGES_URL % (pagenum, channel_id) - request = compat_urllib_request.Request(url) - try: - page = compat_urllib_request.urlopen(request).read().decode('utf8') - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download webpage: %s' % compat_str(err)) - return + page = self._download_webpage(url, channel_id, + u'Downloading page #%s' % pagenum) page = json.loads(page) @@ -1873,20 +1669,11 @@ class YoutubeUserIE(InfoExtractor): _VIDEO_INDICATOR = r'/watch\?v=(.+?)[\<&]' IE_NAME = u'youtube:user' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - - def report_download_page(self, username, start_index): - """Report attempt to download user page.""" - self._downloader.to_screen(u'[youtube] user %s: Downloading video ids from %d to %d' % - (username, start_index, start_index + self._GDATA_PAGE_SIZE)) - def _real_extract(self, url): # Extract username mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'invalid url: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) username = mobj.group(1) @@ -1900,15 +1687,10 @@ class YoutubeUserIE(InfoExtractor): while True: start_index = pagenum * self._GDATA_PAGE_SIZE + 1 - self.report_download_page(username, start_index) - - request = compat_urllib_request.Request(self._GDATA_URL % (username, self._GDATA_PAGE_SIZE, start_index)) - try: - page = compat_urllib_request.urlopen(request).read().decode('utf-8') - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download webpage: %s' % compat_str(err)) - return + gdata_url = self._GDATA_URL % (username, self._GDATA_PAGE_SIZE, start_index) + page = self._download_webpage(gdata_url, username, + u'Downloading video ids from %d to %d' % (start_index, start_index + self._GDATA_PAGE_SIZE)) # Extract video identifiers ids_in_page = [] @@ -1942,34 +1724,19 @@ class BlipTVUserIE(InfoExtractor): _PAGE_SIZE = 12 IE_NAME = u'blip.tv:user' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - - def report_download_page(self, username, pagenum): - """Report attempt to download user page.""" - self.to_screen(u'user %s: Downloading video ids from page %d' % - (username, pagenum)) - def _real_extract(self, url): # Extract username mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'invalid url: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) username = mobj.group(1) page_base = 'http://m.blip.tv/pr/show_get_full_episode_list?users_id=%s&lite=0&esi=1' - request = compat_urllib_request.Request(url) - - try: - page = compat_urllib_request.urlopen(request).read().decode('utf-8') - mobj = re.search(r'data-users-id="([^"]+)"', page) - page_base = page_base % mobj.group(1) - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download webpage: %s' % compat_str(err)) - return + page = self._download_webpage(url, username, u'Downloading user page') + mobj = re.search(r'data-users-id="([^"]+)"', page) + page_base = page_base % mobj.group(1) # Download video ids using BlipTV Ajax calls. Result size per @@ -1981,14 +1748,9 @@ class BlipTVUserIE(InfoExtractor): pagenum = 1 while True: - self.report_download_page(username, pagenum) url = page_base + "&page=" + str(pagenum) - request = compat_urllib_request.Request( url ) - try: - page = compat_urllib_request.urlopen(request).read().decode('utf-8') - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download webpage: %s' % str(err)) - return + page = self._download_webpage(url, username, + u'Downloading video ids from page %d' % pagenum) # Extract video identifiers ids_in_page = [] @@ -2020,10 +1782,6 @@ class DepositFilesIE(InfoExtractor): _VALID_URL = r'(?:http://)?(?:\w+\.)?depositfiles\.com/(?:../(?#locale))?files/(.+)' - def report_download_webpage(self, file_id): - """Report webpage download.""" - self.to_screen(u'%s: Downloading webpage' % file_id) - def _real_extract(self, url): file_id = url.split('/')[-1] # Rebuild url in english locale @@ -2036,8 +1794,7 @@ class DepositFilesIE(InfoExtractor): self.report_download_webpage(file_id) webpage = compat_urllib_request.urlopen(request).read() except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'Unable to retrieve file webpage: %s' % compat_str(err)) - return + raise ExtractorError(u'Unable to retrieve file webpage: %s' % compat_str(err)) # Search for the real file URL mobj = re.search(r'
(Attention.*?)', webpage, re.DOTALL) if (mobj is not None) and (mobj.group(1) is not None): restriction_message = re.sub('\s+', ' ', mobj.group(1)).strip() - self._downloader.report_error(u'%s' % restriction_message) + raise ExtractorError(u'%s' % restriction_message) else: - self._downloader.report_error(u'unable to extract download URL from: %s' % url) - return + raise ExtractorError(u'Unable to extract download URL from: %s' % url) file_url = mobj.group(1) file_extension = os.path.splitext(file_url)[1][1:] @@ -2057,8 +1813,7 @@ class DepositFilesIE(InfoExtractor): # Search for file title mobj = re.search(r'', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract title') - return + raise ExtractorError(u'Unable to extract title') file_title = mobj.group(1).decode('utf-8') return [{ @@ -2130,8 +1885,7 @@ class FacebookIE(InfoExtractor): def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) video_id = mobj.group('ID') url = 'https://www.facebook.com/video/video.php?v=%s' % video_id @@ -2184,8 +1938,7 @@ class BlipTVIE(InfoExtractor): def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) urlp = compat_urllib_parse_urlparse(url) if urlp.path.startswith('/play/'): @@ -2231,8 +1984,7 @@ class BlipTVIE(InfoExtractor): json_code_bytes = urlh.read() json_code = json_code_bytes.decode('utf-8') except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to read video info webpage: %s' % compat_str(err)) - return + raise ExtractorError(u'Unable to read video info webpage: %s' % compat_str(err)) try: json_data = json.loads(json_code) @@ -2262,8 +2014,7 @@ class BlipTVIE(InfoExtractor): 'user_agent': 'iTunes/10.6.1', } except (ValueError,KeyError) as err: - self._downloader.report_error(u'unable to parse video information: %s' % repr(err)) - return + raise ExtractorError(u'Unable to parse video information: %s' % repr(err)) return [info] @@ -2274,14 +2025,10 @@ class MyVideoIE(InfoExtractor): _VALID_URL = r'(?:http://)?(?:www\.)?myvideo\.de/watch/([0-9]+)/([^?/]+).*' IE_NAME = u'myvideo' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - def _real_extract(self,url): mobj = re.match(self._VALID_URL, url) if mobj is None: - self._download.report_error(u'invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) video_id = mobj.group(1) @@ -2293,14 +2040,12 @@ class MyVideoIE(InfoExtractor): mobj = re.search(r'([^<]+)', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract title') - return + raise ExtractorError(u'Unable to extract title') video_title = mobj.group(1) @@ -2354,12 +2099,6 @@ class ComedyCentralIE(InfoExtractor): """Receives a URL and returns True if suitable for this IE.""" return re.match(cls._VALID_URL, url, re.VERBOSE) is not None - def report_config_download(self, episode_id, media_id): - self.to_screen(u'%s: Downloading configuration for %s' % (episode_id, media_id)) - - def report_index_download(self, episode_id): - self.to_screen(u'%s: Downloading show index' % episode_id) - def _print_formats(self, formats): print('Available formats:') for x in formats: @@ -2369,8 +2108,7 @@ class ComedyCentralIE(InfoExtractor): def _real_extract(self, url): mobj = re.match(self._VALID_URL, url, re.VERBOSE) if mobj is None: - self._downloader.report_error(u'invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) if mobj.group('shortname'): if mobj.group('shortname') in ('tds', 'thedailyshow'): @@ -2393,24 +2131,15 @@ class ComedyCentralIE(InfoExtractor): else: epTitle = mobj.group('episode') - req = compat_urllib_request.Request(url) self.report_extraction(epTitle) - try: - htmlHandle = compat_urllib_request.urlopen(req) - html = htmlHandle.read() - webpage = html.decode('utf-8') - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download webpage: %s' % compat_str(err)) - return + webpage,htmlHandle = self._download_webpage_handle(url, epTitle) if dlNewest: url = htmlHandle.geturl() mobj = re.match(self._VALID_URL, url, re.VERBOSE) if mobj is None: - self._downloader.report_error(u'Invalid redirected URL: ' + url) - return + raise ExtractorError(u'Invalid redirected URL: ' + url) if mobj.group('episode') == '': - self._downloader.report_error(u'Redirected URL is still not specific: ' + url) - return + raise ExtractorError(u'Redirected URL is still not specific: ' + url) epTitle = mobj.group('episode') mMovieParams = re.findall('(?:[^/]+)/(?P[^/?]+)[/?]?.*$' IE_NAME = u'escapist' - def report_config_download(self, showName): - self.to_screen(u'%s: Downloading configuration' % showName) - def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) showName = mobj.group('showname') videoId = mobj.group('episode') self.report_extraction(showName) - try: - webPage = compat_urllib_request.urlopen(url) - webPageBytes = webPage.read() - m = re.match(r'text/html; charset="?([^"]+)"?', webPage.headers['Content-Type']) - webPage = webPageBytes.decode(m.group(1) if m else 'utf-8') - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download webpage: ' + compat_str(err)) - return + webPage = self._download_webpage(url, showName) descMatch = re.search('(.*?)\s+-\s+XVID', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract video title') - return + raise ExtractorError(u'Unable to extract video title') video_title = mobj.group(1) # Extract video thumbnail mobj = re.search(r'http://(?:img.*?\.)xvideos.com/videos/thumbs/[a-fA-F0-9]+/[a-fA-F0-9]+/[a-fA-F0-9]+/[a-fA-F0-9]+/([a-fA-F0-9.]+jpg)', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract video thumbnail') - return + raise ExtractorError(u'Unable to extract video thumbnail') video_thumbnail = mobj.group(0) info = { @@ -2712,9 +2406,6 @@ class SoundcloudIE(InfoExtractor): _VALID_URL = r'^(?:https?://)?(?:www\.)?soundcloud\.com/([\w\d-]+)/([\w\d-]+)' IE_NAME = u'soundcloud' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - def report_resolve(self, video_id): """Report information extraction.""" self.to_screen(u'%s: Resolving id' % video_id) @@ -2722,48 +2413,39 @@ class SoundcloudIE(InfoExtractor): def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) # extract uploader (which is in the url) uploader = mobj.group(1) # extract simple title (uploader + slug of song title) slug_title = mobj.group(2) simple_title = uploader + u'-' + slug_title + full_title = '%s/%s' % (uploader, slug_title) - self.report_resolve('%s/%s' % (uploader, slug_title)) + self.report_resolve(full_title) url = 'http://soundcloud.com/%s/%s' % (uploader, slug_title) resolv_url = 'http://api.soundcloud.com/resolve.json?url=' + url + '&client_id=b45b1aa10f1ac2941910a7f0d10f8e28' - request = compat_urllib_request.Request(resolv_url) - try: - info_json_bytes = compat_urllib_request.urlopen(request).read() - info_json = info_json_bytes.decode('utf-8') - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download video webpage: %s' % compat_str(err)) - return + info_json = self._download_webpage(resolv_url, full_title, u'Downloading info JSON') info = json.loads(info_json) video_id = info['id'] - self.report_extraction('%s/%s' % (uploader, slug_title)) + self.report_extraction(full_title) streams_url = 'https://api.sndcdn.com/i1/tracks/' + str(video_id) + '/streams?client_id=b45b1aa10f1ac2941910a7f0d10f8e28' - request = compat_urllib_request.Request(streams_url) - try: - stream_json_bytes = compat_urllib_request.urlopen(request).read() - stream_json = stream_json_bytes.decode('utf-8') - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download stream definitions: %s' % compat_str(err)) - return + stream_json = self._download_webpage(streams_url, full_title, + u'Downloading stream definitions', + u'unable to download stream definitions') streams = json.loads(stream_json) mediaURL = streams['http_mp3_128_url'] + upload_date = unified_strdate(info['created_at']) return [{ 'id': info['id'], 'url': mediaURL, 'uploader': info['user']['username'], - 'upload_date': info['created_at'], + 'upload_date': upload_date, 'title': info['title'], 'ext': u'mp3', 'description': info['description'], @@ -2779,10 +2461,7 @@ class SoundcloudSetIE(InfoExtractor): """ _VALID_URL = r'^(?:https?://)?(?:www\.)?soundcloud\.com/([\w\d-]+)/sets/([\w\d-]+)' - IE_NAME = u'soundcloud' - - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) + IE_NAME = u'soundcloud:set' def report_resolve(self, video_id): """Report information extraction.""" @@ -2791,26 +2470,20 @@ class SoundcloudSetIE(InfoExtractor): def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) # extract uploader (which is in the url) uploader = mobj.group(1) # extract simple title (uploader + slug of song title) slug_title = mobj.group(2) simple_title = uploader + u'-' + slug_title + full_title = '%s/sets/%s' % (uploader, slug_title) - self.report_resolve('%s/sets/%s' % (uploader, slug_title)) + self.report_resolve(full_title) url = 'http://soundcloud.com/%s/sets/%s' % (uploader, slug_title) resolv_url = 'http://api.soundcloud.com/resolve.json?url=' + url + '&client_id=b45b1aa10f1ac2941910a7f0d10f8e28' - request = compat_urllib_request.Request(resolv_url) - try: - info_json_bytes = compat_urllib_request.urlopen(request).read() - info_json = info_json_bytes.decode('utf-8') - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download video webpage: %s' % compat_str(err)) - return + info_json = self._download_webpage(resolv_url, full_title) videos = [] info = json.loads(info_json) @@ -2819,19 +2492,14 @@ class SoundcloudSetIE(InfoExtractor): self._downloader.report_error(u'unable to download video webpage: %s' % compat_str(err['error_message'])) return + self.report_extraction(full_title) for track in info['tracks']: video_id = track['id'] - self.report_extraction('%s/sets/%s' % (uploader, slug_title)) streams_url = 'https://api.sndcdn.com/i1/tracks/' + str(video_id) + '/streams?client_id=b45b1aa10f1ac2941910a7f0d10f8e28' - request = compat_urllib_request.Request(streams_url) - try: - stream_json_bytes = compat_urllib_request.urlopen(request).read() - stream_json = stream_json_bytes.decode('utf-8') - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'unable to download stream definitions: %s' % compat_str(err)) - return + stream_json = self._download_webpage(streams_url, video_id, u'Downloading track info JSON') + self.report_extraction(video_id) streams = json.loads(stream_json) mediaURL = streams['http_mp3_128_url'] @@ -2839,7 +2507,7 @@ class SoundcloudSetIE(InfoExtractor): 'id': video_id, 'url': mediaURL, 'uploader': track['user']['username'], - 'upload_date': track['created_at'], + 'upload_date': unified_strdate(track['created_at']), 'title': track['title'], 'ext': u'mp3', 'description': track['description'], @@ -2854,25 +2522,22 @@ class InfoQIE(InfoExtractor): def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) webpage = self._download_webpage(url, video_id=url) self.report_extraction(url) # Extract video URL - mobj = re.search(r"jsclassref='([^']*)'", webpage) + mobj = re.search(r"jsclassref ?= ?'([^']*)'", webpage) if mobj is None: - self._downloader.report_error(u'unable to extract video url') - return + raise ExtractorError(u'Unable to extract video url') real_id = compat_urllib_parse.unquote(base64.b64decode(mobj.group(1).encode('ascii')).decode('utf-8')) video_url = 'rtmpe://video.infoq.com/cfx/st/' + real_id # Extract title mobj = re.search(r'contentTitle = "(.*?)";', webpage) if mobj is None: - self._downloader.report_error(u'unable to extract video title') - return + raise ExtractorError(u'Unable to extract video title') video_title = mobj.group(1) # Extract description @@ -2904,9 +2569,6 @@ class MixcloudIE(InfoExtractor): _VALID_URL = r'^(?:https?://)?(?:www\.)?mixcloud\.com/([\w\d-]+)/([\w\d-]+)' IE_NAME = u'mixcloud' - def __init__(self, downloader=None): - InfoExtractor.__init__(self, downloader) - def report_download_json(self, file_id): """Report JSON download.""" self.to_screen(u'Downloading json') @@ -2950,8 +2612,7 @@ class MixcloudIE(InfoExtractor): def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.report_error(u'invalid URL: %s' % url) - return + raise ExtractorError(u'Invalid URL: %s' % url) # extract uploader & filename from url uploader = mobj.group(1).decode('utf-8') file_id = uploader + "-" + mobj.group(2).decode('utf-8') @@ -2964,8 +2625,7 @@ class MixcloudIE(InfoExtractor): self.report_download_json(file_url) jsonData = compat_urllib_request.urlopen(request).read() except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self._downloader.report_error(u'Unable to retrieve file: %s' % compat_str(err)) - return + raise ExtractorError(u'Unable to retrieve file: %s' % compat_str(err)) # parse JSON json_data = json.loads(jsonData) @@ -2988,8 +2648,7 @@ class MixcloudIE(InfoExtractor): break # got it! else: if req_format not in formats: - self._downloader.report_error(u'format is not available') - return + raise ExtractorError(u'Format is not available') url_list = self.get_urls(formats, req_format) file_url = self.check_urls(url_list) @@ -3014,10 +2673,6 @@ class StanfordOpenClassroomIE(InfoExtractor): _VALID_URL = r'^(?:https?://)?openclassroom.stanford.edu(?P/?|(/MainFolder/(?:HomePage|CoursePage|VideoPage)\.php([?]course=(?P[^&]+)(&video=(?P