Compare commits
9 Commits
2014.04.07
...
2014.04.07
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5863bdf33 | ||
|
|
b58ddb32ba | ||
|
|
b9e12a8140 | ||
|
|
104aa7388a | ||
|
|
c3855d28b0 | ||
|
|
734f90bb41 | ||
|
|
91a6addeeb | ||
|
|
9afb76c5ad | ||
|
|
dfb2cb5cfd |
@@ -286,6 +286,9 @@ class YoutubeDL(object):
|
|||||||
"""Print message to stdout if not in quiet mode."""
|
"""Print message to stdout if not in quiet mode."""
|
||||||
return self.to_stdout(message, skip_eol, check_quiet=True)
|
return self.to_stdout(message, skip_eol, check_quiet=True)
|
||||||
|
|
||||||
|
def _write_string(self, s, out=None):
|
||||||
|
write_string(s, out=out, encoding=self.params.get('encoding'))
|
||||||
|
|
||||||
def to_stdout(self, message, skip_eol=False, check_quiet=False):
|
def to_stdout(self, message, skip_eol=False, check_quiet=False):
|
||||||
"""Print message to stdout if not in quiet mode."""
|
"""Print message to stdout if not in quiet mode."""
|
||||||
if self.params.get('logger'):
|
if self.params.get('logger'):
|
||||||
@@ -295,7 +298,7 @@ class YoutubeDL(object):
|
|||||||
terminator = ['\n', ''][skip_eol]
|
terminator = ['\n', ''][skip_eol]
|
||||||
output = message + terminator
|
output = message + terminator
|
||||||
|
|
||||||
write_string(output, self._screen_file)
|
self._write_string(output, self._screen_file)
|
||||||
|
|
||||||
def to_stderr(self, message):
|
def to_stderr(self, message):
|
||||||
"""Print message to stderr."""
|
"""Print message to stderr."""
|
||||||
@@ -305,7 +308,7 @@ class YoutubeDL(object):
|
|||||||
else:
|
else:
|
||||||
message = self._bidi_workaround(message)
|
message = self._bidi_workaround(message)
|
||||||
output = message + '\n'
|
output = message + '\n'
|
||||||
write_string(output, self._err_file)
|
self._write_string(output, self._err_file)
|
||||||
|
|
||||||
def to_console_title(self, message):
|
def to_console_title(self, message):
|
||||||
if not self.params.get('consoletitle', False):
|
if not self.params.get('consoletitle', False):
|
||||||
@@ -315,21 +318,21 @@ class YoutubeDL(object):
|
|||||||
# already of type unicode()
|
# already of type unicode()
|
||||||
ctypes.windll.kernel32.SetConsoleTitleW(ctypes.c_wchar_p(message))
|
ctypes.windll.kernel32.SetConsoleTitleW(ctypes.c_wchar_p(message))
|
||||||
elif 'TERM' in os.environ:
|
elif 'TERM' in os.environ:
|
||||||
write_string('\033]0;%s\007' % message, self._screen_file)
|
self._write_string('\033]0;%s\007' % message, self._screen_file)
|
||||||
|
|
||||||
def save_console_title(self):
|
def save_console_title(self):
|
||||||
if not self.params.get('consoletitle', False):
|
if not self.params.get('consoletitle', False):
|
||||||
return
|
return
|
||||||
if 'TERM' in os.environ:
|
if 'TERM' in os.environ:
|
||||||
# Save the title on stack
|
# Save the title on stack
|
||||||
write_string('\033[22;0t', self._screen_file)
|
self._write_string('\033[22;0t', self._screen_file)
|
||||||
|
|
||||||
def restore_console_title(self):
|
def restore_console_title(self):
|
||||||
if not self.params.get('consoletitle', False):
|
if not self.params.get('consoletitle', False):
|
||||||
return
|
return
|
||||||
if 'TERM' in os.environ:
|
if 'TERM' in os.environ:
|
||||||
# Restore the title from stack
|
# Restore the title from stack
|
||||||
write_string('\033[23;0t', self._screen_file)
|
self._write_string('\033[23;0t', self._screen_file)
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.save_console_title()
|
self.save_console_title()
|
||||||
@@ -1211,9 +1214,16 @@ class YoutubeDL(object):
|
|||||||
if not self.params.get('verbose'):
|
if not self.params.get('verbose'):
|
||||||
return
|
return
|
||||||
|
|
||||||
write_string('[debug] Encodings: locale %s, fs %s, out %s, pref %s\n' %
|
write_string(
|
||||||
(locale.getpreferredencoding(), sys.getfilesystemencoding(), sys.stdout.encoding, self.get_encoding()))
|
'[debug] Encodings: locale %s, fs %s, out %s, pref %s\n' % (
|
||||||
write_string('[debug] youtube-dl version ' + __version__ + '\n')
|
locale.getpreferredencoding(),
|
||||||
|
sys.getfilesystemencoding(),
|
||||||
|
sys.stdout.encoding,
|
||||||
|
self.get_encoding()),
|
||||||
|
encoding=None
|
||||||
|
)
|
||||||
|
|
||||||
|
self._write_string('[debug] youtube-dl version ' + __version__ + '\n')
|
||||||
try:
|
try:
|
||||||
sp = subprocess.Popen(
|
sp = subprocess.Popen(
|
||||||
['git', 'rev-parse', '--short', 'HEAD'],
|
['git', 'rev-parse', '--short', 'HEAD'],
|
||||||
@@ -1222,20 +1232,20 @@ class YoutubeDL(object):
|
|||||||
out, err = sp.communicate()
|
out, err = sp.communicate()
|
||||||
out = out.decode().strip()
|
out = out.decode().strip()
|
||||||
if re.match('[0-9a-f]+', out):
|
if re.match('[0-9a-f]+', out):
|
||||||
write_string('[debug] Git HEAD: ' + out + '\n')
|
self._write_string('[debug] Git HEAD: ' + out + '\n')
|
||||||
except:
|
except:
|
||||||
try:
|
try:
|
||||||
sys.exc_clear()
|
sys.exc_clear()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
write_string('[debug] Python version %s - %s' %
|
self._write_string('[debug] Python version %s - %s' %
|
||||||
(platform.python_version(), platform_name()) + '\n')
|
(platform.python_version(), platform_name()) + '\n')
|
||||||
|
|
||||||
proxy_map = {}
|
proxy_map = {}
|
||||||
for handler in self._opener.handlers:
|
for handler in self._opener.handlers:
|
||||||
if hasattr(handler, 'proxies'):
|
if hasattr(handler, 'proxies'):
|
||||||
proxy_map.update(handler.proxies)
|
proxy_map.update(handler.proxies)
|
||||||
write_string('[debug] Proxy map: ' + compat_str(proxy_map) + '\n')
|
self._write_string('[debug] Proxy map: ' + compat_str(proxy_map) + '\n')
|
||||||
|
|
||||||
def _setup_opener(self):
|
def _setup_opener(self):
|
||||||
timeout_val = self.params.get('socket_timeout')
|
timeout_val = self.params.get('socket_timeout')
|
||||||
|
|||||||
@@ -208,6 +208,7 @@ from .rottentomatoes import RottenTomatoesIE
|
|||||||
from .roxwel import RoxwelIE
|
from .roxwel import RoxwelIE
|
||||||
from .rtlnow import RTLnowIE
|
from .rtlnow import RTLnowIE
|
||||||
from .rts import RTSIE
|
from .rts import RTSIE
|
||||||
|
from .rtve import RTVEALaCartaIE
|
||||||
from .rutube import (
|
from .rutube import (
|
||||||
RutubeIE,
|
RutubeIE,
|
||||||
RutubeChannelIE,
|
RutubeChannelIE,
|
||||||
|
|||||||
84
youtube_dl/extractor/rtve.py
Normal file
84
youtube_dl/extractor/rtve.py
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# encoding: utf-8
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import re
|
||||||
|
import base64
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from ..utils import (
|
||||||
|
struct_unpack,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RTVEALaCartaIE(InfoExtractor):
|
||||||
|
IE_NAME = 'rtve.es:alacarta'
|
||||||
|
IE_DESC = 'RTVE a la carta'
|
||||||
|
_VALID_URL = r'http://www\.rtve\.es/alacarta/videos/[^/]+/[^/]+/(?P<id>\d+)'
|
||||||
|
|
||||||
|
_TEST = {
|
||||||
|
'url': 'http://www.rtve.es/alacarta/videos/balonmano/o-swiss-cup-masculina-final-espana-suecia/2491869/',
|
||||||
|
'md5': '18fcd45965bdd076efdb12cd7f6d7b9e',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '2491869',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Balonmano - Swiss Cup masculina. Final: España-Suecia',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def _decrypt_url(self, png):
|
||||||
|
encrypted_data = base64.b64decode(png)
|
||||||
|
text_index = encrypted_data.find(b'tEXt')
|
||||||
|
text_chunk = encrypted_data[text_index-4:]
|
||||||
|
length = struct_unpack('!I', text_chunk[:4])[0]
|
||||||
|
# Use bytearray to get integers when iterating in both python 2.x and 3.x
|
||||||
|
data = bytearray(text_chunk[8:8+length])
|
||||||
|
data = [chr(b) for b in data if b != 0]
|
||||||
|
hash_index = data.index('#')
|
||||||
|
alphabet_data = data[:hash_index]
|
||||||
|
url_data = data[hash_index+1:]
|
||||||
|
|
||||||
|
alphabet = []
|
||||||
|
e = 0
|
||||||
|
d = 0
|
||||||
|
for l in alphabet_data:
|
||||||
|
if d == 0:
|
||||||
|
alphabet.append(l)
|
||||||
|
d = e = (e + 1) % 4
|
||||||
|
else:
|
||||||
|
d -= 1
|
||||||
|
url = ''
|
||||||
|
f = 0
|
||||||
|
e = 3
|
||||||
|
b = 1
|
||||||
|
for letter in url_data:
|
||||||
|
if f == 0:
|
||||||
|
l = int(letter)*10
|
||||||
|
f = 1
|
||||||
|
else:
|
||||||
|
if e == 0:
|
||||||
|
l += int(letter)
|
||||||
|
url += alphabet[l]
|
||||||
|
e = (b + 3) % 4
|
||||||
|
f = 0
|
||||||
|
b += 1
|
||||||
|
else:
|
||||||
|
e -= 1
|
||||||
|
|
||||||
|
return url
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
mobj = re.match(self._VALID_URL, url)
|
||||||
|
video_id = mobj.group('id')
|
||||||
|
info = self._download_json(
|
||||||
|
'http://www.rtve.es/api/videos/%s/config/alacarta_videos.json' % video_id,
|
||||||
|
video_id)['page']['items'][0]
|
||||||
|
png_url = 'http://www.rtve.es/ztnr/movil/thumbnail/default/videos/%s.png' % video_id
|
||||||
|
png = self._download_webpage(png_url, video_id, 'Downloading url information')
|
||||||
|
video_url = self._decrypt_url(png)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': video_id,
|
||||||
|
'title': info['title'],
|
||||||
|
'url': video_url,
|
||||||
|
'thumbnail': info['image'],
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ from ..utils import (
|
|||||||
|
|
||||||
|
|
||||||
class TeamcocoIE(InfoExtractor):
|
class TeamcocoIE(InfoExtractor):
|
||||||
_VALID_URL = r'http://teamcoco\.com/video/(?P<video_id>[0-9]+)?/?(?P<url_title>.*)'
|
_VALID_URL = r'http://teamcoco\.com/video/(?P<video_id>[0-9]+)?/?(?P<display_id>.*)'
|
||||||
_TESTS = [
|
_TESTS = [
|
||||||
{
|
{
|
||||||
'url': 'http://teamcoco.com/video/80187/conan-becomes-a-mary-kay-beauty-consultant',
|
'url': 'http://teamcoco.com/video/80187/conan-becomes-a-mary-kay-beauty-consultant',
|
||||||
@@ -33,21 +33,19 @@ class TeamcocoIE(InfoExtractor):
|
|||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
mobj = re.match(self._VALID_URL, url)
|
mobj = re.match(self._VALID_URL, url)
|
||||||
if mobj is None:
|
|
||||||
raise ExtractorError('Invalid URL: %s' % url)
|
display_id = mobj.group('display_id')
|
||||||
url_title = mobj.group('url_title')
|
webpage = self._download_webpage(url, display_id)
|
||||||
webpage = self._download_webpage(url, url_title)
|
|
||||||
|
|
||||||
video_id = mobj.group("video_id")
|
video_id = mobj.group("video_id")
|
||||||
if video_id == '':
|
if not video_id:
|
||||||
video_id = self._html_search_regex(
|
video_id = self._html_search_regex(
|
||||||
r'<article class="video" data-id="(\d+?)"',
|
r'<article class="video" data-id="(\d+?)"',
|
||||||
webpage, 'video id')
|
webpage, 'video id')
|
||||||
|
|
||||||
self.report_extraction(video_id)
|
|
||||||
|
|
||||||
data_url = 'http://teamcoco.com/cvp/2.0/%s.xml' % video_id
|
data_url = 'http://teamcoco.com/cvp/2.0/%s.xml' % video_id
|
||||||
data = self._download_xml(data_url, video_id, 'Downloading data webpage')
|
data = self._download_xml(
|
||||||
|
data_url, display_id, 'Downloading data webpage')
|
||||||
|
|
||||||
qualities = ['500k', '480p', '1000k', '720p', '1080p']
|
qualities = ['500k', '480p', '1000k', '720p', '1080p']
|
||||||
formats = []
|
formats = []
|
||||||
@@ -82,6 +80,7 @@ class TeamcocoIE(InfoExtractor):
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
'id': video_id,
|
'id': video_id,
|
||||||
|
'display_id': display_id,
|
||||||
'formats': formats,
|
'formats': formats,
|
||||||
'title': self._og_search_title(webpage),
|
'title': self._og_search_title(webpage),
|
||||||
'thumbnail': self._og_search_thumbnail(webpage),
|
'thumbnail': self._og_search_thumbnail(webpage),
|
||||||
|
|||||||
@@ -910,25 +910,81 @@ def platform_name():
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def write_string(s, out=None):
|
def _windows_write_string(s, out):
|
||||||
|
""" Returns True if the string was written using special methods,
|
||||||
|
False if it has yet to be written out."""
|
||||||
|
# Adapted from http://stackoverflow.com/a/3259271/35070
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
import ctypes.wintypes
|
||||||
|
|
||||||
|
WIN_OUTPUT_IDS = {
|
||||||
|
1: -11,
|
||||||
|
2: -12,
|
||||||
|
}
|
||||||
|
|
||||||
|
fileno = out.fileno()
|
||||||
|
if fileno not in WIN_OUTPUT_IDS:
|
||||||
|
return False
|
||||||
|
|
||||||
|
GetStdHandle = ctypes.WINFUNCTYPE(
|
||||||
|
ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD)(
|
||||||
|
("GetStdHandle", ctypes.windll.kernel32))
|
||||||
|
h = GetStdHandle(WIN_OUTPUT_IDS[fileno])
|
||||||
|
|
||||||
|
WriteConsoleW = ctypes.WINFUNCTYPE(
|
||||||
|
ctypes.wintypes.BOOL, ctypes.wintypes.HANDLE, ctypes.wintypes.LPWSTR,
|
||||||
|
ctypes.wintypes.DWORD, ctypes.POINTER(ctypes.wintypes.DWORD),
|
||||||
|
ctypes.wintypes.LPVOID)(("WriteConsoleW", ctypes.windll.kernel32))
|
||||||
|
written = ctypes.wintypes.DWORD(0)
|
||||||
|
|
||||||
|
GetFileType = ctypes.WINFUNCTYPE(ctypes.wintypes.DWORD, ctypes.wintypes.DWORD)(("GetFileType", ctypes.windll.kernel32))
|
||||||
|
FILE_TYPE_CHAR = 0x0002
|
||||||
|
FILE_TYPE_REMOTE = 0x8000
|
||||||
|
GetConsoleMode = ctypes.WINFUNCTYPE(
|
||||||
|
ctypes.wintypes.BOOL, ctypes.wintypes.HANDLE,
|
||||||
|
ctypes.POINTER(ctypes.wintypes.DWORD))(
|
||||||
|
("GetConsoleMode", ctypes.windll.kernel32))
|
||||||
|
INVALID_HANDLE_VALUE = ctypes.wintypes.DWORD(-1).value
|
||||||
|
|
||||||
|
def not_a_console(handle):
|
||||||
|
if handle == INVALID_HANDLE_VALUE or handle is None:
|
||||||
|
return True
|
||||||
|
return ((GetFileType(handle) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR
|
||||||
|
or GetConsoleMode(handle, ctypes.byref(ctypes.wintypes.DWORD())) == 0)
|
||||||
|
|
||||||
|
if not_a_console(h):
|
||||||
|
return False
|
||||||
|
|
||||||
|
remaining = len(s)
|
||||||
|
while remaining > 0:
|
||||||
|
ret = WriteConsoleW(
|
||||||
|
h, s, min(len(s), 1024), ctypes.byref(written), None)
|
||||||
|
if ret == 0:
|
||||||
|
raise OSError('Failed to write string')
|
||||||
|
remaining -= written.value
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def write_string(s, out=None, encoding=None):
|
||||||
if out is None:
|
if out is None:
|
||||||
out = sys.stderr
|
out = sys.stderr
|
||||||
assert type(s) == compat_str
|
assert type(s) == compat_str
|
||||||
|
|
||||||
|
if sys.platform == 'win32' and encoding is None and hasattr(out, 'fileno'):
|
||||||
|
if _windows_write_string(s, out):
|
||||||
|
return
|
||||||
|
|
||||||
if ('b' in getattr(out, 'mode', '') or
|
if ('b' in getattr(out, 'mode', '') or
|
||||||
sys.version_info[0] < 3): # Python 2 lies about mode of sys.stderr
|
sys.version_info[0] < 3): # Python 2 lies about mode of sys.stderr
|
||||||
s = s.encode(preferredencoding(), 'ignore')
|
byt = s.encode(encoding or preferredencoding(), 'ignore')
|
||||||
try:
|
out.write(byt)
|
||||||
out.write(s)
|
elif hasattr(out, 'buffer'):
|
||||||
except UnicodeEncodeError:
|
enc = encoding or getattr(out, 'encoding', None) or preferredencoding()
|
||||||
# In Windows shells, this can fail even when the codec is just charmap!?
|
byt = s.encode(enc, 'ignore')
|
||||||
# See https://wiki.python.org/moin/PrintFails#Issue
|
out.buffer.write(byt)
|
||||||
if sys.platform == 'win32' and hasattr(out, 'encoding'):
|
|
||||||
s = s.encode(out.encoding, 'ignore').decode(out.encoding)
|
|
||||||
out.write(s)
|
|
||||||
else:
|
else:
|
||||||
raise
|
out.write(s)
|
||||||
|
|
||||||
out.flush()
|
out.flush()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
|
|
||||||
__version__ = '2014.04.07'
|
__version__ = '2014.04.07.3'
|
||||||
|
|||||||
Reference in New Issue
Block a user