mirror of
https://github.com/l1ving/youtube-dl
synced 2025-02-15 17:42:52 +08:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
8b888cd0c7
@ -48,24 +48,36 @@ class PluzzIE(FranceTVBaseInfoExtractor):
|
|||||||
|
|
||||||
class FranceTvInfoIE(FranceTVBaseInfoExtractor):
|
class FranceTvInfoIE(FranceTVBaseInfoExtractor):
|
||||||
IE_NAME = 'francetvinfo.fr'
|
IE_NAME = 'francetvinfo.fr'
|
||||||
_VALID_URL = r'https?://www\.francetvinfo\.fr/replay.*/(?P<title>.+)\.html'
|
_VALID_URL = r'https?://www\.francetvinfo\.fr/.*/(?P<title>.+)\.html'
|
||||||
|
|
||||||
_TEST = {
|
_TESTS = [{
|
||||||
'url': 'http://www.francetvinfo.fr/replay-jt/france-3/soir-3/jt-grand-soir-3-lundi-26-aout-2013_393427.html',
|
'url': 'http://www.francetvinfo.fr/replay-jt/france-3/soir-3/jt-grand-soir-3-lundi-26-aout-2013_393427.html',
|
||||||
'file': '84981923.mp4',
|
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
|
'id': '84981923',
|
||||||
|
'ext': 'mp4',
|
||||||
'title': 'Soir 3',
|
'title': 'Soir 3',
|
||||||
},
|
},
|
||||||
'params': {
|
'params': {
|
||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
},
|
},
|
||||||
|
}, {
|
||||||
|
'url': 'http://www.francetvinfo.fr/elections/europeennes/direct-europeennes-regardez-le-debat-entre-les-candidats-a-la-presidence-de-la-commission_600639.html',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'EV_20019',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Débat des candidats à la Commission européenne',
|
||||||
|
'description': 'Débat des candidats à la Commission européenne',
|
||||||
|
},
|
||||||
|
'params': {
|
||||||
|
'skip_download': 'HLS (reqires ffmpeg)'
|
||||||
}
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
mobj = re.match(self._VALID_URL, url)
|
mobj = re.match(self._VALID_URL, url)
|
||||||
page_title = mobj.group('title')
|
page_title = mobj.group('title')
|
||||||
webpage = self._download_webpage(url, page_title)
|
webpage = self._download_webpage(url, page_title)
|
||||||
video_id = self._search_regex(r'id-video=(\d+?)[@"]', webpage, 'video id')
|
video_id = self._search_regex(r'id-video=((?:[^0-9]*?_)?[0-9]+)[@"]', webpage, 'video id')
|
||||||
return self._extract_video(video_id)
|
return self._extract_video(video_id)
|
||||||
|
|
||||||
|
|
||||||
|
@ -672,7 +672,7 @@ class GenericIE(InfoExtractor):
|
|||||||
# HTML5 video
|
# HTML5 video
|
||||||
found = re.findall(r'(?s)<video[^<]*(?:>.*?<source.*?)? src="([^"]+)"', webpage)
|
found = re.findall(r'(?s)<video[^<]*(?:>.*?<source.*?)? src="([^"]+)"', webpage)
|
||||||
if not found:
|
if not found:
|
||||||
found = re.findall(
|
found = re.search(
|
||||||
r'(?i)<meta\s+(?=(?:[a-z-]+="[^"]+"\s+)*http-equiv="refresh")'
|
r'(?i)<meta\s+(?=(?:[a-z-]+="[^"]+"\s+)*http-equiv="refresh")'
|
||||||
r'(?:[a-z-]+="[^"]+"\s+)*?content="[0-9]{,2};url=\'([^\']+)\'"',
|
r'(?:[a-z-]+="[^"]+"\s+)*?content="[0-9]{,2};url=\'([^\']+)\'"',
|
||||||
webpage)
|
webpage)
|
||||||
|
@ -1138,6 +1138,10 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor):
|
|||||||
# upload date
|
# upload date
|
||||||
upload_date = None
|
upload_date = None
|
||||||
mobj = re.search(r'(?s)id="eow-date.*?>(.*?)</span>', video_webpage)
|
mobj = re.search(r'(?s)id="eow-date.*?>(.*?)</span>', video_webpage)
|
||||||
|
if mobj is None:
|
||||||
|
mobj = re.search(
|
||||||
|
r'(?s)id="watch-uploader-info".*?>.*?Published on (.*?)</strong>',
|
||||||
|
video_webpage)
|
||||||
if mobj is not None:
|
if mobj is not None:
|
||||||
upload_date = ' '.join(re.sub(r'[/,-]', r' ', mobj.group(1)).split())
|
upload_date = ' '.join(re.sub(r'[/,-]', r' ', mobj.group(1)).split())
|
||||||
upload_date = unified_strdate(upload_date)
|
upload_date = unified_strdate(upload_date)
|
||||||
@ -1771,9 +1775,12 @@ class YoutubeFeedsInfoExtractor(YoutubeBaseInfoExtractor):
|
|||||||
feed_entries.extend(
|
feed_entries.extend(
|
||||||
self.url_result(video_id, 'Youtube', video_id=video_id)
|
self.url_result(video_id, 'Youtube', video_id=video_id)
|
||||||
for video_id in ids)
|
for video_id in ids)
|
||||||
if info['paging'] is None:
|
mobj = re.search(
|
||||||
|
r'data-uix-load-more-href="/?[^"]+paging=(?P<paging>\d+)',
|
||||||
|
feed_html)
|
||||||
|
if mobj is None:
|
||||||
break
|
break
|
||||||
paging = info['paging']
|
paging = mobj.group('paging')
|
||||||
return self.playlist_result(feed_entries, playlist_title=self._PLAYLIST_TITLE)
|
return self.playlist_result(feed_entries, playlist_title=self._PLAYLIST_TITLE)
|
||||||
|
|
||||||
class YoutubeSubscriptionsIE(YoutubeFeedsInfoExtractor):
|
class YoutubeSubscriptionsIE(YoutubeFeedsInfoExtractor):
|
||||||
|
@ -9,6 +9,7 @@ from .common import AudioConversionError, PostProcessor
|
|||||||
from ..utils import (
|
from ..utils import (
|
||||||
check_executable,
|
check_executable,
|
||||||
compat_subprocess_get_DEVNULL,
|
compat_subprocess_get_DEVNULL,
|
||||||
|
encodeArgument,
|
||||||
encodeFilename,
|
encodeFilename,
|
||||||
PostProcessingError,
|
PostProcessingError,
|
||||||
prepend_extension,
|
prepend_extension,
|
||||||
@ -48,7 +49,7 @@ class FFmpegPostProcessor(PostProcessor):
|
|||||||
for path in input_paths:
|
for path in input_paths:
|
||||||
files_cmd.extend(['-i', encodeFilename(path, True)])
|
files_cmd.extend(['-i', encodeFilename(path, True)])
|
||||||
cmd = ([self._get_executable(), '-y'] + files_cmd
|
cmd = ([self._get_executable(), '-y'] + files_cmd
|
||||||
+ opts +
|
+ [encodeArgument(o) for o in opts] +
|
||||||
[encodeFilename(self._ffmpeg_filename_argument(out_path), True)])
|
[encodeFilename(self._ffmpeg_filename_argument(out_path), True)])
|
||||||
|
|
||||||
if self._downloader.params.get('verbose', False):
|
if self._downloader.params.get('verbose', False):
|
||||||
|
@ -6,6 +6,7 @@ from .common import PostProcessor
|
|||||||
from ..utils import (
|
from ..utils import (
|
||||||
check_executable,
|
check_executable,
|
||||||
hyphenate_date,
|
hyphenate_date,
|
||||||
|
subprocess_check_output
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -57,7 +58,7 @@ class XAttrMetadataPP(PostProcessor):
|
|||||||
elif user_has_xattr:
|
elif user_has_xattr:
|
||||||
cmd = ['xattr', '-w', key, value, path]
|
cmd = ['xattr', '-w', key, value, path]
|
||||||
|
|
||||||
subprocess.check_output(cmd)
|
subprocess_check_output(cmd)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# On Unix, and can't find pyxattr, setfattr, or xattr.
|
# On Unix, and can't find pyxattr, setfattr, or xattr.
|
||||||
|
@ -540,6 +540,16 @@ def encodeFilename(s, for_subprocess=False):
|
|||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
return s.encode(encoding, 'ignore')
|
return s.encode(encoding, 'ignore')
|
||||||
|
|
||||||
|
|
||||||
|
def encodeArgument(s):
|
||||||
|
if not isinstance(s, compat_str):
|
||||||
|
# Legacy code that uses byte strings
|
||||||
|
# Uncomment the following line after fixing all post processors
|
||||||
|
#assert False, 'Internal error: %r should be of type %r, is %r' % (s, compat_str, type(s))
|
||||||
|
s = s.decode('ascii')
|
||||||
|
return encodeFilename(s, True)
|
||||||
|
|
||||||
|
|
||||||
def decodeOption(optval):
|
def decodeOption(optval):
|
||||||
if optval is None:
|
if optval is None:
|
||||||
return optval
|
return optval
|
||||||
@ -1429,3 +1439,15 @@ def qualities(quality_ids):
|
|||||||
|
|
||||||
|
|
||||||
DEFAULT_OUTTMPL = '%(title)s-%(id)s.%(ext)s'
|
DEFAULT_OUTTMPL = '%(title)s-%(id)s.%(ext)s'
|
||||||
|
|
||||||
|
try:
|
||||||
|
subprocess_check_output = subprocess.check_output
|
||||||
|
except AttributeError:
|
||||||
|
def subprocess_check_output(*args, **kwargs):
|
||||||
|
assert 'input' not in kwargs
|
||||||
|
p = subprocess.Popen(*args, stdout=subprocess.PIPE, **kwargs)
|
||||||
|
output, _ = p.communicate()
|
||||||
|
ret = p.poll()
|
||||||
|
if ret:
|
||||||
|
raise subprocess.CalledProcessError(ret, p.args, output=output)
|
||||||
|
return output
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
|
|
||||||
__version__ = '2014.05.13'
|
__version__ = '2014.05.16.1'
|
||||||
|
Loading…
Reference in New Issue
Block a user