Compare commits
32 Commits
2015.02.20
...
2015.02.23
Author | SHA1 | Date | |
---|---|---|---|
bd61a9e770 | |||
3438e7acd2 | |||
09c200acf2 | |||
716889cab1 | |||
409693984f | |||
04e8c11080 | |||
80af2b73ab | |||
3cc57f9645 | |||
a65d4e7f14 | |||
543ec2136b | |||
93b5071f73 | |||
ddc369f073 | |||
fcc3e6138b | |||
9fe6ef7ab2 | |||
c010af6f19 | |||
35b7982303 | |||
f311cfa231 | |||
e086e0eb6c | |||
314368c822 | |||
c5181ab410 | |||
ea5152cae1 | |||
255fca5eea | |||
4aeccadf4e | |||
93540ee10e | |||
8fb3ac3649 | |||
77b2986b5b | |||
62b013df0d | |||
fad6768bd1 | |||
a78125f925 | |||
a00a8bcc8a | |||
365577f567 | |||
5da6bd0083 |
1
AUTHORS
1
AUTHORS
@ -111,3 +111,4 @@ Paul Hartmann
|
|||||||
Frans de Jonge
|
Frans de Jonge
|
||||||
Robin de Rooij
|
Robin de Rooij
|
||||||
Ryan Schmidt
|
Ryan Schmidt
|
||||||
|
Leslie P. Polzer
|
||||||
|
@ -571,7 +571,7 @@ Support requests for services that **do** purchase the rights to distribute thei
|
|||||||
|
|
||||||
### How can I detect whether a given URL is supported by youtube-dl?
|
### How can I detect whether a given URL is supported by youtube-dl?
|
||||||
|
|
||||||
For one, have a look at the [list of supported sites](docs/supportedsites.md). Note that it can sometimes happen that the site changes its URL scheme (say, from http://example.com/v/1234567 to http://example.com/v/1234567 ) and youtube-dl reports an URL of a service in that list as unsupported. In that case, simply report a bug.
|
For one, have a look at the [list of supported sites](docs/supportedsites.md). Note that it can sometimes happen that the site changes its URL scheme (say, from http://example.com/video/1234567 to http://example.com/v/1234567 ) and youtube-dl reports an URL of a service in that list as unsupported. In that case, simply report a bug.
|
||||||
|
|
||||||
It is *not* possible to detect whether a URL is supported or not. That's because youtube-dl contains a generic extractor which matches **all** URLs. You may be tempted to disable, exclude, or remove the generic extractor, but the generic extractor not only allows users to extract videos from lots of websites that embed a video from another service, but may also be used to extract video from a service that it's hosting itself. Therefore, we neither recommend nor support disabling, excluding, or removing the generic extractor.
|
It is *not* possible to detect whether a URL is supported or not. That's because youtube-dl contains a generic extractor which matches **all** URLs. You may be tempted to disable, exclude, or remove the generic extractor, but the generic extractor not only allows users to extract videos from lots of websites that embed a video from another service, but may also be used to extract video from a service that it's hosting itself. Therefore, we neither recommend nor support disabling, excluding, or removing the generic extractor.
|
||||||
|
|
||||||
|
@ -45,12 +45,12 @@ for test in get_testcases():
|
|||||||
|
|
||||||
RESULT = ('.' + domain + '\n' in LIST or '\n' + domain + '\n' in LIST)
|
RESULT = ('.' + domain + '\n' in LIST or '\n' + domain + '\n' in LIST)
|
||||||
|
|
||||||
if RESULT and ('info_dict' not in test or 'age_limit' not in test['info_dict']
|
if RESULT and ('info_dict' not in test or 'age_limit' not in test['info_dict'] or
|
||||||
or test['info_dict']['age_limit'] != 18):
|
test['info_dict']['age_limit'] != 18):
|
||||||
print('\nPotential missing age_limit check: {0}'.format(test['name']))
|
print('\nPotential missing age_limit check: {0}'.format(test['name']))
|
||||||
|
|
||||||
elif not RESULT and ('info_dict' in test and 'age_limit' in test['info_dict']
|
elif not RESULT and ('info_dict' in test and 'age_limit' in test['info_dict'] and
|
||||||
and test['info_dict']['age_limit'] == 18):
|
test['info_dict']['age_limit'] == 18):
|
||||||
print('\nPotential false negative: {0}'.format(test['name']))
|
print('\nPotential false negative: {0}'.format(test['name']))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -72,6 +72,8 @@
|
|||||||
- **CeskaTelevize**
|
- **CeskaTelevize**
|
||||||
- **channel9**: Channel 9
|
- **channel9**: Channel 9
|
||||||
- **Chilloutzone**
|
- **Chilloutzone**
|
||||||
|
- **chirbit**
|
||||||
|
- **chirbit:profile**
|
||||||
- **Cinchcast**
|
- **Cinchcast**
|
||||||
- **Cinemassacre**
|
- **Cinemassacre**
|
||||||
- **clipfish**
|
- **clipfish**
|
||||||
@ -330,6 +332,7 @@
|
|||||||
- **prosiebensat1**: ProSiebenSat.1 Digital
|
- **prosiebensat1**: ProSiebenSat.1 Digital
|
||||||
- **Pyvideo**
|
- **Pyvideo**
|
||||||
- **QuickVid**
|
- **QuickVid**
|
||||||
|
- **R7**
|
||||||
- **radio.de**
|
- **radio.de**
|
||||||
- **radiobremen**
|
- **radiobremen**
|
||||||
- **radiofrance**
|
- **radiofrance**
|
||||||
@ -385,7 +388,8 @@
|
|||||||
- **soundcloud:playlist**
|
- **soundcloud:playlist**
|
||||||
- **soundcloud:set**
|
- **soundcloud:set**
|
||||||
- **soundcloud:user**
|
- **soundcloud:user**
|
||||||
- **Soundgasm**
|
- **soundgasm**
|
||||||
|
- **soundgasm:profile**
|
||||||
- **southpark.cc.com**
|
- **southpark.cc.com**
|
||||||
- **southpark.de**
|
- **southpark.de**
|
||||||
- **Space**
|
- **Space**
|
||||||
@ -559,6 +563,7 @@
|
|||||||
- **youtube:subscriptions**: YouTube.com subscriptions feed, "ytsubs" keyword (requires authentication)
|
- **youtube:subscriptions**: YouTube.com subscriptions feed, "ytsubs" keyword (requires authentication)
|
||||||
- **youtube:user**: YouTube.com user videos (URL or "ytuser" keyword)
|
- **youtube:user**: YouTube.com user videos (URL or "ytuser" keyword)
|
||||||
- **youtube:watch_later**: Youtube watch later list, ":ytwatchlater" for short (requires authentication)
|
- **youtube:watch_later**: Youtube watch later list, ":ytwatchlater" for short (requires authentication)
|
||||||
|
- **Zapiks**
|
||||||
- **ZDF**
|
- **ZDF**
|
||||||
- **ZDFChannel**
|
- **ZDFChannel**
|
||||||
- **zingmp3:album**: mp3.zing.vn albums
|
- **zingmp3:album**: mp3.zing.vn albums
|
||||||
|
@ -34,8 +34,8 @@ def _make_testfunc(testfile):
|
|||||||
def test_func(self):
|
def test_func(self):
|
||||||
as_file = os.path.join(TEST_DIR, testfile)
|
as_file = os.path.join(TEST_DIR, testfile)
|
||||||
swf_file = os.path.join(TEST_DIR, test_id + '.swf')
|
swf_file = os.path.join(TEST_DIR, test_id + '.swf')
|
||||||
if ((not os.path.exists(swf_file))
|
if ((not os.path.exists(swf_file)) or
|
||||||
or os.path.getmtime(swf_file) < os.path.getmtime(as_file)):
|
os.path.getmtime(swf_file) < os.path.getmtime(as_file)):
|
||||||
# Recompile
|
# Recompile
|
||||||
try:
|
try:
|
||||||
subprocess.check_call([
|
subprocess.check_call([
|
||||||
|
@ -308,8 +308,8 @@ class YoutubeDL(object):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
if (sys.version_info >= (3,) and sys.platform != 'win32' and
|
if (sys.version_info >= (3,) and sys.platform != 'win32' and
|
||||||
sys.getfilesystemencoding() in ['ascii', 'ANSI_X3.4-1968']
|
sys.getfilesystemencoding() in ['ascii', 'ANSI_X3.4-1968'] and
|
||||||
and not params.get('restrictfilenames', False)):
|
not params.get('restrictfilenames', False)):
|
||||||
# On Python 3, the Unicode filesystem API will throw errors (#1474)
|
# On Python 3, the Unicode filesystem API will throw errors (#1474)
|
||||||
self.report_warning(
|
self.report_warning(
|
||||||
'Assuming --restrict-filenames since file system encoding '
|
'Assuming --restrict-filenames since file system encoding '
|
||||||
@ -1366,8 +1366,8 @@ class YoutubeDL(object):
|
|||||||
"""Download a given list of URLs."""
|
"""Download a given list of URLs."""
|
||||||
outtmpl = self.params.get('outtmpl', DEFAULT_OUTTMPL)
|
outtmpl = self.params.get('outtmpl', DEFAULT_OUTTMPL)
|
||||||
if (len(url_list) > 1 and
|
if (len(url_list) > 1 and
|
||||||
'%' not in outtmpl
|
'%' not in outtmpl and
|
||||||
and self.params.get('max_downloads') != 1):
|
self.params.get('max_downloads') != 1):
|
||||||
raise SameFileError(outtmpl)
|
raise SameFileError(outtmpl)
|
||||||
|
|
||||||
for url in url_list:
|
for url in url_list:
|
||||||
|
@ -189,14 +189,14 @@ def _real_main(argv=None):
|
|||||||
# In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
|
# In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
|
||||||
if opts.outtmpl is not None:
|
if opts.outtmpl is not None:
|
||||||
opts.outtmpl = opts.outtmpl.decode(preferredencoding())
|
opts.outtmpl = opts.outtmpl.decode(preferredencoding())
|
||||||
outtmpl = ((opts.outtmpl is not None and opts.outtmpl)
|
outtmpl = ((opts.outtmpl is not None and opts.outtmpl) or
|
||||||
or (opts.format == '-1' and opts.usetitle and '%(title)s-%(id)s-%(format)s.%(ext)s')
|
(opts.format == '-1' and opts.usetitle and '%(title)s-%(id)s-%(format)s.%(ext)s') or
|
||||||
or (opts.format == '-1' and '%(id)s-%(format)s.%(ext)s')
|
(opts.format == '-1' and '%(id)s-%(format)s.%(ext)s') or
|
||||||
or (opts.usetitle and opts.autonumber and '%(autonumber)s-%(title)s-%(id)s.%(ext)s')
|
(opts.usetitle and opts.autonumber and '%(autonumber)s-%(title)s-%(id)s.%(ext)s') or
|
||||||
or (opts.usetitle and '%(title)s-%(id)s.%(ext)s')
|
(opts.usetitle and '%(title)s-%(id)s.%(ext)s') or
|
||||||
or (opts.useid and '%(id)s.%(ext)s')
|
(opts.useid and '%(id)s.%(ext)s') or
|
||||||
or (opts.autonumber and '%(autonumber)s-%(id)s.%(ext)s')
|
(opts.autonumber and '%(autonumber)s-%(id)s.%(ext)s') or
|
||||||
or DEFAULT_OUTTMPL)
|
DEFAULT_OUTTMPL)
|
||||||
if not os.path.splitext(outtmpl)[1] and opts.extractaudio:
|
if not os.path.splitext(outtmpl)[1] and opts.extractaudio:
|
||||||
parser.error('Cannot download a video and extract audio into the same'
|
parser.error('Cannot download a video and extract audio into the same'
|
||||||
' file! Use "{0}.%(ext)s" instead of "{0}" as the output'
|
' file! Use "{0}.%(ext)s" instead of "{0}" as the output'
|
||||||
|
@ -311,14 +311,14 @@ class FileDownloader(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nooverwrites_and_exists = (
|
nooverwrites_and_exists = (
|
||||||
self.params.get('nooverwrites', False)
|
self.params.get('nooverwrites', False) and
|
||||||
and os.path.exists(encodeFilename(filename))
|
os.path.exists(encodeFilename(filename))
|
||||||
)
|
)
|
||||||
|
|
||||||
continuedl_and_exists = (
|
continuedl_and_exists = (
|
||||||
self.params.get('continuedl', False)
|
self.params.get('continuedl', False) and
|
||||||
and os.path.isfile(encodeFilename(filename))
|
os.path.isfile(encodeFilename(filename)) and
|
||||||
and not self.params.get('nopart', False)
|
not self.params.get('nopart', False)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check file already present
|
# Check file already present
|
||||||
|
@ -325,8 +325,8 @@ class F4mFD(FileDownloader):
|
|||||||
state['frag_index'] += 1
|
state['frag_index'] += 1
|
||||||
|
|
||||||
estimated_size = (
|
estimated_size = (
|
||||||
(state['downloaded_bytes'] + frag_total_bytes)
|
(state['downloaded_bytes'] + frag_total_bytes) /
|
||||||
/ (state['frag_index'] + 1) * total_frags)
|
(state['frag_index'] + 1) * total_frags)
|
||||||
time_now = time.time()
|
time_now = time.time()
|
||||||
state['total_bytes_estimate'] = estimated_size
|
state['total_bytes_estimate'] = estimated_size
|
||||||
state['elapsed'] = time_now - start
|
state['elapsed'] = time_now - start
|
||||||
|
@ -63,6 +63,10 @@ from .ccc import CCCIE
|
|||||||
from .ceskatelevize import CeskaTelevizeIE
|
from .ceskatelevize import CeskaTelevizeIE
|
||||||
from .channel9 import Channel9IE
|
from .channel9 import Channel9IE
|
||||||
from .chilloutzone import ChilloutzoneIE
|
from .chilloutzone import ChilloutzoneIE
|
||||||
|
from .chirbit import (
|
||||||
|
ChirbitIE,
|
||||||
|
ChirbitProfileIE,
|
||||||
|
)
|
||||||
from .cinchcast import CinchcastIE
|
from .cinchcast import CinchcastIE
|
||||||
from .clipfish import ClipfishIE
|
from .clipfish import ClipfishIE
|
||||||
from .cliphunter import CliphunterIE
|
from .cliphunter import CliphunterIE
|
||||||
@ -364,6 +368,7 @@ from .promptfile import PromptFileIE
|
|||||||
from .prosiebensat1 import ProSiebenSat1IE
|
from .prosiebensat1 import ProSiebenSat1IE
|
||||||
from .pyvideo import PyvideoIE
|
from .pyvideo import PyvideoIE
|
||||||
from .quickvid import QuickVidIE
|
from .quickvid import QuickVidIE
|
||||||
|
from .r7 import R7IE
|
||||||
from .radiode import RadioDeIE
|
from .radiode import RadioDeIE
|
||||||
from .radiobremen import RadioBremenIE
|
from .radiobremen import RadioBremenIE
|
||||||
from .radiofrance import RadioFranceIE
|
from .radiofrance import RadioFranceIE
|
||||||
@ -424,7 +429,10 @@ from .soundcloud import (
|
|||||||
SoundcloudUserIE,
|
SoundcloudUserIE,
|
||||||
SoundcloudPlaylistIE
|
SoundcloudPlaylistIE
|
||||||
)
|
)
|
||||||
from .soundgasm import SoundgasmIE
|
from .soundgasm import (
|
||||||
|
SoundgasmIE,
|
||||||
|
SoundgasmProfileIE
|
||||||
|
)
|
||||||
from .southpark import (
|
from .southpark import (
|
||||||
SouthParkIE,
|
SouthParkIE,
|
||||||
SouthparkDeIE,
|
SouthparkDeIE,
|
||||||
@ -612,6 +620,7 @@ from .youtube import (
|
|||||||
YoutubeUserIE,
|
YoutubeUserIE,
|
||||||
YoutubeWatchLaterIE,
|
YoutubeWatchLaterIE,
|
||||||
)
|
)
|
||||||
|
from .zapiks import ZapiksIE
|
||||||
from .zdf import ZDFIE, ZDFChannelIE
|
from .zdf import ZDFIE, ZDFChannelIE
|
||||||
from .zingmp3 import (
|
from .zingmp3 import (
|
||||||
ZingMp3SongIE,
|
ZingMp3SongIE,
|
||||||
|
@ -28,7 +28,6 @@ class AdobeTVIE(InfoExtractor):
|
|||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
video_id = self._match_id(url)
|
video_id = self._match_id(url)
|
||||||
|
|
||||||
webpage = self._download_webpage(url, video_id)
|
webpage = self._download_webpage(url, video_id)
|
||||||
|
|
||||||
player = self._parse_json(
|
player = self._parse_json(
|
||||||
@ -44,8 +43,10 @@ class AdobeTVIE(InfoExtractor):
|
|||||||
self._html_search_meta('datepublished', webpage, 'upload date'))
|
self._html_search_meta('datepublished', webpage, 'upload date'))
|
||||||
|
|
||||||
duration = parse_duration(
|
duration = parse_duration(
|
||||||
self._html_search_meta('duration', webpage, 'duration')
|
self._html_search_meta('duration', webpage, 'duration') or
|
||||||
or self._search_regex(r'Runtime:\s*(\d{2}:\d{2}:\d{2})', webpage, 'duration'))
|
self._search_regex(
|
||||||
|
r'Runtime:\s*(\d{2}:\d{2}:\d{2})',
|
||||||
|
webpage, 'duration', fatal=False))
|
||||||
|
|
||||||
view_count = str_to_int(self._search_regex(
|
view_count = str_to_int(self._search_regex(
|
||||||
r'<div class="views">\s*Views?:\s*([\d,.]+)\s*</div>',
|
r'<div class="views">\s*Views?:\s*([\d,.]+)\s*</div>',
|
||||||
|
@ -11,8 +11,8 @@ from ..utils import (
|
|||||||
|
|
||||||
|
|
||||||
class AppleTrailersIE(InfoExtractor):
|
class AppleTrailersIE(InfoExtractor):
|
||||||
_VALID_URL = r'https?://(?:www\.)?trailers\.apple\.com/trailers/(?P<company>[^/]+)/(?P<movie>[^/]+)'
|
_VALID_URL = r'https?://(?:www\.)?trailers\.apple\.com/(?:trailers|ca)/(?P<company>[^/]+)/(?P<movie>[^/]+)'
|
||||||
_TEST = {
|
_TESTS = [{
|
||||||
"url": "http://trailers.apple.com/trailers/wb/manofsteel/",
|
"url": "http://trailers.apple.com/trailers/wb/manofsteel/",
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'manofsteel',
|
'id': 'manofsteel',
|
||||||
@ -63,7 +63,10 @@ class AppleTrailersIE(InfoExtractor):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}, {
|
||||||
|
'url': 'http://trailers.apple.com/ca/metropole/autrui/',
|
||||||
|
'only_matching': True,
|
||||||
|
}]
|
||||||
|
|
||||||
_JSON_RE = r'iTunes.playURL\((.*?)\);'
|
_JSON_RE = r'iTunes.playURL\((.*?)\);'
|
||||||
|
|
||||||
|
84
youtube_dl/extractor/chirbit.py
Normal file
84
youtube_dl/extractor/chirbit.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from ..utils import (
|
||||||
|
parse_duration,
|
||||||
|
int_or_none,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ChirbitIE(InfoExtractor):
|
||||||
|
IE_NAME = 'chirbit'
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?chirb\.it/(?:(?:wp|pl)/|fb_chirbit_player\.swf\?key=)?(?P<id>[\da-zA-Z]+)'
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'http://chirb.it/PrIPv5',
|
||||||
|
'md5': '9847b0dad6ac3e074568bf2cfb197de8',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'PrIPv5',
|
||||||
|
'ext': 'mp3',
|
||||||
|
'title': 'Фасадстрой',
|
||||||
|
'duration': 52,
|
||||||
|
'view_count': int,
|
||||||
|
'comment_count': int,
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
'url': 'https://chirb.it/fb_chirbit_player.swf?key=PrIPv5',
|
||||||
|
'only_matching': True,
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
audio_id = self._match_id(url)
|
||||||
|
|
||||||
|
webpage = self._download_webpage(
|
||||||
|
'http://chirb.it/%s' % audio_id, audio_id)
|
||||||
|
|
||||||
|
audio_url = self._search_regex(
|
||||||
|
r'"setFile"\s*,\s*"([^"]+)"', webpage, 'audio url')
|
||||||
|
|
||||||
|
title = self._search_regex(
|
||||||
|
r'itemprop="name">([^<]+)', webpage, 'title')
|
||||||
|
duration = parse_duration(self._html_search_meta(
|
||||||
|
'duration', webpage, 'duration', fatal=False))
|
||||||
|
view_count = int_or_none(self._search_regex(
|
||||||
|
r'itemprop="playCount"\s*>(\d+)', webpage,
|
||||||
|
'listen count', fatal=False))
|
||||||
|
comment_count = int_or_none(self._search_regex(
|
||||||
|
r'>(\d+) Comments?:', webpage,
|
||||||
|
'comment count', fatal=False))
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': audio_id,
|
||||||
|
'url': audio_url,
|
||||||
|
'title': title,
|
||||||
|
'duration': duration,
|
||||||
|
'view_count': view_count,
|
||||||
|
'comment_count': comment_count,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ChirbitProfileIE(InfoExtractor):
|
||||||
|
IE_NAME = 'chirbit:profile'
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?chirbit.com/(?:rss/)?(?P<id>[^/]+)'
|
||||||
|
_TEST = {
|
||||||
|
'url': 'http://chirbit.com/ScarletBeauty',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'ScarletBeauty',
|
||||||
|
'title': 'Chirbits by ScarletBeauty',
|
||||||
|
},
|
||||||
|
'playlist_mincount': 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
profile_id = self._match_id(url)
|
||||||
|
|
||||||
|
rss = self._download_xml(
|
||||||
|
'http://chirbit.com/rss/%s' % profile_id, profile_id)
|
||||||
|
|
||||||
|
entries = [
|
||||||
|
self.url_result(audio_url.text, 'Chirbit')
|
||||||
|
for audio_url in rss.findall('./channel/item/link')]
|
||||||
|
|
||||||
|
title = rss.find('./channel/title').text
|
||||||
|
|
||||||
|
return self.playlist_result(entries, profile_id, title)
|
@ -391,6 +391,16 @@ class InfoExtractor(object):
|
|||||||
if blocked_iframe:
|
if blocked_iframe:
|
||||||
msg += ' Visit %s for more details' % blocked_iframe
|
msg += ' Visit %s for more details' % blocked_iframe
|
||||||
raise ExtractorError(msg, expected=True)
|
raise ExtractorError(msg, expected=True)
|
||||||
|
if '<title>The URL you requested has been blocked</title>' in content[:512]:
|
||||||
|
msg = (
|
||||||
|
'Access to this webpage has been blocked by Indian censorship. '
|
||||||
|
'Use a VPN or proxy server (with --proxy) to route around it.')
|
||||||
|
block_msg = self._html_search_regex(
|
||||||
|
r'</h1><p>(.*?)</p>',
|
||||||
|
content, 'block message', default=None)
|
||||||
|
if block_msg:
|
||||||
|
msg += ' (Message: "%s")' % block_msg.replace('\n', ' ')
|
||||||
|
raise ExtractorError(msg, expected=True)
|
||||||
|
|
||||||
return content
|
return content
|
||||||
|
|
||||||
@ -798,8 +808,8 @@ class InfoExtractor(object):
|
|||||||
media_nodes = manifest.findall('{http://ns.adobe.com/f4m/2.0}media')
|
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':
|
if manifest_version == '2.0':
|
||||||
manifest_url = ('/'.join(manifest_url.split('/')[:-1]) + '/'
|
manifest_url = ('/'.join(manifest_url.split('/')[:-1]) + '/' +
|
||||||
+ (media_el.attrib.get('href') or media_el.attrib.get('url')))
|
(media_el.attrib.get('href') or media_el.attrib.get('url')))
|
||||||
tbr = int_or_none(media_el.attrib.get('bitrate'))
|
tbr = int_or_none(media_el.attrib.get('bitrate'))
|
||||||
formats.append({
|
formats.append({
|
||||||
'format_id': '-'.join(filter(None, [f4m_id, 'f4m-%d' % (i if tbr is None else tbr)])),
|
'format_id': '-'.join(filter(None, [f4m_id, 'f4m-%d' % (i if tbr is None else tbr)])),
|
||||||
@ -823,7 +833,7 @@ class InfoExtractor(object):
|
|||||||
'url': m3u8_url,
|
'url': m3u8_url,
|
||||||
'ext': ext,
|
'ext': ext,
|
||||||
'protocol': 'm3u8',
|
'protocol': 'm3u8',
|
||||||
'preference': -1,
|
'preference': preference - 1 if preference else -1,
|
||||||
'resolution': 'multiple',
|
'resolution': 'multiple',
|
||||||
'format_note': 'Quality selection URL',
|
'format_note': 'Quality selection URL',
|
||||||
}]
|
}]
|
||||||
|
@ -25,8 +25,9 @@ class DefenseGouvFrIE(InfoExtractor):
|
|||||||
r"flashvars.pvg_id=\"(\d+)\";",
|
r"flashvars.pvg_id=\"(\d+)\";",
|
||||||
webpage, 'ID')
|
webpage, 'ID')
|
||||||
|
|
||||||
json_url = ('http://static.videos.gouv.fr/brightcovehub/export/json/'
|
json_url = (
|
||||||
+ video_id)
|
'http://static.videos.gouv.fr/brightcovehub/export/json/%s' %
|
||||||
|
video_id)
|
||||||
info = self._download_json(json_url, title, 'Downloading JSON config')
|
info = self._download_json(json_url, title, 'Downloading JSON config')
|
||||||
video_url = info['renditions'][0]['url']
|
video_url = info['renditions'][0]['url']
|
||||||
|
|
||||||
|
@ -31,10 +31,10 @@ class EscapistIE(InfoExtractor):
|
|||||||
webpage = self._download_webpage(url, video_id)
|
webpage = self._download_webpage(url, video_id)
|
||||||
|
|
||||||
uploader_id = self._html_search_regex(
|
uploader_id = self._html_search_regex(
|
||||||
r"<h1 class='headline'><a href='/videos/view/(.*?)'",
|
r"<h1\s+class='headline'>\s*<a\s+href='/videos/view/(.*?)'",
|
||||||
webpage, 'uploader ID', fatal=False)
|
webpage, 'uploader ID', fatal=False)
|
||||||
uploader = self._html_search_regex(
|
uploader = self._html_search_regex(
|
||||||
r"<h1 class='headline'>(.*?)</a>",
|
r"<h1\s+class='headline'>(.*?)</a>",
|
||||||
webpage, 'uploader', fatal=False)
|
webpage, 'uploader', fatal=False)
|
||||||
description = self._html_search_meta('description', webpage)
|
description = self._html_search_meta('description', webpage)
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ class EscapistIE(InfoExtractor):
|
|||||||
title = raw_title.partition(' : ')[2]
|
title = raw_title.partition(' : ')[2]
|
||||||
|
|
||||||
config_url = compat_urllib_parse.unquote(self._html_search_regex(
|
config_url = compat_urllib_parse.unquote(self._html_search_regex(
|
||||||
r'<param name="flashvars" value="config=([^"&]+)', webpage, 'config URL'))
|
r'<param\s+name="flashvars"\s+value="config=([^"&]+)', webpage, 'config URL'))
|
||||||
|
|
||||||
formats = []
|
formats = []
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ from ..compat import (
|
|||||||
compat_urllib_parse,
|
compat_urllib_parse,
|
||||||
compat_urllib_request,
|
compat_urllib_request,
|
||||||
)
|
)
|
||||||
|
from ..utils import remove_end
|
||||||
|
|
||||||
|
|
||||||
class GDCVaultIE(InfoExtractor):
|
class GDCVaultIE(InfoExtractor):
|
||||||
@ -68,7 +69,9 @@ class GDCVaultIE(InfoExtractor):
|
|||||||
akami_url = xml_description.find('./metadata/akamaiHost').text
|
akami_url = xml_description.find('./metadata/akamaiHost').text
|
||||||
slide_video_path = xml_description.find('./metadata/slideVideo').text
|
slide_video_path = xml_description.find('./metadata/slideVideo').text
|
||||||
video_formats.append({
|
video_formats.append({
|
||||||
'url': 'rtmp://' + akami_url + '/' + slide_video_path,
|
'url': 'rtmp://%s/ondemand?ovpfv=1.1' % 'fms.digitallyspeaking.com/cfx/st',
|
||||||
|
'play_path': remove_end(slide_video_path, '.flv'),
|
||||||
|
'ext': 'flv',
|
||||||
'format_note': 'slide deck video',
|
'format_note': 'slide deck video',
|
||||||
'quality': -2,
|
'quality': -2,
|
||||||
'preference': -2,
|
'preference': -2,
|
||||||
@ -76,7 +79,9 @@ class GDCVaultIE(InfoExtractor):
|
|||||||
})
|
})
|
||||||
speaker_video_path = xml_description.find('./metadata/speakerVideo').text
|
speaker_video_path = xml_description.find('./metadata/speakerVideo').text
|
||||||
video_formats.append({
|
video_formats.append({
|
||||||
'url': 'rtmp://' + akami_url + '/' + speaker_video_path,
|
'url': 'rtmp://%s/ondemand?ovpfv=1.1' % 'fms.digitallyspeaking.com/cfx/st',
|
||||||
|
'play_path': remove_end(speaker_video_path, '.flv'),
|
||||||
|
'ext': 'flv',
|
||||||
'format_note': 'speaker video',
|
'format_note': 'speaker video',
|
||||||
'quality': -1,
|
'quality': -1,
|
||||||
'preference': -1,
|
'preference': -1,
|
||||||
|
@ -547,7 +547,16 @@ class GenericIE(InfoExtractor):
|
|||||||
'id': 'aanslagen-kopenhagen',
|
'id': 'aanslagen-kopenhagen',
|
||||||
'title': 'Aanslagen Kopenhagen | RTL Nieuws',
|
'title': 'Aanslagen Kopenhagen | RTL Nieuws',
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
# Zapiks embed
|
||||||
|
{
|
||||||
|
'url': 'http://www.skipass.com/news/116090-bon-appetit-s5ep3-baqueira-mi-cor.html',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '118046',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'EP3S5 - Bon Appétit - Baqueira Mi Corazon !',
|
||||||
|
}
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
def report_following_redirect(self, new_url):
|
def report_following_redirect(self, new_url):
|
||||||
@ -1098,6 +1107,12 @@ class GenericIE(InfoExtractor):
|
|||||||
if mobj is not None:
|
if mobj is not None:
|
||||||
return self.url_result(mobj.group('url'), 'Livestream')
|
return self.url_result(mobj.group('url'), 'Livestream')
|
||||||
|
|
||||||
|
# Look for Zapiks embed
|
||||||
|
mobj = re.search(
|
||||||
|
r'<iframe[^>]+src="(?P<url>https?://(?:www\.)?zapiks\.fr/index\.php\?.+?)"', webpage)
|
||||||
|
if mobj is not None:
|
||||||
|
return self.url_result(mobj.group('url'), 'Zapiks')
|
||||||
|
|
||||||
def check_video(vurl):
|
def check_video(vurl):
|
||||||
if YoutubeIE.suitable(vurl):
|
if YoutubeIE.suitable(vurl):
|
||||||
return True
|
return True
|
||||||
|
88
youtube_dl/extractor/r7.py
Normal file
88
youtube_dl/extractor/r7.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from ..utils import (
|
||||||
|
js_to_json,
|
||||||
|
unescapeHTML,
|
||||||
|
int_or_none,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class R7IE(InfoExtractor):
|
||||||
|
_VALID_URL = r'''(?x)https?://
|
||||||
|
(?:
|
||||||
|
(?:[a-zA-Z]+)\.r7\.com(?:/[^/]+)+/idmedia/|
|
||||||
|
noticias\.r7\.com(?:/[^/]+)+/[^/]+-|
|
||||||
|
player\.r7\.com/video/i/
|
||||||
|
)
|
||||||
|
(?P<id>[\da-f]{24})
|
||||||
|
'''
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'http://videos.r7.com/policiais-humilham-suspeito-a-beira-da-morte-morre-com-dignidade-/idmedia/54e7050b0cf2ff57e0279389.html',
|
||||||
|
'md5': '403c4e393617e8e8ddc748978ee8efde',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '54e7050b0cf2ff57e0279389',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Policiais humilham suspeito à beira da morte: "Morre com dignidade"',
|
||||||
|
'thumbnail': 're:^https?://.*\.jpg$',
|
||||||
|
'duration': 98,
|
||||||
|
'like_count': int,
|
||||||
|
'view_count': int,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
'url': 'http://esportes.r7.com/videos/cigano-manda-recado-aos-fas/idmedia/4e176727b51a048ee6646a1b.html',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'http://noticias.r7.com/record-news/video/representante-do-instituto-sou-da-paz-fala-sobre-fim-do-estatuto-do-desarmamento-5480fc580cf2285b117f438d/',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'http://player.r7.com/video/i/54e7050b0cf2ff57e0279389?play=true&video=http://vsh.r7.com/54e7050b0cf2ff57e0279389/ER7_RE_BG_MORTE_JOVENS_570kbps_2015-02-2009f17818-cc82-4c8f-86dc-89a66934e633-ATOS_copy.mp4&linkCallback=http://videos.r7.com/policiais-humilham-suspeito-a-beira-da-morte-morre-com-dignidade-/idmedia/54e7050b0cf2ff57e0279389.html&thumbnail=http://vtb.r7.com/ER7_RE_BG_MORTE_JOVENS_570kbps_2015-02-2009f17818-cc82-4c8f-86dc-89a66934e633-thumb.jpg&idCategory=192&share=true&layout=full&full=true',
|
||||||
|
'only_matching': True,
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
video_id = self._match_id(url)
|
||||||
|
|
||||||
|
webpage = self._download_webpage(
|
||||||
|
'http://player.r7.com/video/i/%s' % video_id, video_id)
|
||||||
|
|
||||||
|
item = self._parse_json(js_to_json(self._search_regex(
|
||||||
|
r'(?s)var\s+item\s*=\s*({.+?});', webpage, 'player')), video_id)
|
||||||
|
|
||||||
|
title = unescapeHTML(item['title'])
|
||||||
|
thumbnail = item.get('init', {}).get('thumbUri')
|
||||||
|
duration = None
|
||||||
|
|
||||||
|
statistics = item.get('statistics', {})
|
||||||
|
like_count = int_or_none(statistics.get('likes'))
|
||||||
|
view_count = int_or_none(statistics.get('views'))
|
||||||
|
|
||||||
|
formats = []
|
||||||
|
for format_key, format_dict in item['playlist'][0].items():
|
||||||
|
src = format_dict.get('src')
|
||||||
|
if not src:
|
||||||
|
continue
|
||||||
|
format_id = format_dict.get('format') or format_key
|
||||||
|
if duration is None:
|
||||||
|
duration = format_dict.get('duration')
|
||||||
|
if '.f4m' in src:
|
||||||
|
formats.extend(self._extract_f4m_formats(src, video_id, preference=-1))
|
||||||
|
elif src.endswith('.m3u8'):
|
||||||
|
formats.extend(self._extract_m3u8_formats(src, video_id, 'mp4', preference=-2))
|
||||||
|
else:
|
||||||
|
formats.append({
|
||||||
|
'url': src,
|
||||||
|
'format_id': format_id,
|
||||||
|
})
|
||||||
|
self._sort_formats(formats)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': video_id,
|
||||||
|
'title': title,
|
||||||
|
'thumbnail': thumbnail,
|
||||||
|
'duration': duration,
|
||||||
|
'like_count': like_count,
|
||||||
|
'view_count': view_count,
|
||||||
|
'formats': formats,
|
||||||
|
}
|
@ -6,6 +6,7 @@ import re
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
|
from ..compat import compat_urlparse
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
struct_unpack,
|
struct_unpack,
|
||||||
remove_end,
|
remove_end,
|
||||||
@ -96,12 +97,10 @@ class RTVEALaCartaIE(InfoExtractor):
|
|||||||
).replace('.net.rtve', '.multimedia.cdn.rtve')
|
).replace('.net.rtve', '.multimedia.cdn.rtve')
|
||||||
video_path = self._download_webpage(
|
video_path = self._download_webpage(
|
||||||
auth_url, video_id, 'Getting video url')
|
auth_url, video_id, 'Getting video url')
|
||||||
# Use mvod.akcdn instead of flash.akamaihd.multimedia.cdn to get
|
# Use mvod1.akcdn instead of flash.akamaihd.multimedia.cdn to get
|
||||||
# the right Content-Length header and the mp4 format
|
# the right Content-Length header and the mp4 format
|
||||||
video_url = (
|
video_url = compat_urlparse.urljoin(
|
||||||
'http://mvod.akcdn.rtve.es/{0}&v=2.6.8'
|
'http://mvod1.akcdn.rtve.es/', video_path)
|
||||||
'&fp=MAC%2016,0,0,296&r=MRUGG&g=OEOJWFXNFGCP'.format(video_path)
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'id': video_id,
|
'id': video_id,
|
||||||
|
@ -7,6 +7,7 @@ from .common import InfoExtractor
|
|||||||
|
|
||||||
|
|
||||||
class SoundgasmIE(InfoExtractor):
|
class SoundgasmIE(InfoExtractor):
|
||||||
|
IE_NAME = 'soundgasm'
|
||||||
_VALID_URL = r'https?://(?:www\.)?soundgasm\.net/u/(?P<user>[0-9a-zA-Z_\-]+)/(?P<title>[0-9a-zA-Z_\-]+)'
|
_VALID_URL = r'https?://(?:www\.)?soundgasm\.net/u/(?P<user>[0-9a-zA-Z_\-]+)/(?P<title>[0-9a-zA-Z_\-]+)'
|
||||||
_TEST = {
|
_TEST = {
|
||||||
'url': 'http://soundgasm.net/u/ytdl/Piano-sample',
|
'url': 'http://soundgasm.net/u/ytdl/Piano-sample',
|
||||||
@ -38,3 +39,25 @@ class SoundgasmIE(InfoExtractor):
|
|||||||
'title': audio_title,
|
'title': audio_title,
|
||||||
'description': description
|
'description': description
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SoundgasmProfileIE(InfoExtractor):
|
||||||
|
IE_NAME = 'soundgasm:profile'
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?soundgasm\.net/u/(?P<id>[^/]+)/?(?:\#.*)?$'
|
||||||
|
_TEST = {
|
||||||
|
'url': 'http://soundgasm.net/u/ytdl',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'ytdl',
|
||||||
|
},
|
||||||
|
'playlist_count': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
profile_id = self._match_id(url)
|
||||||
|
|
||||||
|
webpage = self._download_webpage(url, profile_id)
|
||||||
|
|
||||||
|
entries = [
|
||||||
|
self.url_result(audio_url, 'Soundgasm')
|
||||||
|
for audio_url in re.findall(r'href="([^"]+/u/%s/[^"]+)' % profile_id, webpage)]
|
||||||
|
|
||||||
|
return self.playlist_result(entries, profile_id)
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import base64
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
|
from ..utils import qualities
|
||||||
|
|
||||||
|
|
||||||
class TeamcocoIE(InfoExtractor):
|
class TeamcocoIE(InfoExtractor):
|
||||||
@ -24,8 +26,8 @@ class TeamcocoIE(InfoExtractor):
|
|||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '19705',
|
'id': '19705',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
"description": "Louis C.K. got starstruck by George W. Bush, so what? Part one.",
|
'description': 'Louis C.K. got starstruck by George W. Bush, so what? Part one.',
|
||||||
"title": "Louis C.K. Interview Pt. 1 11/3/11",
|
'title': 'Louis C.K. Interview Pt. 1 11/3/11',
|
||||||
'age_limit': 0,
|
'age_limit': 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,42 +44,39 @@ class TeamcocoIE(InfoExtractor):
|
|||||||
display_id = mobj.group('display_id')
|
display_id = mobj.group('display_id')
|
||||||
webpage = self._download_webpage(url, display_id)
|
webpage = self._download_webpage(url, display_id)
|
||||||
|
|
||||||
video_id = mobj.group("video_id")
|
video_id = mobj.group('video_id')
|
||||||
if not video_id:
|
if not video_id:
|
||||||
video_id = self._html_search_regex(
|
video_id = self._html_search_regex(
|
||||||
self._VIDEO_ID_REGEXES, webpage, 'video id')
|
self._VIDEO_ID_REGEXES, webpage, 'video id')
|
||||||
|
|
||||||
data_url = 'http://teamcoco.com/cvp/2.0/%s.xml' % video_id
|
embed_url = 'http://teamcoco.com/embed/v/%s' % video_id
|
||||||
data = self._download_xml(
|
embed = self._download_webpage(
|
||||||
data_url, display_id, 'Downloading data webpage')
|
embed_url, video_id, 'Downloading embed page')
|
||||||
|
|
||||||
|
encoded_data = self._search_regex(
|
||||||
|
r'"preload"\s*:\s*"([^"]+)"', embed, 'encoded data')
|
||||||
|
data = self._parse_json(
|
||||||
|
base64.b64decode(encoded_data.encode('ascii')).decode('utf-8'), video_id)
|
||||||
|
|
||||||
qualities = ['500k', '480p', '1000k', '720p', '1080p']
|
|
||||||
formats = []
|
formats = []
|
||||||
for filed in data.findall('files/file'):
|
get_quality = qualities(['500k', '480p', '1000k', '720p', '1080p'])
|
||||||
if filed.attrib.get('playmode') == 'all':
|
for filed in data['files']:
|
||||||
# it just duplicates one of the entries
|
m_format = re.search(r'(\d+(k|p))\.mp4', filed['url'])
|
||||||
break
|
|
||||||
file_url = filed.text
|
|
||||||
m_format = re.search(r'(\d+(k|p))\.mp4', file_url)
|
|
||||||
if m_format is not None:
|
if m_format is not None:
|
||||||
format_id = m_format.group(1)
|
format_id = m_format.group(1)
|
||||||
else:
|
else:
|
||||||
format_id = filed.attrib['bitrate']
|
format_id = filed['bitrate']
|
||||||
tbr = (
|
tbr = (
|
||||||
int(filed.attrib['bitrate'])
|
int(filed['bitrate'])
|
||||||
if filed.attrib['bitrate'].isdigit()
|
if filed['bitrate'].isdigit()
|
||||||
else None)
|
else None)
|
||||||
|
|
||||||
try:
|
|
||||||
quality = qualities.index(format_id)
|
|
||||||
except ValueError:
|
|
||||||
quality = -1
|
|
||||||
formats.append({
|
formats.append({
|
||||||
'url': file_url,
|
'url': filed['url'],
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'tbr': tbr,
|
'tbr': tbr,
|
||||||
'format_id': format_id,
|
'format_id': format_id,
|
||||||
'quality': quality,
|
'quality': get_quality(format_id),
|
||||||
})
|
})
|
||||||
|
|
||||||
self._sort_formats(formats)
|
self._sort_formats(formats)
|
||||||
@ -86,8 +85,8 @@ class TeamcocoIE(InfoExtractor):
|
|||||||
'id': video_id,
|
'id': video_id,
|
||||||
'display_id': display_id,
|
'display_id': display_id,
|
||||||
'formats': formats,
|
'formats': formats,
|
||||||
'title': self._og_search_title(webpage),
|
'title': data['title'],
|
||||||
'thumbnail': self._og_search_thumbnail(webpage),
|
'thumbnail': data.get('thumb', {}).get('href'),
|
||||||
'description': self._og_search_description(webpage),
|
'description': data.get('teaser'),
|
||||||
'age_limit': self._family_friendly_search(webpage),
|
'age_limit': self._family_friendly_search(webpage),
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ from __future__ import unicode_literals
|
|||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import itertools
|
import itertools
|
||||||
|
import hashlib
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from .subtitles import SubtitlesInfoExtractor
|
from .subtitles import SubtitlesInfoExtractor
|
||||||
@ -225,6 +226,11 @@ class VimeoIE(VimeoBaseInfoExtractor, SubtitlesInfoExtractor):
|
|||||||
if mobj.group('pro') or mobj.group('player'):
|
if mobj.group('pro') or mobj.group('player'):
|
||||||
url = 'http://player.vimeo.com/video/' + video_id
|
url = 'http://player.vimeo.com/video/' + video_id
|
||||||
|
|
||||||
|
password = self._downloader.params.get('videopassword', None)
|
||||||
|
if password:
|
||||||
|
headers['Cookie'] = '%s_password=%s' % (
|
||||||
|
video_id, hashlib.md5(password.encode('utf-8')).hexdigest())
|
||||||
|
|
||||||
# Retrieve video webpage to extract further information
|
# Retrieve video webpage to extract further information
|
||||||
request = compat_urllib_request.Request(url, None, headers)
|
request = compat_urllib_request.Request(url, None, headers)
|
||||||
try:
|
try:
|
||||||
|
110
youtube_dl/extractor/zapiks.py
Normal file
110
youtube_dl/extractor/zapiks.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from ..utils import (
|
||||||
|
parse_duration,
|
||||||
|
parse_iso8601,
|
||||||
|
xpath_with_ns,
|
||||||
|
xpath_text,
|
||||||
|
int_or_none,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ZapiksIE(InfoExtractor):
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?zapiks\.(?:fr|com)/(?:(?:[a-z]{2}/)?(?P<display_id>.+?)\.html|index\.php\?.*\bmedia_id=(?P<id>\d+))'
|
||||||
|
_TESTS = [
|
||||||
|
{
|
||||||
|
'url': 'http://www.zapiks.fr/ep2s3-bon-appetit-eh-be-viva.html',
|
||||||
|
'md5': 'aeb3c473b2d564b2d46d664d28d5f050',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '80798',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'EP2S3 - Bon Appétit - Eh bé viva les pyrénées con!',
|
||||||
|
'description': 'md5:7054d6f6f620c6519be1fe710d4da847',
|
||||||
|
'thumbnail': 're:^https?://.*\.jpg$',
|
||||||
|
'duration': 528,
|
||||||
|
'timestamp': 1359044972,
|
||||||
|
'upload_date': '20130124',
|
||||||
|
'view_count': int,
|
||||||
|
'comment_count': int,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'url': 'http://www.zapiks.com/ep3s5-bon-appetit-baqueira-m-1.html',
|
||||||
|
'only_matching': True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'url': 'http://www.zapiks.com/nl/ep3s5-bon-appetit-baqueira-m-1.html',
|
||||||
|
'only_matching': True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'url': 'http://www.zapiks.fr/index.php?action=playerIframe&media_id=118046&width=640&height=360&autoStart=false&language=fr',
|
||||||
|
'only_matching': True,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
mobj = re.match(self._VALID_URL, url)
|
||||||
|
video_id = mobj.group('id')
|
||||||
|
display_id = mobj.group('display_id') or video_id
|
||||||
|
|
||||||
|
webpage = self._download_webpage(url, display_id)
|
||||||
|
|
||||||
|
if not video_id:
|
||||||
|
video_id = self._search_regex(
|
||||||
|
r'data-media-id="(\d+)"', webpage, 'video id')
|
||||||
|
|
||||||
|
playlist = self._download_xml(
|
||||||
|
'http://www.zapiks.fr/view/index.php?action=playlist&media_id=%s&lang=en' % video_id,
|
||||||
|
display_id)
|
||||||
|
|
||||||
|
NS_MAP = {
|
||||||
|
'jwplayer': 'http://rss.jwpcdn.com/'
|
||||||
|
}
|
||||||
|
|
||||||
|
def ns(path):
|
||||||
|
return xpath_with_ns(path, NS_MAP)
|
||||||
|
|
||||||
|
item = playlist.find('./channel/item')
|
||||||
|
|
||||||
|
title = xpath_text(item, 'title', 'title') or self._og_search_title(webpage)
|
||||||
|
description = self._og_search_description(webpage, default=None)
|
||||||
|
thumbnail = xpath_text(
|
||||||
|
item, ns('./jwplayer:image'), 'thumbnail') or self._og_search_thumbnail(webpage, default=None)
|
||||||
|
duration = parse_duration(self._html_search_meta(
|
||||||
|
'duration', webpage, 'duration', default=None))
|
||||||
|
timestamp = parse_iso8601(self._html_search_meta(
|
||||||
|
'uploadDate', webpage, 'upload date', default=None), ' ')
|
||||||
|
|
||||||
|
view_count = int_or_none(self._search_regex(
|
||||||
|
r'UserPlays:(\d+)', webpage, 'view count', default=None))
|
||||||
|
comment_count = int_or_none(self._search_regex(
|
||||||
|
r'UserComments:(\d+)', webpage, 'comment count', default=None))
|
||||||
|
|
||||||
|
formats = []
|
||||||
|
for source in item.findall(ns('./jwplayer:source')):
|
||||||
|
format_id = source.attrib['label']
|
||||||
|
f = {
|
||||||
|
'url': source.attrib['file'],
|
||||||
|
'format_id': format_id,
|
||||||
|
}
|
||||||
|
m = re.search(r'^(?P<height>\d+)[pP]', format_id)
|
||||||
|
if m:
|
||||||
|
f['height'] = int(m.group('height'))
|
||||||
|
formats.append(f)
|
||||||
|
self._sort_formats(formats)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': video_id,
|
||||||
|
'title': title,
|
||||||
|
'description': description,
|
||||||
|
'thumbnail': thumbnail,
|
||||||
|
'duration': duration,
|
||||||
|
'timestamp': timestamp,
|
||||||
|
'view_count': view_count,
|
||||||
|
'comment_count': comment_count,
|
||||||
|
'formats': formats,
|
||||||
|
}
|
@ -900,8 +900,8 @@ def _windows_write_string(s, out):
|
|||||||
def not_a_console(handle):
|
def not_a_console(handle):
|
||||||
if handle == INVALID_HANDLE_VALUE or handle is None:
|
if handle == INVALID_HANDLE_VALUE or handle is None:
|
||||||
return True
|
return True
|
||||||
return ((GetFileType(handle) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR
|
return ((GetFileType(handle) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR or
|
||||||
or GetConsoleMode(handle, ctypes.byref(ctypes.wintypes.DWORD())) == 0)
|
GetConsoleMode(handle, ctypes.byref(ctypes.wintypes.DWORD())) == 0)
|
||||||
|
|
||||||
if not_a_console(h):
|
if not_a_console(h):
|
||||||
return False
|
return False
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
__version__ = '2015.02.20'
|
__version__ = '2015.02.23'
|
||||||
|
Reference in New Issue
Block a user