Compare commits
28 Commits
2015.01.10
...
2015.01.10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd3063f3fa | ||
|
|
58b1f00d19 | ||
|
|
149f05c7b6 | ||
|
|
8a1b9b068e | ||
|
|
c5a59d9391 | ||
|
|
500b8b41c1 | ||
|
|
be4a824d74 | ||
|
|
ed3958d714 | ||
|
|
6ce08764a1 | ||
|
|
c80ede5f13 | ||
|
|
bc694039e4 | ||
|
|
3462af03e6 | ||
|
|
ea1d5bdcdd | ||
|
|
121c09c7be | ||
|
|
76bfaf6daf | ||
|
|
d89c6e336a | ||
|
|
776dc3992a | ||
|
|
27ca82ebc6 | ||
|
|
385f8ae468 | ||
|
|
b9f030cc26 | ||
|
|
52afb2ac1b | ||
|
|
43bc88903d | ||
|
|
0cd64bd077 | ||
|
|
0551a02b82 | ||
|
|
25fadd06d0 | ||
|
|
7a47d07c6d | ||
|
|
34e48bed3b | ||
|
|
c816336cbd |
1
AUTHORS
1
AUTHORS
@@ -101,3 +101,4 @@ Thijs Vermeir
|
|||||||
Joel Leclerc
|
Joel Leclerc
|
||||||
Christopher Krooss
|
Christopher Krooss
|
||||||
Ondřej Caletka
|
Ondřej Caletka
|
||||||
|
Dinesh S
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -60,10 +60,6 @@ which means you can modify it, redistribute it or use it however you like.
|
|||||||
they would handle
|
they would handle
|
||||||
--extractor-descriptions Output descriptions of all supported
|
--extractor-descriptions Output descriptions of all supported
|
||||||
extractors
|
extractors
|
||||||
--proxy URL Use the specified HTTP/HTTPS proxy. Pass in
|
|
||||||
an empty string (--proxy "") for direct
|
|
||||||
connection
|
|
||||||
--socket-timeout None Time to wait before giving up, in seconds
|
|
||||||
--default-search PREFIX Use this prefix for unqualified URLs. For
|
--default-search PREFIX Use this prefix for unqualified URLs. For
|
||||||
example "gvsearch2:" downloads two videos
|
example "gvsearch2:" downloads two videos
|
||||||
from google videos for youtube-dl "large
|
from google videos for youtube-dl "large
|
||||||
@@ -82,6 +78,18 @@ which means you can modify it, redistribute it or use it however you like.
|
|||||||
--flat-playlist Do not extract the videos of a playlist,
|
--flat-playlist Do not extract the videos of a playlist,
|
||||||
only list them.
|
only list them.
|
||||||
|
|
||||||
|
## Network Options:
|
||||||
|
--proxy URL Use the specified HTTP/HTTPS proxy. Pass in
|
||||||
|
an empty string (--proxy "") for direct
|
||||||
|
connection
|
||||||
|
--socket-timeout SECONDS Time to wait before giving up, in seconds
|
||||||
|
--source-address IP Client-side IP address to bind to
|
||||||
|
(experimental)
|
||||||
|
-4, --force-ipv4 Make all connections via IPv4
|
||||||
|
(experimental)
|
||||||
|
-6, --force-ipv6 Make all connections via IPv6
|
||||||
|
(experimental)
|
||||||
|
|
||||||
## Video Selection:
|
## Video Selection:
|
||||||
--playlist-start NUMBER playlist video to start at (default is 1)
|
--playlist-start NUMBER playlist video to start at (default is 1)
|
||||||
--playlist-end NUMBER playlist video to end at (default is last)
|
--playlist-end NUMBER playlist video to end at (default is last)
|
||||||
@@ -231,6 +239,8 @@ which means you can modify it, redistribute it or use it however you like.
|
|||||||
files in the current directory to debug
|
files in the current directory to debug
|
||||||
problems
|
problems
|
||||||
--print-traffic Display sent and read HTTP traffic
|
--print-traffic Display sent and read HTTP traffic
|
||||||
|
-C, --call-home Contact the youtube-dl server for
|
||||||
|
debugging. (Experimental)
|
||||||
|
|
||||||
## Workarounds:
|
## Workarounds:
|
||||||
--encoding ENCODING Force the specified encoding (experimental)
|
--encoding ENCODING Force the specified encoding (experimental)
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ from .utils import (
|
|||||||
takewhile_inclusive,
|
takewhile_inclusive,
|
||||||
UnavailableVideoError,
|
UnavailableVideoError,
|
||||||
url_basename,
|
url_basename,
|
||||||
|
version_tuple,
|
||||||
write_json_file,
|
write_json_file,
|
||||||
write_string,
|
write_string,
|
||||||
YoutubeDLHandler,
|
YoutubeDLHandler,
|
||||||
@@ -211,6 +212,9 @@ class YoutubeDL(object):
|
|||||||
- "warn": only emit a warning
|
- "warn": only emit a warning
|
||||||
- "detect_or_warn": check whether we can do anything
|
- "detect_or_warn": check whether we can do anything
|
||||||
about it, warn otherwise
|
about it, warn otherwise
|
||||||
|
source_address: (Experimental) Client-side IP address to bind to.
|
||||||
|
call_home: (Experimental) Boolean, true iff we are allowed to
|
||||||
|
contact the youtube-dl servers for debugging.
|
||||||
|
|
||||||
|
|
||||||
The following parameters are not used by YoutubeDL itself, they are used by
|
The following parameters are not used by YoutubeDL itself, they are used by
|
||||||
@@ -1463,6 +1467,17 @@ class YoutubeDL(object):
|
|||||||
proxy_map.update(handler.proxies)
|
proxy_map.update(handler.proxies)
|
||||||
self._write_string('[debug] Proxy map: ' + compat_str(proxy_map) + '\n')
|
self._write_string('[debug] Proxy map: ' + compat_str(proxy_map) + '\n')
|
||||||
|
|
||||||
|
if self.params.get('call_home', False):
|
||||||
|
ipaddr = self.urlopen('https://yt-dl.org/ip').read().decode('utf-8')
|
||||||
|
self._write_string('[debug] Public IP address: %s\n' % ipaddr)
|
||||||
|
latest_version = self.urlopen(
|
||||||
|
'https://yt-dl.org/latest/version').read().decode('utf-8')
|
||||||
|
if version_tuple(latest_version) > version_tuple(__version__):
|
||||||
|
self.report_warning(
|
||||||
|
'You are using an outdated version (newest version: %s)! '
|
||||||
|
'See https://yt-dl.org/update if you need help updating.' %
|
||||||
|
latest_version)
|
||||||
|
|
||||||
def _setup_opener(self):
|
def _setup_opener(self):
|
||||||
timeout_val = self.params.get('socket_timeout')
|
timeout_val = self.params.get('socket_timeout')
|
||||||
self._socket_timeout = 600 if timeout_val is None else float(timeout_val)
|
self._socket_timeout = 600 if timeout_val is None else float(timeout_val)
|
||||||
@@ -1493,9 +1508,8 @@ class YoutubeDL(object):
|
|||||||
proxy_handler = compat_urllib_request.ProxyHandler(proxies)
|
proxy_handler = compat_urllib_request.ProxyHandler(proxies)
|
||||||
|
|
||||||
debuglevel = 1 if self.params.get('debug_printtraffic') else 0
|
debuglevel = 1 if self.params.get('debug_printtraffic') else 0
|
||||||
https_handler = make_HTTPS_handler(
|
https_handler = make_HTTPS_handler(self.params, debuglevel=debuglevel)
|
||||||
self.params.get('nocheckcertificate', False), debuglevel=debuglevel)
|
ydlh = YoutubeDLHandler(self.params, debuglevel=debuglevel)
|
||||||
ydlh = YoutubeDLHandler(debuglevel=debuglevel)
|
|
||||||
opener = compat_urllib_request.build_opener(
|
opener = compat_urllib_request.build_opener(
|
||||||
https_handler, proxy_handler, cookie_processor, ydlh)
|
https_handler, proxy_handler, cookie_processor, ydlh)
|
||||||
# Delete the default user-agent header, which would otherwise apply in
|
# Delete the default user-agent header, which would otherwise apply in
|
||||||
|
|||||||
@@ -327,6 +327,8 @@ def _real_main(argv=None):
|
|||||||
'merge_output_format': opts.merge_output_format,
|
'merge_output_format': opts.merge_output_format,
|
||||||
'postprocessors': postprocessors,
|
'postprocessors': postprocessors,
|
||||||
'fixup': opts.fixup,
|
'fixup': opts.fixup,
|
||||||
|
'source_address': opts.source_address,
|
||||||
|
'call_home': opts.call_home,
|
||||||
}
|
}
|
||||||
|
|
||||||
with YoutubeDL(ydl_opts) as ydl:
|
with YoutubeDL(ydl_opts) as ydl:
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import getpass
|
|||||||
import optparse
|
import optparse
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@@ -307,6 +308,32 @@ else:
|
|||||||
compat_kwargs = lambda kwargs: kwargs
|
compat_kwargs = lambda kwargs: kwargs
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info < (2, 7):
|
||||||
|
def compat_socket_create_connection(address, timeout, source_address=None):
|
||||||
|
host, port = address
|
||||||
|
err = None
|
||||||
|
for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
|
||||||
|
af, socktype, proto, canonname, sa = res
|
||||||
|
sock = None
|
||||||
|
try:
|
||||||
|
sock = socket.socket(af, socktype, proto)
|
||||||
|
sock.settimeout(timeout)
|
||||||
|
if source_address:
|
||||||
|
sock.bind(source_address)
|
||||||
|
sock.connect(sa)
|
||||||
|
return sock
|
||||||
|
except socket.error as _:
|
||||||
|
err = _
|
||||||
|
if sock is not None:
|
||||||
|
sock.close()
|
||||||
|
if err is not None:
|
||||||
|
raise err
|
||||||
|
else:
|
||||||
|
raise error("getaddrinfo returns an empty list")
|
||||||
|
else:
|
||||||
|
compat_socket_create_connection = socket.create_connection
|
||||||
|
|
||||||
|
|
||||||
# Fix https://github.com/rg3/youtube-dl/issues/4223
|
# Fix https://github.com/rg3/youtube-dl/issues/4223
|
||||||
# See http://bugs.python.org/issue9161 for what is broken
|
# See http://bugs.python.org/issue9161 for what is broken
|
||||||
def workaround_optparse_bug9161():
|
def workaround_optparse_bug9161():
|
||||||
@@ -343,6 +370,7 @@ __all__ = [
|
|||||||
'compat_parse_qs',
|
'compat_parse_qs',
|
||||||
'compat_print',
|
'compat_print',
|
||||||
'compat_str',
|
'compat_str',
|
||||||
|
'compat_socket_create_connection',
|
||||||
'compat_subprocess_get_DEVNULL',
|
'compat_subprocess_get_DEVNULL',
|
||||||
'compat_urllib_error',
|
'compat_urllib_error',
|
||||||
'compat_urllib_parse',
|
'compat_urllib_parse',
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ from .arte import (
|
|||||||
ArteTVEmbedIE,
|
ArteTVEmbedIE,
|
||||||
)
|
)
|
||||||
from .atresplayer import AtresPlayerIE
|
from .atresplayer import AtresPlayerIE
|
||||||
|
from .atttechchannel import ATTTechChannelIE
|
||||||
from .audiomack import AudiomackIE, AudiomackAlbumIE
|
from .audiomack import AudiomackIE, AudiomackAlbumIE
|
||||||
from .auengine import AUEngineIE
|
from .auengine import AUEngineIE
|
||||||
from .azubu import AzubuIE
|
from .azubu import AzubuIE
|
||||||
@@ -69,6 +70,7 @@ from .cnn import (
|
|||||||
CNNArticleIE,
|
CNNArticleIE,
|
||||||
)
|
)
|
||||||
from .collegehumor import CollegeHumorIE
|
from .collegehumor import CollegeHumorIE
|
||||||
|
from .collegerama import CollegeRamaIE
|
||||||
from .comedycentral import ComedyCentralIE, ComedyCentralShowsIE
|
from .comedycentral import ComedyCentralIE, ComedyCentralShowsIE
|
||||||
from .comcarcoff import ComCarCoffIE
|
from .comcarcoff import ComCarCoffIE
|
||||||
from .commonmistakes import CommonMistakesIE
|
from .commonmistakes import CommonMistakesIE
|
||||||
@@ -206,6 +208,7 @@ from .jove import JoveIE
|
|||||||
from .jukebox import JukeboxIE
|
from .jukebox import JukeboxIE
|
||||||
from .jpopsukitv import JpopsukiIE
|
from .jpopsukitv import JpopsukiIE
|
||||||
from .kankan import KankanIE
|
from .kankan import KankanIE
|
||||||
|
from .karaoketv import KaraoketvIE
|
||||||
from .keezmovies import KeezMoviesIE
|
from .keezmovies import KeezMoviesIE
|
||||||
from .khanacademy import KhanAcademyIE
|
from .khanacademy import KhanAcademyIE
|
||||||
from .kickstarter import KickStarterIE
|
from .kickstarter import KickStarterIE
|
||||||
@@ -339,6 +342,7 @@ from .ro220 import Ro220IE
|
|||||||
from .rottentomatoes import RottenTomatoesIE
|
from .rottentomatoes import RottenTomatoesIE
|
||||||
from .roxwel import RoxwelIE
|
from .roxwel import RoxwelIE
|
||||||
from .rtbf import RTBFIE
|
from .rtbf import RTBFIE
|
||||||
|
from .rte import RteIE
|
||||||
from .rtlnl import RtlXlIE
|
from .rtlnl import RtlXlIE
|
||||||
from .rtlnow import RTLnowIE
|
from .rtlnow import RTLnowIE
|
||||||
from .rtp import RTPIE
|
from .rtp import RTPIE
|
||||||
|
|||||||
55
youtube_dl/extractor/atttechchannel.py
Normal file
55
youtube_dl/extractor/atttechchannel.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from ..utils import unified_strdate
|
||||||
|
|
||||||
|
|
||||||
|
class ATTTechChannelIE(InfoExtractor):
|
||||||
|
_VALID_URL = r'https?://techchannel\.att\.com/play-video\.cfm/([^/]+/)*(?P<id>.+)'
|
||||||
|
_TEST = {
|
||||||
|
'url': 'http://techchannel.att.com/play-video.cfm/2014/1/27/ATT-Archives-The-UNIX-System-Making-Computers-Easier-to-Use',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '11316',
|
||||||
|
'display_id': 'ATT-Archives-The-UNIX-System-Making-Computers-Easier-to-Use',
|
||||||
|
'ext': 'flv',
|
||||||
|
'title': 'AT&T Archives : The UNIX System: Making Computers Easier to Use',
|
||||||
|
'description': 'A 1982 film about UNIX is the foundation for software in use around Bell Labs and AT&T.',
|
||||||
|
'thumbnail': 're:^https?://.*\.jpg$',
|
||||||
|
'upload_date': '20140127',
|
||||||
|
},
|
||||||
|
'params': {
|
||||||
|
# rtmp download
|
||||||
|
'skip_download': True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
display_id = self._match_id(url)
|
||||||
|
|
||||||
|
webpage = self._download_webpage(url, display_id)
|
||||||
|
|
||||||
|
video_url = self._search_regex(
|
||||||
|
r"url\s*:\s*'(rtmp://[^']+)'",
|
||||||
|
webpage, 'video URL')
|
||||||
|
|
||||||
|
video_id = self._search_regex(
|
||||||
|
r'mediaid\s*=\s*(\d+)',
|
||||||
|
webpage, 'video id', fatal=False)
|
||||||
|
|
||||||
|
title = self._og_search_title(webpage)
|
||||||
|
description = self._og_search_description(webpage)
|
||||||
|
thumbnail = self._og_search_thumbnail(webpage)
|
||||||
|
upload_date = unified_strdate(self._search_regex(
|
||||||
|
r'[Rr]elease\s+date:\s*(\d{1,2}/\d{1,2}/\d{4})',
|
||||||
|
webpage, 'upload date', fatal=False), False)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': video_id,
|
||||||
|
'display_id': display_id,
|
||||||
|
'url': video_url,
|
||||||
|
'ext': 'flv',
|
||||||
|
'title': title,
|
||||||
|
'description': description,
|
||||||
|
'thumbnail': thumbnail,
|
||||||
|
'upload_date': upload_date,
|
||||||
|
}
|
||||||
92
youtube_dl/extractor/collegerama.py
Normal file
92
youtube_dl/extractor/collegerama.py
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from ..compat import compat_urllib_request
|
||||||
|
from ..utils import (
|
||||||
|
float_or_none,
|
||||||
|
int_or_none,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CollegeRamaIE(InfoExtractor):
|
||||||
|
_VALID_URL = r'https?://collegerama\.tudelft\.nl/Mediasite/Play/(?P<id>[\da-f]+)'
|
||||||
|
_TESTS = [
|
||||||
|
{
|
||||||
|
'url': 'https://collegerama.tudelft.nl/Mediasite/Play/585a43626e544bdd97aeb71a0ec907a01d',
|
||||||
|
'md5': '481fda1c11f67588c0d9d8fbdced4e39',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '585a43626e544bdd97aeb71a0ec907a01d',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Een nieuwe wereld: waarden, bewustzijn en techniek van de mensheid 2.0.',
|
||||||
|
'description': '',
|
||||||
|
'thumbnail': 're:^https?://.*\.jpg$',
|
||||||
|
'duration': 7713.088,
|
||||||
|
'timestamp': 1413309600,
|
||||||
|
'upload_date': '20141014',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'url': 'https://collegerama.tudelft.nl/Mediasite/Play/86a9ea9f53e149079fbdb4202b521ed21d?catalog=fd32fd35-6c99-466c-89d4-cd3c431bc8a4',
|
||||||
|
'md5': 'ef1fdded95bdf19b12c5999949419c92',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '86a9ea9f53e149079fbdb4202b521ed21d',
|
||||||
|
'ext': 'wmv',
|
||||||
|
'title': '64ste Vakantiecursus: Afvalwater',
|
||||||
|
'description': 'md5:7fd774865cc69d972f542b157c328305',
|
||||||
|
'duration': 10853,
|
||||||
|
'timestamp': 1326446400,
|
||||||
|
'upload_date': '20120113',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
video_id = self._match_id(url)
|
||||||
|
|
||||||
|
player_options_request = {
|
||||||
|
"getPlayerOptionsRequest": {
|
||||||
|
"ResourceId": video_id,
|
||||||
|
"QueryString": "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request = compat_urllib_request.Request(
|
||||||
|
'http://collegerama.tudelft.nl/Mediasite/PlayerService/PlayerService.svc/json/GetPlayerOptions',
|
||||||
|
json.dumps(player_options_request))
|
||||||
|
request.add_header('Content-Type', 'application/json')
|
||||||
|
|
||||||
|
player_options = self._download_json(request, video_id)
|
||||||
|
|
||||||
|
presentation = player_options['d']['Presentation']
|
||||||
|
title = presentation['Title']
|
||||||
|
description = presentation.get('Description')
|
||||||
|
thumbnail = None
|
||||||
|
duration = float_or_none(presentation.get('Duration'), 1000)
|
||||||
|
timestamp = int_or_none(presentation.get('UnixTime'), 1000)
|
||||||
|
|
||||||
|
formats = []
|
||||||
|
for stream in presentation['Streams']:
|
||||||
|
for video in stream['VideoUrls']:
|
||||||
|
thumbnail_url = stream.get('ThumbnailUrl')
|
||||||
|
if thumbnail_url:
|
||||||
|
thumbnail = 'http://collegerama.tudelft.nl' + thumbnail_url
|
||||||
|
format_id = video['MediaType']
|
||||||
|
if format_id == 'SS':
|
||||||
|
continue
|
||||||
|
formats.append({
|
||||||
|
'url': video['Location'],
|
||||||
|
'format_id': format_id,
|
||||||
|
})
|
||||||
|
self._sort_formats(formats)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': video_id,
|
||||||
|
'title': title,
|
||||||
|
'description': description,
|
||||||
|
'thumbnail': thumbnail,
|
||||||
|
'duration': duration,
|
||||||
|
'timestamp': timestamp,
|
||||||
|
'formats': formats,
|
||||||
|
}
|
||||||
@@ -742,8 +742,14 @@ class InfoExtractor(object):
|
|||||||
'Unable to download f4m manifest')
|
'Unable to download f4m manifest')
|
||||||
|
|
||||||
formats = []
|
formats = []
|
||||||
|
manifest_version = '1.0'
|
||||||
media_nodes = manifest.findall('{http://ns.adobe.com/f4m/1.0}media')
|
media_nodes = manifest.findall('{http://ns.adobe.com/f4m/1.0}media')
|
||||||
|
if not media_nodes:
|
||||||
|
manifest_version = '2.0'
|
||||||
|
media_nodes = manifest.findall('{http://ns.adobe.com/f4m/2.0}media')
|
||||||
for i, media_el in enumerate(media_nodes):
|
for i, media_el in enumerate(media_nodes):
|
||||||
|
if manifest_version == '2.0':
|
||||||
|
manifest_url = '/'.join(manifest_url.split('/')[:-1]) + '/' + media_el.attrib.get('href')
|
||||||
tbr = int_or_none(media_el.attrib.get('bitrate'))
|
tbr = int_or_none(media_el.attrib.get('bitrate'))
|
||||||
format_id = 'f4m-%d' % (i if tbr is None else tbr)
|
format_id = 'f4m-%d' % (i if tbr is None else tbr)
|
||||||
formats.append({
|
formats.append({
|
||||||
|
|||||||
@@ -122,7 +122,6 @@ class EightTracksIE(InfoExtractor):
|
|||||||
entries = []
|
entries = []
|
||||||
|
|
||||||
for i in range(track_count):
|
for i in range(track_count):
|
||||||
|
|
||||||
api_json = None
|
api_json = None
|
||||||
download_tries = 0
|
download_tries = 0
|
||||||
|
|
||||||
|
|||||||
41
youtube_dl/extractor/karaoketv.py
Normal file
41
youtube_dl/extractor/karaoketv.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from ..compat import compat_urllib_parse
|
||||||
|
from ..utils import (
|
||||||
|
ExtractorError,
|
||||||
|
js_to_json,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class KaraoketvIE(InfoExtractor):
|
||||||
|
_VALID_URL = r'http://karaoketv\.co\.il/\?container=songs&id=(?P<id>[0-9]+)'
|
||||||
|
_TEST = {
|
||||||
|
'url': 'http://karaoketv.co.il/?container=songs&id=171568',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '171568',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'אל העולם שלך - רותם כהן - שרים קריוקי',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
video_id = self._match_id(url)
|
||||||
|
webpage = self._download_webpage(url, video_id)
|
||||||
|
|
||||||
|
page_video_url = self._og_search_video_url(webpage, video_id)
|
||||||
|
config_json = compat_urllib_parse.unquote_plus(self._search_regex(
|
||||||
|
r'config=(.*)', page_video_url, 'configuration'))
|
||||||
|
|
||||||
|
urls_info_json = self._download_json(
|
||||||
|
config_json, video_id, 'Downloading configuration',
|
||||||
|
transform_source=js_to_json)
|
||||||
|
|
||||||
|
url = urls_info_json['playlist'][0]['url']
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': video_id,
|
||||||
|
'title': self._og_search_title(webpage),
|
||||||
|
'url': url,
|
||||||
|
}
|
||||||
@@ -7,8 +7,10 @@ from .common import InfoExtractor
|
|||||||
from ..utils import (
|
from ..utils import (
|
||||||
ExtractorError,
|
ExtractorError,
|
||||||
float_or_none,
|
float_or_none,
|
||||||
|
parse_duration,
|
||||||
unified_strdate,
|
unified_strdate,
|
||||||
)
|
)
|
||||||
|
from .subtitles import SubtitlesInfoExtractor
|
||||||
|
|
||||||
|
|
||||||
class NRKIE(InfoExtractor):
|
class NRKIE(InfoExtractor):
|
||||||
@@ -71,8 +73,8 @@ class NRKIE(InfoExtractor):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class NRKTVIE(InfoExtractor):
|
class NRKTVIE(SubtitlesInfoExtractor):
|
||||||
_VALID_URL = r'http://tv\.nrk(?:super)?\.no/(?:serie/[^/]+|program)/(?P<id>[a-zA-Z]{4}\d{8})(?:/\d{2}-\d{2}-\d{4})?(?:#del=(?P<part_id>\d+))?'
|
_VALID_URL = r'(?P<baseurl>http://tv\.nrk(?:super)?\.no/)(?:serie/[^/]+|program)/(?P<id>[a-zA-Z]{4}\d{8})(?:/\d{2}-\d{2}-\d{4})?(?:#del=(?P<part_id>\d+))?'
|
||||||
|
|
||||||
_TESTS = [
|
_TESTS = [
|
||||||
{
|
{
|
||||||
@@ -147,6 +149,29 @@ class NRKTVIE(InfoExtractor):
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def _seconds2str(self, s):
|
||||||
|
return '%02d:%02d:%02d.%03d' % (s / 3600, (s % 3600) / 60, s % 60, (s % 1) * 1000)
|
||||||
|
|
||||||
|
def _debug_print(self, txt):
|
||||||
|
if self._downloader.params.get('verbose', False):
|
||||||
|
self.to_screen('[debug] %s' % txt)
|
||||||
|
|
||||||
|
def _extract_captions(self, subtitlesurl, video_id, baseurl):
|
||||||
|
url = "%s%s" % (baseurl, subtitlesurl)
|
||||||
|
self._debug_print('%s: Subtitle url: %s' % (video_id, url))
|
||||||
|
captions = self._download_xml(url, video_id, 'Downloading subtitles')
|
||||||
|
lang = captions.get('lang', 'no')
|
||||||
|
ps = captions.findall('./{0}body/{0}div/{0}p'.format('{http://www.w3.org/ns/ttml}'))
|
||||||
|
srt = ''
|
||||||
|
for pos, p in enumerate(ps):
|
||||||
|
begin = parse_duration(p.get('begin'))
|
||||||
|
duration = parse_duration(p.get('dur'))
|
||||||
|
starttime = self._seconds2str(begin)
|
||||||
|
endtime = self._seconds2str(begin + duration)
|
||||||
|
text = '\n'.join(p.itertext())
|
||||||
|
srt += '%s\r\n%s --> %s\r\n%s\r\n\r\n' % (str(pos), starttime, endtime, text)
|
||||||
|
return {lang: srt}
|
||||||
|
|
||||||
def _extract_f4m(self, manifest_url, video_id):
|
def _extract_f4m(self, manifest_url, video_id):
|
||||||
return self._extract_f4m_formats(manifest_url + '?hdcore=3.1.1&plugin=aasp-3.1.1.69.124', video_id)
|
return self._extract_f4m_formats(manifest_url + '?hdcore=3.1.1&plugin=aasp-3.1.1.69.124', video_id)
|
||||||
|
|
||||||
@@ -154,6 +179,7 @@ class NRKTVIE(InfoExtractor):
|
|||||||
mobj = re.match(self._VALID_URL, url)
|
mobj = re.match(self._VALID_URL, url)
|
||||||
video_id = mobj.group('id')
|
video_id = mobj.group('id')
|
||||||
part_id = mobj.group('part_id')
|
part_id = mobj.group('part_id')
|
||||||
|
baseurl = mobj.group('baseurl')
|
||||||
|
|
||||||
webpage = self._download_webpage(url, video_id)
|
webpage = self._download_webpage(url, video_id)
|
||||||
|
|
||||||
@@ -210,9 +236,18 @@ class NRKTVIE(InfoExtractor):
|
|||||||
m3u8_url = re.search(r'data-hls-media="([^"]+)"', webpage)
|
m3u8_url = re.search(r'data-hls-media="([^"]+)"', webpage)
|
||||||
if m3u8_url:
|
if m3u8_url:
|
||||||
formats.extend(self._extract_m3u8_formats(m3u8_url.group(1), video_id, 'mp4'))
|
formats.extend(self._extract_m3u8_formats(m3u8_url.group(1), video_id, 'mp4'))
|
||||||
|
|
||||||
self._sort_formats(formats)
|
self._sort_formats(formats)
|
||||||
|
|
||||||
|
subtitles_url = self._html_search_regex(
|
||||||
|
r'data-subtitlesurl[ ]*=[ ]*"([^"]+)"',
|
||||||
|
webpage, 'subtitle URL', default=None)
|
||||||
|
subtitles = None
|
||||||
|
if subtitles_url:
|
||||||
|
subtitles = self._extract_captions(subtitles_url, video_id, baseurl)
|
||||||
|
if self._downloader.params.get('listsubtitles', False):
|
||||||
|
self._list_available_subtitles(video_id, subtitles)
|
||||||
|
return
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'id': video_id,
|
'id': video_id,
|
||||||
'title': title,
|
'title': title,
|
||||||
@@ -221,4 +256,5 @@ class NRKTVIE(InfoExtractor):
|
|||||||
'upload_date': upload_date,
|
'upload_date': upload_date,
|
||||||
'duration': duration,
|
'duration': duration,
|
||||||
'formats': formats,
|
'formats': formats,
|
||||||
|
'subtitles': subtitles,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,13 +128,16 @@ class ORFTVthekIE(InfoExtractor):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Audios on ORF radio are only available for 7 days, so we can't add tests.
|
|
||||||
|
|
||||||
|
|
||||||
class ORFOE1IE(InfoExtractor):
|
class ORFOE1IE(InfoExtractor):
|
||||||
IE_NAME = 'orf:oe1'
|
IE_NAME = 'orf:oe1'
|
||||||
IE_DESC = 'Radio Österreich 1'
|
IE_DESC = 'Radio Österreich 1'
|
||||||
_VALID_URL = r'http://oe1\.orf\.at/programm/(?P<id>[0-9]+)'
|
_VALID_URL = r'http://oe1\.orf\.at/(?:programm/|konsole.*?#\?track_id=)(?P<id>[0-9]+)'
|
||||||
|
|
||||||
|
# Audios on ORF radio are only available for 7 days, so we can't add tests.
|
||||||
|
_TEST = {
|
||||||
|
'url': 'http://oe1.orf.at/konsole?show=on_demand#?track_id=394211',
|
||||||
|
'only_matching': True,
|
||||||
|
}
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
show_id = self._match_id(url)
|
show_id = self._match_id(url)
|
||||||
@@ -160,7 +163,7 @@ class ORFOE1IE(InfoExtractor):
|
|||||||
|
|
||||||
|
|
||||||
class ORFFM4IE(InfoExtractor):
|
class ORFFM4IE(InfoExtractor):
|
||||||
IE_DESC = 'orf:fm4'
|
IE_NAME = 'orf:fm4'
|
||||||
IE_DESC = 'radio FM4'
|
IE_DESC = 'radio FM4'
|
||||||
_VALID_URL = r'http://fm4\.orf\.at/7tage/?#(?P<date>[0-9]+)/(?P<show>\w+)'
|
_VALID_URL = r'http://fm4\.orf\.at/7tage/?#(?P<date>[0-9]+)/(?P<show>\w+)'
|
||||||
|
|
||||||
|
|||||||
62
youtube_dl/extractor/rte.py
Normal file
62
youtube_dl/extractor/rte.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
|
||||||
|
from ..utils import (
|
||||||
|
float_or_none,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RteIE(InfoExtractor):
|
||||||
|
_VALID_URL = r'http?://(?:www\.)?rte\.ie/player/[^/]{2,3}/show/(?P<id>[0-9]+)/'
|
||||||
|
_TEST = {
|
||||||
|
'url': 'http://www.rte.ie/player/de/show/10363114/',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '10363114',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'One News',
|
||||||
|
'thumbnail': 're:^https?://.*\.jpg$',
|
||||||
|
'description': 'The One O\'Clock News followed by Weather.',
|
||||||
|
'duration': 436.844,
|
||||||
|
},
|
||||||
|
'params': {
|
||||||
|
'skip_download': 'f4m fails with --test atm'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
video_id = self._match_id(url)
|
||||||
|
webpage = self._download_webpage(url, video_id)
|
||||||
|
|
||||||
|
title = self._og_search_title(webpage)
|
||||||
|
description = self._html_search_meta('description', webpage, 'description')
|
||||||
|
duration = float_or_none(self._html_search_meta(
|
||||||
|
'duration', webpage, 'duration', fatal=False), 1000)
|
||||||
|
|
||||||
|
thumbnail_id = self._search_regex(
|
||||||
|
r'<meta name="thumbnail" content="uri:irus:(.*?)" />', webpage, 'thumbnail')
|
||||||
|
thumbnail = 'http://img.rasset.ie/' + thumbnail_id + '.jpg'
|
||||||
|
|
||||||
|
feeds_url = self._html_search_meta("feeds-prefix", webpage, 'feeds url') + video_id
|
||||||
|
json_string = self._download_json(feeds_url, video_id)
|
||||||
|
|
||||||
|
# f4m_url = server + relative_url
|
||||||
|
f4m_url = json_string['shows'][0]['media:group'][0]['rte:server'] + json_string['shows'][0]['media:group'][0]['url']
|
||||||
|
f4m_formats = self._extract_f4m_formats(f4m_url, video_id)
|
||||||
|
f4m_formats = [{
|
||||||
|
'format_id': f['format_id'],
|
||||||
|
'url': f['url'],
|
||||||
|
'ext': 'mp4',
|
||||||
|
'width': f['width'],
|
||||||
|
'height': f['height'],
|
||||||
|
} for f in f4m_formats]
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': video_id,
|
||||||
|
'title': title,
|
||||||
|
'formats': f4m_formats,
|
||||||
|
'description': description,
|
||||||
|
'thumbnail': thumbnail,
|
||||||
|
'duration': duration,
|
||||||
|
}
|
||||||
@@ -148,14 +148,6 @@ def parseOpts(overrideArguments=None):
|
|||||||
'--extractor-descriptions',
|
'--extractor-descriptions',
|
||||||
action='store_true', dest='list_extractor_descriptions', default=False,
|
action='store_true', dest='list_extractor_descriptions', default=False,
|
||||||
help='Output descriptions of all supported extractors')
|
help='Output descriptions of all supported extractors')
|
||||||
general.add_option(
|
|
||||||
'--proxy', dest='proxy',
|
|
||||||
default=None, metavar='URL',
|
|
||||||
help='Use the specified HTTP/HTTPS proxy. Pass in an empty string (--proxy "") for direct connection')
|
|
||||||
general.add_option(
|
|
||||||
'--socket-timeout',
|
|
||||||
dest='socket_timeout', type=float, default=None,
|
|
||||||
help='Time to wait before giving up, in seconds')
|
|
||||||
general.add_option(
|
general.add_option(
|
||||||
'--default-search',
|
'--default-search',
|
||||||
dest='default_search', metavar='PREFIX',
|
dest='default_search', metavar='PREFIX',
|
||||||
@@ -173,6 +165,31 @@ def parseOpts(overrideArguments=None):
|
|||||||
default=False,
|
default=False,
|
||||||
help='Do not extract the videos of a playlist, only list them.')
|
help='Do not extract the videos of a playlist, only list them.')
|
||||||
|
|
||||||
|
network = optparse.OptionGroup(parser, 'Network Options')
|
||||||
|
network.add_option(
|
||||||
|
'--proxy', dest='proxy',
|
||||||
|
default=None, metavar='URL',
|
||||||
|
help='Use the specified HTTP/HTTPS proxy. Pass in an empty string (--proxy "") for direct connection')
|
||||||
|
network.add_option(
|
||||||
|
'--socket-timeout',
|
||||||
|
dest='socket_timeout', type=float, default=None, metavar='SECONDS',
|
||||||
|
help='Time to wait before giving up, in seconds')
|
||||||
|
network.add_option(
|
||||||
|
'--source-address',
|
||||||
|
metavar='IP', dest='source_address', default=None,
|
||||||
|
help='Client-side IP address to bind to (experimental)',
|
||||||
|
)
|
||||||
|
network.add_option(
|
||||||
|
'-4', '--force-ipv4',
|
||||||
|
action='store_const', const='0.0.0.0', dest='source_address',
|
||||||
|
help='Make all connections via IPv4 (experimental)',
|
||||||
|
)
|
||||||
|
network.add_option(
|
||||||
|
'-6', '--force-ipv6',
|
||||||
|
action='store_const', const='::', dest='source_address',
|
||||||
|
help='Make all connections via IPv6 (experimental)',
|
||||||
|
)
|
||||||
|
|
||||||
selection = optparse.OptionGroup(parser, 'Video Selection')
|
selection = optparse.OptionGroup(parser, 'Video Selection')
|
||||||
selection.add_option(
|
selection.add_option(
|
||||||
'--playlist-start',
|
'--playlist-start',
|
||||||
@@ -488,6 +505,10 @@ def parseOpts(overrideArguments=None):
|
|||||||
'--print-traffic',
|
'--print-traffic',
|
||||||
dest='debug_printtraffic', action='store_true', default=False,
|
dest='debug_printtraffic', action='store_true', default=False,
|
||||||
help='Display sent and read HTTP traffic')
|
help='Display sent and read HTTP traffic')
|
||||||
|
verbosity.add_option(
|
||||||
|
'-C', '--call-home',
|
||||||
|
dest='call_home', action='store_true', default=False,
|
||||||
|
help='Contact the youtube-dl server for debugging. (Experimental)')
|
||||||
|
|
||||||
filesystem = optparse.OptionGroup(parser, 'Filesystem Options')
|
filesystem = optparse.OptionGroup(parser, 'Filesystem Options')
|
||||||
filesystem.add_option(
|
filesystem.add_option(
|
||||||
@@ -652,6 +673,7 @@ def parseOpts(overrideArguments=None):
|
|||||||
help='Execute a command on the file after downloading, similar to find\'s -exec syntax. Example: --exec \'adb push {} /sdcard/Music/ && rm {}\'')
|
help='Execute a command on the file after downloading, similar to find\'s -exec syntax. Example: --exec \'adb push {} /sdcard/Music/ && rm {}\'')
|
||||||
|
|
||||||
parser.add_option_group(general)
|
parser.add_option_group(general)
|
||||||
|
parser.add_option_group(network)
|
||||||
parser.add_option_group(selection)
|
parser.add_option_group(selection)
|
||||||
parser.add_option_group(downloader)
|
parser.add_option_group(downloader)
|
||||||
parser.add_option_group(filesystem)
|
parser.add_option_group(filesystem)
|
||||||
|
|||||||
@@ -82,12 +82,15 @@ class FFmpegPostProcessor(PostProcessor):
|
|||||||
def run_ffmpeg_multiple_files(self, input_paths, out_path, opts):
|
def run_ffmpeg_multiple_files(self, input_paths, out_path, opts):
|
||||||
self.check_version()
|
self.check_version()
|
||||||
|
|
||||||
|
oldest_mtime = min(
|
||||||
|
os.stat(encodeFilename(path)).st_mtime for path in input_paths)
|
||||||
|
|
||||||
files_cmd = []
|
files_cmd = []
|
||||||
for path in input_paths:
|
for path in input_paths:
|
||||||
files_cmd.extend([encodeArgument('-i'), encodeFilename(path, True)])
|
files_cmd.extend([encodeArgument('-i'), encodeFilename(path, True)])
|
||||||
cmd = ([encodeFilename(self._executable, True), encodeArgument('-y')] +
|
cmd = ([encodeFilename(self._executable, True), encodeArgument('-y')] +
|
||||||
files_cmd
|
files_cmd +
|
||||||
+ [encodeArgument(o) for o in 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):
|
||||||
@@ -98,6 +101,7 @@ class FFmpegPostProcessor(PostProcessor):
|
|||||||
stderr = stderr.decode('utf-8', 'replace')
|
stderr = stderr.decode('utf-8', 'replace')
|
||||||
msg = stderr.strip().split('\n')[-1]
|
msg = stderr.strip().split('\n')[-1]
|
||||||
raise FFmpegPostProcessorError(msg)
|
raise FFmpegPostProcessorError(msg)
|
||||||
|
os.utime(encodeFilename(out_path), (oldest_mtime, oldest_mtime))
|
||||||
if self._deletetempfiles:
|
if self._deletetempfiles:
|
||||||
for ipath in input_paths:
|
for ipath in input_paths:
|
||||||
os.remove(ipath)
|
os.remove(ipath)
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ def update_self(to_screen, verbose):
|
|||||||
to_screen('It looks like you installed youtube-dl with a package manager, pip, setup.py or a tarball. Please use that to update.')
|
to_screen('It looks like you installed youtube-dl with a package manager, pip, setup.py or a tarball. Please use that to update.')
|
||||||
return
|
return
|
||||||
|
|
||||||
https_handler = make_HTTPS_handler(False)
|
https_handler = make_HTTPS_handler({})
|
||||||
opener = compat_urllib_request.build_opener(https_handler)
|
opener = compat_urllib_request.build_opener(https_handler)
|
||||||
|
|
||||||
# Check if there is a new version
|
# Check if there is a new version
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import ctypes
|
|||||||
import datetime
|
import datetime
|
||||||
import email.utils
|
import email.utils
|
||||||
import errno
|
import errno
|
||||||
|
import functools
|
||||||
import gzip
|
import gzip
|
||||||
import itertools
|
import itertools
|
||||||
import io
|
import io
|
||||||
@@ -34,7 +35,9 @@ from .compat import (
|
|||||||
compat_chr,
|
compat_chr,
|
||||||
compat_getenv,
|
compat_getenv,
|
||||||
compat_html_entities,
|
compat_html_entities,
|
||||||
|
compat_http_client,
|
||||||
compat_parse_qs,
|
compat_parse_qs,
|
||||||
|
compat_socket_create_connection,
|
||||||
compat_str,
|
compat_str,
|
||||||
compat_urllib_error,
|
compat_urllib_error,
|
||||||
compat_urllib_parse,
|
compat_urllib_parse,
|
||||||
@@ -391,13 +394,14 @@ def formatSeconds(secs):
|
|||||||
return '%d' % secs
|
return '%d' % secs
|
||||||
|
|
||||||
|
|
||||||
def make_HTTPS_handler(opts_no_check_certificate, **kwargs):
|
def make_HTTPS_handler(params, **kwargs):
|
||||||
|
opts_no_check_certificate = params.get('nocheckcertificate', False)
|
||||||
if hasattr(ssl, 'create_default_context'): # Python >= 3.4 or 2.7.9
|
if hasattr(ssl, 'create_default_context'): # Python >= 3.4 or 2.7.9
|
||||||
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||||
if opts_no_check_certificate:
|
if opts_no_check_certificate:
|
||||||
context.verify_mode = ssl.CERT_NONE
|
context.verify_mode = ssl.CERT_NONE
|
||||||
try:
|
try:
|
||||||
return compat_urllib_request.HTTPSHandler(context=context, **kwargs)
|
return YoutubeDLHTTPSHandler(params, context=context, **kwargs)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Python 2.7.8
|
# Python 2.7.8
|
||||||
# (create_default_context present but HTTPSHandler has no context=)
|
# (create_default_context present but HTTPSHandler has no context=)
|
||||||
@@ -420,17 +424,14 @@ def make_HTTPS_handler(opts_no_check_certificate, **kwargs):
|
|||||||
except ssl.SSLError:
|
except ssl.SSLError:
|
||||||
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv23)
|
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv23)
|
||||||
|
|
||||||
class HTTPSHandlerV3(compat_urllib_request.HTTPSHandler):
|
return YoutubeDLHTTPSHandler(params, https_conn_class=HTTPSConnectionV3, **kwargs)
|
||||||
def https_open(self, req):
|
|
||||||
return self.do_open(HTTPSConnectionV3, req)
|
|
||||||
return HTTPSHandlerV3(**kwargs)
|
|
||||||
else: # Python < 3.4
|
else: # Python < 3.4
|
||||||
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
||||||
context.verify_mode = (ssl.CERT_NONE
|
context.verify_mode = (ssl.CERT_NONE
|
||||||
if opts_no_check_certificate
|
if opts_no_check_certificate
|
||||||
else ssl.CERT_REQUIRED)
|
else ssl.CERT_REQUIRED)
|
||||||
context.set_default_verify_paths()
|
context.set_default_verify_paths()
|
||||||
return compat_urllib_request.HTTPSHandler(context=context, **kwargs)
|
return YoutubeDLHTTPSHandler(params, context=context, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class ExtractorError(Exception):
|
class ExtractorError(Exception):
|
||||||
@@ -544,6 +545,26 @@ class ContentTooShortError(Exception):
|
|||||||
self.expected = expected
|
self.expected = expected
|
||||||
|
|
||||||
|
|
||||||
|
def _create_http_connection(ydl_handler, http_class, is_https, *args, **kwargs):
|
||||||
|
hc = http_class(*args, **kwargs)
|
||||||
|
source_address = ydl_handler._params.get('source_address')
|
||||||
|
if source_address is not None:
|
||||||
|
sa = (source_address, 0)
|
||||||
|
if hasattr(hc, 'source_address'): # Python 2.7+
|
||||||
|
hc.source_address = sa
|
||||||
|
else: # Python 2.6
|
||||||
|
def _hc_connect(self, *args, **kwargs):
|
||||||
|
sock = compat_socket_create_connection(
|
||||||
|
(self.host, self.port), self.timeout, sa)
|
||||||
|
if is_https:
|
||||||
|
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
|
||||||
|
else:
|
||||||
|
self.sock = sock
|
||||||
|
hc.connect = functools.partial(_hc_connect, hc)
|
||||||
|
|
||||||
|
return hc
|
||||||
|
|
||||||
|
|
||||||
class YoutubeDLHandler(compat_urllib_request.HTTPHandler):
|
class YoutubeDLHandler(compat_urllib_request.HTTPHandler):
|
||||||
"""Handler for HTTP requests and responses.
|
"""Handler for HTTP requests and responses.
|
||||||
|
|
||||||
@@ -562,6 +583,15 @@ class YoutubeDLHandler(compat_urllib_request.HTTPHandler):
|
|||||||
public domain.
|
public domain.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def __init__(self, params, *args, **kwargs):
|
||||||
|
compat_urllib_request.HTTPHandler.__init__(self, *args, **kwargs)
|
||||||
|
self._params = params
|
||||||
|
|
||||||
|
def http_open(self, req):
|
||||||
|
return self.do_open(functools.partial(
|
||||||
|
_create_http_connection, self, compat_http_client.HTTPConnection, False),
|
||||||
|
req)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def deflate(data):
|
def deflate(data):
|
||||||
try:
|
try:
|
||||||
@@ -631,6 +661,18 @@ class YoutubeDLHandler(compat_urllib_request.HTTPHandler):
|
|||||||
https_response = http_response
|
https_response = http_response
|
||||||
|
|
||||||
|
|
||||||
|
class YoutubeDLHTTPSHandler(compat_urllib_request.HTTPSHandler):
|
||||||
|
def __init__(self, params, https_conn_class=None, *args, **kwargs):
|
||||||
|
compat_urllib_request.HTTPSHandler.__init__(self, *args, **kwargs)
|
||||||
|
self._https_conn_class = https_conn_class or compat_http_client.HTTPSConnection
|
||||||
|
self._params = params
|
||||||
|
|
||||||
|
def https_open(self, req):
|
||||||
|
return self.do_open(functools.partial(
|
||||||
|
_create_http_connection, self, self._https_conn_class, True),
|
||||||
|
req)
|
||||||
|
|
||||||
|
|
||||||
def parse_iso8601(date_str, delimiter='T'):
|
def parse_iso8601(date_str, delimiter='T'):
|
||||||
""" Return a UNIX timestamp from the given date """
|
""" Return a UNIX timestamp from the given date """
|
||||||
|
|
||||||
@@ -679,9 +721,6 @@ def unified_strdate(date_str, day_first=True):
|
|||||||
'%b %dth %Y %I:%M%p',
|
'%b %dth %Y %I:%M%p',
|
||||||
'%Y-%m-%d',
|
'%Y-%m-%d',
|
||||||
'%Y/%m/%d',
|
'%Y/%m/%d',
|
||||||
'%d.%m.%Y',
|
|
||||||
'%d/%m/%Y',
|
|
||||||
'%d/%m/%y',
|
|
||||||
'%Y/%m/%d %H:%M:%S',
|
'%Y/%m/%d %H:%M:%S',
|
||||||
'%Y-%m-%d %H:%M:%S',
|
'%Y-%m-%d %H:%M:%S',
|
||||||
'%Y-%m-%d %H:%M:%S.%f',
|
'%Y-%m-%d %H:%M:%S.%f',
|
||||||
@@ -696,10 +735,16 @@ def unified_strdate(date_str, day_first=True):
|
|||||||
]
|
]
|
||||||
if day_first:
|
if day_first:
|
||||||
format_expressions.extend([
|
format_expressions.extend([
|
||||||
|
'%d.%m.%Y',
|
||||||
|
'%d/%m/%Y',
|
||||||
|
'%d/%m/%y',
|
||||||
'%d/%m/%Y %H:%M:%S',
|
'%d/%m/%Y %H:%M:%S',
|
||||||
])
|
])
|
||||||
else:
|
else:
|
||||||
format_expressions.extend([
|
format_expressions.extend([
|
||||||
|
'%m.%d.%Y',
|
||||||
|
'%m/%d/%Y',
|
||||||
|
'%m/%d/%y',
|
||||||
'%m/%d/%Y %H:%M:%S',
|
'%m/%d/%Y %H:%M:%S',
|
||||||
])
|
])
|
||||||
for expression in format_expressions:
|
for expression in format_expressions:
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
__version__ = '2015.01.10'
|
__version__ = '2015.01.10.2'
|
||||||
|
|||||||
Reference in New Issue
Block a user