|
|
@ -2270,6 +2270,19 @@ class YoutubePlaylistIE(YoutubePlaylistBaseInfoExtractor):
|
|
|
|
r'(?s)<h1 class="pl-header-title[^"]*"[^>]*>\s*(.*?)\s*</h1>',
|
|
|
|
r'(?s)<h1 class="pl-header-title[^"]*"[^>]*>\s*(.*?)\s*</h1>',
|
|
|
|
page, 'title', default=None)
|
|
|
|
page, 'title', default=None)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_UPLOADER_BASE = r'class=["\']pl-header-details[^>]+>\s*<li>\s*<a[^>]+\bhref='
|
|
|
|
|
|
|
|
uploader = self._search_regex(
|
|
|
|
|
|
|
|
r'%s["\']/(?:user|channel)/[^>]+>([^<]+)' % _UPLOADER_BASE,
|
|
|
|
|
|
|
|
page, 'uploader', default=None)
|
|
|
|
|
|
|
|
mobj = re.search(
|
|
|
|
|
|
|
|
r'%s(["\'])(?P<path>/(?:user|channel)/(?P<uploader_id>.+?))\1' % _UPLOADER_BASE,
|
|
|
|
|
|
|
|
page)
|
|
|
|
|
|
|
|
if mobj:
|
|
|
|
|
|
|
|
uploader_id = mobj.group('uploader_id')
|
|
|
|
|
|
|
|
uploader_url = compat_urlparse.urljoin(url, mobj.group('path'))
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
uploader_id = uploader_url = None
|
|
|
|
|
|
|
|
|
|
|
|
has_videos = True
|
|
|
|
has_videos = True
|
|
|
|
|
|
|
|
|
|
|
|
if not playlist_title:
|
|
|
|
if not playlist_title:
|
|
|
@ -2280,8 +2293,15 @@ class YoutubePlaylistIE(YoutubePlaylistBaseInfoExtractor):
|
|
|
|
except StopIteration:
|
|
|
|
except StopIteration:
|
|
|
|
has_videos = False
|
|
|
|
has_videos = False
|
|
|
|
|
|
|
|
|
|
|
|
return has_videos, self.playlist_result(
|
|
|
|
playlist = self.playlist_result(
|
|
|
|
self._entries(page, playlist_id), playlist_id, playlist_title)
|
|
|
|
self._entries(page, playlist_id), playlist_id, playlist_title)
|
|
|
|
|
|
|
|
playlist.update({
|
|
|
|
|
|
|
|
'uploader': uploader,
|
|
|
|
|
|
|
|
'uploader_id': uploader_id,
|
|
|
|
|
|
|
|
'uploader_url': uploader_url,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return has_videos, playlist
|
|
|
|
|
|
|
|
|
|
|
|
def _check_download_just_video(self, url, playlist_id):
|
|
|
|
def _check_download_just_video(self, url, playlist_id):
|
|
|
|
# Check if it's a video-specific URL
|
|
|
|
# Check if it's a video-specific URL
|
|
|
|