Compare commits
8 Commits
2014.02.20
...
2014.02.21
Author | SHA1 | Date | |
---|---|---|---|
1cf563d84b | |||
f7300c5c90 | |||
3489b7d26c | |||
acd2bcc384 | |||
43e77ca455 | |||
da36297988 | |||
dbb94fb044 | |||
d68f0cdb23 |
@ -13,6 +13,7 @@ from ..utils import (
|
||||
compat_urllib_parse,
|
||||
compat_urllib_request,
|
||||
compat_urlparse,
|
||||
compat_xml_parse_error,
|
||||
|
||||
ExtractorError,
|
||||
HEADRequest,
|
||||
@ -241,10 +242,10 @@ class GenericIE(InfoExtractor):
|
||||
|
||||
# Is it an RSS feed?
|
||||
try:
|
||||
doc = xml.etree.ElementTree.fromstring(webpage)
|
||||
doc = xml.etree.ElementTree.fromstring(webpage.encode('utf-8'))
|
||||
if doc.tag == 'rss':
|
||||
return self._extract_rss(url, video_id, doc)
|
||||
except xml.etree.ElementTree.ParseError:
|
||||
except compat_xml_parse_error:
|
||||
pass
|
||||
|
||||
# it's tempting to parse this further, but you would
|
||||
|
@ -6,14 +6,15 @@ from .common import InfoExtractor
|
||||
|
||||
|
||||
class WimpIE(InfoExtractor):
|
||||
_VALID_URL = r'(?:http://)?(?:www\.)?wimp\.com/([^/]+)/'
|
||||
_VALID_URL = r'http://(?:www\.)?wimp\.com/([^/]+)/'
|
||||
_TEST = {
|
||||
'url': 'http://www.wimp.com/deerfence/',
|
||||
'file': 'deerfence.flv',
|
||||
'md5': '8b215e2e0168c6081a1cf84b2846a2b5',
|
||||
'url': 'http://www.wimp.com/maruexhausted/',
|
||||
'md5': 'f1acced123ecb28d9bb79f2479f2b6a1',
|
||||
'info_dict': {
|
||||
"title": "Watch Till End: Herd of deer jump over a fence.",
|
||||
"description": "These deer look as fluid as running water when they jump over this fence as a herd. This video is one that needs to be watched until the very end for the true majesty to be witnessed, but once it comes, it's sure to take your breath away.",
|
||||
'id': 'maruexhausted',
|
||||
'ext': 'flv',
|
||||
'title': 'Maru is exhausted.',
|
||||
'description': 'md5:57e099e857c0a4ea312542b684a869b8',
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,4 +31,4 @@ class WimpIE(InfoExtractor):
|
||||
'title': self._og_search_title(webpage),
|
||||
'thumbnail': self._og_search_thumbnail(webpage),
|
||||
'description': self._og_search_description(webpage),
|
||||
}
|
||||
}
|
@ -297,6 +297,23 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor):
|
||||
u"format": "141",
|
||||
},
|
||||
},
|
||||
# DASH manifest with encrypted signature
|
||||
{
|
||||
u'url': u'https://www.youtube.com/watch?v=IB3lcPjvWLA',
|
||||
u'info_dict': {
|
||||
u'id': u'IB3lcPjvWLA',
|
||||
u'ext': u'm4a',
|
||||
u'title': u'Afrojack - The Spark ft. Spree Wilson',
|
||||
u'description': u'md5:3199ed45ee8836572865580804d7ac0f',
|
||||
u'uploader': u'AfrojackVEVO',
|
||||
u'uploader_id': u'AfrojackVEVO',
|
||||
u'upload_date': u'20131011',
|
||||
},
|
||||
u"params": {
|
||||
u'youtube_include_dash_manifest': True,
|
||||
u'format': '141',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@ -1272,8 +1289,8 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor):
|
||||
mobj = re.search(r';ytplayer.config = ({.*?});', video_webpage)
|
||||
if not mobj:
|
||||
raise ValueError('Could not find vevo ID')
|
||||
info = json.loads(mobj.group(1))
|
||||
args = info['args']
|
||||
ytplayer_config = json.loads(mobj.group(1))
|
||||
args = ytplayer_config['args']
|
||||
# Easy way to know if the 's' value is in url_encoded_fmt_stream_map
|
||||
# this signatures are encrypted
|
||||
if 'url_encoded_fmt_stream_map' not in args:
|
||||
@ -1366,12 +1383,24 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor):
|
||||
raise ExtractorError(u'no conn, hlsvp or url_encoded_fmt_stream_map information found in video info')
|
||||
|
||||
# Look for the DASH manifest
|
||||
dash_manifest_url_lst = video_info.get('dashmpd')
|
||||
if (dash_manifest_url_lst and dash_manifest_url_lst[0] and
|
||||
self._downloader.params.get('youtube_include_dash_manifest', False)):
|
||||
if (self._downloader.params.get('youtube_include_dash_manifest', False)):
|
||||
try:
|
||||
# The DASH manifest used needs to be the one from the original video_webpage.
|
||||
# The one found in get_video_info seems to be using different signatures.
|
||||
# However, in the case of an age restriction there won't be any embedded dashmpd in the video_webpage.
|
||||
# Luckily, it seems, this case uses some kind of default signature (len == 86), so the
|
||||
# combination of get_video_info and the _static_decrypt_signature() decryption fallback will work here.
|
||||
if age_gate:
|
||||
dash_manifest_url = video_info.get('dashmpd')[0]
|
||||
else:
|
||||
dash_manifest_url = ytplayer_config['args']['dashmpd']
|
||||
def decrypt_sig(mobj):
|
||||
s = mobj.group(1)
|
||||
dec_s = self._decrypt_signature(s, video_id, player_url, age_gate)
|
||||
return '/signature/%s' % dec_s
|
||||
dash_manifest_url = re.sub(r'/s/([\w\.]+)', decrypt_sig, dash_manifest_url)
|
||||
dash_doc = self._download_xml(
|
||||
dash_manifest_url_lst[0], video_id,
|
||||
dash_manifest_url, video_id,
|
||||
note=u'Downloading DASH manifest',
|
||||
errnote=u'Could not download DASH manifest')
|
||||
for r in dash_doc.findall(u'.//{urn:mpeg:DASH:schema:MPD:2011}Representation'):
|
||||
@ -1443,9 +1472,9 @@ class YoutubePlaylistIE(YoutubeBaseInfoExtractor):
|
||||
|
|
||||
((?:PL|EC|UU|FL|RD)[0-9A-Za-z-_]{10,})
|
||||
)"""
|
||||
_TEMPLATE_URL = 'https://www.youtube.com/playlist?list=%s&page=%s'
|
||||
_TEMPLATE_URL = 'https://www.youtube.com/playlist?list=%s'
|
||||
_MORE_PAGES_INDICATOR = r'data-link-type="next"'
|
||||
_VIDEO_RE = r'href="/watch\?v=(?P<id>[0-9A-Za-z_-]{11})&[^"]*?index=(?P<index>\d+)'
|
||||
_VIDEO_RE = r'href="\s*/watch\?v=(?P<id>[0-9A-Za-z_-]{11})&[^"]*?index=(?P<index>\d+)'
|
||||
IE_NAME = u'youtube:playlist'
|
||||
|
||||
def _real_initialize(self):
|
||||
@ -1493,29 +1522,31 @@ class YoutubePlaylistIE(YoutubeBaseInfoExtractor):
|
||||
raise ExtractorError(u'For downloading YouTube.com top lists, use '
|
||||
u'the "yttoplist" keyword, for example "youtube-dl \'yttoplist:music:Top Tracks\'"', expected=True)
|
||||
|
||||
url = self._TEMPLATE_URL % playlist_id
|
||||
page = self._download_webpage(url, playlist_id)
|
||||
more_widget_html = content_html = page
|
||||
|
||||
# Extract the video ids from the playlist pages
|
||||
ids = []
|
||||
|
||||
for page_num in itertools.count(1):
|
||||
url = self._TEMPLATE_URL % (playlist_id, page_num)
|
||||
page = self._download_webpage(url, playlist_id, u'Downloading page #%s' % page_num)
|
||||
matches = re.finditer(self._VIDEO_RE, page)
|
||||
matches = re.finditer(self._VIDEO_RE, content_html)
|
||||
# We remove the duplicates and the link with index 0
|
||||
# (it's not the first video of the playlist)
|
||||
new_ids = orderedSet(m.group('id') for m in matches if m.group('index') != '0')
|
||||
ids.extend(new_ids)
|
||||
|
||||
if re.search(self._MORE_PAGES_INDICATOR, page) is None:
|
||||
mobj = re.search(r'data-uix-load-more-href="/?(?P<more>[^"]+)"', more_widget_html)
|
||||
if not mobj:
|
||||
break
|
||||
|
||||
try:
|
||||
playlist_title = self._og_search_title(page)
|
||||
except RegexNotFoundError:
|
||||
self.report_warning(
|
||||
u'Playlist page is missing OpenGraph title, falling back ...',
|
||||
playlist_id)
|
||||
playlist_title = self._html_search_regex(
|
||||
r'<h1 class="pl-header-title">(.*?)</h1>', page, u'title')
|
||||
more = self._download_json(
|
||||
'https://youtube.com/%s' % mobj.group('more'), playlist_id, 'Downloading page #%s' % page_num)
|
||||
content_html = more['content_html']
|
||||
more_widget_html = more['load_more_widget_html']
|
||||
|
||||
playlist_title = self._html_search_regex(
|
||||
r'<h1 class="pl-header-title">\s*(.*?)\s*</h1>', page, u'title')
|
||||
|
||||
url_results = self._ids_to_results(ids)
|
||||
return self.playlist_result(url_results, playlist_id, playlist_title)
|
||||
|
@ -174,6 +174,11 @@ try:
|
||||
except NameError:
|
||||
compat_chr = chr
|
||||
|
||||
try:
|
||||
from xml.etree.ElementTree import ParseError as compat_xml_parse_error
|
||||
except ImportError: # Python 2.6
|
||||
from xml.parsers.expat import ExpatError as compat_xml_parse_error
|
||||
|
||||
def compat_ord(c):
|
||||
if type(c) is int: return c
|
||||
else: return ord(c)
|
||||
|
@ -1,2 +1,2 @@
|
||||
|
||||
__version__ = '2014.02.20'
|
||||
__version__ = '2014.02.21.1'
|
||||
|
Reference in New Issue
Block a user