Modified Youtube video/playlist matching; fixes #668; fixes #585

This commit is contained in:
Filippo Valsorda 2013-02-26 19:02:31 +01:00
parent 6324fd1d74
commit 89de9eb125
3 changed files with 59 additions and 33 deletions

View file

@ -74,13 +74,15 @@ class InfoExtractor(object):
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)."""
@ -137,7 +139,6 @@ class YoutubeIE(InfoExtractor):
(?: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
@ -189,9 +190,11 @@ class YoutubeIE(InfoExtractor):
}
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."""
@ -1668,17 +1671,17 @@ class YoutubePlaylistIE(InfoExtractor):
(?:\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'
@ -1686,9 +1689,10 @@ class YoutubePlaylistIE(InfoExtractor):
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."""
@ -1701,13 +1705,8 @@ class YoutubePlaylistIE(InfoExtractor):
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 = []
@ -1727,7 +1726,12 @@ class YoutubePlaylistIE(InfoExtractor):
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
@ -2313,9 +2317,10 @@ class ComedyCentralIE(InfoExtractor):
'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)
@ -3628,9 +3633,10 @@ class SteamIE(InfoExtractor):
(?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)
@ -4004,9 +4010,10 @@ class TEDIE(InfoExtractor):
/(?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)