self._ready = False
self.set_downloader(downloader)
- def suitable(self, url):
+ @classmethod
+ def suitable(cls, url):
"""Receives a URL and returns True if suitable for this IE."""
- return re.match(self._VALID_URL, url) is not None
+ return re.match(cls._VALID_URL, url) is not None
- def working(self):
+ @classmethod
+ def working(cls):
"""Getter method for _WORKING."""
- return self._WORKING
+ return cls._WORKING
def initialize(self):
"""Initializes an instance (authentication, etc)."""
(?:youtu\.be/|(?:\w+\.)?youtube(?:-nocookie)?\.com/|
tube\.majestyc\.net/) # the various hostnames, with wildcard subdomains
(?:.*?\#/)? # handle anchor (#/) redirect urls
- (?!view_play_list|my_playlists|artist|playlist) # ignore playlist URLs
(?: # the various things that can precede the ID:
(?:(?:v|embed|e)/) # v/ or embed/ or e/
|(?: # or the v= param in all its forms
}
IE_NAME = u'youtube'
- def suitable(self, url):
+ @classmethod
+ def suitable(cls, url):
"""Receives a URL and returns True if suitable for this IE."""
- return re.match(self._VALID_URL, url, re.VERBOSE) is not None
+ if YoutubePlaylistIE.suitable(url): return False
+ return re.match(cls._VALID_URL, url, re.VERBOSE) is not None
def report_lang(self):
"""Report attempt to set language."""
else:
raise netrc.NetrcParseError('No authenticators for %s' % self._NETRC_MACHINE)
except (IOError, netrc.NetrcParseError) as err:
- self._downloader.to_stderr(u'WARNING: parsing .netrc: %s' % compat_str(err))
+ self._downloader.report_warning(u'parsing .netrc: %s' % compat_str(err))
return
# Set language
self.report_lang()
compat_urllib_request.urlopen(request).read()
except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err:
- self._downloader.to_stderr(u'WARNING: unable to set language: %s' % compat_str(err))
+ self._downloader.report_warning(u'unable to set language: %s' % compat_str(err))
return
# No authentication to be performed
try:
login_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.to_stderr(u'WARNING: unable to fetch login page: %s' % compat_str(err))
+ self._downloader.report_warning(u'unable to fetch login page: %s' % compat_str(err))
return
galx = None
self.report_login()
login_results = compat_urllib_request.urlopen(request).read().decode('utf-8')
if re.search(r'(?i)<form[^>]* id="gaia_loginform"', login_results) is not None:
- self._downloader.to_stderr(u'WARNING: unable to log in: bad username or password')
+ self._downloader.report_warning(u'unable to log in: bad username or password')
return
except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err:
- self._downloader.to_stderr(u'WARNING: unable to log in: %s' % compat_str(err))
+ self._downloader.report_warning(u'unable to log in: %s' % compat_str(err))
return
# Confirm age
self._downloader.trouble(u'ERROR: invalid download number %s for query "%s"' % (n, query))
return
elif n > self._max_youtube_results:
- self._downloader.to_stderr(u'WARNING: ytsearch returns max %i results (you requested %i)' % (self._max_youtube_results, n))
+ self._downloader.report_warning(u'ytsearch returns max %i results (you requested %i)' % (self._max_youtube_results, n))
n = self._max_youtube_results
self._download_n_results(query, n)
return
return
api_response = json.loads(data)['data']
+ if not 'items' in api_response:
+ self._downloader.trouble(u'[youtube] No video results')
+ return
+
new_ids = list(video['id'] for video in api_response['items'])
video_ids += new_ids
self._downloader.trouble(u'ERROR: invalid download number %s for query "%s"' % (n, query))
return
elif n > self._max_google_results:
- self._downloader.to_stderr(u'WARNING: gvsearch returns max %i results (you requested %i)' % (self._max_google_results, n))
+ 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
self._downloader.trouble(u'ERROR: invalid download number %s for query "%s"' % (n, query))
return
elif n > self._max_yahoo_results:
- self._downloader.to_stderr(u'WARNING: yvsearch returns max %i results (you requested %i)' % (self._max_yahoo_results, n))
+ self._downloader.report_warning(u'yvsearch returns max %i results (you requested %i)' % (self._max_yahoo_results, n))
n = self._max_yahoo_results
self._download_n_results(query, n)
return
(?:\w+\.)?
youtube\.com/
(?:
- (?:course|view_play_list|my_playlists|artist|playlist)
- \? .*? (p|a|list)=
+ (?:course|view_play_list|my_playlists|artist|playlist|watch)
+ \? (?:.*?&)*? (?:p|a|list)=
| user/.*?/user/
| p/
| user/.*?#[pg]/c/
)
- (?:PL|EC)?
- |PL|EC)
- ([0-9A-Za-z-_]{10,})
- (?:/.*?/([0-9A-Za-z_-]+))?
- .*"""
+ ((?:PL|EC|UU)?[0-9A-Za-z-_]{10,})
+ .*
+ |
+ ((?:PL|EC|UU)[0-9A-Za-z-_]{10,})
+ )"""
_TEMPLATE_URL = 'https://gdata.youtube.com/feeds/api/playlists/%s?max-results=%i&start-index=%i&v=2&alt=json'
_MAX_RESULTS = 50
IE_NAME = u'youtube:playlist'
def __init__(self, downloader=None):
InfoExtractor.__init__(self, downloader)
- def suitable(self, url):
+ @classmethod
+ def suitable(cls, url):
"""Receives a URL and returns True if suitable for this IE."""
- return re.match(self._VALID_URL, url, re.VERBOSE) is not None
+ 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.trouble(u'ERROR: invalid url: %s' % url)
return
- # Single video case
- if mobj.group(3) is not None:
- self._downloader.download([mobj.group(3)])
- return
-
# Download playlist videos from API
- playlist_id = mobj.group(2)
+ playlist_id = mobj.group(1) or mobj.group(2)
page_num = 1
videos = []
self._downloader.trouble(u'ERROR: Invalid JSON in API response: ' + compat_str(err))
return
- videos += [(entry['yt$position']['$t'], entry['content']['src']) for entry in response['feed']['entry']]
+ if not 'feed' in response or not 'entry' in response['feed']:
+ self._downloader.trouble(u'ERROR: Got a malformed response from YouTube API')
+ return
+ videos += [ (entry['yt$position']['$t'], entry['content']['src'])
+ for entry in response['feed']['entry']
+ if 'content' in entry ]
if len(response['feed']['entry']) < self._MAX_RESULTS:
break
page_num += 1
- videos = map(operator.itemgetter(1), sorted(videos))
-
+ videos = [v[1] for v in sorted(videos)]
total = len(videos)
playliststart = self._downloader.params.get('playliststart', 1) - 1
else:
raise netrc.NetrcParseError('No authenticators for %s' % self._NETRC_MACHINE)
except (IOError, netrc.NetrcParseError) as err:
- self._downloader.to_stderr(u'WARNING: parsing .netrc: %s' % compat_str(err))
+ self._downloader.report_warning(u'parsing .netrc: %s' % compat_str(err))
return
if useremail is None:
self.report_login()
login_results = compat_urllib_request.urlopen(request).read()
if re.search(r'<form(.*)name="login"(.*)</form>', login_results) is not None:
- self._downloader.to_stderr(u'WARNING: unable to log in: bad username/password, or exceded login rate limit (~3/min). Check credentials or wait.')
+ self._downloader.report_warning(u'unable to log in: bad username/password, or exceded login rate limit (~3/min). Check credentials or wait.')
return
except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err:
- self._downloader.to_stderr(u'WARNING: unable to log in: %s' % compat_str(err))
+ self._downloader.report_warning(u'unable to log in: %s' % compat_str(err))
return
def _real_extract(self, url):
'400': '384x216',
}
- def suitable(self, url):
+ @classmethod
+ def suitable(cls, url):
"""Receives a URL and returns True if suitable for this IE."""
- return re.match(self._VALID_URL, url, re.VERBOSE) is not None
+ return re.match(cls._VALID_URL, url, re.VERBOSE) is not None
def report_extraction(self, episode_id):
self._downloader.to_screen(u'[comedycentral] %s: Extracting information' % episode_id)
(?P<videoID>\d*)(?P<extra>\??) #For urltype == video we sometimes get the videoID
"""
- def suitable(self, url):
+ @classmethod
+ def suitable(cls, url):
"""Receives a URL and returns True if suitable for this IE."""
- return re.match(self._VALID_URL, url, re.VERBOSE) is not None
+ return re.match(cls._VALID_URL, url, re.VERBOSE) is not None
def _real_extract(self, url):
m = re.match(self._VALID_URL, url, re.VERBOSE)
# Get the video date
result = re.search(r'Date:</label>(?P<date>.*) </li>', webpage)
if result is None:
- self._downloader.to_stderr(u'WARNING: unable to extract video date')
+ self._downloader.report_warning(u'unable to extract video date')
upload_date = None
else:
upload_date = result.group('date').strip()
# Get the video uploader
result = re.search(r'Submitted:</label>(?P<uploader>.*)</li>', webpage)
if result is None:
- self._downloader.to_stderr(u'WARNING: unable to extract uploader')
+ self._downloader.report_warning(u'unable to extract uploader')
video_uploader = None
else:
video_uploader = result.group('uploader').strip()
/(?P<name>\w+) # Here goes the name and then ".html"
'''
- def suitable(self, url):
+ @classmethod
+ def suitable(cls, url):
"""Receives a URL and returns True if suitable for this IE."""
- return re.match(self._VALID_URL, url, re.VERBOSE) is not None
+ return re.match(cls._VALID_URL, url, re.VERBOSE) is not None
def _real_extract(self, url):
m=re.match(self._VALID_URL, url, re.VERBOSE)