From ea783d01e1bbe56657bff752d062bfb1d8a9bc3e Mon Sep 17 00:00:00 2001 From: Jason Normore Date: Sat, 10 May 2014 23:18:20 -0400 Subject: [PATCH 0001/1761] Added VineUserIE extractor for vine user timeline Added vine user timeline extractor using unofficial vine api user profile and timeline api endpoints. --- test/test_playlists.py | 8 +++++++ youtube_dl/extractor/__init__.py | 5 ++++- youtube_dl/extractor/vine.py | 36 ++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/test/test_playlists.py b/test/test_playlists.py index fe6274e60..cc871698a 100644 --- a/test/test_playlists.py +++ b/test/test_playlists.py @@ -23,6 +23,7 @@ from youtube_dl.extractor import ( VimeoUserIE, VimeoAlbumIE, VimeoGroupsIE, + VineUserIE, UstreamChannelIE, SoundcloudSetIE, SoundcloudUserIE, @@ -102,6 +103,13 @@ class TestPlaylists(unittest.TestCase): self.assertEqual(result['title'], 'Rolex Awards for Enterprise') self.assertTrue(len(result['entries']) > 72) + def test_vine_user(self): + dl = FakeYDL() + ie = VineUserIE(dl) + result = ie.extract('https://vine.co/Visa') + self.assertIsPlaylist(result) + self.assertTrue(len(result['entries']) >= 50) + def test_ustream_channel(self): dl = FakeYDL() ie = UstreamChannelIE(dl) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 9529077c7..bc5af1d9e 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -305,7 +305,10 @@ from .vimeo import ( VimeoReviewIE, VimeoWatchLaterIE, ) -from .vine import VineIE +from .vine import ( + VineIE, + VineUserIE, +) from .viki import VikiIE from .vk import VKIE from .vube import VubeIE diff --git a/youtube_dl/extractor/vine.py b/youtube_dl/extractor/vine.py index 5136ec466..99e0b6400 100644 --- a/youtube_dl/extractor/vine.py +++ b/youtube_dl/extractor/vine.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import re import json +import itertools from .common import InfoExtractor from ..utils import unified_strdate @@ -58,3 +59,38 @@ class VineIE(InfoExtractor): 'repost_count': data['reposts']['count'], 'formats': formats, } + +class VineUserIE(InfoExtractor): + IE_NAME = 'vine:user' + _VALID_URL = r'(?:https?://)?vine\.co/(?P[^/]+)/?(\?.*)?$' + _VINE_BASE_URL = "https://vine.co/" + + def _profile_url(self, user): + return "%sapi/users/profiles/vanity/%s"%(self._VINE_BASE_URL, user) + + def _timeline_url(self, user_id, page=1): + return "%sapi/timelines/users/%s?page=%s"%(self._VINE_BASE_URL, user_id, page) + + def _profile_data(self, user): + return self._download_json(self._profile_url(user), user) + + def _timeline_data(self, user): + profile_data = self._profile_data(user) + user_id = profile_data['data']['userId'] + timeline_data = [] + for pagenum in itertools.count(1): + timeline_page = self._download_json(self._timeline_url(user_id, pagenum), user) + timeline_data.extend(timeline_page['data']['records']) + if timeline_page['data']['nextPage'] is None: + break + return timeline_data + + def _extract_videos(self, user): + timeline_data = self._timeline_data(user) + entries = [self.url_result(e['permalinkUrl'], 'Vine') for e in timeline_data] + return self.playlist_result(entries, user) + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + user = mobj.group('user') + return self._extract_videos(user) From fdb205b19e9980cd5a619b09d5828e12095b48b9 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 11 May 2014 20:13:22 -0700 Subject: [PATCH 0002/1761] Enable testing on Python 3.4 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 45b71f11b..c6cc7a994 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ python: - "2.6" - "2.7" - "3.3" + - "3.4" script: nosetests test --verbose notifications: email: From 1476b497ebda9155d442065bb2a987d86c29026f Mon Sep 17 00:00:00 2001 From: hojel Date: Mon, 12 May 2014 01:28:56 -0700 Subject: [PATCH 0003/1761] [slutload] Add new extractor --- youtube_dl/extractor/slutload.py | 46 ++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 youtube_dl/extractor/slutload.py diff --git a/youtube_dl/extractor/slutload.py b/youtube_dl/extractor/slutload.py new file mode 100644 index 000000000..095adfc15 --- /dev/null +++ b/youtube_dl/extractor/slutload.py @@ -0,0 +1,46 @@ +import re + +from .common import InfoExtractor +from ..utils import ( + ExtractorError, +) + +class SlutloadIE(InfoExtractor): + _VALID_URL = r'^https?://(?:\w+\.)?slutload\.com/video/[^/]+/(?P[^/]+)/?$' + _TEST = { + u'url': u'http://www.slutload.com/video/virginie-baisee-en-cam/TD73btpBqSxc/', + u'file': u'TD73btpBqSxc.mp4', + u'md5': u'0cf531ae8006b530bd9df947a6a0df77', + u'info_dict': { + u"title": u"virginie baisee en cam", + u"age_limit": 18, + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + + video_id = mobj.group('videoid') + + # Get webpage content + webpage = self._download_webpage(url, video_id) + + # Get the video title + video_title = self._html_search_regex(r'

([^<]+)', + webpage, u'title').strip() + + # Get the video url + result = re.compile(r'
Date: Mon, 12 May 2014 01:29:19 -0700 Subject: [PATCH 0004/1761] [slutload] Add new extractor --- youtube_dl/extractor/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 9529077c7..697bcab87 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -230,6 +230,7 @@ from .scivee import SciVeeIE from .servingsys import ServingSysIE from .sina import SinaIE from .slideshare import SlideshareIE +from .slutload import SlutloadIE from .smotri import ( SmotriIE, SmotriCommunityIE, From 749fe60c1eaa157db4360edf55cf41a10489f349 Mon Sep 17 00:00:00 2001 From: hojel Date: Mon, 12 May 2014 03:48:40 -0700 Subject: [PATCH 0005/1761] [nuvid] Add new extractor --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/nuvid.py | 39 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 youtube_dl/extractor/nuvid.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 9529077c7..287044180 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -194,6 +194,7 @@ from .nowvideo import NowVideoIE from .nrk import NRKIE from .ntv import NTVIE from .nytimes import NYTimesIE +from .nuvid import NuvidIE from .oe1 import OE1IE from .ooyala import OoyalaIE from .orf import ORFIE diff --git a/youtube_dl/extractor/nuvid.py b/youtube_dl/extractor/nuvid.py new file mode 100644 index 000000000..2e5198c1a --- /dev/null +++ b/youtube_dl/extractor/nuvid.py @@ -0,0 +1,39 @@ +import re + +from .common import InfoExtractor + +class NuvidIE(InfoExtractor): + _VALID_URL = r'^https?://(?:www|m)\.nuvid\.com/video/(?P\d+)' + _TEST = { + u'url': u'http://m.nuvid.com/video/1310741/', + u'file': u'1310741.mp4', + u'md5': u'eab207b7ac4fccfb4e23c86201f11277', + u'info_dict': { + u"title": u"Horny babes show their awesome bodeis and", + u"age_limit": 18, + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + + video_id = mobj.group('videoid') + + # Get webpage content + murl = url.replace('//www.', '//m.') + webpage = self._download_webpage(murl, video_id) + + video_title = self._html_search_regex(r'
\s+]*>([^<]+)

', webpage, 'video_title').strip() + + video_url = 'http://m.nuvid.com'+self._html_search_regex(r'href="(/mp4/[^"]+)"[^>]*data-link_type="mp4"', webpage, 'video_url') + + video_thumb = self._html_search_regex(r'href="(/thumbs/[^"]+)"[^>]*data-link_type="thumbs"', webpage, 'video_thumb') + + info = {'id': video_id, + 'url': video_url, + 'title': video_title, + 'thumbnail': video_thumb, + 'ext': 'mp4', + 'age_limit': 18} + + return [info] From 33c7ff861ec6288a6e437deb73a277067ac9e267 Mon Sep 17 00:00:00 2001 From: hojel Date: Mon, 12 May 2014 03:58:07 -0700 Subject: [PATCH 0006/1761] [hentaistigma] Add new extractor --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/hentaistigma.py | 43 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 youtube_dl/extractor/hentaistigma.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 9529077c7..228f62b40 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -109,6 +109,7 @@ from .googleplus import GooglePlusIE from .googlesearch import GoogleSearchIE from .hark import HarkIE from .helsinki import HelsinkiIE +from .hentaistigma import HentaiStigmaIE from .hotnewhiphop import HotNewHipHopIE from .howcast import HowcastIE from .huffpost import HuffPostIE diff --git a/youtube_dl/extractor/hentaistigma.py b/youtube_dl/extractor/hentaistigma.py new file mode 100644 index 000000000..4f2d30599 --- /dev/null +++ b/youtube_dl/extractor/hentaistigma.py @@ -0,0 +1,43 @@ +import re + +from .common import InfoExtractor + +class HentaiStigmaIE(InfoExtractor): + _VALID_URL = r'^https?://hentai\.animestigma\.com/(?P[^/]+)' + _TEST = { + u'url': u'http://hentai.animestigma.com/inyouchuu-etsu-bonus/', + u'file': u'inyouchuu-etsu-bonus.mp4', + u'md5': u'4e3d07422a68a4cc363d8f57c8bf0d23', + u'info_dict': { + u"title": u"Inyouchuu Etsu Bonus", + u"age_limit": 18, + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + + video_id = mobj.group('videoid') + + # Get webpage content + webpage = self._download_webpage(url, video_id) + + # Get the video title + video_title = self._html_search_regex(r'

]*>([^<]+)', + webpage, u'title').strip() + + # Get the wrapper url + wrap_url = self._html_search_regex(r'', start_page, 'xml root', None, False) + direct_url = self._search_regex( + r's1\.addVariable\("file",\s*encodeURIComponent\("(/[^"]+)"\)\);', + start_page, 'url', default=None) + if direct_url: + video_url = 'http://www.gdcvault.com/' + direct_url + title = self._html_search_regex( + r'Session Name\s*(.*?)', + start_page, 'title') + return { + 'id': video_id, + 'url': video_url, + 'ext': 'flv', + 'title': title, + } + + xml_root = self._html_search_regex( + r'', start_page, 'xml root') + xml_root = self._html_search_regex( + r'', start_page, 'xml filename', None, False) + xml_name = self._html_search_regex( + r'', start_page, 'xml filename') From b490b8849a01d4406bb8ed35cec928882909e3a4 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 25 Jul 2014 10:47:35 +0200 Subject: [PATCH 0446/1761] release 2014.07.25.1 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 479b98abf..e77494595 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.07.25' +__version__ = '2014.07.25.1' From cbf915f3f63a85e090d561fe4de218b55cb7fa59 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 25 Jul 2014 11:39:17 +0200 Subject: [PATCH 0447/1761] [livestream] Parse SMIL (#2713) --- youtube_dl/extractor/livestream.py | 70 ++++++++++++++++++++++++++---- youtube_dl/utils.py | 4 +- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/youtube_dl/extractor/livestream.py b/youtube_dl/extractor/livestream.py index 1ea1bbab4..444771bd3 100644 --- a/youtube_dl/extractor/livestream.py +++ b/youtube_dl/extractor/livestream.py @@ -5,11 +5,14 @@ import json from .common import InfoExtractor from ..utils import ( + compat_str, compat_urllib_parse_urlparse, compat_urlparse, - xpath_with_ns, - compat_str, + ExtractorError, + find_xpath_attr, + int_or_none, orderedSet, + xpath_with_ns, ) @@ -24,20 +27,71 @@ class LivestreamIE(InfoExtractor): 'ext': 'mp4', 'title': 'Live from Webster Hall NYC', 'upload_date': '20121012', + 'like_count': int, + 'view_count': int, + 'thumbnail': 're:^http://.*\.jpg$' } } def _extract_video_info(self, video_data): - video_url = ( - video_data.get('progressive_url_hd') or - video_data.get('progressive_url') + video_id = compat_str(video_data['id']) + + FORMAT_KEYS = ( + ('sd', 'progressive_url'), + ('hd', 'progressive_url_hd'), ) + formats = [{ + 'format_id': format_id, + 'url': video_data[key], + 'quality': i + 1, + } for i, (format_id, key) in enumerate(FORMAT_KEYS) + if video_data.get(key)] + + smil_url = video_data.get('smil_url') + if smil_url: + _SWITCH_XPATH = ( + './/{http://www.w3.org/2001/SMIL20/Language}body/' + '{http://www.w3.org/2001/SMIL20/Language}switch') + smil_doc = self._download_xml( + smil_url, video_id, note='Downloading SMIL information') + + title_node = find_xpath_attr( + smil_doc, './/{http://www.w3.org/2001/SMIL20/Language}meta', + 'name', 'title') + if title_node is None: + self.report_warning('Cannot find SMIL id') + switch_node = smil_doc.find(_SWITCH_XPATH) + else: + title_id = title_node.attrib['content'] + switch_node = find_xpath_attr( + smil_doc, _SWITCH_XPATH, 'id', title_id) + if switch_node is None: + raise ExtractorError('Cannot find switch node') + video_nodes = switch_node.findall( + '{http://www.w3.org/2001/SMIL20/Language}video') + + for vn in video_nodes: + tbr = int_or_none(vn.attrib.get('system-bitrate')) + furl = ( + 'http://livestream-f.akamaihd.net/%s?v=3.0.3&fp=WIN%%2014,0,0,145&seek=%s' % + (vn.attrib['src'], vn.attrib['clipBegin'])) + formats.append({ + 'url': furl, + 'format_id': 'smil_%d' % tbr, + 'ext': 'flv', + 'tbr': tbr, + 'preference': -1000, + }) + self._sort_formats(formats) + return { - 'id': compat_str(video_data['id']), - 'url': video_url, + 'id': video_id, + 'formats': formats, 'title': video_data['caption'], - 'thumbnail': video_data['thumbnail_url'], + 'thumbnail': video_data.get('thumbnail_url'), 'upload_date': video_data['updated_at'].replace('-', '')[:8], + 'like_count': video_data.get('likes', {}).get('total'), + 'view_count': video_data.get('views'), } def _real_extract(self, url): diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 3ecd798d7..0d0bbe8f6 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -242,8 +242,8 @@ else: if sys.version_info >= (2,7): def find_xpath_attr(node, xpath, key, val): """ Find the xpath xpath[@key=val] """ - assert re.match(r'^[a-zA-Z]+$', key) - assert re.match(r'^[a-zA-Z0-9@\s:._]*$', val) + assert re.match(r'^[a-zA-Z-]+$', key) + assert re.match(r'^[a-zA-Z0-9@\s:._-]*$', val) expr = xpath + u"[@%s='%s']" % (key, val) return node.find(expr) else: From 3182f3e2dc62cf918fa12f578e2bbfc952862320 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 25 Jul 2014 11:46:51 +0200 Subject: [PATCH 0448/1761] [justin.tv] Fix page reporting (#3352) youtube-dl -j http://www.twitch.tv/fang_i3anger still fails though. --- youtube_dl/extractor/justintv.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/youtube_dl/extractor/justintv.py b/youtube_dl/extractor/justintv.py index 7083db12e..27017e89f 100644 --- a/youtube_dl/extractor/justintv.py +++ b/youtube_dl/extractor/justintv.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals +import itertools import json import os import re @@ -43,10 +44,11 @@ class JustinTVIE(InfoExtractor): } # Return count of items, list of *valid* items - def _parse_page(self, url, video_id): - info_json = self._download_webpage(url, video_id, - 'Downloading video info JSON', - 'unable to download video info JSON') + def _parse_page(self, url, video_id, counter): + info_json = self._download_webpage( + url, video_id, + 'Downloading video info JSON on page %d' % counter, + 'Unable to download video info JSON %d' % counter) response = json.loads(info_json) if type(response) != list: @@ -138,11 +140,10 @@ class JustinTVIE(InfoExtractor): entries = [] offset = 0 limit = self._JUSTIN_PAGE_LIMIT - while True: - if paged: - self.report_download_page(video_id, offset) + for counter in itertools.count(1): page_url = api + ('?offset=%d&limit=%d' % (offset, limit)) - page_count, page_info = self._parse_page(page_url, video_id) + page_count, page_info = self._parse_page( + page_url, video_id, counter) entries.extend(page_info) if not paged or page_count != limit: break From 7fa547ab027f52f2570fd3a6022c10830424227e Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 25 Jul 2014 11:50:10 +0200 Subject: [PATCH 0449/1761] [livestream] Make clipBegin optional in SMIL --- youtube_dl/extractor/livestream.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/livestream.py b/youtube_dl/extractor/livestream.py index 444771bd3..2914343b9 100644 --- a/youtube_dl/extractor/livestream.py +++ b/youtube_dl/extractor/livestream.py @@ -73,8 +73,10 @@ class LivestreamIE(InfoExtractor): for vn in video_nodes: tbr = int_or_none(vn.attrib.get('system-bitrate')) furl = ( - 'http://livestream-f.akamaihd.net/%s?v=3.0.3&fp=WIN%%2014,0,0,145&seek=%s' % - (vn.attrib['src'], vn.attrib['clipBegin'])) + 'http://livestream-f.akamaihd.net/%s?v=3.0.3&fp=WIN%%2014,0,0,145' % + (vn.attrib['src'])) + if 'clipBegin' in vn.attrib: + furl += '&ssek=' + vn.attrib['clipBegin'] formats.append({ 'url': furl, 'format_id': 'smil_%d' % tbr, From 8f3034d871388a6b19967862968ee3b217ac3b22 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 25 Jul 2014 11:53:52 +0200 Subject: [PATCH 0450/1761] [livestream] Do not fail if SMIL download fails --- youtube_dl/extractor/livestream.py | 79 +++++++++++++++++------------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/youtube_dl/extractor/livestream.py b/youtube_dl/extractor/livestream.py index 2914343b9..c0c2d9b09 100644 --- a/youtube_dl/extractor/livestream.py +++ b/youtube_dl/extractor/livestream.py @@ -33,6 +33,49 @@ class LivestreamIE(InfoExtractor): } } + def _parse_smil(self, video_id, smil_url): + formats = [] + _SWITCH_XPATH = ( + './/{http://www.w3.org/2001/SMIL20/Language}body/' + '{http://www.w3.org/2001/SMIL20/Language}switch') + smil_doc = self._download_xml( + smil_url, video_id, + note='Downloading SMIL information', + errnote='Unable to download SMIL information', + fatal=False) + if smil_doc is False: # Download failed + return formats + title_node = find_xpath_attr( + smil_doc, './/{http://www.w3.org/2001/SMIL20/Language}meta', + 'name', 'title') + if title_node is None: + self.report_warning('Cannot find SMIL id') + switch_node = smil_doc.find(_SWITCH_XPATH) + else: + title_id = title_node.attrib['content'] + switch_node = find_xpath_attr( + smil_doc, _SWITCH_XPATH, 'id', title_id) + if switch_node is None: + raise ExtractorError('Cannot find switch node') + video_nodes = switch_node.findall( + '{http://www.w3.org/2001/SMIL20/Language}video') + + for vn in video_nodes: + tbr = int_or_none(vn.attrib.get('system-bitrate')) + furl = ( + 'http://livestream-f.akamaihd.net/%s?v=3.0.3&fp=WIN%%2014,0,0,145' % + (vn.attrib['src'])) + if 'clipBegin' in vn.attrib: + furl += '&ssek=' + vn.attrib['clipBegin'] + formats.append({ + 'url': furl, + 'format_id': 'smil_%d' % tbr, + 'ext': 'flv', + 'tbr': tbr, + 'preference': -1000, + }) + return formats + def _extract_video_info(self, video_data): video_id = compat_str(video_data['id']) @@ -49,41 +92,7 @@ class LivestreamIE(InfoExtractor): smil_url = video_data.get('smil_url') if smil_url: - _SWITCH_XPATH = ( - './/{http://www.w3.org/2001/SMIL20/Language}body/' - '{http://www.w3.org/2001/SMIL20/Language}switch') - smil_doc = self._download_xml( - smil_url, video_id, note='Downloading SMIL information') - - title_node = find_xpath_attr( - smil_doc, './/{http://www.w3.org/2001/SMIL20/Language}meta', - 'name', 'title') - if title_node is None: - self.report_warning('Cannot find SMIL id') - switch_node = smil_doc.find(_SWITCH_XPATH) - else: - title_id = title_node.attrib['content'] - switch_node = find_xpath_attr( - smil_doc, _SWITCH_XPATH, 'id', title_id) - if switch_node is None: - raise ExtractorError('Cannot find switch node') - video_nodes = switch_node.findall( - '{http://www.w3.org/2001/SMIL20/Language}video') - - for vn in video_nodes: - tbr = int_or_none(vn.attrib.get('system-bitrate')) - furl = ( - 'http://livestream-f.akamaihd.net/%s?v=3.0.3&fp=WIN%%2014,0,0,145' % - (vn.attrib['src'])) - if 'clipBegin' in vn.attrib: - furl += '&ssek=' + vn.attrib['clipBegin'] - formats.append({ - 'url': furl, - 'format_id': 'smil_%d' % tbr, - 'ext': 'flv', - 'tbr': tbr, - 'preference': -1000, - }) + formats.extend(self._parse_smil(video_id, smil_url)) self._sort_formats(formats) return { From 1220352ff72d3cb49a6e7cbc1097c8fb7bcb4c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Fri, 25 Jul 2014 21:33:29 +0700 Subject: [PATCH 0451/1761] [tvplay] Add extractor (Closes #3245) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/tvplay.py | 85 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 youtube_dl/extractor/tvplay.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 2bb93d938..56b9accce 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -322,6 +322,7 @@ from .tumblr import TumblrIE from .tutv import TutvIE from .tvigle import TvigleIE from .tvp import TvpIE +from .tvplay import TVPlayIE from .udemy import ( UdemyIE, UdemyCourseIE diff --git a/youtube_dl/extractor/tvplay.py b/youtube_dl/extractor/tvplay.py new file mode 100644 index 000000000..a56a7ab5f --- /dev/null +++ b/youtube_dl/extractor/tvplay.py @@ -0,0 +1,85 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ( + ExtractorError, + parse_iso8601, + qualities, +) + + +class TVPlayIE(InfoExtractor): + _VALID_URL = r'http://(?:www\.)?tvplay\.lv/parraides/[^/]+/(?P\d+)' + _TESTS = [ + { + 'url': 'http://www.tvplay.lv/parraides/vinas-melo-labak/418113?autostart=true', + 'info_dict': { + 'id': '418113', + 'ext': 'flv', + 'title': 'Kādi ir īri? - Viņas melo labāk', + 'description': 'Baiba apsmej īrus, kādi tie ir un ko viņi dara.', + 'duration': 25, + 'timestamp': 1406097056, + 'upload_date': '20140723', + }, + 'params': { + # rtmp download + 'skip_download': True, + }, + }, + ] + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + video = self._download_json( + 'http://playapi.mtgx.tv/v1/videos/%s' % video_id, video_id, 'Downloading video JSON') + + if video['is_geo_blocked']: + raise ExtractorError( + 'This content is not available in your country due to copyright reasons', expected=True) + + streams = self._download_json( + 'http://playapi.mtgx.tv/v1/videos/stream/%s' % video_id, video_id, 'Downloading streams JSON') + + quality = qualities(['hls', 'medium', 'high']) + formats = [] + for format_id, video_url in streams['streams'].items(): + if not video_url: + continue + fmt = { + 'format_id': format_id, + 'preference': quality(format_id), + } + if video_url.startswith('rtmp'): + m = re.search(r'^(?Prtmp://[^/]+/(?P[^/]+))/(?P.+)$', video_url) + if not m: + continue + fmt.update({ + 'ext': 'flv', + 'url': m.group('url'), + 'app': m.group('app'), + 'play_path': m.group('playpath'), + }) + else: + fmt.update({ + 'url': video_url, + }) + formats.append(fmt) + + self._sort_formats(formats) + + return { + 'id': video_id, + 'title': video['title'], + 'description': video['description'], + 'duration': video['duration'], + 'timestamp': parse_iso8601(video['created_at']), + 'view_count': video['views']['total'], + 'age_limit': video.get('age_limit', 0), + 'formats': formats, + } From 11b85ce62ef8bafb6c459103ad4e95279dfb9dcb Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 25 Jul 2014 23:37:32 +0200 Subject: [PATCH 0452/1761] [YouTubeDL] Best practices (Closes #3370) --- youtube_dl/YoutubeDL.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index f295174cf..14a1d06ab 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -275,7 +275,7 @@ class YoutubeDL(object): return message assert hasattr(self, '_output_process') - assert type(message) == type('') + assert isinstance(message, compat_str) line_count = message.count('\n') + 1 self._output_process.stdin.write((message + '\n').encode('utf-8')) self._output_process.stdin.flush() @@ -303,7 +303,7 @@ class YoutubeDL(object): def to_stderr(self, message): """Print message to stderr.""" - assert type(message) == type('') + assert isinstance(message, compat_str) if self.params.get('logger'): self.params['logger'].error(message) else: @@ -849,7 +849,7 @@ class YoutubeDL(object): # Keep for backwards compatibility info_dict['stitle'] = info_dict['title'] - if not 'format' in info_dict: + if 'format' not in info_dict: info_dict['format'] = info_dict['ext'] reason = self._match_entry(info_dict) From 64ce58db38091b071e74cebe77ba4fac06ddc1c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sat, 26 Jul 2014 00:05:37 +0200 Subject: [PATCH 0453/1761] [abc] Add extractor (closes #3361) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/abc.py | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 youtube_dl/extractor/abc.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 56b9accce..a8e593002 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -1,3 +1,4 @@ +from .abc import ABCIE from .academicearth import AcademicEarthCourseIE from .addanime import AddAnimeIE from .adultswim import AdultSwimIE diff --git a/youtube_dl/extractor/abc.py b/youtube_dl/extractor/abc.py new file mode 100644 index 000000000..7d89f44ee --- /dev/null +++ b/youtube_dl/extractor/abc.py @@ -0,0 +1,48 @@ +from __future__ import unicode_literals + +import re +import json + +from .common import InfoExtractor + + +class ABCIE(InfoExtractor): + IE_NAME = 'abc.net.au' + _VALID_URL = r'http://www\.abc\.net\.au/news/[^/]+/[^/]+/(?P\d+)' + + _TEST = { + 'url': 'http://www.abc.net.au/news/2014-07-25/bringing-asylum-seekers-to-australia-would-give/5624716', + 'md5': 'dad6f8ad011a70d9ddf887ce6d5d0742', + 'info_dict': { + 'id': '5624716', + 'ext': 'mp4', + 'title': 'Bringing asylum seekers to Australia would give them right to asylum claims: professor', + 'description': 'md5:ba36fa5e27e5c9251fd929d339aea4af', + }, + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + webpage = self._download_webpage(url, video_id) + + urls_info_json = self._search_regex( + r'inlineVideoData\.push\((.*?)\);', webpage, 'video urls', + flags=re.DOTALL) + urls_info = json.loads(urls_info_json.replace('\'', '"')) + formats = [{ + 'url': url_info['url'], + 'width': int(url_info['width']), + 'height': int(url_info['height']), + 'tbr': int(url_info['bitrate']), + 'filesize': int(url_info['filesize']), + } for url_info in urls_info] + self._sort_formats(formats) + + return { + 'id': video_id, + 'title': self._og_search_title(webpage), + 'formats': formats, + 'description': self._og_search_description(webpage), + 'thumbnail': self._og_search_thumbnail(webpage), + } From 366b1f3cfe9993dfdd80116fcf8a91b7a3eff75d Mon Sep 17 00:00:00 2001 From: Naglis Jonaitis Date: Sat, 26 Jul 2014 14:35:23 +0300 Subject: [PATCH 0454/1761] [izlesene] Add new extractor. Closes #3184 --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/izlesene.py | 94 ++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 youtube_dl/extractor/izlesene.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index a8e593002..2bf8bc5e8 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -141,6 +141,7 @@ from .ivi import ( IviIE, IviCompilationIE ) +from .izlesene import IzleseneIE from .jadorecettepub import JadoreCettePubIE from .jeuxvideo import JeuxVideoIE from .jukebox import JukeboxIE diff --git a/youtube_dl/extractor/izlesene.py b/youtube_dl/extractor/izlesene.py new file mode 100644 index 000000000..e51358595 --- /dev/null +++ b/youtube_dl/extractor/izlesene.py @@ -0,0 +1,94 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import get_element_by_id, parse_iso8601, determine_ext, int_or_none + + +class IzleseneIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.|m\.)?izlesene\.com/(?:video|embedplayer)/(?:[^/]+/)?(?P[0-9]+)' + _STREAM_URL = 'http://panel.izlesene.com/api/streamurl/{id:}/{format:}' + _TEST = { + 'url': 'http://www.izlesene.com/video/sevincten-cildirtan-dogum-gunu-hediyesi/7599694', + 'md5': '4384f9f0ea65086734b881085ee05ac2', + 'info_dict': { + 'id': '7599694', + 'title': u'Sevinçten Çıldırtan Doğum Günü Hediyesi', + 'upload_date': '20140702', + 'uploader_id': 'pelikzzle', + 'description': u'Annesi oğluna doğum günü hediyesi olarak minecraft cd si alıyor, ve çocuk hunharca seviniyor', + 'timestamp': 1404298698, + 'duration': 95, + 'ext': 'mp4', + 'thumbnail': 're:^http://.*\.jpg', + 'age_limit': 0, + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + url = 'http://www.izlesene.com/video/%s' % video_id + + webpage = self._download_webpage(url, video_id) + + title = self._og_search_title(webpage) + description = self._og_search_description(webpage) + thumbnail = self._og_search_thumbnail(webpage) + duration = int( + self._html_search_regex( + r'"videoduration"\s?:\s?"([^"]+)"', webpage, 'duration', + fatal=False, default='0') + ) / 1000 + view_count = get_element_by_id('videoViewCount', + webpage).replace('.', '') + timestamp = parse_iso8601(self._html_search_meta('uploadDate', webpage, + 'upload date', fatal=False)) + family_friendly = self._html_search_meta('isFamilyFriendly', webpage, + 'age limit', fatal=False) + uploader = self._html_search_regex(r"adduserUsername\s?=\s?'([^']+)';", + webpage, 'uploader', fatal=False, + default='') + comment_count = self._html_search_regex( + r'comment_count\s?=\s?\'([^\']+)\';', + webpage, 'uploader', fatal=False) + + content_url = self._html_search_meta('contentURL', webpage, + 'content URL', fatal=False) + ext = determine_ext(content_url) + + # Might be empty for some videos. + qualities = self._html_search_regex(r'"quality"\s?:\s?"([^"]+)"', + webpage, 'qualities', fatal=False, + default='') + + formats = [] + for quality in qualities.split('|'): + json = self._download_json( + self._STREAM_URL.format(id=video_id, format=quality), video_id, + note=u'Getting video URL for "%s" quality' % quality, + errnote=u'Failed to get video URL for "%s" quality' % quality + ) + video_format = '%sp' % quality if quality else 'sd' + formats.append({ + 'url': json.get('streamurl'), + 'ext': ext, + 'format': video_format, + 'format_id': video_format, + }) + + return { + 'id': video_id, + 'title': title, + 'formats': formats, + 'description': description, + 'thumbnail': thumbnail, + 'duration': duration, + 'view_count': int_or_none(view_count), + 'timestamp': timestamp, + 'age_limit': 18 if family_friendly == 'False' else 0, + 'uploader_id': uploader, + 'comment_count': int_or_none(comment_count), + } From 71aa656d134f728f7600a48f5015a8c84abe745d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 27 Jul 2014 02:05:06 +0700 Subject: [PATCH 0455/1761] [streamcloud] Remove duration and modernize (Closes #3374) --- youtube_dl/extractor/streamcloud.py | 30 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/youtube_dl/extractor/streamcloud.py b/youtube_dl/extractor/streamcloud.py index 9faf3a5e3..172def221 100644 --- a/youtube_dl/extractor/streamcloud.py +++ b/youtube_dl/extractor/streamcloud.py @@ -1,4 +1,6 @@ # coding: utf-8 +from __future__ import unicode_literals + import re import time @@ -10,18 +12,18 @@ from ..utils import ( class StreamcloudIE(InfoExtractor): - IE_NAME = u'streamcloud.eu' + IE_NAME = 'streamcloud.eu' _VALID_URL = r'https?://streamcloud\.eu/(?P[a-zA-Z0-9_-]+)/(?P[^#?]*)\.html' _TEST = { - u'url': u'http://streamcloud.eu/skp9j99s4bpz/youtube-dl_test_video_____________-BaW_jenozKc.mp4.html', - u'file': u'skp9j99s4bpz.mp4', - u'md5': u'6bea4c7fa5daaacc2a946b7146286686', - u'info_dict': { - u'title': u'youtube-dl test video \'/\\ ä ↭', - u'duration': 9, + 'url': 'http://streamcloud.eu/skp9j99s4bpz/youtube-dl_test_video_____________-BaW_jenozKc.mp4.html', + 'md5': '6bea4c7fa5daaacc2a946b7146286686', + 'info_dict': { + 'id': 'skp9j99s4bpz', + 'ext': 'mp4', + 'title': 'youtube-dl test video \'/\\ ä ↭', }, - u'skip': u'Only available from the EU' + 'skip': 'Only available from the EU' } def _real_extract(self, url): @@ -46,21 +48,17 @@ class StreamcloudIE(InfoExtractor): req = compat_urllib_request.Request(url, post, headers) webpage = self._download_webpage( - req, video_id, note=u'Downloading video page ...') + req, video_id, note='Downloading video page ...') title = self._html_search_regex( - r']*>([^<]+)<', webpage, u'title') + r']*>([^<]+)<', webpage, 'title') video_url = self._search_regex( - r'file:\s*"([^"]+)"', webpage, u'video URL') - duration_str = self._search_regex( - r'duration:\s*"?([0-9]+)"?', webpage, u'duration', fatal=False) - duration = None if duration_str is None else int(duration_str) + r'file:\s*"([^"]+)"', webpage, 'video URL') thumbnail = self._search_regex( - r'image:\s*"([^"]+)"', webpage, u'thumbnail URL', fatal=False) + r'image:\s*"([^"]+)"', webpage, 'thumbnail URL', fatal=False) return { 'id': video_id, 'title': title, 'url': video_url, - 'duration': duration, 'thumbnail': thumbnail, } From cb3ff6fb01fd099ab4102d0f1212abb50e06e5ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 27 Jul 2014 02:38:05 +0700 Subject: [PATCH 0456/1761] [godtube] Add extractor (Closes #3367) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/godtube.py | 58 ++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 youtube_dl/extractor/godtube.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index a8e593002..b8b341afd 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -115,6 +115,7 @@ from .gamespot import GameSpotIE from .gametrailers import GametrailersIE from .gdcvault import GDCVaultIE from .generic import GenericIE +from .godtube import GodTubeIE from .googleplus import GooglePlusIE from .googlesearch import GoogleSearchIE from .gorillavid import GorillaVidIE diff --git a/youtube_dl/extractor/godtube.py b/youtube_dl/extractor/godtube.py new file mode 100644 index 000000000..73bd6d890 --- /dev/null +++ b/youtube_dl/extractor/godtube.py @@ -0,0 +1,58 @@ +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ( + parse_duration, + parse_iso8601, +) + + +class GodTubeIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?godtube\.com/watch/\?v=(?P[\da-zA-Z]+)' + _TESTS = [ + { + 'url': 'https://www.godtube.com/watch/?v=0C0CNNNU', + 'md5': '77108c1e4ab58f48031101a1a2119789', + 'info_dict': { + 'id': '0C0CNNNU', + 'ext': 'mp4', + 'title': 'Woman at the well.', + 'duration': 159, + 'timestamp': 1205712000, + 'uploader': 'beverlybmusic', + 'upload_date': '20080317', + 'thumbnail': 're:^https?://.*\.jpg$', + }, + }, + ] + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + config = self._download_xml( + 'http://www.godtube.com/resource/mediaplayer/%s.xml' % video_id.lower(), + video_id, 'Downloading player config XML') + + video_url = config.find('.//file').text + uploader = config.find('.//author').text + timestamp = parse_iso8601(config.find('.//date').text) + duration = parse_duration(config.find('.//duration').text) + thumbnail = config.find('.//image').text + + media = self._download_xml( + 'http://www.godtube.com/media/xml/?v=%s' % video_id, video_id, 'Downloading media XML') + + title = media.find('.//title').text + + return { + 'id': video_id, + 'url': video_url, + 'title': title, + 'thumbnail': thumbnail, + 'timestamp': timestamp, + 'uploader': uploader, + 'duration': duration, + } From a954584f63cdcd81df37d3499f420a906aef8862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Mon, 28 Jul 2014 00:27:27 +0700 Subject: [PATCH 0457/1761] [bandcamp] Replace 404 playlist test --- test/test_playlists.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_playlists.py b/test/test_playlists.py index c221c47b9..4f188345b 100644 --- a/test/test_playlists.py +++ b/test/test_playlists.py @@ -193,10 +193,10 @@ class TestPlaylists(unittest.TestCase): def test_bandcamp_album(self): dl = FakeYDL() ie = BandcampAlbumIE(dl) - result = ie.extract('http://mpallante.bandcamp.com/album/nightmare-night-ep') + result = ie.extract('http://nightbringer.bandcamp.com/album/hierophany-of-the-open-grave') self.assertIsPlaylist(result) - self.assertEqual(result['title'], 'Nightmare Night EP') - assertGreaterEqual(self, len(result['entries']), 4) + self.assertEqual(result['title'], 'Hierophany of the Open Grave') + assertGreaterEqual(self, len(result['entries']), 9) def test_smotri_community(self): dl = FakeYDL() From 8d2cc6fbb158738b8fd4fafaacf613b4e38757e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Mon, 28 Jul 2014 00:40:17 +0700 Subject: [PATCH 0458/1761] [blinkx] Fix duration --- youtube_dl/extractor/blinkx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/blinkx.py b/youtube_dl/extractor/blinkx.py index 7d558e262..3e461e715 100644 --- a/youtube_dl/extractor/blinkx.py +++ b/youtube_dl/extractor/blinkx.py @@ -52,7 +52,7 @@ class BlinkxIE(InfoExtractor): 'height': int(m['h']), }) elif m['type'] == 'original': - duration = m['d'] + duration = float(m['d']) elif m['type'] == 'youtube': yt_id = m['link'] self.to_screen('Youtube video detected: %s' % yt_id) From 0fc74a0d9191677e9b0e498ea66ddd387d01116f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Mon, 28 Jul 2014 00:45:46 +0700 Subject: [PATCH 0459/1761] [br] Fix test --- youtube_dl/extractor/br.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/br.py b/youtube_dl/extractor/br.py index f7f2f713a..737f01a8c 100644 --- a/youtube_dl/extractor/br.py +++ b/youtube_dl/extractor/br.py @@ -22,8 +22,8 @@ class BRIE(InfoExtractor): 'info_dict': { 'id': '25e279aa-1ffd-40fd-9955-5325bd48a53a', 'ext': 'mp4', - 'title': 'Am 1. und 2. August in Oberammergau', - 'description': 'md5:dfd224e5aa6819bc1fcbb7826a932021', + 'title': 'Wenn das Traditions-Theater wackelt', + 'description': 'Heimatsound-Festival 2014: Wenn das Traditions-Theater wackelt', } }, { From 65bc504db83d6429b6dcde771c0d8c39196a0017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Mon, 28 Jul 2014 00:51:38 +0700 Subject: [PATCH 0460/1761] [br] Extract duration --- youtube_dl/extractor/br.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/youtube_dl/extractor/br.py b/youtube_dl/extractor/br.py index 737f01a8c..86f0c2861 100644 --- a/youtube_dl/extractor/br.py +++ b/youtube_dl/extractor/br.py @@ -7,6 +7,7 @@ from .common import InfoExtractor from ..utils import ( ExtractorError, int_or_none, + parse_duration, ) @@ -24,6 +25,7 @@ class BRIE(InfoExtractor): 'ext': 'mp4', 'title': 'Wenn das Traditions-Theater wackelt', 'description': 'Heimatsound-Festival 2014: Wenn das Traditions-Theater wackelt', + 'duration': 34, } }, { @@ -34,6 +36,7 @@ class BRIE(InfoExtractor): 'ext': 'mp4', 'title': 'Über den Pass', 'description': 'Die Eroberung der Alpen: Über den Pass', + 'duration': 2588, } }, { @@ -44,6 +47,7 @@ class BRIE(InfoExtractor): 'ext': 'aac', 'title': '"Keine neuen Schulden im nächsten Jahr"', 'description': 'Haushaltsentwurf: "Keine neuen Schulden im nächsten Jahr"', + 'duration': 64, } }, { @@ -54,6 +58,7 @@ class BRIE(InfoExtractor): 'ext': 'mp4', 'title': 'Umweltbewusster Häuslebauer', 'description': 'Uwe Erdelt: Umweltbewusster Häuslebauer', + 'duration': 116, } }, { @@ -64,6 +69,7 @@ class BRIE(InfoExtractor): 'ext': 'mp4', 'title': 'Folge 1 - Metaphysik', 'description': 'Kant für Anfänger: Folge 1 - Metaphysik', + 'duration': 893, 'uploader': 'Eva Maria Steimle', 'upload_date': '20140117', } @@ -84,6 +90,7 @@ class BRIE(InfoExtractor): media = { 'id': xml_media.get('externalId'), 'title': xml_media.find('title').text, + 'duration': parse_duration(xml_media.find('duration').text), 'formats': self._extract_formats(xml_media.find('assets')), 'thumbnails': self._extract_thumbnails(xml_media.find('teaserImage/variants')), 'description': ' '.join(xml_media.find('shareTitle').text.splitlines()), From 1a9b9649fbad88ef9f264d2f0e1804ba70c11469 Mon Sep 17 00:00:00 2001 From: Tim Sogard Date: Sun, 27 Jul 2014 17:14:29 -0700 Subject: [PATCH 0461/1761] Check load_more_widget_html for feed paging --- youtube_dl/extractor/youtube.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index c48d1b8ef..cd35a1620 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -1325,6 +1325,7 @@ class YoutubeFeedsInfoExtractor(YoutubeBaseInfoExtractor): u'%s feed' % self._FEED_NAME, u'Downloading page %s' % i) feed_html = info.get('feed_html') or info.get('content_html') + load_more_widget_html = info.get('load_more_widget_html') or feed_html m_ids = re.finditer(r'"/watch\?v=(.*?)["&]', feed_html) ids = orderedSet(m.group(1) for m in m_ids) feed_entries.extend( @@ -1332,7 +1333,7 @@ class YoutubeFeedsInfoExtractor(YoutubeBaseInfoExtractor): for video_id in ids) mobj = re.search( r'data-uix-load-more-href="/?[^"]+paging=(?P\d+)', - feed_html) + load_more_widget_html) if mobj is None: break paging = mobj.group('paging') From 7e8d73c18378ea469b8f1a2185768b16e5b5c947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Mon, 28 Jul 2014 14:37:13 +0200 Subject: [PATCH 0462/1761] [francetv] Extract all the available formats (#3278) For some videos the resolution is not included in the url, we will need to look in the m3u8 manifest. --- youtube_dl/extractor/francetv.py | 36 ++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/youtube_dl/extractor/francetv.py b/youtube_dl/extractor/francetv.py index 1fbe6d175..9e2a93871 100644 --- a/youtube_dl/extractor/francetv.py +++ b/youtube_dl/extractor/francetv.py @@ -19,17 +19,35 @@ class FranceTVBaseInfoExtractor(InfoExtractor): + video_id, video_id, 'Downloading XML config') manifest_url = info.find('videos/video/url').text - video_url = manifest_url.replace('manifest.f4m', 'index_2_av.m3u8') - video_url = video_url.replace('/z/', '/i/') + manifest_url = manifest_url.replace('/z/', '/i/') + + if url.startswith('rtmp'): + formats = [{'url': manifest_url, 'ext': 'flv'}] + else: + formats = [] + available_formats = self._search_regex(r'/[^,]*,(.*?),k\.mp4', manifest_url, 'available formats') + for index, format_descr in enumerate(available_formats.split(',')): + format_info = { + 'url': manifest_url.replace('manifest.f4m', 'index_%d_av.m3u8' % index), + 'ext': 'mp4', + } + m_resolution = re.search(r'(?P\d+)x(?P\d+)', format_descr) + if m_resolution is not None: + format_info.update({ + 'width': int(m_resolution.group('width')), + 'height': int(m_resolution.group('height')), + }) + formats.append(format_info) + thumbnail_path = info.find('image').text - return {'id': video_id, - 'ext': 'flv' if video_url.startswith('rtmp') else 'mp4', - 'url': video_url, - 'title': info.find('titre').text, - 'thumbnail': compat_urlparse.urljoin('http://pluzz.francetv.fr', thumbnail_path), - 'description': info.find('synopsis').text, - } + return { + 'id': video_id, + 'title': info.find('titre').text, + 'formats': formats, + 'thumbnail': compat_urlparse.urljoin('http://pluzz.francetv.fr', thumbnail_path), + 'description': info.find('synopsis').text, + } class PluzzIE(FranceTVBaseInfoExtractor): From 4958ae205873980189793885824418533cd27041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Mon, 28 Jul 2014 15:21:05 +0200 Subject: [PATCH 0463/1761] [francetv] Fix wrong variable name --- youtube_dl/extractor/francetv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/francetv.py b/youtube_dl/extractor/francetv.py index 9e2a93871..1b0e8e5d5 100644 --- a/youtube_dl/extractor/francetv.py +++ b/youtube_dl/extractor/francetv.py @@ -21,7 +21,7 @@ class FranceTVBaseInfoExtractor(InfoExtractor): manifest_url = info.find('videos/video/url').text manifest_url = manifest_url.replace('/z/', '/i/') - if url.startswith('rtmp'): + if manifest_url.startswith('rtmp'): formats = [{'url': manifest_url, 'ext': 'flv'}] else: formats = [] From 31bb8d3f5142f68c9da389caf9fa2356464cc35e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Mon, 28 Jul 2014 15:25:56 +0200 Subject: [PATCH 0464/1761] [bloomberg] Extract the available formats (closes #2776) It uses a helper method in the InfoExtractor class. The downloader will pick the requested formats using the bitrate in the info dict. --- youtube_dl/downloader/f4m.py | 11 +++++++++-- youtube_dl/extractor/bloomberg.py | 5 ++--- youtube_dl/extractor/common.py | 17 +++++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/youtube_dl/downloader/f4m.py b/youtube_dl/downloader/f4m.py index e6be6ae6c..71353f607 100644 --- a/youtube_dl/downloader/f4m.py +++ b/youtube_dl/downloader/f4m.py @@ -220,6 +220,7 @@ class F4mFD(FileDownloader): def real_download(self, filename, info_dict): man_url = info_dict['url'] + requested_bitrate = info_dict.get('tbr') self.to_screen('[download] Downloading f4m manifest') manifest = self.ydl.urlopen(man_url).read() self.report_destination(filename) @@ -233,8 +234,14 @@ class F4mFD(FileDownloader): doc = etree.fromstring(manifest) formats = [(int(f.attrib.get('bitrate', -1)), f) for f in doc.findall(_add_ns('media'))] - formats = sorted(formats, key=lambda f: f[0]) - rate, media = formats[-1] + if requested_bitrate is None: + # get the best format + formats = sorted(formats, key=lambda f: f[0]) + rate, media = formats[-1] + else: + rate, media = list(filter( + lambda f: int(f[0]) == requested_bitrate, formats))[0] + base_url = compat_urlparse.urljoin(man_url, media.attrib['url']) bootstrap = base64.b64decode(doc.find(_add_ns('bootstrapInfo')).text) metadata = base64.b64decode(media.find(_add_ns('metadata')).text) diff --git a/youtube_dl/extractor/bloomberg.py b/youtube_dl/extractor/bloomberg.py index 25fb79e14..c51a97ce4 100644 --- a/youtube_dl/extractor/bloomberg.py +++ b/youtube_dl/extractor/bloomberg.py @@ -10,7 +10,7 @@ class BloombergIE(InfoExtractor): _TEST = { 'url': 'http://www.bloomberg.com/video/shah-s-presentation-on-foreign-exchange-strategies-qurhIVlJSB6hzkVi229d8g.html', - 'md5': '7bf08858ff7c203c870e8a6190e221e5', + # The md5 checksum changes 'info_dict': { 'id': 'qurhIVlJSB6hzkVi229d8g', 'ext': 'flv', @@ -31,8 +31,7 @@ class BloombergIE(InfoExtractor): return { 'id': name.split('-')[-1], 'title': title, - 'url': f4m_url, - 'ext': 'flv', + 'formats': self._extract_f4m_formats(f4m_url, name), 'description': self._og_search_description(webpage), 'thumbnail': self._og_search_thumbnail(webpage), } diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 52c00186e..59030e127 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -18,6 +18,7 @@ from ..utils import ( clean_html, compiled_regex_type, ExtractorError, + int_or_none, RegexNotFoundError, sanitize_filename, unescapeHTML, @@ -590,6 +591,22 @@ class InfoExtractor(object): self.to_screen(msg) time.sleep(timeout) + def _extract_f4m_formats(self, manifest_url, video_id): + manifest = self._download_xml(manifest_url, video_id) + + formats = [] + for media_el in manifest.findall('{http://ns.adobe.com/f4m/1.0}media'): + formats.append({ + 'url': manifest_url, + 'ext': 'flv', + 'tbr': int_or_none(media_el.attrib.get('bitrate')), + 'width': int_or_none(media_el.attrib.get('width')), + 'height': int_or_none(media_el.attrib.get('height')), + }) + self._sort_formats(formats) + + return formats + class SearchInfoExtractor(InfoExtractor): """ From f036a6328e716835c4d3a0d4e0e28fc76184d9c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Mon, 28 Jul 2014 15:42:19 +0200 Subject: [PATCH 0465/1761] [extractor/common] _extract_f4m_formats: Use more specific messages when downloading the manifest --- youtube_dl/extractor/common.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 59030e127..342bfb8b3 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -592,7 +592,9 @@ class InfoExtractor(object): time.sleep(timeout) def _extract_f4m_formats(self, manifest_url, video_id): - manifest = self._download_xml(manifest_url, video_id) + manifest = self._download_xml( + manifest_url, video_id, 'Downloading f4m manifest', + 'Unable to download f4m manifest') formats = [] for media_el in manifest.findall('{http://ns.adobe.com/f4m/1.0}media'): From a00d73c8c8fe1c33053ccc102153c13ead1614ec Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Mon, 28 Jul 2014 13:40:58 -0500 Subject: [PATCH 0466/1761] Add Patreon extractor --- youtube_dl/extractor/patreon.py | 127 ++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 youtube_dl/extractor/patreon.py diff --git a/youtube_dl/extractor/patreon.py b/youtube_dl/extractor/patreon.py new file mode 100644 index 000000000..da1ad065a --- /dev/null +++ b/youtube_dl/extractor/patreon.py @@ -0,0 +1,127 @@ +# encoding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ( + ExtractorError, + compat_html_parser, + #compat_urllib_request, + #compat_urllib_parse, +) + + +class PatreonHTMLParser(compat_html_parser.HTMLParser): + _PREFIX = 'http://www.patreon.com' + _ATTACH_TAGS = 5 * ['div'] + _ATTACH_CLASSES = [ + 'fancyboxhidden', 'box photo double', 'boxwrapper double', + 'hiddendisplay shareinfo', 'attach' + ] + _INFO_TAGS = 4 * ['div'] + _INFO_CLASSES = [ + 'fancyboxhidden', 'box photo double', 'boxwrapper double', + 'hiddendisplay shareinfo' + ] + + def get_creation_info(self, html_data): + self.tag_stack = [] + self.attrs_stack = [] + self.creation_info = {} + self.feed(html_data) + + def handle_starttag(self, tag, attrs): + self.tag_stack.append(tag.lower()) + self.attrs_stack.append(dict(attrs)) + + def handle_endtag(self, tag): + self.tag_stack.pop() + self.attrs_stack.pop() + + def handle_data(self, data): + # Check first if this is a creation attachment + if self.tag_stack[-6:-1] == self._ATTACH_TAGS: + attrs_classes = [ + x.get('class', '').lower() for x in self.attrs_stack[-6:-1] + ] + if attrs_classes == self._ATTACH_CLASSES: + if self.tag_stack[-1] == 'a': + url = self._PREFIX + self.attrs_stack[-1].get('href') + self.creation_info['url'] = url + if '.' in data: + self.creation_info['ext'] = data.rsplit('.')[-1] + # Next, check if this is within the div containing the creation info + if self.tag_stack[-5:-1] == self._INFO_TAGS: + attrs_classes = [ + x.get('class', '').lower() for x in self.attrs_stack[-5:-1] + ] + if attrs_classes == self._INFO_CLASSES: + if self.attrs_stack[-1].get('class') == 'utitle': + self.creation_info['title'] = data.strip() + + +class PatreonIE(InfoExtractor): + IE_NAME = 'patreon' + _VALID_URL = r'https?://(?:www\.)?patreon\.com/creation\?hid=(.+)' + _TESTS = [ + { + 'url': 'http://www.patreon.com/creation?hid=743933', + 'md5': 'e25505eec1053a6e6813b8ed369875cc', + 'name': 'Patreon', + 'info_dict': { + 'id': '743933', + 'ext': 'mp3', + 'title': 'Episode 166: David Smalley of Dogma Debate', + 'uploader': 'Cognitive Dissonance Podcast', + }, + }, + ] + + # Currently Patreon exposes download URL via hidden CSS, so login is not + # needed. Keeping this commented for when this inevitably changes. + ''' + def _login(self): + (username, password) = self._get_login_info() + if username is None: + return + + login_form = { + 'redirectUrl': 'http://www.patreon.com/', + 'email': username, + 'password': password, + } + + request = compat_urllib_request.Request( + 'https://www.patreon.com/processLogin', + compat_urllib_parse.urlencode(login_form).encode('utf-8') + ) + login_page = self._download_webpage(request, None, note='Logging in as %s' % username) + + if re.search(r'onLoginFailed', login_page): + raise ExtractorError('Unable to login, incorrect username and/or password', expected=True) + + def _real_initialize(self): + self._login() + ''' + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group(1) + + info_page = self._download_webpage(url, video_id) + + ret = {'id': video_id} + try: + ret['uploader'] = re.search( + r'(.+) is creating', info_page + ).group(1) + except AttributeError: + pass + + parser = PatreonHTMLParser() + parser.get_creation_info(info_page) + if not parser.creation_info.get('url'): + raise ExtractionError('Unable to retrieve creation URL') + ret.update(parser.creation_info) + return ret From 27ace98f5159efdf6942e69ec73c5840cce26fbf Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Mon, 28 Jul 2014 13:41:28 -0500 Subject: [PATCH 0467/1761] Add import for Patreon extractor --- youtube_dl/extractor/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index b8b341afd..cf7a8d6e1 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -226,6 +226,7 @@ from .oe1 import OE1IE from .ooyala import OoyalaIE from .orf import ORFIE from .parliamentliveuk import ParliamentLiveUKIE +from .patreon import PatreonIE from .pbs import PBSIE from .photobucket import PhotobucketIE from .playvid import PlayvidIE From 8646eb790e2352ec08c50357b9957cbe5548ddaa Mon Sep 17 00:00:00 2001 From: SyxbEaEQ2 Date: Tue, 29 Jul 2014 00:31:33 +0200 Subject: [PATCH 0468/1761] [gamestar] Add new extractor --- youtube_dl/extractor/gamestar.py | 68 ++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 youtube_dl/extractor/gamestar.py diff --git a/youtube_dl/extractor/gamestar.py b/youtube_dl/extractor/gamestar.py new file mode 100644 index 000000000..5c9decdea --- /dev/null +++ b/youtube_dl/extractor/gamestar.py @@ -0,0 +1,68 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor + +class GameStarIE(InfoExtractor): + _VALID_URL = r'http://www\.gamestar\.de/videos/.*,(?P[0-9]+)\.html' + _TEST = { + 'url': 'http://www.gamestar.de/videos/trailer,3/hobbit-3-die-schlacht-der-fuenf-heere,76110.html', + 'md5': '96974ecbb7fd8d0d20fca5a00810cea7', + 'info_dict': { + 'id': '76110', + 'ext': 'mp4', + 'title': 'Hobbit 3: Die Schlacht der Fünf Heere - Teaser-Trailer zum dritten Teil', + 'description': 'Der Teaser-Trailer zu Hobbit 3: Die Schlacht der Fünf Heere zeigt einige Szenen aus dem dritten Teil der Saga und kündigt den vollständigen Trailer an.', + 'thumbnail': 'http://images.gamestar.de/images/idgwpgsgp/bdb/2494525/600x.jpg', + 'upload_date': '20140728', + 'duration': 17 + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + + og_title = self._og_search_title(webpage) + title = og_title.replace(' - Video bei GameStar.de', '').strip() + + url = 'http://gamestar.de/_misc/videos/portal/getVideoUrl.cfm?premium=0&videoId=' + video_id + + description = self._og_search_description(webpage).strip() + + og_thumbnail = self._og_search_thumbnail(webpage) + thumbnail = 'http:' + og_thumbnail + + upload_date_raw = self._html_search_regex( + r'Datum: ([0-9]+\.[0-9]+\.[0-9]+)  ', + webpage, 'upload_date').split('.') + upload_date = upload_date_raw[2] + upload_date_raw[1] + upload_date_raw[0] + + duration_raw = self._html_search_regex( + r'  Länge: ([0-9]+:[0-9]+)', webpage, 'duration').split(':') + duration = int(duration_raw[0])*60 + int(duration_raw[1]) + + view_count_raw = self._html_search_regex( + r'  Zuschauer: ([0-9\.]+)  ', webpage, 'view_count') + view_count = int(view_count_raw.replace('.', '')) + + comment_count_raw = self._html_search_regex( + r'>Kommentieren \(([0-9]+)\)', webpage, 'comment_count') + comment_count = int(comment_count_raw) + + return { + 'id': video_id, + 'title': title, + 'url': url, + 'ext': 'mp4', + 'thumbnail': thumbnail, + 'description': description, + 'upload_date': upload_date, + 'duration': duration, + 'view_count': view_count, + 'comment_count': comment_count + } From a2a1b0baa2ca6dd6dca5442ef3cff7f8fedae448 Mon Sep 17 00:00:00 2001 From: SyxbEaEQ2 Date: Tue, 29 Jul 2014 00:37:18 +0200 Subject: [PATCH 0469/1761] [gamestar] Add new extractor (init) --- youtube_dl/extractor/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index b8b341afd..5ab89a1bf 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -112,6 +112,7 @@ from .funnyordie import FunnyOrDieIE from .gamekings import GamekingsIE from .gameone import GameOneIE from .gamespot import GameSpotIE +from .gamestar import GameStarIE from .gametrailers import GametrailersIE from .gdcvault import GDCVaultIE from .generic import GenericIE From 895ba7d1dd5b92259272198976d150847014b644 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 29 Jul 2014 05:59:47 +0200 Subject: [PATCH 0470/1761] [gamestar] Use helper methods to not break if something changes (#3393) --- youtube_dl/extractor/gamestar.py | 34 +++++++++++++++++++------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/youtube_dl/extractor/gamestar.py b/youtube_dl/extractor/gamestar.py index 5c9decdea..50f8fc7e7 100644 --- a/youtube_dl/extractor/gamestar.py +++ b/youtube_dl/extractor/gamestar.py @@ -4,6 +4,13 @@ from __future__ import unicode_literals import re from .common import InfoExtractor +from ..utils import ( + int_or_none, + parse_duration, + str_to_int, + unified_strdate, +) + class GameStarIE(InfoExtractor): _VALID_URL = r'http://www\.gamestar\.de/videos/.*,(?P[0-9]+)\.html' @@ -34,25 +41,24 @@ class GameStarIE(InfoExtractor): description = self._og_search_description(webpage).strip() - og_thumbnail = self._og_search_thumbnail(webpage) - thumbnail = 'http:' + og_thumbnail + thumbnail = self._proto_relative_url( + self._og_search_thumbnail(webpage), scheme='http:') - upload_date_raw = self._html_search_regex( + upload_date = unified_strdate(self._html_search_regex( r'Datum: ([0-9]+\.[0-9]+\.[0-9]+)  ', - webpage, 'upload_date').split('.') - upload_date = upload_date_raw[2] + upload_date_raw[1] + upload_date_raw[0] + webpage, 'upload_date', fatal=False)) - duration_raw = self._html_search_regex( - r'  Länge: ([0-9]+:[0-9]+)', webpage, 'duration').split(':') - duration = int(duration_raw[0])*60 + int(duration_raw[1]) + duration = parse_duration(self._html_search_regex( + r'  Länge: ([0-9]+:[0-9]+)', webpage, 'duration', + fatal=False)) - view_count_raw = self._html_search_regex( - r'  Zuschauer: ([0-9\.]+)  ', webpage, 'view_count') - view_count = int(view_count_raw.replace('.', '')) + view_count = str_to_int(self._html_search_regex( + r'  Zuschauer: ([0-9\.]+)  ', webpage, + 'view_count', fatal=False)) - comment_count_raw = self._html_search_regex( - r'>Kommentieren \(([0-9]+)\)', webpage, 'comment_count') - comment_count = int(comment_count_raw) + comment_count = int_or_none(self._html_search_regex( + r'>Kommentieren \(([0-9]+)\)', webpage, 'comment_count', + fatal=False)) return { 'id': video_id, From c7b3209668ab722dfab8ebd7b9bb5eb6145f117d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Tue, 29 Jul 2014 20:43:31 +0700 Subject: [PATCH 0471/1761] [swrmediathek] Improve _VALID_URL --- youtube_dl/extractor/swrmediathek.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/swrmediathek.py b/youtube_dl/extractor/swrmediathek.py index 6c688c520..5d9d70367 100644 --- a/youtube_dl/extractor/swrmediathek.py +++ b/youtube_dl/extractor/swrmediathek.py @@ -8,7 +8,7 @@ from ..utils import parse_duration class SWRMediathekIE(InfoExtractor): - _VALID_URL = r'https?://(?:www\.)?swrmediathek\.de/player\.htm\?show=(?P[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12})' + _VALID_URL = r'https?://(?:www\.)?swrmediathek\.de/(?:content/)?player\.htm\?show=(?P[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12})' _TESTS = [{ 'url': 'http://swrmediathek.de/player.htm?show=849790d0-dab8-11e3-a953-0026b975f2e6', @@ -52,6 +52,20 @@ class SWRMediathekIE(InfoExtractor): 'uploader': 'SWR 2', 'uploader_id': '284670', } + }, { + 'url': 'http://swrmediathek.de/content/player.htm?show=52dc7e00-15c5-11e4-84bc-0026b975f2e6', + 'md5': '881531487d0633080a8cc88d31ef896f', + 'info_dict': { + 'id': '52dc7e00-15c5-11e4-84bc-0026b975f2e6', + 'ext': 'mp4', + 'title': 'Familienspaß am Bodensee', + 'description': 'md5:0b591225a32cfde7be1629ed49fe4315', + 'thumbnail': 're:http://.*\.jpg', + 'duration': 1784, + 'upload_date': '20140727', + 'uploader': 'SWR Fernsehen BW', + 'uploader_id': '281130', + } }] def _real_extract(self, url): From 1f7ccb90147184a6234e3b6d603ccec9ee7880e4 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 29 Jul 2014 17:17:43 +0200 Subject: [PATCH 0472/1761] [generic] Add --default-search fixup_error This restores the ability to enter URLs without a scheme (and default to http), but still fail if the input is a search term. --- youtube_dl/__init__.py | 4 ++-- youtube_dl/extractor/generic.py | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 6ff0be00f..a3a8013fb 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -258,7 +258,7 @@ def parseOpts(overrideArguments=None): general.add_option( '--default-search', dest='default_search', metavar='PREFIX', - help='Use this prefix for unqualified URLs. For example "gvsearch2:" downloads two videos from google videos for youtube-dl "large apple". Use the value "auto" to let youtube-dl guess. The default value "error" just throws an error.') + help='Use this prefix for unqualified URLs. For example "gvsearch2:" downloads two videos from google videos for youtube-dl "large apple". Use the value "auto" to let youtube-dl guess ("auto_warning" to emit a warning when guessing). "error" just throws an error. The default value "fixup_error" repairs broken URLs, but emits an error if this is not possible instead of searching.') general.add_option( '--ignore-config', action='store_true', @@ -709,7 +709,7 @@ def _real_main(argv=None): date = DateRange.day(opts.date) else: date = DateRange(opts.dateafter, opts.datebefore) - if opts.default_search not in ('auto', 'auto_warning', None) and ':' not in opts.default_search: + if opts.default_search not in ('auto', 'auto_warning', 'error', 'fixup_error', None) and ':' not in opts.default_search: parser.error(u'--default-search invalid; did you forget a colon (:) at the end?') # Do not download videos when there are audio-only formats diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 9db27f9aa..bcb076594 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -383,13 +383,13 @@ class GenericIE(InfoExtractor): if not parsed_url.scheme: default_search = self._downloader.params.get('default_search') if default_search is None: - default_search = 'error' + default_search = 'fixup_error' - if default_search in ('auto', 'auto_warning'): + if default_search in ('auto', 'auto_warning', 'fixup_error'): if '/' in url: self._downloader.report_warning('The url doesn\'t specify the protocol, trying with http') return self.url_result('http://' + url) - else: + elif default_search != 'fixup_error': if default_search == 'auto_warning': if re.match(r'^(?:url|URL)$', url): raise ExtractorError( @@ -399,7 +399,8 @@ class GenericIE(InfoExtractor): self._downloader.report_warning( 'Falling back to youtube search for %s . Set --default-search "auto" to suppress this warning.' % url) return self.url_result('ytsearch:' + url) - elif default_search == 'error': + + if default_search in ('error', 'fixup_error'): raise ExtractorError( ('%r is not a valid URL. ' 'Set --default-search "ytsearch" (or run youtube-dl "ytsearch:%s" ) to search YouTube' From 10b04ff7f4cdd77cee9e8fcda1a9f77f75a1317f Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 29 Jul 2014 17:19:07 +0200 Subject: [PATCH 0473/1761] Move --bidi-workaround to workarounds option group Duh. --- youtube_dl/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index a3a8013fb..429630ce5 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -252,9 +252,6 @@ def parseOpts(overrideArguments=None): general.add_option( '--socket-timeout', dest='socket_timeout', type=float, default=None, help=u'Time to wait before giving up, in seconds') - general.add_option( - '--bidi-workaround', dest='bidi_workaround', action='store_true', - help=u'Work around terminals that lack bidirectional text support. Requires bidiv or fribidi executable in PATH') general.add_option( '--default-search', dest='default_search', metavar='PREFIX', @@ -386,6 +383,9 @@ def parseOpts(overrideArguments=None): dest='headers', action='append', help='specify a custom HTTP header and its value, separated by a colon \':\'. You can use this option multiple times', ) + workarounds.add_option( + '--bidi-workaround', dest='bidi_workaround', action='store_true', + help=u'Work around terminals that lack bidirectional text support. Requires bidiv or fribidi executable in PATH') verbosity.add_option('-q', '--quiet', action='store_true', dest='quiet', help='activates quiet mode', default=False) From bff74bdd1a0eaf22e1dbd6c3b9b7bf3fd5cab62f Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Wed, 30 Jul 2014 09:49:55 +0200 Subject: [PATCH 0474/1761] [vevo] Sort formats (Fixes #3399) --- youtube_dl/extractor/vevo.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/extractor/vevo.py b/youtube_dl/extractor/vevo.py index eada13ce9..d2ffd1b6b 100644 --- a/youtube_dl/extractor/vevo.py +++ b/youtube_dl/extractor/vevo.py @@ -177,6 +177,7 @@ class VevoIE(InfoExtractor): self._downloader.report_warning( 'Cannot download SMIL information, falling back to JSON ..') + self._sort_formats(formats) timestamp_ms = int(self._search_regex( r'/Date\((\d+)\)/', video_info['launchDate'], 'launch date')) From 4f31d0f2b7610d3b19ffbe55d5b8f4ef231187da Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Wed, 30 Jul 2014 09:50:22 +0200 Subject: [PATCH 0475/1761] release 2014.07.30 --- README.md | 13 ++++++++----- youtube_dl/version.py | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index af880ccc2..a42dfb856 100644 --- a/README.md +++ b/README.md @@ -46,15 +46,15 @@ which means you can modify it, redistribute it or use it however you like. an empty string (--proxy "") for direct connection --socket-timeout None Time to wait before giving up, in seconds - --bidi-workaround Work around terminals that lack - bidirectional text support. Requires bidiv - or fribidi executable in PATH --default-search PREFIX Use this prefix for unqualified URLs. For example "gvsearch2:" downloads two videos from google videos for youtube-dl "large apple". Use the value "auto" to let - youtube-dl guess. The default value "error" - just throws an error. + youtube-dl guess ("auto_warning" to emit a + warning when guessing). "error" just throws + an error. The default value "fixup_error" + repairs broken URLs, but emits an error if + this is not possible instead of searching. --ignore-config Do not read configuration files. When given in the global configuration file /etc /youtube-dl.conf: do not read the user @@ -213,6 +213,9 @@ which means you can modify it, redistribute it or use it however you like. --add-header FIELD:VALUE specify a custom HTTP header and its value, separated by a colon ':'. You can use this option multiple times + --bidi-workaround Work around terminals that lack + bidirectional text support. Requires bidiv + or fribidi executable in PATH ## Video Format Options: -f, --format FORMAT video format code, specify the order of diff --git a/youtube_dl/version.py b/youtube_dl/version.py index e77494595..6e7d56cf7 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.07.25.1' +__version__ = '2014.07.30' From c3f0b12b0f1db168b6d30df68e33a9dba077728e Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Wed, 30 Jul 2014 15:30:07 -0500 Subject: [PATCH 0476/1761] fix exception --- youtube_dl/extractor/patreon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/patreon.py b/youtube_dl/extractor/patreon.py index da1ad065a..4efb18d6c 100644 --- a/youtube_dl/extractor/patreon.py +++ b/youtube_dl/extractor/patreon.py @@ -122,6 +122,6 @@ class PatreonIE(InfoExtractor): parser = PatreonHTMLParser() parser.get_creation_info(info_page) if not parser.creation_info.get('url'): - raise ExtractionError('Unable to retrieve creation URL') + raise ExtractorError('Unable to retrieve creation URL') ret.update(parser.creation_info) return ret From c7667c2d7f602aecfd8a39f26d8151a363ba0b5e Mon Sep 17 00:00:00 2001 From: SyxbEaEQ2 Date: Thu, 31 Jul 2014 03:08:24 +0200 Subject: [PATCH 0477/1761] [downloader/(common/http)] Changes calculation of the rate-limit. (Fix #2297, fix #2140, fix #595, fix #2370) --- youtube_dl/downloader/common.py | 15 +++++++++------ youtube_dl/downloader/http.py | 31 ++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/youtube_dl/downloader/common.py b/youtube_dl/downloader/common.py index 917f3450e..6404e1928 100644 --- a/youtube_dl/downloader/common.py +++ b/youtube_dl/downloader/common.py @@ -77,8 +77,10 @@ class FileDownloader(object): def calc_eta(start, now, total, current): if total is None: return None + if now is None: + now = time.time() dif = now - start - if current == 0 or dif < 0.001: # One millisecond + if current == 0 or dif < 0.001: # One millisecond return None rate = float(current) / dif return int((float(total) - float(current)) / rate) @@ -92,7 +94,7 @@ class FileDownloader(object): @staticmethod def calc_speed(start, now, bytes): dif = now - start - if bytes == 0 or dif < 0.001: # One millisecond + if bytes == 0 or dif < 0.001: # One millisecond return None return float(bytes) / dif @@ -105,7 +107,7 @@ class FileDownloader(object): @staticmethod def best_block_size(elapsed_time, bytes): new_min = max(bytes / 2.0, 1.0) - new_max = min(max(bytes * 2.0, 1.0), 4194304) # Do not surpass 4 MB + new_max = min(max(bytes * 2.0, 1.0), 4194304) # Do not surpass 4 MB if elapsed_time < 0.001: return int(new_max) rate = bytes / elapsed_time @@ -143,18 +145,19 @@ class FileDownloader(object): def report_error(self, *args, **kargs): self.ydl.report_error(*args, **kargs) - def slow_down(self, start_time, byte_counter): + def slow_down(self, start_time, now, byte_counter): """Sleep if the download speed is over the rate limit.""" rate_limit = self.params.get('ratelimit', None) if rate_limit is None or byte_counter == 0: return - now = time.time() + if now is None: + now = time.time() elapsed = now - start_time if elapsed <= 0.0: return speed = float(byte_counter) / elapsed if speed > rate_limit: - time.sleep((byte_counter - rate_limit * (now - start_time)) / rate_limit) + time.sleep((byte_counter / rate_limit) - elapsed) def temp_name(self, filename): """Returns a temporary filename for the given filename.""" diff --git a/youtube_dl/downloader/http.py b/youtube_dl/downloader/http.py index f79e6a995..462be2739 100644 --- a/youtube_dl/downloader/http.py +++ b/youtube_dl/downloader/http.py @@ -128,16 +128,21 @@ class HttpFD(FileDownloader): byte_counter = 0 + resume_len block_size = self.params.get('buffersize', 1024) start = time.time() + + # measure time over whole while-loop, so slow_down() and best_block_size() work together properly + now = None # needed for slow_down() in the first loop run + before = start # start measuring while True: + # Download and write - before = time.time() data_block = data.read(block_size if not is_test else min(block_size, data_len - byte_counter)) - after = time.time() - if len(data_block) == 0: - break byte_counter += len(data_block) - # Open file just in time + # exit loop when download is finished + if len(data_block) == 0: + break + + # Open destination file just in time if stream is None: try: (stream, tmpfilename) = sanitize_open(tmpfilename, open_mode) @@ -153,11 +158,22 @@ class HttpFD(FileDownloader): self.to_stderr(u"\n") self.report_error(u'unable to write data: %s' % str(err)) return False + + # Apply rate limit + self.slow_down(start, now, byte_counter - resume_len) + + # end measuring of one loop run + now = time.time() + after = now + + # Adjust block size if not self.params.get('noresizebuffer', False): block_size = self.best_block_size(after - before, len(data_block)) + before = after + # Progress message - speed = self.calc_speed(start, time.time(), byte_counter - resume_len) + speed = self.calc_speed(start, now, byte_counter - resume_len) if data_len is None: eta = percent = None else: @@ -178,9 +194,6 @@ class HttpFD(FileDownloader): if is_test and byte_counter == data_len: break - # Apply rate limit - self.slow_down(start, byte_counter - resume_len) - if stream is None: self.to_stderr(u"\n") self.report_error(u'Did not get any data blocks') From 0138968a6a5d18e5aca23b52819cd10015997831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Thu, 31 Jul 2014 20:26:52 +0700 Subject: [PATCH 0478/1761] [vidme] Add extractor (Closes #3404) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/vidme.py | 68 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 youtube_dl/extractor/vidme.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 5ab89a1bf..6a9e937af 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -347,6 +347,7 @@ from .videofyme import VideofyMeIE from .videopremium import VideoPremiumIE from .videott import VideoTtIE from .videoweed import VideoWeedIE +from .vidme import VidmeIE from .vimeo import ( VimeoIE, VimeoChannelIE, diff --git a/youtube_dl/extractor/vidme.py b/youtube_dl/extractor/vidme.py new file mode 100644 index 000000000..5c89824c1 --- /dev/null +++ b/youtube_dl/extractor/vidme.py @@ -0,0 +1,68 @@ +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ( + int_or_none, + float_or_none, + str_to_int, +) + + +class VidmeIE(InfoExtractor): + _VALID_URL = r'https?://vid\.me/(?:e/)?(?P[\da-zA-Z]+)' + _TEST = { + 'url': 'https://vid.me/QNB', + 'md5': 'f42d05e7149aeaec5c037b17e5d3dc82', + 'info_dict': { + 'id': 'QNB', + 'ext': 'mp4', + 'title': 'Fishing for piranha - the easy way', + 'description': 'source: https://www.facebook.com/photo.php?v=312276045600871', + 'duration': 119.92, + 'timestamp': 1406313244, + 'upload_date': '20140725', + 'thumbnail': 're:^https?://.*\.jpg', + }, + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + + video_url = self._html_search_regex(r'\s*([\d,\.]+)\s*plays?', webpage, 'view count', fatal=False)) + like_count = str_to_int(self._html_search_regex( + r'class="score js-video-vote-score"[^>]+data-score="([\d,\.\s]+)">', + webpage, 'like count', fatal=False)) + comment_count = str_to_int(self._html_search_regex( + r'class="js-comment-count"[^>]+data-count="([\d,\.\s]+)">', + webpage, 'comment count', fatal=False)) + + return { + 'id': video_id, + 'url': video_url, + 'title': title, + 'description': description, + 'thumbnail': thumbnail, + 'timestamp': timestamp, + 'width': width, + 'height': height, + 'duration': duration, + 'view_count': view_count, + 'like_count': like_count, + 'comment_count': comment_count, + } From b4f23afbd1dd9ee924828a2ad41a2318f8d6323a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Thu, 31 Jul 2014 20:35:29 +0700 Subject: [PATCH 0479/1761] [ard] Encode url (Closes #3412) --- youtube_dl/extractor/ard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/ard.py b/youtube_dl/extractor/ard.py index 30a85c8c1..7ee2ef463 100644 --- a/youtube_dl/extractor/ard.py +++ b/youtube_dl/extractor/ard.py @@ -44,7 +44,7 @@ class ARDIE(InfoExtractor): else: video_id = m.group('video_id') - webpage = self._download_webpage(url, video_id) + webpage = self._download_webpage(url.encode('utf-8'), video_id) title = self._html_search_regex( [r'(.*?)

', From 5622f29ae434be658443970e58303309df63c877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Thu, 31 Jul 2014 21:23:15 +0700 Subject: [PATCH 0480/1761] [ard] Quote path part instead of whole URL encode --- youtube_dl/extractor/ard.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/ard.py b/youtube_dl/extractor/ard.py index 7ee2ef463..957bdefcb 100644 --- a/youtube_dl/extractor/ard.py +++ b/youtube_dl/extractor/ard.py @@ -8,6 +8,8 @@ from ..utils import ( determine_ext, ExtractorError, qualities, + compat_urllib_parse_urlparse, + compat_urllib_parse, ) @@ -44,7 +46,10 @@ class ARDIE(InfoExtractor): else: video_id = m.group('video_id') - webpage = self._download_webpage(url.encode('utf-8'), video_id) + urlp = compat_urllib_parse_urlparse(url) + url = urlp._replace(path=compat_urllib_parse.quote(urlp.path.encode('utf-8'))).geturl() + + webpage = self._download_webpage(url, video_id) title = self._html_search_regex( [r'(.*?)', From f4776371ae6e5472ec6dc96084461df621e99d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Fri, 1 Aug 2014 19:08:09 +0700 Subject: [PATCH 0481/1761] [izlesene] Minor changes --- youtube_dl/extractor/izlesene.py | 83 +++++++++++++++++--------------- youtube_dl/utils.py | 2 + 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/youtube_dl/extractor/izlesene.py b/youtube_dl/extractor/izlesene.py index e51358595..79e8430b5 100644 --- a/youtube_dl/extractor/izlesene.py +++ b/youtube_dl/extractor/izlesene.py @@ -4,25 +4,31 @@ from __future__ import unicode_literals import re from .common import InfoExtractor -from ..utils import get_element_by_id, parse_iso8601, determine_ext, int_or_none +from ..utils import ( + get_element_by_id, + parse_iso8601, + determine_ext, + int_or_none, + str_to_int, +) class IzleseneIE(InfoExtractor): - _VALID_URL = r'https?://(?:www\.|m\.)?izlesene\.com/(?:video|embedplayer)/(?:[^/]+/)?(?P[0-9]+)' + _VALID_URL = r'https?://(?:(?:www|m)\.)?izlesene\.com/(?:video|embedplayer)/(?:[^/]+/)?(?P[0-9]+)' _STREAM_URL = 'http://panel.izlesene.com/api/streamurl/{id:}/{format:}' _TEST = { 'url': 'http://www.izlesene.com/video/sevincten-cildirtan-dogum-gunu-hediyesi/7599694', 'md5': '4384f9f0ea65086734b881085ee05ac2', 'info_dict': { 'id': '7599694', - 'title': u'Sevinçten Çıldırtan Doğum Günü Hediyesi', - 'upload_date': '20140702', - 'uploader_id': 'pelikzzle', - 'description': u'Annesi oğluna doğum günü hediyesi olarak minecraft cd si alıyor, ve çocuk hunharca seviniyor', - 'timestamp': 1404298698, - 'duration': 95, 'ext': 'mp4', + 'title': 'Sevinçten Çıldırtan Doğum Günü Hediyesi', + 'description': 'Annesi oğluna doğum günü hediyesi olarak minecraft cd si alıyor, ve çocuk hunharca seviniyor', 'thumbnail': 're:^http://.*\.jpg', + 'uploader_id': 'pelikzzle', + 'timestamp': 1404298698, + 'upload_date': '20140702', + 'duration': 95.395, 'age_limit': 0, } } @@ -37,58 +43,55 @@ class IzleseneIE(InfoExtractor): title = self._og_search_title(webpage) description = self._og_search_description(webpage) thumbnail = self._og_search_thumbnail(webpage) - duration = int( - self._html_search_regex( - r'"videoduration"\s?:\s?"([^"]+)"', webpage, 'duration', - fatal=False, default='0') - ) / 1000 - view_count = get_element_by_id('videoViewCount', - webpage).replace('.', '') - timestamp = parse_iso8601(self._html_search_meta('uploadDate', webpage, - 'upload date', fatal=False)) - family_friendly = self._html_search_meta('isFamilyFriendly', webpage, - 'age limit', fatal=False) - uploader = self._html_search_regex(r"adduserUsername\s?=\s?'([^']+)';", - webpage, 'uploader', fatal=False, - default='') - comment_count = self._html_search_regex( - r'comment_count\s?=\s?\'([^\']+)\';', - webpage, 'uploader', fatal=False) - content_url = self._html_search_meta('contentURL', webpage, - 'content URL', fatal=False) - ext = determine_ext(content_url) + uploader = self._html_search_regex( + r"adduserUsername\s*=\s*'([^']+)';", webpage, 'uploader', fatal=False, default='') + timestamp = parse_iso8601(self._html_search_meta( + 'uploadDate', webpage, 'upload date', fatal=False)) + + duration = int_or_none(self._html_search_regex( + r'"videoduration"\s*:\s*"([^"]+)"', webpage, 'duration', fatal=False)) + if duration: + duration /= 1000.0 + + view_count = str_to_int(get_element_by_id('videoViewCount', webpage)) + comment_count = self._html_search_regex( + r'comment_count\s*=\s*\'([^\']+)\';', webpage, 'uploader', fatal=False) + + family_friendly = self._html_search_meta( + 'isFamilyFriendly', webpage, 'age limit', fatal=False) + + content_url = self._html_search_meta( + 'contentURL', webpage, 'content URL', fatal=False) + ext = determine_ext(content_url, 'mp4') # Might be empty for some videos. - qualities = self._html_search_regex(r'"quality"\s?:\s?"([^"]+)"', - webpage, 'qualities', fatal=False, - default='') + qualities = self._html_search_regex( + r'"quality"\s*:\s*"([^"]+)"', webpage, 'qualities', fatal=False, default='') formats = [] for quality in qualities.split('|'): json = self._download_json( self._STREAM_URL.format(id=video_id, format=quality), video_id, - note=u'Getting video URL for "%s" quality' % quality, - errnote=u'Failed to get video URL for "%s" quality' % quality + note='Getting video URL for "%s" quality' % quality, + errnote='Failed to get video URL for "%s" quality' % quality ) - video_format = '%sp' % quality if quality else 'sd' formats.append({ 'url': json.get('streamurl'), 'ext': ext, - 'format': video_format, - 'format_id': video_format, + 'format_id': '%sp' % quality if quality else 'sd', }) return { 'id': video_id, 'title': title, - 'formats': formats, 'description': description, 'thumbnail': thumbnail, + 'uploader_id': uploader, + 'timestamp': timestamp, 'duration': duration, 'view_count': int_or_none(view_count), - 'timestamp': timestamp, - 'age_limit': 18 if family_friendly == 'False' else 0, - 'uploader_id': uploader, 'comment_count': int_or_none(comment_count), + 'age_limit': 18 if family_friendly == 'False' else 0, + 'formats': formats, } diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 0d0bbe8f6..e40b367c2 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -852,6 +852,8 @@ def unified_strdate(date_str): return upload_date def determine_ext(url, default_ext=u'unknown_video'): + if url is None: + return default_ext guess = url.partition(u'?')[0].rpartition(u'.')[2] if re.match(r'^[A-Za-z0-9]+$', guess): return guess From 201e9eaa0e7298f50fc98555c871d4458870680f Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 2 Aug 2014 06:35:18 +0200 Subject: [PATCH 0482/1761] [youtube] Show format ID in signature deobfuscation -v output --- youtube_dl/extractor/youtube.py | 83 +++++++++++++++++---------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index c48d1b8ef..511e30c05 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -806,51 +806,54 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): url_map = {} for url_data_str in encoded_url_map.split(','): url_data = compat_parse_qs(url_data_str) - if 'itag' in url_data and 'url' in url_data: - url = url_data['url'][0] - if 'sig' in url_data: - url += '&signature=' + url_data['sig'][0] - elif 's' in url_data: - encrypted_sig = url_data['s'][0] + if 'itag' not in url_data or 'url' not in url_data: + continue + format_id = url_data['itag'][0] + url = url_data['url'][0] - if not age_gate: - jsplayer_url_json = self._search_regex( - r'"assets":.+?"js":\s*("[^"]+")', - video_webpage, u'JS player URL') - player_url = json.loads(jsplayer_url_json) + if 'sig' in url_data: + url += '&signature=' + url_data['sig'][0] + elif 's' in url_data: + encrypted_sig = url_data['s'][0] + + if not age_gate: + jsplayer_url_json = self._search_regex( + r'"assets":.+?"js":\s*("[^"]+")', + video_webpage, u'JS player URL') + player_url = json.loads(jsplayer_url_json) + if player_url is None: + player_url_json = self._search_regex( + r'ytplayer\.config.*?"url"\s*:\s*("[^"]+")', + video_webpage, u'age gate player URL') + player_url = json.loads(player_url_json) + + if self._downloader.params.get('verbose'): if player_url is None: - player_url_json = self._search_regex( - r'ytplayer\.config.*?"url"\s*:\s*("[^"]+")', - video_webpage, u'age gate player URL') - player_url = json.loads(player_url_json) - - if self._downloader.params.get('verbose'): - if player_url is None: - player_version = 'unknown' - player_desc = 'unknown' + player_version = 'unknown' + player_desc = 'unknown' + else: + if player_url.endswith('swf'): + player_version = self._search_regex( + r'-(.+?)(?:/watch_as3)?\.swf$', player_url, + u'flash player', fatal=False) + player_desc = 'flash player %s' % player_version else: - if player_url.endswith('swf'): - player_version = self._search_regex( - r'-(.+?)(?:/watch_as3)?\.swf$', player_url, - u'flash player', fatal=False) - player_desc = 'flash player %s' % player_version - else: - player_version = self._search_regex( - r'html5player-([^/]+?)(?:/html5player)?\.js', - player_url, - 'html5 player', fatal=False) - player_desc = u'html5 player %s' % player_version + player_version = self._search_regex( + r'html5player-([^/]+?)(?:/html5player)?\.js', + player_url, + 'html5 player', fatal=False) + player_desc = u'html5 player %s' % player_version - parts_sizes = u'.'.join(compat_str(len(part)) for part in encrypted_sig.split('.')) - self.to_screen(u'encrypted signature length %d (%s), itag %s, %s' % - (len(encrypted_sig), parts_sizes, url_data['itag'][0], player_desc)) + parts_sizes = u'.'.join(compat_str(len(part)) for part in encrypted_sig.split('.')) + self.to_screen(u'{%s} encrypted signature length %d (%s), itag %s, %s' % + (format_id, len(encrypted_sig), parts_sizes, url_data['itag'][0], player_desc)) - signature = self._decrypt_signature( - encrypted_sig, video_id, player_url, age_gate) - url += '&signature=' + signature - if 'ratebypass' not in url: - url += '&ratebypass=yes' - url_map[url_data['itag'][0]] = url + signature = self._decrypt_signature( + encrypted_sig, video_id, player_url, age_gate) + url += '&signature=' + signature + if 'ratebypass' not in url: + url += '&ratebypass=yes' + url_map[format_id] = url formats = _map_to_format_list(url_map) elif video_info.get('hlsvp'): manifest_url = video_info['hlsvp'][0] From 98eb1c3fa265b2aeb7729e62e4349ec01148f8a6 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 2 Aug 2014 11:55:20 +0200 Subject: [PATCH 0483/1761] [youtube] Clean up -v signature output --- youtube_dl/extractor/youtube.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index 511e30c05..97558b8c0 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -845,8 +845,8 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): player_desc = u'html5 player %s' % player_version parts_sizes = u'.'.join(compat_str(len(part)) for part in encrypted_sig.split('.')) - self.to_screen(u'{%s} encrypted signature length %d (%s), itag %s, %s' % - (format_id, len(encrypted_sig), parts_sizes, url_data['itag'][0], player_desc)) + self.to_screen(u'{%s} signature length %s, %s' % + (format_id, parts_sizes, player_desc)) signature = self._decrypt_signature( encrypted_sig, video_id, player_url, age_gate) From 60064c53f154020b2ace26528a372c42e7d895f1 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 2 Aug 2014 12:21:53 +0200 Subject: [PATCH 0484/1761] [youtube] Make cache ID a tuple of lengths instead of just the whole length --- youtube_dl/extractor/youtube.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index 97558b8c0..d7e9845f7 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -344,7 +344,11 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): """Indicate the download will use the RTMP protocol.""" self.to_screen(u'RTMP download detected') - def _extract_signature_function(self, video_id, player_url, slen): + def _signature_cache_id(self, example_sig): + """ Return a string representation of a signature """ + return u'.'.join(compat_str(len(part)) for part in example_sig.split('.')) + + def _extract_signature_function(self, video_id, player_url, example_sig): id_m = re.match( r'.*-(?P[a-zA-Z0-9_-]+)(?:/watch_as3|/html5player)?\.(?P[a-z]+)$', player_url) @@ -354,7 +358,8 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): player_id = id_m.group('id') # Read from filesystem cache - func_id = '%s_%s_%d' % (player_type, player_id, slen) + func_id = '%s_%s_%s' % ( + player_type, player_id, self._signature_cache_id(example_sig)) assert os.path.basename(func_id) == func_id cache_dir = get_cachedir(self._downloader.params) @@ -388,7 +393,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): if cache_enabled: try: - test_string = u''.join(map(compat_chr, range(slen))) + test_string = u''.join(map(compat_chr, range(len(example_sig)))) cache_res = res(test_string) cache_spec = [ord(c) for c in cache_res] try: @@ -404,7 +409,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): return res - def _print_sig_code(self, func, slen): + def _print_sig_code(self, func, example_sig): def gen_sig_code(idxs): def _genslice(start, end, step): starts = u'' if start == 0 else str(start) @@ -433,11 +438,14 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): else: yield _genslice(start, i, step) - test_string = u''.join(map(compat_chr, range(slen))) + test_string = u''.join(map(compat_chr, range(len(example_sig)))) cache_res = func(test_string) cache_spec = [ord(c) for c in cache_res] expr_code = u' + '.join(gen_sig_code(cache_spec)) - code = u'if len(s) == %d:\n return %s\n' % (slen, expr_code) + signature_id_tuple = '(%s)' % ( + ', '.join(compat_str(len(p)) for p in example_sig.split('.'))) + code = (u'if tuple(len(p) for p in s.split(\'.\')) == %s:\n' + u' return %s\n') % (signature_id_tuple, expr_code) self.to_screen(u'Extracted signature function:\n' + code) def _parse_sig_js(self, jscode): @@ -468,17 +476,17 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): player_id = (player_url, len(s)) if player_id not in self._player_cache: func = self._extract_signature_function( - video_id, player_url, len(s) + video_id, player_url, s ) self._player_cache[player_id] = func func = self._player_cache[player_id] if self._downloader.params.get('youtube_print_sig_code'): - self._print_sig_code(func, len(s)) + self._print_sig_code(func, s) return func(s) except Exception as e: tb = traceback.format_exc() raise ExtractorError( - u'Automatic signature extraction failed: ' + tb, cause=e) + u'Signature extraction failed: ' + tb, cause=e) def _get_available_subtitles(self, video_id, webpage): try: @@ -844,7 +852,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): 'html5 player', fatal=False) player_desc = u'html5 player %s' % player_version - parts_sizes = u'.'.join(compat_str(len(part)) for part in encrypted_sig.split('.')) + parts_sizes = self._signature_cache_id(encrypted_sig) self.to_screen(u'{%s} signature length %s, %s' % (format_id, parts_sizes, player_desc)) From 62af3a0eb5008f21e59949d07430fa2e36dd7e85 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 2 Aug 2014 12:23:18 +0200 Subject: [PATCH 0485/1761] [youtube] Use new signature cache ID for in-memory cache as well --- youtube_dl/extractor/youtube.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index d7e9845f7..3c9b0b584 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -473,7 +473,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): if player_url.startswith(u'//'): player_url = u'https:' + player_url try: - player_id = (player_url, len(s)) + player_id = (player_url, self._signature_cache_id(s)) if player_id not in self._player_cache: func = self._extract_signature_function( video_id, player_url, s From 61aabb9d701a7d67ddec55e6c21810fd59db5e92 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 2 Aug 2014 12:25:40 +0200 Subject: [PATCH 0486/1761] release 2014.08.02 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 6e7d56cf7..1a2cef396 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.07.30' +__version__ = '2014.08.02' From 7a5e7b303c6186f01e475789de7ef8cc3f9eea94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sat, 2 Aug 2014 17:56:01 +0700 Subject: [PATCH 0487/1761] [ubu] Add extractor (Close #3418) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/ubu.py | 56 ++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 youtube_dl/extractor/ubu.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index f6c0ee795..e73bea881 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -327,6 +327,7 @@ from .tutv import TutvIE from .tvigle import TvigleIE from .tvp import TvpIE from .tvplay import TVPlayIE +from.ubu import UbuIE from .udemy import ( UdemyIE, UdemyCourseIE diff --git a/youtube_dl/extractor/ubu.py b/youtube_dl/extractor/ubu.py new file mode 100644 index 000000000..0182d67ec --- /dev/null +++ b/youtube_dl/extractor/ubu.py @@ -0,0 +1,56 @@ +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import int_or_none + + +class UbuIE(InfoExtractor): + _VALID_URL = r'http://(?:www\.)?ubu\.com/film/(?P[\da-z_-]+)\.html' + _TEST = { + 'url': 'http://ubu.com/film/her_noise.html', + 'md5': '8edd46ee8aa6b265fb5ed6cf05c36bc9', + 'info_dict': { + 'id': 'her_noise', + 'ext': 'mp4', + 'title': 'Her Noise - The Making Of (2007)', + 'duration': 3600, + }, + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + + title = self._html_search_regex( + r'.+?Film & Video: ([^<]+)', webpage, 'title') + + duration = int_or_none(self._html_search_regex( + r'Duration: (\d+) minutes', webpage, 'duration', fatal=False, default=None)) + if duration: + duration *= 60 + + formats = [] + + FORMAT_REGEXES = [ + ['sq', r"'flashvars'\s*,\s*'file=([^']+)'"], + ['hq', r'href="(http://ubumexico\.centro\.org\.mx/video/[^"]+)"'] + ] + + for format_id, format_regex in FORMAT_REGEXES: + m = re.search(format_regex, webpage) + if m: + formats.append({ + 'url': m.group(1), + 'format_id': format_id, + }) + + return { + 'id': video_id, + 'title': title, + 'duration': duration, + 'formats': formats, + } From 8d7d9d34521bcfa1b846964f404e8769d2e85ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sat, 2 Aug 2014 19:09:36 +0700 Subject: [PATCH 0488/1761] [pbs] Add support for frontline videos (Closes #3414 #3405) --- youtube_dl/extractor/pbs.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/pbs.py b/youtube_dl/extractor/pbs.py index 64cded707..ec95d0704 100644 --- a/youtube_dl/extractor/pbs.py +++ b/youtube_dl/extractor/pbs.py @@ -32,13 +32,21 @@ class PBSIE(InfoExtractor): }, } - def _real_extract(self, url): + def _extract_ids(self, url): mobj = re.match(self._VALID_URL, url) presumptive_id = mobj.group('presumptive_id') display_id = presumptive_id if presumptive_id: webpage = self._download_webpage(url, display_id) + + # frontline video embed + media_id = self._search_regex( + r"div\s*:\s*'videoembed'\s*,\s*mediaid\s*:\s*'(\d+)'", + webpage, 'frontline video ID', fatal=False, default=None) + if media_id: + return media_id, presumptive_id + url = self._search_regex( r'', webpage, 'player URL') @@ -57,6 +65,11 @@ class PBSIE(InfoExtractor): video_id = mobj.group('id') display_id = video_id + return video_id, display_id + + def _real_extract(self, url): + video_id, display_id = self._extract_ids(url) + info_url = 'http://video.pbs.org/videoInfo/%s?format=json' % video_id info = self._download_json(info_url, display_id) From c97797a737ee96fa5d8f76f73581796b60774637 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 2 Aug 2014 18:16:52 +0200 Subject: [PATCH 0489/1761] release 2014.08.02.1 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 1a2cef396..401fa3d10 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.08.02' +__version__ = '2014.08.02.1' From 493987fefe5d12697df98b6e0eef106e77ac64aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 3 Aug 2014 01:20:51 +0700 Subject: [PATCH 0490/1761] [ubu] Add missing whitespace --- youtube_dl/extractor/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index e73bea881..66c873789 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -327,7 +327,7 @@ from .tutv import TutvIE from .tvigle import TvigleIE from .tvp import TvpIE from .tvplay import TVPlayIE -from.ubu import UbuIE +from .ubu import UbuIE from .udemy import ( UdemyIE, UdemyCourseIE From 5537dce84da34110198fc9b46c1770e5eca0fa8b Mon Sep 17 00:00:00 2001 From: David Fabijan Date: Sun, 3 Aug 2014 10:50:25 +0200 Subject: [PATCH 0491/1761] [Mojvideo] Add new extractor --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/mojvideo.py | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 youtube_dl/extractor/mojvideo.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 66c873789..468c7dc29 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -181,6 +181,7 @@ from .mixcloud import MixcloudIE from .mlb import MLBIE from .mpora import MporaIE from .mofosex import MofosexIE +from .mojvideo import MojvideoIE from .mooshare import MooshareIE from .morningstar import MorningstarIE from .motherless import MotherlessIE diff --git a/youtube_dl/extractor/mojvideo.py b/youtube_dl/extractor/mojvideo.py new file mode 100644 index 000000000..db315c17e --- /dev/null +++ b/youtube_dl/extractor/mojvideo.py @@ -0,0 +1,46 @@ +import re + +from .common import InfoExtractor + +class MojvideoIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?mojvideo\.com/video-.*/(?P[a-f0-9]+)' + _TEST = { + 'url': 'http://www.mojvideo.com/video-v-avtu-pred-mano-rdecelaska-alfi-nipic/3d1ed4497707730b2906', + 'md5': 'f7fd662cc8ce2be107b0d4f2c0483ae7', + 'info_dict': { + 'id': '3d1ed4497707730b2906', + 'ext': 'mp4', + 'title': 'V avtu pred mano rdečelaska - Alfi Nipič', + 'description':'Video: V avtu pred mano rdečelaska - Alfi Nipič', + 'height':378, + 'width':480 + # TODO more properties, either as: + # * A value + # * MD5 checksum; start the string with md5: + # * A regular expression; start the string with re: + # * Any Python type (for example int or float) + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + # TODO more code goes here, for example ... + webpage = self._download_webpage(url, video_id) + title = self._html_search_regex(r'(.*?)', webpage, 'title') + description = self._search_regex(r'', webpage, 'video description') + final_url = self._html_search_regex(r'mp4: \'(.*)\'', webpage, 'video url') + height=int(self._search_regex(r'',webpage,"video height")) + width=int(self._search_regex(r'',webpage,"video width")) + + return { + 'id': video_id, + 'title': title, + 'description': description, + 'ext': 'mp4', + 'url': final_url, + 'height':height, + 'width':width + # TODO more properties (see youtube_dl/extractor/common.py) + } \ No newline at end of file From be79b079070e321dd9ab63573494709f9ae81cbd Mon Sep 17 00:00:00 2001 From: David Fabijan Date: Sun, 3 Aug 2014 11:55:51 +0200 Subject: [PATCH 0492/1761] [Mojvideo] Add new extractor (minor changes) --- youtube_dl/extractor/mojvideo.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/youtube_dl/extractor/mojvideo.py b/youtube_dl/extractor/mojvideo.py index db315c17e..db2bb6dc2 100644 --- a/youtube_dl/extractor/mojvideo.py +++ b/youtube_dl/extractor/mojvideo.py @@ -12,13 +12,8 @@ class MojvideoIE(InfoExtractor): 'ext': 'mp4', 'title': 'V avtu pred mano rdečelaska - Alfi Nipič', 'description':'Video: V avtu pred mano rdečelaska - Alfi Nipič', - 'height':378, + 'height':37 8, 'width':480 - # TODO more properties, either as: - # * A value - # * MD5 checksum; start the string with md5: - # * A regular expression; start the string with re: - # * Any Python type (for example int or float) } } @@ -26,7 +21,6 @@ class MojvideoIE(InfoExtractor): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('id') - # TODO more code goes here, for example ... webpage = self._download_webpage(url, video_id) title = self._html_search_regex(r'(.*?)', webpage, 'title') description = self._search_regex(r'', webpage, 'video description') @@ -42,5 +36,4 @@ class MojvideoIE(InfoExtractor): 'url': final_url, 'height':height, 'width':width - # TODO more properties (see youtube_dl/extractor/common.py) } \ No newline at end of file From 78b296b0ff3f759d17ca1b5de9fb057b6867c089 Mon Sep 17 00:00:00 2001 From: David Fabijan Date: Sun, 3 Aug 2014 11:56:32 +0200 Subject: [PATCH 0493/1761] [Mojvideo] Add new extractor (minor changes) --- youtube_dl/extractor/mojvideo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/mojvideo.py b/youtube_dl/extractor/mojvideo.py index db2bb6dc2..1223fdf2f 100644 --- a/youtube_dl/extractor/mojvideo.py +++ b/youtube_dl/extractor/mojvideo.py @@ -12,7 +12,7 @@ class MojvideoIE(InfoExtractor): 'ext': 'mp4', 'title': 'V avtu pred mano rdečelaska - Alfi Nipič', 'description':'Video: V avtu pred mano rdečelaska - Alfi Nipič', - 'height':37 8, + 'height':378, 'width':480 } } From 548f31d99c5439b1d9de849fe78e00341e887447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Mon, 4 Aug 2014 00:04:47 +0700 Subject: [PATCH 0494/1761] [vimeo] Use original URL when for standard vimeo.com links (Closes #3428) Some videos that are freely accessible without password via the original URL (e.g. http://vimeo.com/channels/keypeele/75629013) ask for password when accessed via http://vimeo.com/. --- youtube_dl/extractor/vimeo.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/vimeo.py b/youtube_dl/extractor/vimeo.py index a3c6e83b0..10844f39e 100644 --- a/youtube_dl/extractor/vimeo.py +++ b/youtube_dl/extractor/vimeo.py @@ -121,6 +121,21 @@ class VimeoIE(VimeoBaseInfoExtractor, SubtitlesInfoExtractor): 'videopassword': 'youtube-dl', }, }, + { + 'url': 'http://vimeo.com/channels/keypeele/75629013', + 'md5': '2f86a05afe9d7abc0b9126d229bbe15d', + 'note': 'Video is freely available via original URL ' + 'and protected with password when accessed via http://vimeo.com/75629013', + 'info_dict': { + 'id': '75629013', + 'ext': 'mp4', + 'title': 'Key & Peele: Terrorist Interrogation', + 'description': 'md5:8678b246399b070816b12313e8b4eb5c', + 'uploader_id': 'atencio', + 'uploader': 'Peter Atencio', + 'duration': 187, + }, + }, { 'url': 'http://vimeo.com/76979871', 'md5': '3363dd6ffebe3784d56f4132317fd446', @@ -196,8 +211,6 @@ class VimeoIE(VimeoBaseInfoExtractor, SubtitlesInfoExtractor): video_id = mobj.group('id') if mobj.group('pro') or mobj.group('player'): url = 'http://player.vimeo.com/video/' + video_id - else: - url = 'https://vimeo.com/' + video_id # Retrieve video webpage to extract further information request = compat_urllib_request.Request(url, None, headers) From a229909fa616c8b2820ea3b254861f07bedcd376 Mon Sep 17 00:00:00 2001 From: Naglis Jonaitis Date: Sun, 3 Aug 2014 21:24:44 +0300 Subject: [PATCH 0495/1761] [jove] Add new extractor. Closes #3177 --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/jove.py | 64 ++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 youtube_dl/extractor/jove.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 2bf8bc5e8..c80a1bd48 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -144,6 +144,7 @@ from .ivi import ( from .izlesene import IzleseneIE from .jadorecettepub import JadoreCettePubIE from .jeuxvideo import JeuxVideoIE +from .jove import JoveIE from .jukebox import JukeboxIE from .justintv import JustinTVIE from .jpopsukitv import JpopsukiIE diff --git a/youtube_dl/extractor/jove.py b/youtube_dl/extractor/jove.py new file mode 100644 index 000000000..a7110b683 --- /dev/null +++ b/youtube_dl/extractor/jove.py @@ -0,0 +1,64 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re +from datetime import datetime + +from .common import InfoExtractor +from ..utils import determine_ext, ExtractorError + + +class JoveIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?jove\.com/video/(?P[0-9]+)' + _CHAPTERS_URL = 'http://www.jove.com/video-chapters?videoid={video_id:}' + _TEST = { + 'url': 'http://www.jove.com/video/2744/electrode-positioning-montage-transcranial-direct-current', + 'md5': '93723888d82dbd6ba8b3d7d0cd65dd2b', + 'info_dict': { + 'id': '2744', + 'ext': 'mp4', + 'title': 'Electrode Positioning and Montage in Transcranial Direct Current Stimulation', + 'description': 'Transcranial direct current stimulation (tDCS) is an established technique to modulate cortical excitability1,2. It has been ...', + 'thumbnail': 're:^https?://.*\.png$', + 'upload_date': '20110523', + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + title = self._html_search_meta('citation_title', webpage, 'title') + thumbnail = self._og_search_thumbnail(webpage) + description = self._html_search_meta( + 'description', webpage, 'description', fatal=False) + publish_date = self._html_search_meta( + 'citation_publication_date', webpage, 'publish date', fatal=False) + if publish_date: + publish_date = datetime.strptime(publish_date, + '%Y/%m/%d').strftime('%Y%m%d') + + # Not the same as video_id. + chapters_id = self._html_search_regex( + r'/video-chapters\?videoid=([0-9]+)', webpage, 'chapters id') + chapters_xml = self._download_xml( + self._CHAPTERS_URL.format(video_id=chapters_id), + video_id, note='Downloading chapter XML', + errnote='Failed to download chapter XML' + ) + video_url = chapters_xml.attrib.get('video') + if not video_url: + raise ExtractorError('Failed to get the video URL') + + ext = determine_ext(video_url) + + return { + 'id': video_id, + 'title': title, + 'url': video_url, + 'ext': ext, + 'thumbnail': thumbnail, + 'description': description, + 'upload_date': publish_date, + } From 5ecd7b0a922a07fb74bd32ac1b55cfd73181849c Mon Sep 17 00:00:00 2001 From: Sebastian Haas Date: Sun, 3 Aug 2014 20:47:56 +0200 Subject: [PATCH 0496/1761] [fm4] Add new extractor --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/fm4.py | 49 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 youtube_dl/extractor/fm4.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 66c873789..e5ce08bc1 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -96,6 +96,7 @@ from .fktv import ( FKTVPosteckeIE, ) from .flickr import FlickrIE +from .fm4 import FM4IE from .fourtube import FourTubeIE from .franceculture import FranceCultureIE from .franceinter import FranceInterIE diff --git a/youtube_dl/extractor/fm4.py b/youtube_dl/extractor/fm4.py new file mode 100644 index 000000000..4eb63ffa9 --- /dev/null +++ b/youtube_dl/extractor/fm4.py @@ -0,0 +1,49 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import calendar +import datetime +import re + +from .common import InfoExtractor + +# audios on fm4.orf.at are only available for 7 days, so we can't +# add tests. + + +class FM4IE(InfoExtractor): + IE_DESC = 'fm4.orf.at' + _VALID_URL = r'http://fm4\.orf\.at/7tage#(?P[0-9]+)/(?P[\w]+)' + + def _extract_entry_dict(self, info, title, subtitle): + result = { + 'id': info['loopStreamId'].replace('.mp3', ''), + 'url': 'http://loopstream01.apa.at/?channel=fm4&id=%s' % info['loopStreamId'], + 'title': title, + 'description': subtitle, + 'duration': (info['end'] - info['start']) / 1000, + 'timestamp': info['start'] / 1000, + 'ext': 'mp3' + } + + return result + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + show_date = mobj.group('date') + show_id = mobj.group('show') + + data = self._download_json( + 'http://audioapi.orf.at/fm4/json/2.0/broadcasts/%s/4%s' % (show_date, show_id), + show_id + ) + + entries = [ self._extract_entry_dict(t, data['title'], data['subtitle']) for t in data['streams']] + + return { + '_type': 'playlist', + 'id': show_id, + 'title': data['title'], + 'description': data['subtitle'], + 'entries': entries + } From 3e510af38d795aa3de2a86af5320f91656a7833b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dobros=C5=82aw=20=C5=BBybort?= Date: Mon, 4 Aug 2014 21:37:36 +0200 Subject: [PATCH 0497/1761] [vimeo] Ignore video 'base' thumbnail (Closes #3438) --- youtube_dl/extractor/vimeo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/vimeo.py b/youtube_dl/extractor/vimeo.py index 10844f39e..11c7d7e81 100644 --- a/youtube_dl/extractor/vimeo.py +++ b/youtube_dl/extractor/vimeo.py @@ -276,7 +276,7 @@ class VimeoIE(VimeoBaseInfoExtractor, SubtitlesInfoExtractor): if video_thumbnail is None: video_thumbs = config["video"].get("thumbs") if video_thumbs and isinstance(video_thumbs, dict): - _, video_thumbnail = sorted((int(width), t_url) for (width, t_url) in video_thumbs.items())[-1] + _, video_thumbnail = sorted((int(width if width.isdigit() else 0), t_url) for (width, t_url) in video_thumbs.items())[-1] # Extract video description video_description = None From 6994e70651180cfe7c5d097fee517de78429c18d Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Tue, 5 Aug 2014 00:26:23 -0500 Subject: [PATCH 0498/1761] Fix CSS parsing for Patreon Some of the CSS classes end in " double", so this commit refines the HTML parsing to account for both kinds of classes, and also adds an additional test case. --- youtube_dl/extractor/patreon.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/youtube_dl/extractor/patreon.py b/youtube_dl/extractor/patreon.py index 4efb18d6c..4ddff42e6 100644 --- a/youtube_dl/extractor/patreon.py +++ b/youtube_dl/extractor/patreon.py @@ -16,15 +16,25 @@ class PatreonHTMLParser(compat_html_parser.HTMLParser): _PREFIX = 'http://www.patreon.com' _ATTACH_TAGS = 5 * ['div'] _ATTACH_CLASSES = [ - 'fancyboxhidden', 'box photo double', 'boxwrapper double', + 'fancyboxhidden', 'box photo', 'boxwrapper', 'hiddendisplay shareinfo', 'attach' ] _INFO_TAGS = 4 * ['div'] _INFO_CLASSES = [ - 'fancyboxhidden', 'box photo double', 'boxwrapper double', + 'fancyboxhidden', 'box photo', 'boxwrapper', 'hiddendisplay shareinfo' ] + def _match(self, attrs_classes, desired): + if attrs_classes == desired: + return True + elif len(attrs_classes) == len(desired): + return all( + x.startswith(y) + for x, y in zip(attrs_classes, desired) + ) + return False + def get_creation_info(self, html_data): self.tag_stack = [] self.attrs_stack = [] @@ -45,7 +55,7 @@ class PatreonHTMLParser(compat_html_parser.HTMLParser): attrs_classes = [ x.get('class', '').lower() for x in self.attrs_stack[-6:-1] ] - if attrs_classes == self._ATTACH_CLASSES: + if self._match(attrs_classes, self._ATTACH_CLASSES): if self.tag_stack[-1] == 'a': url = self._PREFIX + self.attrs_stack[-1].get('href') self.creation_info['url'] = url @@ -56,7 +66,7 @@ class PatreonHTMLParser(compat_html_parser.HTMLParser): attrs_classes = [ x.get('class', '').lower() for x in self.attrs_stack[-5:-1] ] - if attrs_classes == self._INFO_CLASSES: + if self._match(attrs_classes, self._INFO_CLASSES): if self.attrs_stack[-1].get('class') == 'utitle': self.creation_info['title'] = data.strip() @@ -65,10 +75,10 @@ class PatreonIE(InfoExtractor): IE_NAME = 'patreon' _VALID_URL = r'https?://(?:www\.)?patreon\.com/creation\?hid=(.+)' _TESTS = [ + # CSS names with "double" in the name, i.e. "boxwrapper double" { 'url': 'http://www.patreon.com/creation?hid=743933', 'md5': 'e25505eec1053a6e6813b8ed369875cc', - 'name': 'Patreon', 'info_dict': { 'id': '743933', 'ext': 'mp3', @@ -76,6 +86,16 @@ class PatreonIE(InfoExtractor): 'uploader': 'Cognitive Dissonance Podcast', }, }, + { + 'url': 'http://www.patreon.com/creation?hid=754133', + 'md5': '3eb09345bf44bf60451b8b0b81759d0a', + 'info_dict': { + 'id': '754133', + 'ext': 'mp3', + 'title': 'CD 167 Extra', + 'uploader': 'Cognitive Dissonance Podcast', + }, + }, ] # Currently Patreon exposes download URL via hidden CSS, so login is not From 1ce464aba9048b697615df1cd3aa2f5675bff009 Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Tue, 5 Aug 2014 00:38:43 -0500 Subject: [PATCH 0499/1761] Add more information about running tests, add syntax highlighting There was no information in the README about how to handle multiple tests for a given extractor. This commit adds an explanation of how this is handled. It also adds some syntax highlighting. --- README.md | 119 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index a42dfb856..cecfd1098 100644 --- a/README.md +++ b/README.md @@ -303,10 +303,12 @@ The current default template is `%(title)s-%(id)s.%(ext)s`. In some cases, you don't want special characters such as 中, spaces, or &, such as when transferring the downloaded filename to a Windows system or the filename through an 8bit-unsafe channel. In these cases, add the `--restrict-filenames` flag to get a shorter title: - $ youtube-dl --get-filename -o "%(title)s.%(ext)s" BaW_jenozKc - youtube-dl test video ''_ä↭𝕐.mp4 # All kinds of weird characters - $ youtube-dl --get-filename -o "%(title)s.%(ext)s" BaW_jenozKc --restrict-filenames - youtube-dl_test_video_.mp4 # A simple file name +```bash +$ youtube-dl --get-filename -o "%(title)s.%(ext)s" BaW_jenozKc +youtube-dl test video ''_ä↭𝕐.mp4 # All kinds of weird characters +$ youtube-dl --get-filename -o "%(title)s.%(ext)s" BaW_jenozKc --restrict-filenames +youtube-dl_test_video_.mp4 # A simple file name +``` # VIDEO SELECTION @@ -317,14 +319,16 @@ Videos can be filtered by their upload date using the options `--date`, `--dateb Examples: - # Download only the videos uploaded in the last 6 months - $ youtube-dl --dateafter now-6months +```bash +# Download only the videos uploaded in the last 6 months +$ youtube-dl --dateafter now-6months - # Download only the videos uploaded on January 1, 1970 - $ youtube-dl --date 19700101 +# Download only the videos uploaded on January 1, 1970 +$ youtube-dl --date 19700101 - $ # will only download the videos uploaded in the 200x decade - $ youtube-dl --dateafter 20000101 --datebefore 20091231 +$ # will only download the videos uploaded in the 200x decade +$ youtube-dl --dateafter 20000101 --datebefore 20091231 +``` # FAQ @@ -399,49 +403,76 @@ If you want to add support for a new site, you can follow this quick list (assum 2. Check out the source code with `git clone git@github.com:YOUR_GITHUB_USERNAME/youtube-dl.git` 3. Start a new git branch with `cd youtube-dl; git checkout -b yourextractor` 4. Start with this simple template and save it to `youtube_dl/extractor/yourextractor.py`: + ```python + # coding: utf-8 + from __future__ import unicode_literals - # coding: utf-8 - from __future__ import unicode_literals + import re - import re + from .common import InfoExtractor - from .common import InfoExtractor - - - class YourExtractorIE(InfoExtractor): - _VALID_URL = r'https?://(?:www\.)?yourextractor\.com/watch/(?P[0-9]+)' - _TEST = { - 'url': 'http://yourextractor.com/watch/42', - 'md5': 'TODO: md5 sum of the first 10KiB of the video file', - 'info_dict': { - 'id': '42', - 'ext': 'mp4', - 'title': 'Video title goes here', - # TODO more properties, either as: - # * A value - # * MD5 checksum; start the string with md5: - # * A regular expression; start the string with re: - # * Any Python type (for example int or float) - } + + class YourExtractorIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?yourextractor\.com/watch/(?P[0-9]+)' + _TEST = { + 'url': 'http://yourextractor.com/watch/42', + 'md5': 'TODO: md5 sum of the first 10KiB of the video file', + 'info_dict': { + 'id': '42', + 'ext': 'mp4', + 'title': 'Video title goes here', + # TODO more properties, either as: + # * A value + # * MD5 checksum; start the string with md5: + # * A regular expression; start the string with re: + # * Any Python type (for example int or float) } + } - def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') - - # TODO more code goes here, for example ... - webpage = self._download_webpage(url, video_id) - title = self._html_search_regex(r'

(.*?)

', webpage, 'title') - - return { - 'id': video_id, - 'title': title, - # TODO more properties (see youtube_dl/extractor/common.py) - } + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + # TODO more code goes here, for example ... + webpage = self._download_webpage(url, video_id) + title = self._html_search_regex(r'

(.*?)

', webpage, 'title') + return { + 'id': video_id, + 'title': title, + # TODO more properties (see youtube_dl/extractor/common.py) + } + ``` 5. Add an import in [`youtube_dl/extractor/__init__.py`](https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/__init__.py). 6. Run `python test/test_download.py TestDownload.test_YourExtractor`. This *should fail* at first, but you can continually re-run it until you're done. + * If you decide to add more than one test, then rename the ``_TEST`` variable to ``_TESTS`` and make it into a list of dictionaries, like the example below. The tests will be then respectfully be named `TestDownload.test_YourExtractor`, `TestDownload.test_YourExtractor_1`, `TestDownload.test_YourExtractor_2`, etc. + ```python + _TESTS = [ + { + 'url': 'http://yourextractor.com/watch/42', + 'md5': 'TODO: md5 sum of the first 10KiB of the video file', + 'info_dict': { + 'id': '42', + 'ext': 'mp4', + 'title': 'Video title goes here', + # TODO more properties, either as: + # * A value + # * MD5 checksum; start the string with md5: + # * A regular expression; start the string with re: + # * Any Python type (for example int or float) + } + }, + { + 'url': 'http://yourextractor.com/watch/43', + 'md5': 'TODO: md5 sum of the first 10KiB of the video file', + 'info_dict': { + 'id': '43', + 'ext': 'mp4', + 'title': 'Video title goes here', + } + } + ] + ``` 7. Have a look at [`youtube_dl/common/extractor/common.py`](https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/common.py) for possible helper methods and a [detailed description of what your extractor should return](https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/common.py#L38). Add tests and code for as many as you want. 8. If you can, check the code with [pyflakes](https://pypi.python.org/pypi/pyflakes) (a good idea) and [pep8](https://pypi.python.org/pypi/pep8) (optional, ignore E501). 9. When the tests pass, [add](https://www.kernel.org/pub/software/scm/git/docs/git-add.html) the new files and [commit](https://www.kernel.org/pub/software/scm/git/docs/git-commit.html) them and [push](https://www.kernel.org/pub/software/scm/git/docs/git-push.html) the result, like this: From e48a2c646d8f424d68585f6765287387f2f5b229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Tue, 5 Aug 2014 19:09:11 +0700 Subject: [PATCH 0500/1761] Credit @matrixik for #3441 --- youtube_dl/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 429630ce5..f9c16e426 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -66,6 +66,7 @@ __authors__ = ( 'Naglis Jonaitis', 'Charles Chen', 'Hassaan Ali', + 'Dobrosław Żybort', ) __license__ = 'Public Domain' From 6de0595eb845bc913f3bcae9126a5a8476048e5c Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 5 Aug 2014 17:02:47 +0200 Subject: [PATCH 0501/1761] release 2014.08.05 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 401fa3d10..08b5339f6 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.08.02.1' +__version__ = '2014.08.05' From 6b8492a782464fabfc8412790f01d934ea5b6631 Mon Sep 17 00:00:00 2001 From: Naglis Jonaitis Date: Wed, 6 Aug 2014 02:26:42 +0300 Subject: [PATCH 0502/1761] [firedrive] fix broken extractor --- youtube_dl/extractor/firedrive.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/youtube_dl/extractor/firedrive.py b/youtube_dl/extractor/firedrive.py index 6d73c8a4a..af439ccfe 100644 --- a/youtube_dl/extractor/firedrive.py +++ b/youtube_dl/extractor/firedrive.py @@ -42,7 +42,6 @@ class FiredriveIE(InfoExtractor): fields = dict(re.findall(r'''(?x) Date: Wed, 6 Aug 2014 14:44:29 +0200 Subject: [PATCH 0503/1761] Fixed the encoding --- youtube-dl | Bin 3445 -> 534171 bytes youtube_dl/extractor/mojvideo.py | 2 ++ 2 files changed, 2 insertions(+) diff --git a/youtube-dl b/youtube-dl index e3eb8774caa258ddbaa51323938fbd36c4fc170d..87b20758a8c21be72a75432c7eec14a604c69d55 100755 GIT binary patch literal 534171 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ðWKVpR>`691F9sJy#EX%Ot@POy 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 Ged3%<= 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�BxxNMSV4N0qbm5DL-mf*OX?88F1sK0<;mq_jj; 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≻;eJn@T~uL#CiGi8PTmYV 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 XXg)ZDx7{cKgcG0|aWYnP6T^Q26dqrA diff --git a/youtube_dl/extractor/mojvideo.py b/youtube_dl/extractor/mojvideo.py index 1223fdf2f..ddfef6d3c 100644 --- a/youtube_dl/extractor/mojvideo.py +++ b/youtube_dl/extractor/mojvideo.py @@ -1,3 +1,5 @@ +# coding: utf-8 +from __future__ import unicode_literals import re from .common import InfoExtractor From b42a2a720bb7f1bba0bd8bf326b34e2bcc7a98e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Wed, 6 Aug 2014 20:37:59 +0700 Subject: [PATCH 0504/1761] [mojvideo] Switch to API, handle errors, remove faked width and height --- youtube_dl/extractor/mojvideo.py | 47 ++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/youtube_dl/extractor/mojvideo.py b/youtube_dl/extractor/mojvideo.py index ddfef6d3c..90b460d65 100644 --- a/youtube_dl/extractor/mojvideo.py +++ b/youtube_dl/extractor/mojvideo.py @@ -1,41 +1,58 @@ # coding: utf-8 from __future__ import unicode_literals + import re from .common import InfoExtractor +from ..utils import ( + ExtractorError, + parse_duration, +) + class MojvideoIE(InfoExtractor): - _VALID_URL = r'https?://(?:www\.)?mojvideo\.com/video-.*/(?P[a-f0-9]+)' + _VALID_URL = r'https?://(?:www\.)?mojvideo\.com/video-(?P[^/]+)/(?P[a-f0-9]+)' _TEST = { 'url': 'http://www.mojvideo.com/video-v-avtu-pred-mano-rdecelaska-alfi-nipic/3d1ed4497707730b2906', 'md5': 'f7fd662cc8ce2be107b0d4f2c0483ae7', 'info_dict': { 'id': '3d1ed4497707730b2906', + 'display_id': 'v-avtu-pred-mano-rdecelaska-alfi-nipic', 'ext': 'mp4', 'title': 'V avtu pred mano rdečelaska - Alfi Nipič', - 'description':'Video: V avtu pred mano rdečelaska - Alfi Nipič', - 'height':378, - 'width':480 + 'thumbnail': 're:^http://.*\.jpg$', + 'duration': 242, } } def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('id') + display_id = mobj.group('display_id') - webpage = self._download_webpage(url, video_id) - title = self._html_search_regex(r'(.*?)', webpage, 'title') - description = self._search_regex(r'', webpage, 'video description') - final_url = self._html_search_regex(r'mp4: \'(.*)\'', webpage, 'video url') - height=int(self._search_regex(r'',webpage,"video height")) - width=int(self._search_regex(r'',webpage,"video width")) + # XML is malformed + playerapi = self._download_webpage( + 'http://www.mojvideo.com/playerapi.php?v=%s&t=1' % video_id, display_id) + + if 'true' in playerapi: + error_desc = self._html_search_regex( + r'([^<]*)', playerapi, 'error description', fatal=False) + raise ExtractorError('%s said: %s' % (self.IE_NAME, error_desc), expected=True) + + title = self._html_search_regex( + r'([^<]+)', playerapi, 'title') + video_url = self._html_search_regex( + r'([^<]+)', playerapi, 'video URL') + thumbnail = self._html_search_regex( + r'([^<]+)', playerapi, 'thumbnail', fatal=False) + duration = parse_duration(self._html_search_regex( + r'([^<]+)', playerapi, 'duration', fatal=False)) return { 'id': video_id, + 'display_id': display_id, + 'url': video_url, 'title': title, - 'description': description, - 'ext': 'mp4', - 'url': final_url, - 'height':height, - 'width':width + 'thumbnail': thumbnail, + 'duration': duration, } \ No newline at end of file From 4665664c922107a70fb06efe6c9891e163883f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Wed, 6 Aug 2014 20:40:55 +0700 Subject: [PATCH 0505/1761] Credit @DavidFabijan for mojvideo (#3423) --- youtube_dl/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index f9c16e426..9b41587e7 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -67,6 +67,7 @@ __authors__ = ( 'Charles Chen', 'Hassaan Ali', 'Dobrosław Żybort', + 'David Fabijan', ) __license__ = 'Public Domain' From cccfab64127df3bf8ffa8fd0f4acea786b9ea06a Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Wed, 6 Aug 2014 19:30:14 +0200 Subject: [PATCH 0506/1761] Restore youtube-dl compat binary Be on the lookout, it might be modified in pull requests. When I come back from my vacation (in three days from now), I'll start looking whether we really need the compat binary. --- youtube-dl | Bin 534171 -> 3445 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/youtube-dl b/youtube-dl index 87b20758a8c21be72a75432c7eec14a604c69d55..e3eb8774caa258ddbaa51323938fbd36c4fc170d 100755 GIT binary patch literal 3445 zcmbVOdvDuD692pU6yp>ajEG1SN zkH;R0Oy=l16*r||&a|cDTB99iwEE17*->GCgxOYmD>K`V*^ zST}-V06PD+fz(%_S{QUDJB<+3-D9Nhj&Mk#;$Fmu*c-lt#jy-h0{zGSu z;=5IPFsO;|?o|KCe6(Yv^-9rt>(9U@$bI(9vy+s8fs35- zu!DnaOq1e^yaIukYcLX;I_CzVG#aY{q(In8g<#4pdiR1}=QmWo-;^45WmOS$iW46_-EykA5swW1*s#@yONOd4* zTRS?~|G_?>Qq&FQWB~NHe2b6aJe>S6P)!Pg9YHjN1U6<|tv_2xntXWo>gD^Z)rXtk z>E_wyI~I5OIDaA$ikw?mOKga5E)C7m}P;#SS}-;_#s0Uu{?>xY`F{; z82a;Q5vN(=$IF0z&|l7zWn5$hV`&^0AqGqI=NR$@!zE`diW2(g8FH4)eU4eUD6)_^ z(l{jxvxIS$&Dng8ewgMg^BK!A4lpdp_(d89i`-A3is7kv8X^t$yu(aWzzQ*O^9N zn!%Zji+jg_ObsWz9#{#x3+chT3c0p#_W*ot@2QQW^2mffdd>)Rj)nVyz4h}cjrKVX zgl)8d0LFF>D~mvl03##lXljGG2QO0^-b%5yN=IcB!a+i->h8pj2b!a*|8?D)ellsb zvCErn{U~S@eo-V!@tIfUBhM$j zyI(s##KC#E8VdE9b`cAw%%y`?k%Dcm>jKG*$J0S z=?7h}Z?i{&skg!X&}`d^9X;rHsW(6Jl|4MN?Tf4pW>JyaSKewSTd6kdE~P1nLPDLo==9nF(C+$%f8xu~nEwBuO7gYCt*lYXrtu`K-)Q`= XXg)ZDx7{cKgcG0|aWYnP6T^Q26dqrA literal 534171 zcmZUaQ;aYS5M9@{ZQHhO+qP}nwrzXAwQbwB`?pQgG@YAF=4q07n1`F(Lrh5T>g+^s zWNAllYUf7a;OSyvZwI9y4Ge+;00001P~7t&vUMcIIm!+Iuyq6gfDV8I;A!vb;%a27 zZ(>8Q`M*aI89E0~RTW48V4&GWWgo%?WmgYq06>s)U;u#s)pmTXowr9D&)t8aG`e~Q zMyFP$d+rA#78l^$dlXmGBL(x8!{YXE5|M@zr9?D6%gfLG)Z^J~oeuU?;6+@LZEm|(cX4&#f(xT*?B(Wzn|_KY%E_< z$fj@EZAGxeM!l5Tbx~xuyLR4)O!k*Av{4nbNlX)e729)@ZNJX#Lo^WV*H9L@E7k&a%t)BGlGx ztVUZeTp5lCp4DH?>B{$rW{69v%fl;H}Ku+7W9>)?>2mRLMi8 zYA;{Ou9il3_0bK>YcjX))pgk=(@hGgq=2A;AemWn_Wn4OP2qx{@Bxq0{I0`TOSe`TG0){#;mV$_}j8MN5?&2HPBY z`f8`TrfCm|hQ{1CQGg;v@AbY1q+DN)QiTtJWz5}iEo|D)4j0uqeOyYpP_kw1qItF- zx|7D~Ud|YUDO;+`wG=<(Z!$bAI=8mILCq9KQT}vI;LyJ}{b=}Bi zatHj-qM*8$mXT+R(FA@ImD>q9`uT!^HcY9VuvJIZy_XY+zyj<26(8@6N7RmpiU!%n18cX6JzI4 zLWC0pK`BEVPy&re;hKzoH)nk2Eh+w09k0$P1P zZndcHh_0*tWYZe-*PUU`8e^H9OsY}=TIY{o&>eZH!IoJ7I_h;W2+M$!^hR9tKMOQ3AN(EE~Rg2cWt-?5t< z{G{@x{Q8@*SFG_*^@L+_&if;(VWKTSegzfUY-pwpkPneSO!9hwrz=#kg(`niy_*{O zssmwra)756$(T9RhP2D-apl(Oug>{-*fmy3xPqn;VQ+ZIwDqi@-fzKS(;)G)h!Bf?%%%vnWz;(~+ zgS78(Q>9!W#qd%aRpN*PuR;L7_FpKkgWrMroNYt(jh7xEIBxhrRXiSDrvZ)AN1(Xo5}cQ#dJu_qcTFM*XKKB` zdnD^z2TbkqY%SnqZIMJhn9tHlU{-W0xB0RW_)kD<0@QhDF=YgGvhodX?;@^!_RlbSWkRNe-i#)J<5(iMhsLaI)%vFebg6FUP7nB(x>fAFiWzT~B3Hye`Jgf} zz^9!nG^%)B8}eywjvXDAc^@;Fm^u>y%GeQtqJGQ;cQSoSK(__9onSY=r~R@kx?&Ra zDI0A!@_V<#APVMIFCw&cOP^*^wsaJS^U70v!A>+IVT;U(S9Xt+i3HDsuwS2U@{o=t#hHRi%TPhhaDZ2FchvZ!Dc$DK)Sz8jGw zG^qd5P$pYK#JEs9lm_k@c`#JWAB3%nq1GT#0u7V_iJ?m!8+dWsHJ}f+BV}rt1J8U* zw-F{Slx(PNO#yWtZoMih3<+;0$YY$F1EMTp~DDla2Og=mxU`65v^z~fQ6 zxe8;mSuM~Q(Af*D4**P4KR`@2ilP5tD@vnEG=Zo7V5Q>IrGgJ71)R>(zBwt>V^;%i zf<>ci8k(s!HwJ3DqDdZZK5EZR4Y@&Rx+kG3v75)RuCRfHj%L=K5?3FE2;mSrFBHtD z+pl0T%cVpDS~PU%MV3&dStf@Ymr(={sMFjRHa4!tKR31V)=-ASG;FYiz-oD(zc!mf zz6Ut;u^9fK9FN|m!6M&M%1^q)(Eq7m&yjR(-GJe;&j)_sW<8!6OwOhF-wfqi0~bw+ zN@;##1@d$qK*AJ7it^m>lyuAi@QAO>9oW-2WuxLY&bBG_iJcEXp%J=Rs{q9K9D$hW z9g9MlJ-Ds{3@vIs0Dnilo3rfc>F$VLH_S;59ct7bz+!4hb3GV3e2)9cm!6q#2+VjA zx&s0DNR2A4nMh-l9Vy%PB5fTsNR!LV8k0ab)dtYr>XZy@k3ytHgD~>!Q%@?jiCPJ4 zLgjF%e5c^9@W@=RjfN5n9|W7hu8(ne4J#TD!Omr3sODx+&ogm06m7 z2?Mc&TkXVjWgFDq838V@y;V|gTp{0fUfZfA7UTKa+T6dJM&7%0>208WLyy*&+3Z?@ zS&)Y3K}B*qfI#fy2v6BO!Kr+9Tq97Y#yzy!1X!v6KGD#DKv(-5Fh)*dd?_0RbWhU7 zaiX6M`zt-|Lx73pA~$NqEf)*Z-XCyD0s;^7MNc-A0u)li#WIV*oI!|OL(I-j!Y4lv z;x^=YO{-4pf}b?MQqlD|V!ELiN}^F^2UKqiEDm?mQtA6qv0psLj7~IXt&&MI_yuQE zvz}DHlv=|qh!n`g?;Q0Z^2Xm?(hpGCW3=soCCNYd#K&_mH%~W`E|NBwJ5P*Wa6Bq9 z9@9se0T!b@rmXmx?(Jf3#`95+{UT0kZ5#JZL&rAF-Mv@-3Z{2{egf%b2APJrTCn3^ z|3ry;mYZQ=N;fSw1w@DQ2Ei4_z5ssLqnIi$&}X~+%=gw2#0^<*U+Tz0 zbUH}kzk8IG$Vk+T+&(T}#59a)9CDGiK_rG%aytBHN>m(%DtXim#q_G!tmN@gIB=?M zWFNW+Q@g{dbL(imrE~WFg=L7mtW?GI6rN1Ebwe0@ zRRYoH6-ks}sQY8b8h2vcqMgJB<~-0+BT{6M52D#kQ9+o;=b4S_=RdwoU+3rZw|-E( zi@<+nmg=D*=c3zB_G9UJ=RNqnwMEKN;Zb?_yLaAkR!zFN^78tC>`6zpmG-67+)}sv zpQrA79VRf20`N2MmRojfJiAaM#IeL)GH6Z=re9hYF<%X6$6qOk945ktU_^G8ZOsZF z%!6igSLPQ>YxRY@vJ185U}+jUVRQEryR zY|PpfvvS-E03d-|gvhvA_vZ z*)Z$^OX9PZ&zYQ3*=nt38(_92B@L@N0eEhT5t@XH)__yIa2kZu7Ll0GqfzsOF|~Xz z#sMz*2nAd8KX3X8VX3=41fjT}UqPx$k5mr6o8xDdtJ{Wqg}h1T=j!wO2~Z`DM3iNV zbDI$uGyF>tK`jbej-+;wXiXq7u@^0cO=WzDoa^a9DBXOjk*TDpHn;R58iYg~fKE~f zk_Nk=7?XHb^C9iBp+gr91x#f-S+wys9z6+!zz?w709$r;`)dH%V1dOay7NLO|0INz z{R^h#z!ySfS|KZAN@NYQG(A*8oT6ea3DC8XGq zQezuzQUVmL1O(FEuXB{}thI<_ijx8Q;xJ1U^))L>^I{1ZleHtzyapya=4+bJjtop1 z*Oj|{9%wa{gqVYni|euk4V-9dOU2XZwODtMAf2p2XR;1S!D^c1-$YpXiuWYHjZx(V zx_yolCvCmN%m!oHMv+#~mWwu-^=y(ejLME8>1~1w(oWi1Ys$L;?AusF}rIRPJF2p)5-e~ zp<>*vzy~tk(MMPVkU-}|tYMrQFjb3$K?c$)wHB?BM=^iKCu^7vWS)3Yw)stYMo*7O&f(pP&S=cm>oy2x^M9qe9 zic)B`J;YhXPhU2R>w)8CbY0dmWI9zDRcu9@u)!QYkk zKB1<5EE0E%UQ+D_+;q{^tL1L?)qv80V#Gtq{-oV5`U41g0IbO2Ul0ZaaT^~}1_8fk zS^UlljjO9DC6L>G1e}hlEjrjD5wXn(cnOUB7UR zOWP;RC{^ATgKEXGl;26aO4f94GkQ^?KE|4u`!wC3bU~y(90>;d^)M=;Pq;n zxi0{T`-#2eC+_7}<3%PEBT(ewR~la>xj@^QWNg zZ@niIwX#RS7isQ$Q|X3@nC!OoLlRG)4s_u|T)>;}hk|G}Oq?F>A2G-Yd@>}%8pSB7 zr3;TJQi8qW!1sf+_*-JkMDDR!3TSE2gT>PeG%NQS9XGi|pXo(B=ELD3d~9Jbd8L>! zhig7aK4u(%lN&^b3Sz@hLh?YU;Jur=Il&H11)A|_Tr@OjCBlWJ9vPM+M142h!*Ct8 zG5D@dlXH>w;;Qfx-U;)H1izh*YWXH@XB=e9)jUwZ4mzZi9nZ!1dwkx`RI~eYvIXeTx)QMAnOrag z^;3A>u#T|yi0T4?9}DJ;#suRY)|pdKXk8mpg=DqPw!SkZj?Sw}+fZoz<)e<*yF)gY zD2?_v$!l-PciGi1rWS<4P9~r|-owl1)u6(D%y8`nBl2qe2o8zA(zB*1`K*hD(_VH* zf(|+?u3x_u$a+mrq-CEepHsuJ@$;D9nMS(|0h{&|7`)4uzc;yRWOzQ0bi3Q{;f^ig z)fc`&z=MQwy0J|r=QGy;3x8V7V7!90@MqwGY%nVWT7Gf@j|Y>pa)Cp|N&4S6996dL z$1rPns$5Vf4XOg{De9(yRe(@HC!_?Pw9(vM3n*((U5FxDm>J*c`V>;>3Hg5wz-p9) z3eF+Kxx#l6eg@^_1zH3on$4xAd(}8bCwO4tx`_G8=-tp(25Zn={03p$W%8&I_9A`C ztW%V7dD2D6yHDIBEKLqN97JP`S~nKO%4uLD!L(){{Q1BF7Q_5!yWz^uVav3rjk@!}T-mI;KO2k^s)8oaogVUsC~ z;y?y2^P=I6uQUND>mNzoAGHr}aYf$*U~QzP{eYrqidieJz%P|ZqL;gX^3{QKMGH|` z=B1(GZw-GB61p-xKsy(vD&Ym%+%OljhR*-EzBgqJ08o&;j|e2+H7UL&l_+Eg=9Foe zJp_80wCA2^y7I)>$9|^qej4DW8p(@IK_n$6v-Xkb2V=vL)xlLk!5l%&Ccw<7^Jt_<0NOjSC|O7}4>`|4x1GD9 z`ul!)soRCd@(&bee;+R^!Wq%U&hY5Hsw@jqP%ab_hCNa;4BWoMz+IB`_^>s)8}5g- z14(xEXqa$KMa%V^+533J?<)ABrS>CAH(J=j#bWRbfa)F!hm@{6ic{6v286483U{x7 zfK806Eal-`!ku7AGV6}Ih36KQTF0s8RUNW(el*&FPR*W?@n(_O8RRnE^eRb*O^NXL zpf{SR&!;ty5QehqH{ajZ$gdilEFk}Bt{ITP=jBPr99WY41;*F^KAzrmqtE5#^i5qnCm%I-~z@QOu7I;DQi}{YY@JANa1I|z3hDQtb2YoFovBUu z8?IIQ6Qz4}__lYSx#h+AzjADFVMG16l9IZJ=3>HL33T%LV-=L}HAV%=qdupqtb}Y^ zuL6YIcsAu?n1i#UIu=}0k#Au9WCe(7G#Arm%E(G1TaQL-<2D~8PWV78PE>J9Q2T~3 za~v&?^+DNPY8FT)Hf#OJUxl0#oZL&?ft8LKLXUQ8n0O?V7GPj-8eSmSpFdkTW$<%M zlZ$9cGsw~6l!1jtl3Vk|xaj!8xah25U%cbjJ{9DzIO+gVHmbZgoagbXb7(vWU4l5y z-zwo7hsVm~3eq`A{gls@g59!sah$_9LmW<_M{|JYo3lw7?`;4b-Q?5D3Q0HaxQxRW z$Ym-O(S!v*w~hPm2Qp#}=4;DzH|)a_)e;+YV0X@KG*>5PiJjJ7%_u2OtR2>!^ujAE z)ozw7Ov2LfVYbtq&*$Al678TKNjSEa5eNfIRMziiTngHVlDEzc2Q>5`TZsp7ja1FG zQO;EUA@dcC0_Hd^&9(SFPK^ZyTQDia6leXD<13XiMNy+{*59zKJLe#VK=7RZRhzd2 zKC1Nwl}h-Byq;W?JF`LI%d^A9VGkcLSt(ln*Hok=g^+5<<%krW^NI$EXrNnAa>3{} zc4|nLjE^jB?j6w^E^HjjgzBISO?%G3^EO}z6UP<0)~hKSjd2dk#4Z4Igq1OHd3`h} z;2M)d=-Q>viZSL_C&b(A+On9F%n#^UW^gTuy0mj*o8#% z!#Ex9=F&l15336$$VA66u4EHiHQ)2?c@mL9?BH$Rw$!`A;fU5Cpv;ewD@(k-Zb(9RfY!$jGy}C7C7<_t}h}R;h8BK|^ z?nY?m&XPF*vmmbb?Rf}F^bwU%xi1x{QSZo-ZeFifVxQ-ChbtUwKjIV2MaBX$qVR(8 zU8fA&i8r@_l~2`2N%>4lhsY)KU=0On!#(B9fV?p)^^H5h}rO z8zJH+SBXl-v>>9L&hB#<%VfS!&ulp{LVCXJ2^0*SHa0r@yDC>xQLOGnyr&pNlN-S! zq2Y36o&Ho^EB76su-1+9Cch#LOl~*C(_KO#+=NdXameUTXZ~dVcANxZoj~K?l#95;#^J_At`<6s`csI)xQ65vEu$cbT5nz zIw+nMR@j(B#6xGM3XR>&JNxbJB~qH(9SPIH1i$8tXpZw`B30TI6==Emtl_p2;(KBk z;&tm#&{Iu#!*KED{Bv_S$$3^j6>e3vNiBwg1 z8e(d95Dt1vYpGKO=o(P1)H9kxtFs{AWrPk~UCg96oQ;o|kVT51fRKv0rirfV&#Q)% zID5rQJW?%4w8QLnK>RW#00)1Ti1=!zBsN%HHf|t6l|%lW^5h>N`ap^j6dSfd_W3#D z37Gause1(mev7azk6eLA{+zB#?AKxt(j&CSHP1Owh0?r$vL;+Hn8CLY01#Vk9Ws^w zK^ae**L=EI>RR77YXarSy{1FjUN?sgJ!~|7+t>p0Za(!A-Onp`cGZGw(WA$9DLdvR}tfEIG-l+Jn@4{|UJm#$*;mHSTcJye&z5+s$ z{O5%H87(lGyHV*$0!D_I;`&}jICYoU4+7I6R9)b`Dl7l>;>Us)eh{aD0EiB-&)!0L zz!E;ZXFXP;A)UQRetYqx`M+R0F-=PrB!qm#xWime5M($0(4WtD1TC?2Yz6&_<%p3!q-e0LQsh+hrjdp;N$99|x8JKzH=We2i7 zep7N6Q@);yYb5W-iEd@&57kjflT`gAPIXEHv}SGb9MH>YN|-l9#eW-+aUX`|WXzQ` z#`p%JQ!6Q@luYOh>_o3BSMY-fCL1$&-_gb5>9;J;TOGC8yC66ruMXf0A{<+%p?B&f z?od(*@@b=}i`Hx{95kjr2zas@63OjAP0zwzxozOa%sEQlN;m#O@^6?63FR3(-TDRj z8@GO3w(ze@l&xnGzw+l7LyZ)WzFWlQO1k!agmZeH!G8l(&7=PLI<}t`97GjO051z# zXry@G`dJE}Cyp&8s1WLr$k?lRt2+oBkfq~eflkY0nc5z+>4l_F77}FP#dbgYh}Hnd z?%@+bjLU;Fi1cZjTf)t15T>VHgXX=p#Lb;YWX2#ul^HXE8WycUo7tz5-@M@3qHj^( zcralU&bYdwTNT@|>?Lv|x_?!#5ThQ+a@m{zwid2^x8JGHU!`U8ZuO)N<9Z>_RtM;B zu6Kw*YnLSI_9i+;fB|pQrnYahJ@0bOm+s7McNE??BXdZ09GBg(I>N2W65Z#;`vpXo z_L|G*N!;SY5*3dI<||2V)~W8F&GrfA&OgY$WRiX3C}jxkmaavv_rbVL^w$JoU_^4( zo!}==I(jS|JC^2`jacrd^lY^Y=yrlZ-bY~zu;ED8$d@Z#b}u4XFU_xJ)<3wu7K@O5 zz29X18gI}#rpgUL+itFz5voMzV69Rc7sm3m`^|0FXf9$*ect1TUJUK#JUktSq(mw0 z)l<=B8kyuWRn?4O`|U)qONxx29ZwJZm$$BLuTO+1rb!2Y#VXsJbN1Kv^*Vp8+|R*b z#`|O0Mh>|Sk6WZ}6t;F|2Qv}#6uv@$$hn z6*UiznV3(;;3zo`Mh;|a>jsi!71A>6bw=L>9k954jT!I-oGdz-bn6}^u8?{*F~kz} zu^C!u_m#E-=PsCePT>YG}gy-kI4afhHjw)Cd_F} zC7a8}7qISg39!f=Q@$VXk3@`*TBA$_Vqg)n`nZfz%S2JYU#EU<8pD|vld{{7-{RUK{Ha1l^* zz{|VQ3cLn#$-RLcO(RgR#i;$w=YZ%@@f_p{LeV+eK9i?Ql*@0pA?$2b~Npv9E4B{X4u7!v)ho znF+d;S}L?xzAAbI8QE&1^4ooFGc*j;(QXg()aaUo+0n1?zn2xo>(JI|K*OwBaX!}e zj7O`{@>n>Vf2>yzJuhL`7>r>j6ViFmBnXQ|anQ8!A#DSG_DfR@!`xn(ti=M>#um~ z%2K_Qa%XjX2va=A0$<2fWkZ>d=ExQ9t!6pAgEeO{6Esixl(RjV&n zqWNj)$)_!k`CtWR?FxACLU^l9H=CHcm>Z%)>`?CYDC0}_)CISj0nu69O`C!AI{3KLOC)ne>&Q-up+_-mUK@U zPF)0rP12_;7*hQbr~7ZcJ`m359+w7I#TZ?Kjvat0kKO{O&VYpTIA&kB-(O1+ zbAk($b{_rVI zfYUlQ?*YRQN^YHVLQ`N3@J3NPx;4+o>*&C$hWJY7!9>O`3Zbv$KvPxBeaoAKkwLDV z@J|wnZxc_dQj@$|0`?;cucp8X&_u5~@05K&>jc}FyK#2jBsd2n=*9I4@FZu1A1{Lb z8upA6=sTdyQGHaLe%b*?3r!f76jkG!ozKi5$Em5DwDed=(>{`m(xm0AS1-&6s-K5q z$-c0{Hpx9u6o?97@I?a5Dgz!=? zot9)r(ApLn=RlzeArC`%TO&_vsITJFDIAg`kl*?HH`y=6joi&9syt& z;Ktvfv2(N7WLQpyisIgX^pm-tvTRJVq8!hLOK0O_wu#HBsq(r0TOv)_q*gaL zX?dxoa!+LzoS5_*kOH03bpM*C`GBT#`rkT30xhfC*a4k*9{#z7DU|GE221fbjkYzo zHcIb-EarQ?ZLcHS=Bj!yO-~l>J&FlZ+BH>0*TkZMNpGRHZ{+qt6^Y)Cd2`iU^~8iL zMc8S((hs*avDxz&fDI)F@_memvsJp#){>6d9zi4Q%4C(Bf~^<$RZ`6`Kx#9Duei;& zcRP1Nt9IXQoFL-DK@5oFcRldKOfg)yoWRfXG(V?KSKe+c6RqsCjr7YrZefHS_uo#e za}|7|;+FLKS<3E9wI8cbX_45PDMif#j=j1g{)XN0QwN^s8;@MWwGZ~Ral9nx~a z+?jpOR2wG8hVByFZ|cwM^)2qyb~E$e7;Zlz47I$^%}F=p^0i!D_661r{Vd~jsc?S3 zp2_yT)3q<(cjoaFF`=nL~vXQa0OfX@6TsafS2$(mR)*m}HM=@a@o!*AKy_(Z|vD0Xw7T+bUHm zYm=3vUZoRn`kQwWXWeleS+Sjs#`M*Qt2e!|+Cn8Ig%*N%`7Sr<&Y7$ls)a|=g%l8W zNO5)vaYTvtjpU8>VS~FOR2q$*dxn*z%4c-{TYc(!ZkeWyHeG)}aq%5f3O^``39bGRur&+T%t z*DrM&BbnpYUBG*l3^7FD7rO@dHu=PKK-oYHU=ayMN%o^^i8X_&1xqfc#NLgK1v3ZQ zV#h|^WNi_jxOjb-_ES|?5AKwPC3CLRsZ6?26NU{9J3XLV_Wp><{utB#W z3w}!a!i(qlFKNXfu}8+ewB1I*P+POAiX*d&vHnw}i(v54=IjQBdlF};U`Q>vy0qL| zz(o4nWP`h_EAcqf(j=4MK=2Qk?JN%$OVJm6GOeXtD%O%)eA00`3ej`qAk3jv7YT(A zhf@m@p?)<>7%(+-RFigtfqxT9R!Gvby!&B2@xZNi2q~2OX-96{d>#}{P&8Lk&w&FR`S(#R}#HEes8xs%50P}#&XRv<@T4Ppfa53k-uHmrv}GJFv`ms1`!NS zQuTKag>k>h4&I^}gQLJa4>&3LKC$L=m@zz?Ks?sZufJz%<0XK%frQ}0Hdn%)N~l6VD%Us>-dOo`IH z@Y8#V#2jzM>DmbqhY)0RWbd7m^N2x#^oTNoJxxet$3)E}=e}6wfyuZuJM6N6(~iVg zlRl=jnpBL6^o8-+t_ue!%G4ahDwAag!35k{YHLIWb0%bw0$Ig75gM5_6z)o)A%JPf zpAA^u#86iW?KQ=O)geGGtd2JLL=8_{`v~E5>^OKQrl?92z5sMP=_?lemUvumh{jq7 z&R(OY1NV?vnwI9w+!vfRT8R8<7Q1IPU$oVXv~qTd+Qt%>86<^K(yM{ATpKJ-!d8KJuaCSaK%ygxHUJ z6Gr_(?Z~#Cyn5q&x#-vQOc`Q_5KpgTQjv%EC;7sh>SdQkL;^)!bpZ~qyAkPf zrTM2!9NtEgMv|IrhlC1hLXC*M@;52t-{fv+O@sqf+MDN=lHEZv?QC`7tSCSj_-*(m zUCyCNv%Y0|86XyJKY+x7f;;n@cY+Mgjo&IMr2G66B(``>X#09ux>XdK|MF{NyE>Dd z1+urfCesk_K$-aoXd@+p|#{E zRYX!@HLvyh^{8aBYy&L58%oFM{tIuL!tkrQ@neHDw{(6~hP}$uX+hFTrgCZ+mdE=_ zpPnL10`b`9ZjxZ#Um@xAB@|h+$$ z!T@-SOMYcEIn}aduwW9udI;?g8xrZ-{HjrckyP61RarL!gs&D3br`cgNI{d1<dz^s2`ugUjr)(!v&8P@&_pv5wT()G%AtddDN4pHJn`mAfO=u#<4TDlWB zB+0r5^d}3L(IF7SS;jtjSWE?b;spPMs~6b1ISOyiFZv74yk0+t*9#>#moEw_#@`|y zpQi(e*@HVDFamsLB^lg3hxCqu9v{WF8}%lbTpsU_&EYTaEd4r`D$J6#%6GtdcX_So zlgf)e8FfW5Y}a$)ez&HHFeQI}R<`=u@tT0l(pgh$1fVaWbkn%ylG*7r=w@k=f1di& zeF>rm6WW84Vx*G@ZY=Ckh>b`+mYfjKM_gEZ3PTsSr%O~oidL~`Wg$DMYf8u~)u*dNxCuR6@{+zI z`g*UpapK`b*))axg^e&OD)B#;sO9pMFb5{bTAaZPKoE1B0~R3X4pOXq9y`T6@^x#aHh z&=W)AucLYvCs!%^CIf`H?ywQQtXp${`>k+z%a_K2s^O24MH)lV8>FjdR*n}iwQEsb zee{%E@{qU>t3sid2!KIt<%eMR;?O;%`Er?rj(K@a<45-^^=9+uHT_)9h4vKpp^v^_ zbH%hwz%^rh_=CK80LN5C5beX%oWpYWi>-cGN%&w;P-zX9L;A|yeD;i~3Q0_6nZm@F zuS%-y7zKkxY)HIr#_UBrBNyo~at!_7kLYX)mg}yDsIiLE05gL7{7Ix)h5C^UPC%ODRWU1w3A;JP^Z~%$D=IiL@yo zUUL#XJS=R;##VLtvWqs{c6MsYe95SL3KxWlyyA!d0K*r zOoWA9pTF~op}i%hyl6Q4w1>#3v-l4D-9#ksT5;IeUj}P(aGMHerMgfv-DnsyV9(lr zx5a66#0ln-m_~d}z_nI0HKV?vd&-AJZw0PGnoJHMkgX5Jk&I$m<+Uw-`;*6FyEJXkhEX>nG6Mf$yWB9wp@u}9xq2R15nw19!z=9c^TI0- zb$e(%0i~zf&zDn!f8hTY3)G7G5%F8Y`D>>E08p(406_bHu|R!&OFK&!ef|GK1!{M% zDF^-kRN%0VbUe0rQr}zsxa|r{8K`v{EEpSR!tzD(Qg;G*)lY)dA>4b{9Y8rF( zx-6_4ocGpVLpkVcQ+VerKEkQLtw>*06ipwGUJQeA^&{eksENpbTGanpk}N!)2q`D0 z(M_<)oD=nWM!oP|A});Z;PRG>^4a_X)Q*b_3P58Jsv;mbPHBmU__o}6N|=;LP*(}d zNm3{JkuiSlTw&cYXOT@mE{!neE3UNm9bA-WIiU2UJ*`CQ`@vP6dQV656i0W$oQ(!w zd&oN@iW`TfN_X7w635@z`wiY+kcrCaT2+^s)#xEfk2G;!^Po4=|5bMq)RQ1Mft>c7 zZjRBJ$CSoU=S;4%em<#BDm4M2IGmeq?K6ZH@MV5Nu_Gl97L_yBb1FRjW;SMi^Q>D# z7*MGRiQ$<|cZQ^P%1RRCNuH@S{q&H<@vk zKV`f81^3ECe`5&3EnUp1n*hxg`2kG(7Q)ZKg5RIbn4QS2dF(gUOf;*JY6+$jyh+xB zb5zh%sFV8TJA`k9;Vqi4Lf8MzT3LY~Kd$l5P25owZ67!7nAbS6D&9xl+*0zz74Xq_ zgS?$lUqSPBjCDqE19d$sMOu~d6Q*Dyie!;g7Qm8B1k{oO;WGVCXT0h%uq}ucDih*D z)PazX(P=~~QAEHFri!OrQi<+43X+q!zW;lU=S0u;&XPwoVE?mcBpO`KV9Kz2ppI8@ zT_`QNIwLT-ptZEl5+{nq+;Z0Y&Qr(Gg@%kG0KFhIkC7`{5K}KYx zUlN}8Bq^-(LHL{o*1MRgI4uAw#8NCI&=vxS+rV7Wcr+w;x0A3>Fm3{5DW{piB=tO4 zr-X+G_$F%e$xiOU?>EoHx{ZQ}PR>)g*A?p&<-P1x?VZQ)uyi6&%XZ|(GYl+umWJ;v zLuP}8ip(=#M_oRcCtbC5zypq`jZ_O@fL3K&fG9}~dqOi2;F4-NJCSMbnc7boiGU~r zR>h`rf-e*of=n8xvM!E5Gzb6B{le@3f2U3w{=4}3hH`^yVxvo_#2CD(JmHj+lV^2n zwVY5>PeP@3d_q0MD1;^4LY&t==7DmM31ml#%5lXKloz{jkYB*lfpM)P)E6c)2ORDG zCkp!weEBHrvntq_Hur6jE%rjJ>7bNf8BeL>Hchl22K310iNO>Bje`pMk2XiU0D9R? zR7if2CP1Crr1_wZfC)&Ds&9k|CkTQs!;jlld9(W9)K>P>l=|Sv%}awS9Y~T^rXIM) z`pf(@jN!fZ(=Ykp((B|foh5Co*o3_85t3ha==?(tyW8i>V>AnQ;Mi!@f`Zbd6ySS?8!_z=bLpxlS z*?F@ifVfOB*ygV5gi4t$+CQqr*1-32vLdLB*z9FnlB1lA1OHa{atuG@=RJV_eEySc z4GnYSKih5Ww>+%QvaqX!Y|`I&u`bDh{$PWH0?n7_y7t4{gKtR!F&6QV*!0cQ>O*?1 zS~SacFCf<9HRhdKxQibNuOewLUg1z3__1L3U~ddvI@sV9D6IW|3FqKeaEUN=b*phS zE8ssNB^AAVuS4zl+_K9?F>ghrtTP(o|tG)331lo0(# z9zsLlQ)cLEgR(bBybabt44NC75T%5wDYi=s?9W|r`ok)AXPfiIE4Hpx0R)uh1k;%E zzY@TD{X27^e*JK+f{-R5I99^kELC)`1UJ zoVUil<*P>Yy@FgA%i0)?Hwr$(CZQHhO+pcqW;O-7~Yub>7HL#y$CEo><{SxMf0zK`#pQB@N#&WH3c4|;GjJgm%mIQ;hzs_3sS z0n6%YNW<*0i!)ckppQFFe4BAsw^uOZW}6h2tjNl5b*GHWKPi$h z`goMJ)b)bHCRbiJ%Q(=t>(F>lo+0R=50({sk0GatWH98Auid1O1X=U9s#3+r(u3wZ2vw@Xpky2*~C%Y%GZd zh0#$JZ8i&Zm5DQ83q0*ROWuFFf{=i-(V1nKwMDcE)Pox15mPJ)hlz4su!TT)TY7)v zb@+F@Oc-4J#@HFw*ys6s1qTG1p)GU&m8jsl6JsMeA*1b8?ayx`$g0K=0t5ILfwX%e zPd}=pt=%B_+1G0)|_wL!Vx>(^QrHGP=aK6grQb~+>jl@DzqiAh2b_NejlT^q zsf(mUEI};t=*NN9||0-+8gpw(X$DZw+(7Gj-!z5WOH zt2<;vTK3ZZo#;IPWxu}dRW^B|+4{x?Gr^+%17wCrD2oGX9M+d{FB;-rf4_|+ z6Vxb3VzA4iamdNRq!i3$r?oFf$n3b$feGvUuTvx~bX^ku4L!JKifI{%l+6%Ygl)19p*CZLOwuac7;SXeG$hV%F+jmpOW&9*rr}_oUatnR*w)!ZP z+?OZzpAOQQ`QttqDVjYCd5mH-zSf&Dsf=_%q&bJSLKVJQLvDj06}Ui3dFp*+l1Y~-XZ=X2XVzv(^Xl9prIQE=_dEJ6t`oTc zmI9zt%mw4B+`i&X8`nW7+?)`Tp#r!pN31?8;G%!qJl&QBq|gYFjk9^QVIV#8uQFrt`x|t!c$&mD+6V4_`g-;H=YH;vRiHShjzTS;tuT=_(Y&U&^0(oj zHgQeI-3_3qN%Nf$AVd2DuCaPeq#vz`ANFj=MAhIdg;#Q*J5H2Y7s*r)<)#Ynu?ryz zgb2&Lt94*bl8j{N$~l0~fE7U7;VJ>oa@$dHJ=rw&HbrT`yJVG-`)} zE61WVF=?-(Gv4*uYW57z%b8(*Z?dXau{FpL&I`RHMoFk{$uH>Y6V`<)-w!N+f-H)&rD!T`*=<4iOt=H06WH5oS`_lt`#d+LJEWj(7 zaZ4c+>pGR@CLQi1d%tdvH~DdRybL<%`H`-_j&=e>;4QiX;@M*!%wkOZ(Z!pFP)uHG zMqBp8Bz`HMj>MMp=Yvpw?qgAY6}YD%^YxFPhW|!m8mX?qnri3uXmBn(Q>|i-!`A*c z+6M1oMU>X;O_9e!8Q2_B*J!w6f>6I&^2FZBpy0 z_;<9(o5hML2{;=&d2%(Uv`^@70Z7=&eIns<0hY@@kaw%p*MxGt4s_7TjtvdHcfE(b zA0n_te>f`;kmt0?!z3%`LM{78*8FsY-{tvG|NWp^u@+3}it_#Vr;DIA`RFD@Ex33$ z{55}-zcKH@e-eRbILVHB?2-UC5LST|Btc8Tki;2}-38VNf(GvccFi@tL1)aw1rtReELay~LJiQ+(sEV{=p80rCg&c1s`I5Cr5U%O zu!BS$ZT1(eS-pXC58%m|H7^+EOv;Czw?73%Zor?j_**~*l`M+;SDe*C5{kx#jfg?U zO!Ry^tuc?WEhmP%v&{a|niDg3vT9(uDuJpkz+TnPdr}X(U%_xZ_vRD1&fyeLpkUWp zBZa!H2a|78%^MyKsSi4XdRnCZ;=<_Hk)4+;7I*wyTEOE!8RTxGA+W zz9fMZ@s@?8u(k8gwpG~R^6|5Y2Wx-AU=kt4zSOr;R`OY%_8t+i7vRaIg`G1`&F^;0 zq&=%acN;o^<+0Vs(L`Tso#qG5t{$uyuD&KQ5>njy0G8!jN>+ef+u?;wBn22$Y2%vz z#FJgQtR`2W?9kD$>4`c4&*w|mt%Bt2&s%8|(hWl_?+zdb3ci^3QsC}x(LM}{tabM3 zSN+V)cSS&-NC5V#?kK}3mSTli3RTXSK~A^^C!<;{@@n`DS3x8CsK|L}RAJqMau@eT+zM zDPpASTX;P&TlWF3>f)cWYpkdyhc|aU#dG#yu$^kf_!b>gb2w?UuyZb0qmBG+X0amQ zwAMgm`W~sT5}ze>w5fKC&LL26K3e!3`kR%ro|MnA0~@p|dH3wEM*rX@L3+h{8lN_+ zkt>+~;bhnSxmk1mm%p@4z^x~`q?L|QJ!J8H6TCl z->)>)jCZsffiNHPY=8a^Uxd*~yp!AMw_veuwb)0}fNOyoA2*MtIXbb341v26jvq>e z4DfJ(KfGTl!x6ff&Cu zO}D!~Ogw<6H9(0RoEs{aj-MQV!py`@R&Z%h?uHbfU9&CK!p^tthKTrn%{dCmi zMb`peh$I;)Q|en3#vQyxXg_d7H6VVX#ab15Z+l~0^vg0QZ~#LR{7={e0P&mSAzJz4 zs;Hh+}{Sb=#c*uZjUxT?bqcx5sWB|CsBQ z6Fle*UPvxzhsWaYy%Fl1@yC@u%oBr?2mo*_n4?* zS9I*p#X%uCLarJM)$cYiT#VpA*F=siSP{)1AP7%5{tL1tU*zWgUtg61{i)*gY5J`S z@-qX(rBD!N0$)>v(GTqxzZM=VCoHza-B-0K%CZ~-jbdC`Tc@OY#mHi9s#Fk z*M`s|@k|uGQG)04>7Q2-x1xX%qfq06MR2XZ%>JT>%V%U`&~DD#@i5TNz%tdvC5$kl zYts5M#@qV({5~yVr7npSS9#CyQ&}w*!o{s?4#>#kW>!G|Rvka^4x`@2VthvNnyZS$XRs859yO{_NZ4w1r2&BYoQ$gMR zMUGS1T?I${ub;>p9vy05sfI=d!~iuD4mZ=XOlx{woSYG8&BF}!%V{a*3>#J7s+X;D z4H88`S=9E_Rh7?p_;+{|_kJj@eI@S?%GC}nM=m=c8*hk!-M;gTOHhxnCfBT?aFSB=%6ybL5^aSahV1 ztb6<1ot`mcc!iXkmW&z@mrsGv!5=u+XYX9k_M)jyAlP_C;H9+td_N>!nQTxxuhea@ z(e|lvh*3@DV~X^b&u|keY?sa*gH-XWMqsav)tLuI1`~qSn&uIwhnI}u?Tx&S7bWpc zAc`UI)0Mwk zRG2Xucq5!5SAyU|pUIVvn8?~5jc#8Lbu>Eg&*1u|w93EMeRVXrx1s>dBJ{nyNjewl@-x1#V{`umQA^VdvTWX1NU?MQPa$1k3O~StGS5huFFZ-EK5-bM!b1 zY#1>aU5`gfp6oun%%Xq79?UtI!IjcdCFE|kTo9h|SN=3_xC5>u6=^_P7=ZPXGG3$? zwlHbd1pm}UEa${lX~8R3p&aL^okgh?I4Xwy9jteS31h@Yo=F)tv{u29NoUjPp}uFU zd&5zetld;jA-At7fPP>(M_t13{7~Bns5f*H^^(5N4Ps_L{Q`nHdtwl{ zi|b)Z$j3>&Jn2Qs{jxEqi`=FDHGKkdOBgP?40YxAS^_98Env|GyifinR;=icn!QsO z<++?QGipqluM%tjYr%>R2lP>EGf;7?g9^}d?Uy!$S!J83u{Z;DwCK$9YAn$daSV1O zpx9J&gh(aWBYIylSR5Hw4I}$TIh|!%eZ&RFaEr#T?iq-w6BOvpzdS9kyw$2s|kot z1WE5D&24TX_b81e*D>$yyKBrYw#zyxGuH_!1g)=S9bST~e0eUIM*2&hY6(ztCLY2r z3Ux~vyP*rg>D!)8j-kqZDgHVuHQsSiPy3h;y275Q(9AIX21s4hQY#?fLQuD$0c#0OQ{hq7LETM14b2=Da0)s+0_bPc{A{f5!^! z2hcgQheE(ZcsiKn67!{?sMgkG*rJN23(g}H&WcNxI{KUreb+L~4W-?zVV=edcweEB!L>ot7u1ZrgitN)yddDtK%FoUXRq%9 z_K{@$BZJ{&Z}53-`f#`T_43j->d5|WgO_k4c%Ci1bEx!l*G~xg{tH=T5i{XP7 zJ>8wL_pmon<=FbXCMo`z-(#Q&C+LqvOP?hc%o5BL+&g4}$Y?}Rm73Oz&1Q}8SNSdq zYd)o3tB^`v<~k;JR8*nr^8rwrD=llL@xFbMF31%br5Io<9Ixij`LY4EG1{ z&wk_<^K*Y^oxAbFp|Tr8S&7jj z{+OL@C5h};mL zO;=(5I$vw}&beE9UvQu|5bASmS0=0T-9RY0wN-9JgVv#$a2u`qIYG)s=Uq6p=igdq zRe;zG8;ZI`(}5*fu)WDZ4aH?HI00ipdgy_*QBS0 z%pPuuYiXa9ts2!RPCoAL8e~2uWhqb3_HG}FK^9e)9@@)6JGs~)+)!t?9utqKb?zn! z2Ao(ZWs2i32gbbJszI9Jtx}2+8qpM_du?#!w6KT<24!ozZ^392_l9-rQx(M4z>RFz4M)x;ldWf` znq3kZvh5tXPyIgSuAU1f_qqBmTj$b6kasPx2@ znMGpK#FZ{koIOBCJHRRSK4J4oVdl=;;`ZwHVImBG*YT5gN> zln{p1bso*Nn+K6iEtMW{NbeonIK&iVVC(lSb#fWNI25_Sjb3G)LV$Fq#-&|fj8rmH zz|6F@keftX;8w2}7L$_Zrd~O^+IoFGGZyUC3jRJ|NNm&&#@K3>jQjVI1AX~kBf$O8 zWb}z5qKZ`FUO)luED$y60fijc9lnIK)MxOUMa6{}ONve-O+d~ymJnImQ=%97da|(O zn*3q5AZHwrfcHtPx?a0d-5HR$m?zUw5VyEtD40S^%T{8C?b7~L8WSMeu z%%6YdnBgSQv0ybY-ZttGjs^dIsi9<(R8~DkxtU#j)qjJ51F9;I5=C;hUP0F`6}IB^ zbg}pFetO(p9IP@Yra18D(d`Hvyt;5|)-4T3Fml4TR4;1kgu9W54wf-LD0>&J04B%C zEB47ot<$J?&z>eX>gUj|OoCn*UvPbGLVzwYPgQj;#iShrNrqiqHn}+xx}qm39fqp( z4*12zm8&5cQ{}%z^?u|UqZ#9*4PM8&UFj|aWSiHUP#eHHTORG4+3Hpd3b<`TPGqR> zq&lq7JMY>XV9I7XvJ*@OuFE4s(icT>2AYwyJD-iw@&Z>FolleNLNx>%KUmet$A27( zA+5`LBUAMsR*1uw7Ck$pQq&+EEdh153DG6u6QN(iC&1Xd)Oo@o@u?CfjcIFb<+X0W zb}}^+Tr!o0wcs<0n3MHIkXjFpuLR>dK!|I(VL^Gx_muxMGZclj3&Z>hbol$7*-93_aa>{*A&)DE|Ae~p3%4sEv zj3w)Gb@F$`5U{(2sf|NSaIY0{TIU?0J<|X=Uifk}KNHf0P!`<|!l#YQET2*LJq@GE z`W^~qRiM$KA6EG?UF7bOj@fknAPuugxY1(@vC?J=d&i=SEn2Ar?#3{K`cL}}-?)V0&4M-oC7X4&)r)74y0jqyV4 z(PwWm7d6yyAw(n!DMWsy1g)|KEXiA%%_DBgeug6ANhucL2N=0?|ZN&`fkWG`jn~x_JxOXzD#b#=ri% zxKZGI8kU1ciI_@mtIg^q9wBaO<8svFi6$R089QY-KhG&yOt>wZ0xgxIXu;N9IA|^V z5TOLo#0OclVCJRzoo|@pUQ7aNhV<_I8@q=7@#o*IAZ4l*VKUBQbfx5_ZzXxzRll|K zVAk5)W~H*yNQbNSbLQ9%`d-D(u(+hMgp^GUbC)2iCF1)aewWFfk=m@!ij-^ynPpp& z#X+LJQ?uzQ=8e8-(I_?q*9CuZa4wwLOQ>)8IkD%$E2lq%EQ8H_U4dE$fqzp`FcA#- zO%3uy_D!+e7-1)=O^vz?b33MXszPs5Q- zT0!X8I(wljUo_w+WpGT`+(w33_Kr-cu^VoZ^cx)KdeMf5*988;3C;#~$5T7>D0C&b zET0X4Y(u#0fsR`E2#goPUR)gqm>*UhIi_mwAF^|B&{v8?Q;8Fj=E%Tq_acKzF8LpY zg$+K}aNaeT%F&=JdSzqhc~hZKX%?Z*7mM!jA-Dz=e9YuglSDx*mlG+`Olsn3JrsRX zstS!|tAHMC94>i0t(nbnKIbfUuCOJ4FD+bqsh4rJA@WWRB_(Vo`Bx+bYFO1Do3&e;t%9!qx4fN9OI|E%?MH_P`dcE-h&CP$R$a1?SS5!M7V$8()Vxh~&qxL5U`K;>h$f6}v2! zWhf)IQhadO@slM71NU};hQ=x!)rtxDx113$XDE>Sk!$Eyy`ls`0`kSAeZ~AI*}XbV z6o>)lM_~_|j~$QS0FLt0yQ;>)D@T9|F~M!nvj(}fU3u%BlO~Ly7|Z(;S|0R4Kk`Rn zNZ?YP0VKipJKAP^=$|4dwoPdDrP&2w3;C?jT0WfX?ov#*E{@14I0YfJ84h981H$*C1o`&Vdy4}KS}4<+9p9~ zND)&fOwraE!Sy01ZR&^kK>Z;Saz258%cRKOn$ML}|Jbkmjh-$=tSyyoBK=9RNR&D% zK#4gVCR4vEs=oSnnMSga9tax2m`7ga$Z$quiu$BexOUkdqkkacD)nP; zWke@1YXQJ3!*ftT&pX~Mc*=JGJed4(rWjy_B3Y~|?KJ?-pp9KMfRX&|PMxw}Byo+q zpln*J(QD;E`)A8x1}bZWMODiCmfdH3s-go0JxkDxElk66N*9(_VnjI1+bA{o2N^&H zVRZ-v{r!p#zAcd)(H}isSE&E?Aju_moF^iPIDKk+;tA0N*9KT#;iN^9f%rgtlotN6{n3 z%i-@kty>hy`(JpcZmB@JgdQnb_?_Be!SUDdujr|lH9~L<3Zv%mv4ydRNHd8iRSjfu zX43`UGtV!!fG?@jB!Heq*kG3*&O>lb@STYZxX*AkzbA7YB#d!a`Sf65fOg!wy}1CM z=Ip?{x{_y}V3PvKGeBf|K=w@IPR8W=AsBe_R#@7!0;vv0@Wu9M(2N+~x0cYRk({ z8{ogu^$^bUzWQ1(Uj5`y&O$@>-X2A2MmEs)M+^=P-zz*FKkX`9E8n^-omHqWCElf5 zhH^jrsT~WCHwN6pgH*%jhaPbd@b>i2YEFQMIns`=`VEw_dut~vGy^u^bpL^9h|Rpu z4oP}Hm}=-u2+*|aoZlw4pGX>3jZQUr7}I4!^nI>H2>IRfF<^H>qezh>F<~gB8j|jv zm?WY-L5v#bI`H67S+Q_%(7z}e^B(iUiQ9Dq7ucnUd1;&;4V^FJhh6o^5$Mwcah~)= zy!Cn5em>azL*TfEXlVtc_@X_g$=6%t$zJ;LtNl9feB{v-r$`7SW4{3+M#AZL*yF7Q z_Uy4Pe+(*G&*1MnwdyJ(G{>n_Rxjq4VOj@4!y*o2 z<-I}@4Bc0UYBZSq2C)#*)>07)JrKRul+Afltw~m8{pju$e~mc(0c8r$X$yq?WIjv+7BT{gFMz`X%uJl z)lB6imtx2^%HGNqvuvn|i*1=jTGa5nGzYIQzf5BS%#BK4xnFd5r_Ut|IKNs8@GUF< zQz|SoH*yM~Jw0L_60r!qZ&tcj6{AX9-_LFxpN6UG_FU&MhL}4z`D}=CeX}U- zX5LQ@0Zfjn?DY%w9}K!U>RMRXw7l=;pI1sb;Qs@IwlT1<{SO8`RPtBpzv6$HqnO0Y z$PUp%hrIHHWDv>_<)^6o2QM94cLW}{(#D7Kj7OAl--Ahd<);P z1ZH5@H~@ZK8Epd>mb@hKq9YWCxfNlEyXDLH2XKe%MUL_Qt#CUDdzR=nvCxLiaoz$m zm!P1xn6tG6T;Ul>OEpX+E&;lbp~Oj&6ls85dMgpTDv1mYR?i)NzU*nK?!t)!V~+W% zlZ$~DTRLQ08H$K>xWt^vx_s2D1g1&S4ZlMBpVi~09|muR2LO=b0suhxpAfl$iPL}c z@GF1lGL`8XYL;L|sJDI1g1QD&1q}SrBb-ge3_CZLWMbq;x@C&1c<|P(oZ`!Pv zQUiOv^r#l`{JJOD5Plu_MfbQF;R8=~+~aLJ+SlpkXq~W^MZ>_*Tf(HfXsPN|7`$$P z`t#Y^WzG`iwftv=PP7Fll!)f~ix@CSVxnf>h%hErm;U`iE0s zDaU*ze9zZ67o#hAonFVdV~a!&xBbvXUNSf2I4Hs);4c$W;PQQ12{4daz;Z^?;>>&coL)=oero>H3*ci>5Gc=_EKHEK!5X2UIL*&X{V)+$@1zu^?1Q+GSU-~~x~ zYLwC4?g-3*W&&N<-X8Gy86v#hQmGCjL~pZ7*o=L@1^l4>!R4i18!+2=BI)(43> z<;ci0Tjl!UW)&naCr&qzC~K(BJ+PP|1@{U54GKKtg`GFU4;nqbP6CO;0}Q($&l_~` zqcXO5W$^LR$G=<=QKeiZfev#e6?>MWr&chfRlj+uvm$$tr@V))JajQYRdW!=wHnM?anQocInJ`0~q2lmK#h1V~Go=kPf3-6F_ z&0H+@DBUdlUJ2H%UHM2)DTS+0T1z!Gv)Y;$X#&j=pkrJET}PvC>x^6{_8DR{RMUaR zRxE48_g+HQ9}M=8oEqQdJ$Eo#h31gDrJmZHo0OW3C21blv^nIKyT)EIYSe)$+)-_t z=8yB%|A1nzgi2l8N!g{kn9$VI4+0vC=;k!poXNqvtsBV4K{9`qo(Vz}T5VlRtUkF(C{?UxRs+Q}nlH>UTlZt5VqYjg>s@fhP%U0$O5a2DI z$ta}N`7Q_Qyd038up^(n&by7E5}R&q>^hR`DW_2;wp+RK8hWaCp?Ay;6A7tDWwC*r zl-R-9=j4Pt=WPrjn&us^T&Z5U}}6`U>>3Cvq&wK zr_P1?$`k_{u9$@0IOD2J(@#u`)Aun(9Oi_fg0qn9=<0vzoI-(Wa~vKrX8?4kr@iz`KPz&8VcQCCk_Q!er2mM${*kwY{|!5QB8IAMArza z!j`PVAeL}CA3KRxSclnlsfk?nw))Dq-N+qr$ClyiQft2wy@SE3h|Q z4eR8lEK}QY#%!t%^{%iv_^{gITger9BAj~+i)jG9e!{cts72TpglkwcI*X6S5s2+} zqC2)3Eh?*_VAYp#$;6U4>YJa8Ztrik8+=F9j9QfS)2%M6u`L9m0~Vd|B2yxbRxGpm zhPg5APTJCxt!>*G3)4}f8UiB+G8Y%N6=9EtvFhRPIRu}yB4)-#r`mgUXH)R*xlW#G z*`W5w;`!(?5yb6N25nP~BjvJ;9JIzMXp93wI@_O2a$$oLzwGO5rvzxF#&XlFLOhFL z2s??y*pbtMsLVo`1hHhaLZO$xZd$!|md3T~;nf7!rkml^C;&M+e;#&q6uj4PPDWM)crDR|5EUrHu|Y_qZVQmp*h6T zx>Jx1bF@ZwpDdXdVjT25bY_sRKKD#0t>m6l6UIna{KN-K55!dT)By8UTV+Q}x8iGJ z6^f#;kJ?3Q4$=W`$PNBS zlSym_IIm1sJ3o!M%o1uiB+?9w&Kv8}VKd$-9PPTqG3$U2oK<_TK{;Wlg4;MW3`t2i zqk4%Xt^q7=nbx*2gV_2&1l$*0a;9TNcq=}ej+gY^%$V$)OT=oNzekWqMn$3pgXs4F zzgJyunyNS9MKMS^f@oZ0xN-=mjdrI{XK91!`r<$eyql1ipekv7P9e3z0EST9%5;Hk zWrAW&B)KBALcPOb%0{!9AcaFg8W%NiQqZ9M=Mzp()h?${KC-NQMdQ)j7df4gO{2!pnAuP0vn@N#;+KMr0!S#-zl-|p;lJ)0*BhR^TxkxkvNrLf5! zJng?-D$gvFhE6v@K4|_2Bb_UjDTF0DB7d)dHeq9f5EHuUmY|@321p5CTBDt)-gad0n#LDsZQT zW@S#9R31f9(MyvDs}Gi5@+jy@o{5rR$TG{)CCt)Y*a7rE61Dk&_INE2=Bd&$F;X%@ zr@+dh*K%NFRL?xpyOQ(Q617i8V+YRWXKnJ!fq~}@{%Yrt_I`hT+E1l$K<;Q)R)_XeDF`kI}T`j!{Koih0$fGeb|_4KDO zs)gYGVL@24#*m$`ds26lD)i*(u;A_3*}M0gaL!nvYuPjCR{X?f)X=$?UgQZANLzn0 z^9xJ$z$C%m7emej&iA2Y$&GCr0!GZUJtQ6fJ636!GUcubdUi%PruPNCAqL)-CNL zpTBwV;C__rn<*t_A6;~s4Y9ihapp?IBGY(gJ<;(yKZ$d3P}1YDqAF+5Y6dcrT2=5xV!Rgu?=u|2-LWN?M47uNysR(+t9 zj8yP&NOi*%i;Up^>6bP(jkhJ^O(G$t3rBK`(RNPbw+KU6&PcI19x0iWC(EWv_N}#>X3{>O^3dP*Wna;Lg8OC4)Tml z3~F}FmlN^}fhff@s{bodix0(!unk~K^&zfL=!t;;0oD+}77%yG`|}GL5wXpr0rVv| z68B{b(ExHXq{agDH?Er&C5L5>9UWI1H;+TD6WMub1NQ+q!(nr=0;q>&(N`UR2&32? zRvV(17)$JQ2BmHuchzJ8Vl4ItD+PVc^=8`~-@KmEhwOsc(_xVbwUp_2uJr0ep3^sq zZxN+rLO|-nb1T|hf-O=V9A$QPsLHvJ>6DV0lJ<_LH;ANL7a4uX#XOvilA@dVdf%t; z#Z5>4!e_pOOIR)57e56#9UxnFGzAuy1?!ve!)X3#sz!FCV8Ix!Bh8v$FFF=IBjZuX z?g7~Bd>Q4*sfcMAlRQWkOh?GG?J4Z6Xs!TIY3@3IqTp8yZ}{0U9Q3BvHKWbqPhGjr z=Wmpk8P|@RoKX+jz45MYqt!@A%z71XSQbqnpNM`_tDQQ|dc|)iT-`HmV6WQf;Z@DW z7gSgGr;@wD>xN&)U$etFJTJCc2Pr)~`dwd$t6#m{V~lJsNG6|QilggU%>i;bKJOv) zl)a*sQNF~muZJb}@m;k?a$VUQyfl)c{iS&c)RME4Qp;Vnj7+~CwLjQlm9sbXLJn%2 z)s;7dRu@Eviw+!bul=nQ*~;r)hBJ4s^R`Lc9$`n!=EvE|ArSYCt8C@96DOt zacjr)?7f4&Kl(P-yULV2RN(WLxXHB-w}SjHVOiY>E`@WrWr4dG^CRc_KPIfm9=JT* zLscFUe92K{Gns`JtsI+M*v>7y1~o_RCo`0vdI#oLdf!&jaS*n(?Rj_=b<7qSFn!%lGb?yg3en%wbGu3TG+#F-(DINnT}*ZY+SxGL!IhI4Xh$4zmb zLLm7LmW+@=u2v=Q)RBRxT*NyJ2SgN{kipRi*B?twA(Css?(6OhOQrCvKqbdKQSCe~ z*?Xv=5w&t$n~j)3CS40FeNJJZc+y5SoYb>`Z}Ku|BFEC;Fgxz$xSn$;#!%34m_`5A zLlSRDHrGJiv2Vdo=5tam3&L5cxEuLE3e8W3D6a)T7!dGgM&PkRI81{Ytlt8RJY0lB zm6Rn9syBGKyL0;K*sG7Wd+3Czt4D(dfuu2UdlFSQiJm{1t_yy&g=prZOfN*}t5)ve zEV>Jl0#$KLkZfDE#a~o2@hU=@$XGm|nr5Is)P>6G0F2o%{TDb17vxKv*=Hqcw~&k! zx_`%iL{~ClrvQ$@qVtNsseObzq=>d2WNCvhLttt0&ze0sae)Zf{R|>*ps3Q6G9RyI zCqOcKGnk*dLw|73ME9sUhP>tk5p{iuL&dw5(7iGA4_i&gQ;N*=;&jyngfx1qR#`N5 z?U=yHE+yUZ$^zNV^P!=|q2Qh` zXUjFCRIAUz4A;>0u{WzH5U9kU%1*%&w72G9mKcuBWmE?EWnU$>$3&6q>$tV%Jip#&Nlv zH>!*_v)E>=NP;FiI`y0dIK)-Gff^q?jmAhbWx&<5OXBP{gtl`8 zl|f;wY9(6$y&5#256NJW{?rYI&YiuR=%}G#LIfLdW)@dGb3_->T58iaK1`&Cv9v&* z-;Ir^Oh8R@2*!?+Q2FXlIhjTCKBp=uH$~!2DV6Kch&%%2jK+)`p5xe~=YB2dKmS!_j_ zOW1}s7Op1GUqhgwd?-8+5Gw*gc71`%lDvFFlNL*0d5!ycNZ6Ss>UP}|Ie4p1dZ9nB z*}uvBJ$UXtOu^MU8wd4}@|ghyosQ%^h~EH*rtU30;Z&VMD{FY~WbHq759nE-eJQk> z_()M)p-WtFCUultp&KLg1~gBtW=oecXp;m)eyODp%sZZu8F5{C37!h`nok%A_PPql zj49c4pH6Q|#q&$ZdOx(*e!*@Owz15qNh$Y1#$W{iH!vs%|CD#a%`~!0|BCKpoh$Uh zg^vT%1xBh^IRo#tOOGG-(dl$Bbdom)#2a6E7CDDZYg=r4FH(q_A#GH&JvIh zuJ;yVPW{N%&ATY!%^H|}08|0MtVL2yAF%~dIHeH=^|w}(x6ionSTiO#()NZmQ@dMq zH^&e)Ta~h0J8Tp46x|+0(SL)0xXo_q^8vc-)|3F5j1IAB#WbhWlN$@`QRJo~nF4JO zKFR1NYdK}HP!>WvM8Y1KPndIun^E${aHfK<`3>8hrJ1ZS^4!C;P%~G_g@X_x+6Q`q zh!-1$OyT8$rGd+JaR7mx-;1RNPLq6 z+KvY+kTvf2pLQ0F`YP-k5w3=d003~U@_#wSJGq(u&weHjKCAR!@xO*4$JqaN0^07o zd_fs;Q%2KG#U)!!mLH-I*=tH$7DZ*5ltg4spETG$c2FceX+8!T0RpK9);| zrHv!hudqG=`mGzCC%yfYP)$aB@>+7az)YmCqpQM&LHlx?5h3b=b z9r(CD()YHvhkt;1?C^h%+M|4BRhasA$wcO+c(|vaiDsR8bLZgW=`_~MZdg7WjY{wz zNB~usp;^#ni86ZPq*0HrkHYICN$xXQ<%aMWDa^((C2}=K0OB-agDQKJat+1qoN zL~|L_`{v24(1~w3xlZEs5{;uVX_VV93Js($>ZZrI=&AO_v}Ci`1cRn z*!vg&yrSx3pFz`RkqjtctO{Vx{8EKMCuY#}Lr2oFQIbi__2I=J{w&9pb^||xyQitS z&0k-}c=sZ<0TeE147tDA1!*C#`*q;e?XZz~q8w3+M}NM+f28-o$?}YL4A^lo-0iU$ zkd!c%Srpj{bZSnf^5iLlOEsCc;8!Sig$X9tau-SAp+p9 z>PoJo!#G*kQ!2{ii?$QFYwcC35wHHW0T!QhGMtLJYH@Z5c5zAg<0uQ-`@A0O($xjX z2p^{NmnqL8iV9SbNoL0+_F0D5gs|&id|Wha8Xc`?dd%qN2x9RlVT1oYT33jd7|S@4 znwsFZPBD+pOYdeNZ!Z@pTj0BXvg5v0Y1IP68FlWfdktz@D8pLnx=Vi|n3a0sTsPSs zj?}(-xg#!R4jY;m&~ul!kE7fBz8_~dt0&<1l!%cl+{@M7BdVgtrJ|4`)C)eK=!PGoc;mfV(%EK78^dEwM4U z0Yv;nN4_?g_hX#fR*3h870>TO(_TFx)QPr8$vT;4+NcfeW@p8p!f7@sTCIho?Kf>on2ozeK<)%RxrO2P2)!ApCzGy~IdM`zJ*QB{(AF>{HWy(DCSA8* zVacP~61j<)H2k|~%*N3!gyB@KFbU?EIFKYNr&Juy5erqAL!Q~{VR<)qx21CYJ8-1K z@OD~JeyWu0-BJxFOAL(fEMvCdY%+h_Kd(pV&+_Jl29YBO6v{Fp(<9_a9&5XI7~y ztxIWHW50du8_l>LHrMYf&?6of6ArT*NFVeJw|C&1RW1Um#s>L6vYXpBq!MHy17GGs z!7+gKC)8|-Yd7rT?DX9Z@{-^w10oVrK2}IA+D92@6`F?H8yR?ZPE%6_fbFVNroNVk zez!JlWR4Da^V+A|j8BDFV4_!RcG5Oy?`RvS;ml(C79RQndCMJ#M+|pE}=KuZCX!J@Tffr>oy(sGq$( zOOV$%0v7W9*Gk8d8yBbP&-M8Xb=KnJi=Fn=DXZ0vI8&a;d^PCjJcRlh5IjLH6-E_8 zf9M{3I0PZ>h&lMep7AzV#r#@MAqaM34ISyfPMI93MHAy1;lKW~EKk8Pvq@P*v4c2$ z{^*cZ@TXzPbdovHb@pDl8~BD<=lC5snyWiU>jn9imt6;giUwV5_vw%={OK(#@tS=U zzhkz|sGTA%8SuLr7NT+^bTw20tpl`NsQ|f@S;-f<7vp*FkM;d1!#uXNYSGiIna5{O zQ)#=efBJs55$kk&eVu^GlU|QL(lG7BGa*#u5U9ol0JqgV&zkt1V5u0cLKxOs##PNh znhE6A4sEP2Wy|N5uN#GghNSfrEJG65Dsj`W2W|s8v!qHKy5r6QM^~t-e-q}B$V_X7_ONQ zyhgn5$$iv^?M9>)W7Z(abgj(#fraCapl9o>*R7(Nr5>WcH@1}D?4iR4nD+XQv7A zs@9m#=pXouFlX_7hM14PyR;3GZ@t6zo}g{3lotqo(*iRB>N>i?z}QUb|fh9YZn1 zS3z1e;3C94>5B^*UTsAsnqHFHR9a`YS61piE~2vEd#$&-=@MAVA64~uGQF1wV$?i) zsgkR=Uv;05QXn-n1%Y90)!3n5Q;TMNE{5w?-lTTI;T05(vw9qjd-B_YIM%}N#+MRa zp7U$y?dLF>T;3gzwnsDHHCr9j%<>nns_~6}*CA1^w_IjkS27m#uk<=Abr%0!d3f;R zubom1x$j@2Y8hG~qGz9b_Y<9xr>$->S6d>cDC>j7h~}}^>UgbSKVJCPUu;sv7VTb? z7b17dleO_2s`^|%m(L*KE+3v_nOz&CzPIS5B9UQ((pG#?p?Z;xvi0tPT)m64h=aO4 zb#6;OHsvF5)OFAqBncbu{!hNCI@pks{$j9@?KccY%HL$Y%;M!RV zYlQy~-mk`)Uv^*uSz}#{fDiN165KdVQHgjVW=UKnVUqUB0ZJ6ibvO3ll6m+0nS4{W z#owAG+++62=FDhXrX!_9P*>`?P_o(kB?w4 z3GOp`5?8Sq&H8-wSjt<91#Pju2;!w3LJHfHbw3{kJX9 z3tiy$H%F%XIht_Nspw=AbpF&29LRp^=aMi!KS_bBiEm7(OB3JtGgq*DV_VNTxofr?&Vzm>_}%Kxhb|Kj!(z5&$w zTcJ0q$Z&~1)Afq7QsnT-Z44%cU%Ne92ZzqJu)hnmA@udi06DB42pn2oob%b&YXxh* zMiL+$Zo4#e9cAQ)TjU>9gDYY6&0T}rlCxf}V29dq((F^V_Zq%2EQC|@^w$Z8{3m9X zv6(ClkTB(&_8p#y^9rxxgXI=f8Qb54Vm;M#k_Ni$uj@mr`3tSSPaXNGjVl-l5g{97 z{PflbT=nU_C+@02!^~H|;IXR4bEj<3>I$Ms-Lk+r?rU5lT~PvBsyF!JG1gM~eZ|5A zDn6-qI;Ho+1~$_z`%C)-yy%v7Z!r{PF3=0;;Ij4C12fAk|*63;7i0(Bl!gcRRc zV-G<|1fSe0_pTzK7O6wKV8~WO6<=_PU|tN@mqAVrGN%N{yv{NgFTwI|56i~?lz{#e zBG1^XaPo|yX2a#+%1D2AX^~)}dllNq*GrL*f0of6we9)GOAx*bBB4jVPazh*$a{x1 zT(3(C&+M4+)c7nSoJ6fV+~cnpNvvK0e_$mG98Jf<&|F z9rs6Q^xQ%aZFrt>O9!xJ&2C^uD-b0_WpsVlS={hRL@#{G{B(VyXM@+(yA&~`4!ITcw3=3mHwb9e^I&H zD3@#^5FA!u+Om#YS@C9Fp!^ho(7q|)3ryKnnTURC$pf=)P#bvIBdt5M;U2zUOXwhP zEKx3pBC#9w!PX|I0rpVo##nHA(-uB~zA_04LXBhz$bpX{uqSuPZgW3KbF^PYUnA< zjY0lj>*;dmqiEPq1St|U5Kt!`5D?n`H&43Q8yh&A{Lk!wgmqf!zt?|gE!P@0cAMkK z-?e%TW&IM32^NaUR1^MzCpeIjjNzcX9hb|@;p833&oU0{It!@}1${kDQ*9-5BNm!? zfrZj&2~+Fq8D=}!ofFuMNG70~I$sRxE83WN5@f^kI!*PXhB*uM9VUexC?@Gn7|8QA zSHnd6)vjz#y{U3MdNE5UMl# zx%NUDD|b+Vp2ScPLFr`SuykqWjjWtRkv3-ob#mDSf$4U9)?cV*VvpC^Rg~OqZ!3DQmd1-E47686 z0{*al{JS}mgGXNjU@fU(RfJ#(6M$z=DkMy3^7-mqX=B_n2mkYT$9x0i! z?=3F5LPK&%LrT7Qi+JYqIn1XXN4W`i3kg$aR9^#2G)a3$^%o=zox8?P+u*07(Kp`M z7X9BeZLiVyFp~cHznXHpzJhq974&t(AvLRM9TAo9wk}pZ!1V}wqvW&*Z%*y`Gk&A* z`@-}QcvIftt69x9hXSpPKCIQHZs|BbxS#=9p?lVpZ8GZ!$uc22)MEa+ON6TomOo); zkR+1KOb3S*9fqC|XTcGnki;(>+P^C*6dB1R8n>s7<)lierB+a=LJF|AL>*N@iNDM~ zl9>y<$G69(awXjD^L*PUd3ArnK*OtzA`uYaJ*54k3*5xgOwGI5&`2fXh*M^k5^N^Y z@{|@;b;+4_d(neabUN-1yShpkm^m!}=-2a0SbK`vI^zr;P<^>~@osYWcf^hbBm0`< z8DE&OkWi8THJTvgM|A)F4TkljNce*E@g|{pCOqc+i$}IWDllNM+32Q zh(d$rH-?;_$cTID+e+JvIP>Ea8d9PK8n$4=Kr+DC3Ws175Wh~CCBnC8&UqGS z;Ml<=v$#^qOW#6)lnGw!v5_-hXcs#QS3eMn0&VQU`ErqoW{NO?<^8$#4#R@Pfij8b zY?=Q^))$heE><$4dZ>;C-#kk+L1#?4`7@`tLe`mt<*z4lrU3lO^6>9NQAqPzs{~HK zabM4;-C@&i!hKfB-D=_#Xe7u+q2fRrb>xf?ficNEGb7E@7$d2Br6!Nvbcz$G^P=Ah zh|Xc^4G`PY*VHtabLeaD?Cj=|K%V`D4GzYWE<5U|>?qsFF|LIqWD%@}h0-_;@(C0e z^Vi&;?&;>J{*4_Kbj`$9vtB7BR0h;geUpK7gU7N>?TR?bwnCdpQQUfvumvFX$9~3W zIfl=oi(&$gbxWa@z=~YfOuv#=oohzcHgGCWkL`~qGZ*8b~RBF(&~>| z3%K2vvAWgvcV(D2I{_e(rxRF_+pu)<#O|hh6V!z=UeVE z(YC)fu(OLHbyfAUYk3RfqIA^uVX`lFM!-oha15c561u}&=k+44 z<#++Lg>%YIDYTXwI{E~}Y2!XVam)&ahjanYn$0QTh1+Vtx&U*E^mO4BO8g^3xb!cL zQa03-Af;y`7hKdVfSnhp;Ar89Hp7AKjA)-|)0XL`@sl8brpCc*(WZ8PhI?a*~G}_Bu6g}d$kk^ zs=GQ*ywCAwPFV8~1(;^6YFr#b&_NZZ&|3gXn{VUyGJ~g)q}NXCq4nQ@Lc)gX_?RI@ z=IW`VqM$3Pkb_eGavCC*U2R?a+5Cd8ZdFV#^Uu?ed#F;AP?7N_mNYhcQNL;CUO2Nd z4?)UMoh9*`;BBpcR_CqARNF+`hKi#u1lJZA(AUL5rNL zm9VHWHSS2uffUa1JO3;5puJHjY((Pd3oLD97=6E}&v6y4x0=`yw=*CWYbm^z*q>c+ z>fw-7*d;Gi`lS{USIrobtx$ZgFsgj&CiIm%bzyB{IL?LoIH6j?C9X6_gdf(36}Sd6 z?D8l*W|b#|Ig4!4DB6(%=koe!lMdXY#7X==){x)rXKW%$&hP%(V-9n$k2i;#1EJff z&d<0wxlrdIA|A}uc@<5SoX|aQ0NSQ{tNfj|{3ay$FshB=Gde}U#@*3TUIgoBf^~&A zk9YBD8Ju#EF{O@u@RES$p+3APZl_wyvscJ5e800*1vlbWylMPFv3~coF(EBIBfj~F zM#c!_v@Sf3%21~%qWtzmspYI_MI%q8-dy-S)<9RL zregeymM&8EPg|wDWYdpYfj~Wsio2hgO8GxkTa9L}ZTPIHpft_R##yXVd-Ko8GH-)! zNm8o(Z4`0%WkLzIjQEAlE#tBdd{p7tH>OBx%Evr^cHFX-7xtaQR6j%xM?BH=!sVRH*4E1SN{2>`8Vnz^%Tu$)g_4n8Q&n@} z`hUYIMHX91|Goa>aW%|m<+jPuxcfva@1>*ID*85G9D%|OP%`5*TO^}&^(1T@ETNJ# zlu3XQdQWKm`I?0TLLs6S=zQ6_Oj0ND$A*LW3vqUR3lTC7u}Fn|ca&IT_h6Fg+^XT% z_Gi!;gFK3u_QB%^y49Iy-ZICO8#XANvWbW`ZxI_&>?!%^lP9joVm)!U+GAY+)-hLt zwl?pLCfu-Yyr>;-u!&CUX(;gYQZU&k%5GlMFU~Rd*g_LnoO}rr7*=8T5RH08u8K(S z;?@GXBNh&2)gk`RqIF4L6N-9x`)6h-CLd$oLp4-YnPKPbLcE%BRMvx4E;w->#D0iv zyY2|VAJ*BPr1U!X#JmBw?KgPr^@*k|gRp@(OZrBvjh<*f`u1@RBLC|um-vsyAvJt_ zU;GD`*&U=MsnnA7c$+4~=08{U5%>12l>j#T;SI2&lb@J3@(~DXC85vB`fE43J_q4IP8Bk-1~Gr1@E_mv%O1B9o)<|% zFb_Pj&S(9d2;s;o>x&}S6+9uefb8dLNNPqo*`_AgS`n57^<{8FHkBhYMcz!`htyXi z$!hyu{@^CAT~_~?gDqB1*4OLh{8|gA5J@@6+difjXF!||L3L4siOxWC+!ra=c?Oje zov80^A?tpsIQ)>nsW$tj2hQ-JMe^^=iL|R78Oq}o2N&iiy(lIBC@S_p(?_IIHUVh` zDkx990S}X z$wJV_9vBvYBMQtbjbaOe)+<1|gAO(oqa9fB88}|!TeJ|-*-RjzizCG~S-ZQk;>U%Y%i zY-oaF&|aO_VDrivo7f2xYq5cLE|?J$~M6h3G#QJrLl_fpCYpGnuZ^Ql+Xeez>E)FGh4adjJ-JLHYL-V>5u!{ zMV<(fqq-8#*m+8$Su-c~6~KHN*lBW$Vw_Y^NHm0H*H{9BVuFqa`$XT+idKc_+~d~JCZ7ub z#@E1i_{2L6yb)1|&4*-5p)p7DaRka9?5LEohL4NJjS#PkI{06_sF=Sz^em=ahpjOn zIDfE~X=xO|A+NQvL#t{tBrRc^HI&F}&>3mRPnS=aN+< z$m`OWULvTDFXB8RrN|d@O-qq4FmM+Tyst=Ac8VLTz?{)rQR9wB?TUmL*_iczvY4WD8kWUZfplgqpmp6FfPMsbzwRh>nq zUsfdS{Timr7VQx~g5@j{4QXHnlOXR3&QKNfSB&}kHc;<_3z;eLWU9T)b6x;QHaz%~ z9MLp8`P?mY>kX{xx=$O(EQi?17tkl>fCoq5@iG1NCn(75irzia%Ju80;pa8XjIIlh z;L7Vm=h=-ww>W6%E6C^7tzTCHJFjdN^vd|AirhZQ4Zp%~b_&TY|Hm?7y3k@LyZ2VW zen_r=Ig&3D6|i(u*-v|92>Q00KCSl-S)hTd!SX+=fGJoniZ5@kOL zhnQ0O6qyy{iy1O!Ola2Xa0g z%~#H;il2oepM|5qg6~wiYovxuMrM>fbfRo1B=1O!e|PCvDUw3}?3BL{0iU~j;5?cC zzl=IbEQyGe!5cavLvR^%ksK|hIGuWa2fPh;yZx-J>>oTi3Izs)lpMun9Q7PIv$}?b zIp!J^XBQr;@aX{G1v4vC&G+amR*&_`0YkaK3^C@F~;WBVNq9| zoXP4P9w8z@ZpR8hBaDb1EbG>Se0if?;$*e<%USVw7J3yslPNqm>=Ab38Spcmx(7x- zGKgsWlv(^ppmH%5_r+1NRQN|j6w@nLn}Ec&T$!GybuQLaAyKlW{a>&tTO~=@{^}VU z2_?lkrlpSOJCAHrg==5bHil34;jN*axY5Z0j#=;KrQZVMf2RS0G@j8oOzQ2#n6`6} znLwei&fv?@p%edtdir-zqq5Q_%*DXd7c}ETC0X2gV?sZhQ{R3slwN*L=8-r2;dafdR$&l*vn14Te^qiwMKNc?UD(-xU~&ZcZE;2ps#x(4J;IsjTK+ zrZ1sK5 zs^X2#f@PIN1W6QGIj{Ib5Hr)DSk1Y?`S0)5$>R%!V-e{{)syf`q5YNJj26MiW)TIn+d3}V$EOMjEC9QcSwFmwRp{4m*dO}Bt6m;I2tHcbCIE)z&J~m z&6Us85UzPp`G%dPu2746y9Cq?>b?-{8F8}`a1aZZe1m3 zjXLbgR0WYQDArjI1D}-lHDMl%SKuB*^@u+Pd4pTj;bkZFZ-6G^cDMdrBCgBzp?GFI zMITs=e7!r!^w@@y02kSLJnAFOV18NIlaP@$h#Vk2=H5gauE0t}x}YMW^l0F-dmC;h zS!-%k=0R~`P##>1w+6BSibCxsDzSwfzUgFgM|s$*mib*Eu7E{ymHmP>DQ|slXu{l zlL(w`$TL~=?eB6Fs60L};1emre9DMLeF}5uxae5sBiS0-5?zTaiD_sXQ^Nz6Kz*A{vOqTJemtE|V02((cf1k)` zru`K6U9Cux!PT0G5Sfa&<&ypALKMP4=N9p`)cf5KDa%6+NHj%2#s;94Uxu}p3DyL< z+!7$t+tL^!`Iwh8d~E#DcK5Q9>1bmH%^=mBIT9_Sd#ay|-f}+3%JZcX36CqX%NBvMyK_0Uv6JSoV)y3*78alHB zq~{qKD;5mvhKnR=Zt49W%n%YO3;y#VbP44YDi!58$vyMi=aCP&$h@4$GwxVwK`Y29 zdekTjIx7sySwU@1OU%MESyrV~xota8%ubx32uV1gsR$>rH=&|gl9+}YaF#}BKCw1Z zKovKHa5JqU)>&))bBcqvau-wx6r(1nq~y3NYey9eoEdCHJ1J>h>B{%xNaU>&)?1#xkPJ?)xaWBUb}ZkKj&;W7 z?F~(Fv-+9b+DXsYsFh18FDgYb#PX(C0tI^Ri!yL$swGing6ZZfwII`7PBzeNpgwj! z137Ru?{qsN@z&|!VY4N0@mm7eVWc6?Z3BEjq}jP^9#xAj4UYPHp#E7tS}ixjmIqu_TfuWTq zpt^wO6Jh5voLee4K~4E1o5cwSh9u~B6|%Ndf!8Jm^q{F#L_tcog>;*B-Mj5RrRbG; zo$aw@+oF-~?^}W9{gtO&I$!Q>-^G&YHxkXnG2oM6WC(CrCPv z8fhA&c%)-kj#@e!?|#a~9^6?^goL?tvS{n-i|C#s$O6wO$29R*K3F7m11+YP@mYG7 zY@Ywkz+Mc~0{Qbyt?lWCGHKfCYz_UpSZfW-i7S`VxK9mVxIgnu@2vdA;*DP8fWTDm zOA*2ZL0|h+iC()2{C?$L5wr=~H7PkaqQG8NnGc-vy}0Tj*~32;X-DAc>Rxdoq3w+h z=>szDtjjh~u~DcA897D3^f3zUw$jY#kli&B)x00o&ZD!yHE4PanWB=MAOQ z_U@XI5R2reD%fyE8{}IwnI64cW=H7H_?}0>ik;}Y(`1>D4k%!CF|62SxOsQ>_pCU2 z3go&EQze-7?ZFO_@l6xS&eusjViFmErq0djlV6HTQr$>Oqy^O%gNQBzFUdgl*s~^3 zX(lc!4Q1l&97lXSWU?@=($`bM9QZx35OM7%&Vi;W>3fc&(dDEcEhW^^u6bkF5J{Q7 zVzG3{`yvyIM9MPC&edjzP128Jbl0z-bBnOr!&Q!0p+5KuiAIvmrNPe9+s<;7IkZy0f|f0S!dI# zdN+rTh1xV~qiW~my7xi&Lw8;{Gp0lZ>5CDQn4=wfQoxIhLh?krYonI?#+oo@eD1z{ zTRZ|khj_la*?G6J{o`n}9G|5|^xb{i-LR#8OypEy`-4wcEQ^*mD%WGr8!N)%$EM8= zasup^Uz=AZiWZchPY`b!rDA+TO*u?d{S;?hY;XtZn`w7H@CJ$AE#Q;dNgR!@!qn~V zl2MMBeM9O)mlFuj_fNF0uSa+F-T6VJPa#&0fe#pvNmzl)oy|y{18__A3OHE_ZzxqV z=6CdJ0zaxKiwd}kz%99t>8Kf8YM5(9$S5FFx5@VGc|~tWkp$bOV_t6FrMHmcAc{0^ z@(!2E1BE)O-N@7%*Yb8;_$L9Ks<*_+zr=8kI+!tw)QJA=@^vS_^F1t$Jd&CXm1_sT z&F&2~Qwa_bKe#YNooWCD>X~IGSS4557B5%3IQcUmSax|fWj&u)6Y^ij8^DVdnx#m97&v+CmGK#L+EfG`Whl>H+1e|95jwW{U^3$41vXo;v` zz&VV7=F2Z$DGUd))cjg?m6(TgyY0bo$JWO1!^f}p1cw-oOR@3`@ba0eRo((d7F-KF zYqH)uP|ceK3&wI&lVBnQN>2FJfEgGM8zef#j3zN?)dF_Bsz{E(-qiu4Eh7F|1O~&7 zCQ+3jZyl@?SMR)itzOaI6v(q;T%#dV>{eY#8(sCPo68mBW|@GyoBo&DwwJ;W856oE zSOTghn{EnAD_P8LV1KMS|CJmdpKnn&M}0A~i_+Lyse%qhi5(}YW1St+XxRZ&Z^g6> zJzsaFhuZ7sHHEnAHf3-g3i;nm3`r%pG<^V=w7ZM^O1Hbg2pk+X^#9mKO zdW=MWP30>w<^KqfvADMP^~oinS%JoU!2SWo>nSC8y@~!3ycG+0(Ak6aMq(=X(gD{K z6b^_b#B&YVnG__gTQY}}s~ZS0y-<0k{by48$cQozbvtK&cBWatI(hDN0dH~Z`~qLr z3hG<6FzwBZM$VN_16%H5c@Vesu&amoLALWI;cZyp$AjxX3dYReUdO`|SndiMSS*V} z$mQd~!sFlgng7+qsvElPyuD1Z0VMws_dp}kg|k;yDg33jI5vm)w(m%^uYInPvlOJxka6Yt%WasUKCv+ByJ1jI2x_(?y`E7|rW zNsQon+;GIzHh|C242!tmXFRj9JLcJxOwout@9afoB$z_U+3zhE?nb z&gIy%-x~{ai1UK;ihbLU_Cp9kFpIdkzX>+Cd)i?dLndNYXjiW0;I?Z7bQDw|kEB3n z;42IUE7Bh~6RIFQTXHoemmHbuql($X+59;2pKk=0ET-|K*F0;wm#W#i1&<5+07oJ5 zOsDQdHK$I?04#YQmk0>%C6!&~2$`tV1yNBkHw^_69((~tAhRn{ig1bPeI$8JB~lc{;lmZz*AEf`E0Rzlf^ zyb3ej6e?`6l^*%TdNcJKnHjpX=d@E1tRJ`m5+xbuOC7T-#DazkesdQtzDP5;loP>P zL-~Fp3uMY(MyXFTK}E)Hc5Y1yj}(Nz#4g$jHy;|URhC`r-}J_`AhU2)-Y2ay1>?&4 z3n_(ZVcw*z9@Hp$CZj6Ja3@lsv04sUsuFqKN$n_#*r&x6aq*B)T+VvOOFu984# z?dX7HWf!GKSs!S(C0euryl^kXHefo57$HuJW9PVRn0y=+7)W2Y)0w#D3ZVFV^!wPD zP_=vjQK??k6Dly;gm^cD64aYgokG#^=preQTRf8eAsGGctn3^_4S;rycSoeb{6*q% zHC(jRRsHgjG0064=d`~<9G@KavF9c{SO@rToL7t(6J1T>oYj_0nfAGfj)+~K->Y> znqARM+q~ptk~q?`u!agM%}w^UH&gVbK6jPeExV+srGH2x)?%AY^~b+%h@!3;Pnc@j zn;CIQ{XM_*=D4ZQnY?lJtLp3=A1$U0^A@t36G@}! ztj3-4Z(JI&J5n>+s=<8`NFmx=aH-p5;1s`SG5pLs7Yq1C-Od8CldObl-)?}Fop^Y- z3N0n2qo#pzJ^$YGR;`CG14-*Y9_)Q&miDmKC+;8YZ>u|4v?Jxf7tCUs;dh11#(0A}_EXTDvA?Eu2oX9Y6&+PLyDBH_aJ z&K%=!BIsepIVDf_TjTJZpq4-Qva$iC&>EpN?>1YtF=C!0rV4U$WUv3EGWEBem;t}H-5vH4UYFdd!wt+5*7g4Bt;PFzJayuTPQ-v(}!&dO1egG zH_)pu*mMf?!cZokLc0P@A<0|Yw1j_2*&=H!4$NYxz&-w;a5o6oOw~HRn85AUnPbMF z6JZt#jqdtMnxAjOU(&#`ebUW8@O8}2&jD>y67 zY6lHf(W^aWzz4f_r@kr6Z3W)or9lqT4Ab&Ak`NiqrhGmuX>x(NY(ss$kwu`f`?J`k z93N*D5R{EcplQn*BW<>9@RvQGjyE1DFUM?Y+`3&iDOD|g!e>g{h^5UIZDZ9QQJ*k4 zr~@IZq@KMCHEGO{c^)P%oA9;GM$ z1eApNhAn;eB)qmeVEBkah{=uC#0nDMv%Bfp>)~d3W!~Ue`dh>3V5ehlg|E;clN1xg zCnMh;Is?aqgw&}grrpoxf<0|j_1WObY7K1*VeqeYNA(QmnJSxi%dCkr@Cc1x^se-_(!652OOSU^jwO`(G!>}rB#B!NMbz=^QDOh z@4&=J#cEbweTkxi^E?6rKD(}Y>R+x~^$!`YHq&WpDsE{2vw#SGMGA`c0__B@6u*u6 zJX}MJ;vh$73;URxjMndrl#Y$BmI_Hwz0Fn)B@L(dB96G+ygZt}Nr#4vrmX` zA=hY`4}WAW{G)r?Bj?s<66!K=Yfid_<@z(va-WvO?{)PVQbR!X!>j--JpoZxe#Er} z80v0mjo zh9&uBV)h~PM!ODy&z*-d@?nCxWszlDJFU77bwZJMXndRZRgD;8TE3I65?K>iK|-ou zM|!#)FvK<`ooqD*C~iik9@S4~6(F!IG8AxG zG#XdkB*0|;^9F&hsakdwWx`SvE8ZshT(y$`Z>Av#sZPD5^N|QinF;RnNxAS0PxIPd zh~EjWQAHnD7BAsQ>xNx!Eb>Kbn6g9)hP~y5Et(a+ojPa>X`_YZrG*VE2yZ6k*CM}M zvJLtM31S&wd}iZJX%39N3G`YSR-Vr(XPlK#hc9IomF#MMEO;)#*vz662P~W~x zAr(K;91*q>V`y90dAVC(UtfF0R6~jvrad z28SE%WK?Uqd<=!?*5A>nyW7z_c&7MIjA2|3# zYcsL)WwfJXJ+&fr$61xh<0gT3yWX-uWd=vh70S~EjesS^I*VK@qGk$qH4AC6MODza zaeHWTz>G($a`IJ6DhlJ-otRu)9Oa-HDWV2sP!5j5b$O-cH^AHrO{#;=kee0+ei5B_ z@IW+RMw)hsRe^cB{1Q>xQkh0g5>1%yGToo57h}48Zo0if~puS`9)jfbVUlJt9Gp z0QMTFQl3O~psHNr(}vH*igIOXTrM%N^K~#woqjVg zGb=M9s6wG}!gp;y6N&p-jjZPXhuYM;G`G3b)t4NebeFMg$Y1O#9{E4HN+Vit~`IoXzO$sZnkcud}1{z}Mv%67pW}-0Gc|KvSK(Tby z_7Pl=!IN>oj&bh`ET;c={7>L6Y|7f+qahwO>iz6*tjb(Y66ZIe#SP2D`DbMSCb@=S z9oINt$oa%dTJT>m-ZH_szb+BcK^61XiB3rXF^M`B((urR1@+64<`-mIt}&PEiHAS` z?jf;`T8BS80d=%;hUP4Ng>JX4u1P(IMPG+S##V<+@>CupX<(_PY2HnwY7LPdmt^p0Gy~dKl-k1gigg?a#FWfEG%_uR+7-^ zTOZAfJTJnB4wjr(K2_gDWJs%Ex?@IHwKlV$RTHcGba(}a*Dgm!MoezE2To>p<|%r< z&~<4mOGsUZZ}tS(Cw*(*hED!iM3ryi^tF6!ZalAu4?a=c9lAID10ejS7YF5tv{YY( z-mfShQDS>^w@?vjnFYh}axw(ROQWpOem}M(A z3B={a1sS-t_ea4_oT-PNzVo@WWRgss7vIIml^-zr*3O$r2G;KdiAy$(3a_rSb@Gai z4K6Hb+iabHiYitCg5iAMiI^8@d}E&}*NTJ#T-Vi-f+Stt9L3B?r%)J(1gXnc*(&(B z@^V%B4@~i6pF)S(kI_=1EJ|9ySlq7hJSy~zUS0&^3}{hiO3K*8D6gRM&M{mW*jBCC=)6q~R~SLT-2KK`bAWl7W^?J7LkjaDs?1F2B?g$~@i%m_{Dm&BS5uc{6c zS#cVpwql|Mf)Nuw!lcF0Q$2d8iOCfI zJc#{e=z^HD#Xrs~kI3urpK2P5|03+2f<%d$ZQZtQ+wRr2ZQHhO+qP}nwr$(i>bv%h zdt#q`BK~t9W<)(yL_N%`s{CeVj)C@^J#JbR1nDxRRG=Cz>=|)?zFG9zDOnRqbCVe5 zpn|6LnQAK6Imx0-qC%d2mU+=B+F3ib#4$4uvdg4iWp>=mKtU83M5)&2t;CpqFQRz- zk<9qm$fynZ$f#BE-TOeMp{M27mC?PkwEF`^mf6GvO)E?IAsPH~F#;AhS=@6HW z5Ri;|IoJxlWELJYVeWlPF?`qqKH!;4utOu!I?3NVi z`{t+BqrRuLudkz^J$%T5kt^tQ9Y#q|A$n?9;q8!okpahG2iL#-$yF$}E$At#>ui(Q z#7)NYH&&nAuDpZd;sgO}Sh!){JYr$)mXc~NZ<4t8sf z-Vb(%156ejp6P31*EwExfKW4#k)_;Etw=HB8Qqz-7sbniyE>Qd>yzXlpWpP~y|}<7 z9XE`yDro)TBm-X&x2<09YBh9zgq|;vo~5-^kgCJ_M4!jUU?ER?i#xLpGQ`OG)_zr) z$n>_v{@4vgk1y5o3aNpw$fs6(Y%Js?=8SZ@f_WPV-l9FM!{rkd!k0sf^fVt|oR=2= z8b=2PD*-(c^tv<&kpj;MJJzVRsC&!ZgL3e48(8tK4ilID_S4g*88MtZH=j0)@KtiYThbAMxRbAld%iP zP(`|R<3`mE#-29=&mwd!t#{cnW4%?=LU|Hn&$3RnHH72#td|tTU{Ct7!V?(;($NKh z`5R$uPL!=>LN;@k^RXHQ)bkm~jb;G#Scd%1Cz|i`fun}syUlK8*U9oHra~oA*6h-} zGmbC|hK-9sx`A>q+2?sM)ZysO$=-DZs$$&+Isi+Rp>TX8d4heY1e1bBXc#;WS+F|t zJZtSBu%e13M^$uWRYE8Xm&X2Cxz0IWJXs+D+q^a2SQT79=?N5!gnKI5q~*%j1+vdc zC3jn+5CH53r5?OAMmaGFxi)=j0U8tblVvb=(unTNFNj|^DCy#cNYwm!JK2GKZ-vz> zi<B%X?O+k&RD3 zDM@ek^A~{LcHXOwqH}-`?AuN3Z*M}M*rS`?U)#w&zT-QucQ4Pv%TqdZ62DHC^%-cq zDY;@&_jmcEYa2f32S+^`24@AEf{j$`f*e~%mU9{UWdZofF4dUaT%IcCQrm91>zJmn?BEk;&mbBFj(3=+g%dXp=dnti;nlxn zn|=lH8-BOq23z47fh$E?tLDtu$f=Pd?&>o98`RhbtlZeT~cp<-~+PxqxI3bPl%OI`=3w^=teLv0hc zo3p0{#CYi;esW_?&FuvjubfwCpJQ;I+6!$h5{wv=Oulb#8|+QRsqgyZcB`gmOoBbx zAz|jYVZ}>zJxvz1y?28rf_>}bv+rXTE@a|m9M5Cx$5yxW>&|J_wskCJb*|jf&&Qt3 z(u)fu)RQO!#t&s@`9r&m5Wayy2!AmQ+rsz+OU;_8e|wv5LWYpj(3G6sjh-Lr(+{rf zKd-MizSCqMA2-yvKk|Hh>|;jfEz0^mXiP;4Et~$J{ zSrxYa{3ufW8`5bnzpb`gnMSCoZjw~zLn_!@p{gl)x=>$S-TG`DNjkLVj863x^{t3o zGx_|@u?{e<=7>kr05OcPS@l9%FS`?|bi# z_7*!re7L7Ql!w($7%A(H$gWj8(9W3R9rlcTB6>O7T%puC=k~2?nl@aej7g!ZtS{VX zTH^e3qvYW>HeHsD0sR7#wzF?qDcF~_lMk1(M{yddgHZ6MnMVcEK+f??9X;IW>A2?Fp(i5AKAL@PVqFlzU?%5ua|M zPWJ&3550k({yOXOgT+Xq5HiQes|&4=8DsK!>;Bh}q3-!`S=1}@>yGtLmTC*hNt~2O z#v@f~nZ1ipFVIhFBcn(t!y~CX8Owtmh@d1!%zDIFh$=fLhRS|pfgW1lh+b;1kH+6p zTsN14QeoWYg#6H^t7~gkk>nPL-c|{$dQV5o1{q_98UTP1iY_h;BN~#%Y*lp)6W%~< zCL+y#iQYcf=T=&CEo-qT^HMTn!jKmha1Nr;R_NDhZ&qOu!cDxn}l+m;giK1G3iDU_IzwMPfotPPw5M9(6gjf~5-IxB}F|TMXvNfd*Kw&lS@^y~%6(XUV`7}@6J4kVfz32jA*lJx%BzPP}G@F`Bj zjM*&c6i)ae!oo$oh>@0_d0*#~Yp+M884mLjbY7>FV61_`@SwvyE1A^tmvi`DjnH$r_m2L&}QX@u?k9cY-3M*9q^0FR-` zF23j#lWi6QcS|Q5cCdJa=yfZTe<{vr8>jZAijVD+%XCggc^NK?_Lyi4FsI#>CV>X! zg)h4OAX!8;&dMkSJsfbXFX78Ho_3YG(=UQq3HB=pf)hQGYLCD$Ge5(wp3IF#)5)}m zR&U=!u%<*Eb0w|Yqv!W-Z@pLG_hYJ)5Oz_%B^4m{blD=HKHoosBg`=N@}Zpwh;;wQ z4FBNuDXk{{Hq0@?WbCW@08N*%XPtCQoUgu4}pep{>O{-P!*%B-E@1BC1Qd@~a zD<^yu3vA<_BjPE~@9NrXGq{>%yZnAhYxKKSpV%=pq~#p-apIt2^8hh(nyI`eWZ+} z{`k^E7dAB{h5KCup}UYW1EFonAuCPz0s_W7G2HCn$$x+L<($G%c{grbwIAJ(ARYnE ze^KKMA3sDfQhlDOjLGo2|DJ!tUNwkTAa`dXsyugGm@Cz%;a#BZR=`5{w`oz z8y{8U)shwCFcsYH$Qla%P-eC7U}{~`z=fit^3=>)MAn;XFN3V<79ixk*zN_4AC!56 zD9b2Cr~4|L9|eC|>EUbkmA52Zzuh29w*@k-iYAOjV5~b{3Ry?Py0MrxkF8D$tfbPya<;StH$x30?W>v^i>_it!lxTlioX}Yog*grYZ-S z0AEy3*~!vJw8w&ud8BQ@)F#l@O1;n|4N%9`I~}JQ*XE{|Q8(oP8-tq>59;k z{$vo^o5b?ZuT^Q+O* ztCpi1V&_Wk&5b?Lr*Kfj=d_#G~Y+PtQX(=v#=m(BVE>EtBFrhc)AT}3MTh*Q` z60Sr580#rjeS{*3>14;Bs_(MK@RFe4|97$u>Yqs#0034ZkVv=3#SGrR>;GD)|8ug= z)x^=s!p`=82^T!U?I``%`afptp!D?qzZ>=R2zUs{|1dBz(=o8qG5n!pB!~KMP0Ifg zNzj70z7+rG&2ij5w~C(~QM_7ZeJP1H1zK z3L-Ee#wLMU;yn0KWTB+Lvq4j`E&IP7eq%{8o^m>H=S2HH=l_(lnL3;Dsg9?1)-)RIBdlrzpKPo{}{Q@OSjj{n8j z{V-MiEmRubZnZ!-?e=VCG-ws|M(JYnA=hp5t5Qjg&2Qd~%bU|6m+s-^hA6jBAV~gW zI}7Je2jBnPqSpHQIeAzB01jFJ0Q~>BMMnQdLjF54{=){NMysiNyG|8#0O^*IfIyM^>qCDc0v1th)b%Lm06g8Zlk}3?2r!s ztNqOsb0VLr&Fs*(*rB(qKQ=X~(6-UYVAD#DTqnIp513K5b!nSPt|@)8)ulG>??ol5 zeWYf!q*S*7G_70JPD3f`OkT#Wd3vU1=j6~%X;X%p?@fGFCVLEAsnhu$N##sKo_v4f z;5XfJ5Enm3<1IB6dYRgzPFc-9hcan6fO08wX;3x*sCQTnh_r}e6eiKTB&A);qG&gw zBF$6T+T)T`I#|)|@o|kL0xzxfM zAteTb<*4S*nO2z0+=lG-ldaCAs%gq71ZL8Av9e9n(VzBunKtCz90A85b!Hez_61zcyg3hqSg3 zKhvsF=>>)JaBtgCwhj)tyc%1Mc?_IWS~nRU)8$e3HkWI!1ybi-(9gIAlO(wuwH>(K!|$QeNKftE*OIuy@n?oP*>!mok-oR8 zpPF=-fkjGh5T|eISMkHW9Rg7!opmb^028fjf^Iwdw3e=0( zdZaqmkgfwLAI$qEUiF6TS2$rRhuJYbi)uL1I$u1$=E!&b*>l_G*Fl59X$|BN=Ep$P zWaNMEhSM2^+M}4q7|RZ{%_hPC&0X^=AtI7(yIII`jz_3%|<*HR16WY#R%U-&k)|NJpoG?nO#bkezw@W7UJ8 zI4_D;F;yIjaY8myyFt%CL<0zzYEp>AIb}F9wUT@j85*8n)5D*FTRCYua~{dJS28 zKToM_{p-0EF_0Xua}XfuZ%BCCUx%}u?870&IUi$fsV)Qqzlv}VNazol+@n92=T?0W zY*AT3ji&Rj-Kx(#+}UTw^hi8uW63a94>1cQux-9OINKMejdN%hT}vx~D})B=wL`~7qXF8LC99+f zIr=WR)lZ1>=1_rfKr`*)gya$$OQu)3c*6Wq#Iq$+`W`=as;KjrGwy&AMKB)rt}Ncp z84j?``qGntl!r?vAs%CZFMz7cczCeP1T#KQKtr%!k5T^Q+H#iHsLxOp(S%YOhTE1| z8gy-yTh_fEJ^tnjdbX0C)xWs_WElDZ0TB{!C6|Tz68k{lAwAzH{SLg97ogZS4O&~Ca)EFzvT-JKI4S9W#-SfzmEl2623`8_{ z#rO)cntADS!Tq}I3v%Rl@_mk*9I;fD#x$|`F^cS2sBNw#b~<4y!`LAHL_m1*VJZT0 zNlHyAOS=VY;{~j%UdQAG*h76dmqq!B0B0Ju`S$=JE8Hc1BQ7X?C=-2$aU)6ZC*MX; zeo1K(-v_T}__n*i9dXD<;icpgK@jsb!$t)=E3TS0VX#vfQ5w#fUxasKP=dm@9!ptz#GD>ho;aN!}af3-MwW5xeapd_&UlA}{;K&uA8AZbb zHPL8mkXx+|;B8w^*}uncpE`l?c`|I_Zx|n!+x{vXf?W_;fbI&x29!vd#icQ9QBgz8 zxsjf6Rq}k7w(@`+NV&QDRIKe9SS(Q$m{7Cz4A^@mLGreZ&*UY!Y`ul@(O*DvoF@I=nV#KC(wr&e7nwMBzZaeBbZENi< zmi~Y<`Q-`OCFYZACF+lmbw=CY807-S=`afzGDhLtr4Awc2d ziHeIRb$anq6lOQe@vCDg3g_q&K22VOoCKO`#yC(=Hi*RHb{su=r|S*I!M!gL0{(2b z%~{?`kW3Ld=__%*iW!4c%OfCciU~V?ls^Sbcm@RE*GHrjo5AJ%Syt^S3kcV}=ADmb z@%_1?miAD3z2f=={X6_>^-F&Q;iZ-Fs} z%v6SUjdUN+X!X14Lkg#jD8^?8@vJ6s;=gH{TfbtFwad`nhTJGeni}uwMgfH*YsWgd zKX3RGjyPZU5H(9|c(Kb3~M}}%S!x_zg2qTY3&}0DPKbOA(9dsDq*Mg#D(Rg!xT@k zwwYqLz)uT?0wVn0vMam<*pd*pR_f{4Vy#!dxHT=$t2ZDgKa{Ulj;r}S1>iS6^-r>6 z3+gnKF{g8`@z_HK!uTZ41;rmmg^xcH@#<)3<#1?^*fFF>QsxbC0(QAK4w=ZPoP3Pt zZo%i!8QA2ZX5B?<0Erb}ra3Lf7VW!{B4-JX+N+H73fEP79aio_rm_OI zj3(R4qu~0|UhF3Mb1D!oJo2E!z|6cn)Sx#cEQ13&T*VH}jU<(G_}s?@y2NTkcgGud zy01s$n%xPSfr#I4)Jr%%UYt6bZI_fdn&Cmr$V^8|E(5w-U$D+}pKI+Mwu{L{WUtOh zE>PhsD^JxxV(tfybgM`f+}C?70c);p6>v*UQ{+_me0z?Ww&!Cn&xJOwXu*cz3p;`Q z!wBs{+7`?d>^othcE@5a(^%SQ)V&Z1OC$6!tn`xoFQ!$EFzNE>2KhZStxc30Gc^WK z_xqE^fw{!~xDfLFkgR|t!3RWk`@ZnJ=h zqY|69IXpu1Mx><-p5=_7RrgzK6%#0q@I0*Ll0E^6XF|nI!uW*An$}cjla1}J)RyW9 zvXQVgg;GsBGiQ1y7fKOPRu=L*5ue&}Y%n^7Y|1-$cGwfvm>_Nd3Mz45>$0=w2=d#nT@XCBh{-0dZ_MA7A}qN1ztbcrcl%z8qQZWn4OJtF;Evw{#P&3dTdW&X*AZx(#Nj#dq9uJc336zj~$qB40r;Z7%Dk)*W64F zy%YM#lf~Gfv77H*%Z~U!+Ozkx6gkis&HGq7}Lz=BHcFDA*tIHB0nti2FL(lsENBl)uU74ia?ff6i0 z`4WuvV)r>$ac2CY-;m96PES|l44vkQdz;B2`F0nQr|f|1t@cZ|Q}!AbNDaY#N^rN=SVrOw zh#l#a;;s==qu|UOx3BJtI3BOr-u#!&c7uG|U$|~|f0_9ic&DJ%ZfHby*V5dPv5nhL z>^6^wTrn26G~WGrCpOKN=lOy)26OhC0HjG+@(I9emGYtK3MAI|A9Rsj8`=CnB#Vk4 z3AdgHB|9#_8?f2wN}=F=t-XMt2+ueBmyMc^Xi3l*)Sj(SWMKnY)ZH>>jXXGiFU(!> zpI(^vZroLd_dCpff&UxSjOl)aA1sty*`NUcK&b%!VHysAhn>qm#VZp%V{7{VjipVQ zZT=U((_pPB{nz?G_`L_q%5J;;;UA^ZixN;KtnH4<)Pa2ya^!glB(X-2!-YK+My9HfNJPrI(#jwWR))4EISWcDMgsKFG-c@C2?@UuZN7O9Rl`rP3fk_s(BHO@cK7g$`$}u-HBd1m( z9Jlaz!WJnI8bz;57|+rxA`W>vobybj0j_);iyT0A)l_V#xj$XxTbcgM`5m!&T>#zqA%W3x6kl?;Ddl1tWA({ zKSt5X-oC9Nl(ph0RcXgv8HQb9x@OTuy0M10ae|{!lS9cP5IaEy@tLq?wLSRMS_GWj z$QlpEuS2)XO$`H)_~q=Q2+0#G`pJlUO+A+raz}?BhF)p6rTEdFLhu$Zgph80Uhy zpW=e->;PRyz!T(ID}Dx|hKA?yK8lGYTw@qwFNS}wGvy~}yin_##Aui1?3Iz=chBfI zCZeBUw=WzIw2<6N=?f~XnY!>_RhaAPhd)#cPHN|$iLF&^5og#@0)s*x4jrWo>S*8aoBO8aYigDcw7kW)DJA0{B8NdflZ@ zV{3Q=b;yp0Tvrx(GL65@yfT_^gqVlSM&Q+MXyg@836V*H8%TiKZN4m!V^YR&sU zE3CBSceyf~o^h;lVcVU|EYh-7Vv55*k(V+0&_ePZwTPJPSHTHS+`dB>*f_$=yt9E} zKh5z^*ym6pBj3(0CKVP)YT=6UUz1!XIXC#S0z+@{PgYaZ@gY z=95rP5TSjgRhjTnSW7N*A$(%?ztqZYC|`j-wQ;IYrqzNHByBdCPzHTO>M;_xXEx$y z>`aL+fG76F?c!j|u8;=rih2yIdn8~q>x8A3TW5cVtslz>@GzlOSApkN6B4H~u*|hY zW~d@M;YQ1Jy+jM!h0{V(_mAj4CYbz~Wq{ESMmV=&OQ&Pk76rojEoi$19n zjC`B0M|^qJSu#iBcq7MRoh-4_+D||^nI+5yEy%!?smfSEFi+uiS99qGf;uTEyXVU+ z1GUmQKnM*lmSm2#>hFqc-!oPK%;Dc{uC1^3x)yRg&4I_IojqNU)jm>-T=Eu(0E;88 z>3wQPAkh~4&xH|#mOgD9Z!apKM-&m8&s+A^n?1Ma$$}32OVwV&=x-7^;Z?Cp)gb`63>HE}No5yw&wS0odG>8ezAur^z` zeAL&+Nyc7gZJJEZ&+wTSuCud>bR<$dZx%$AEkREK1tDsLT?>){%_Y0xS_)>BSRTX8XNX^F$B zLu3J#75O z$vn-&3?DP~@X;+SdBubrs)r>fO$Sq9~T3P_Pa@s;$Poj|p!|C8C3~w3_$#RMF0%uRg1_-_Ldr zxTu`S&_r6k5rOn_xIHY!-qR|DyW9cPtlB0Wu!swzC6G{Dr5xF7tW2Fh;E%>JsR!=^ zbAgq-*KodP6!_kgHPJ!wLCr}>qqq++{k@vJ^Rl$|lJ}{tTTuKMvh7v94+o+X2Vl!( zn;C)B6ii*ppUAd*CuhUAWD(>*iUd$rY?dwrzcf?q*T_4JroC_Q2wqXFNAKLNZfWck zRw=Vgr|03-%o(?h+}!+@B47PH6oLjA9%sL_(AJnlVBfII__15eI59K2S5|}VE9^%J zYH{{==C_xu`7$gSmdj6&1$lNgim0#000~KS3<00Me}Gq1#g(9*$GgNkyeebJ1t!e` z{oQ`F)f&MufZ5}jd6xrpyo6I#gop_*Rz~e}`lyYV;VD603@SI0Tif{^emurf(oQ$k z9HRmHQW7J^Os1y-<{Z4}o%PVBQ_R1#_et-+lkxv5Y^BuJCVTxWYQ2H}-;#0j{}!tJ z4<(ZjWtpfghJXErYB10PtXY{Mukt`0HfgWTAv?K^0~Cwwh}2S|_!}}(zg}XoH^UB- zmju((S!D}Z&vmi(7fC_|2W ztHP<(L8p{VQxpkw;4j1#)T4V+fO66@JuIA8lTLvb*JSWX23u#1c9I$G!SL^=ZE*qB zga~S%mk4u~=q$=a56w`4U7ku}p4y$35H1UCk19cubv`f{HpDzF~CJFen@2SM!F{&UM6lpT~Ki)EF+RAm3glHI246~-l8|GrKEgW;=& zj3m1dDkkhswGBHwwD^m=7ix-J9r_N%_eXEJ!v{*E-D81GO}V4q>`cHrZ6U>O@s3~? z)s$%Va5^KN zN}|o+&93T*yQY$Bmer2*TN|=i6+x?@(%6Xo8y|ue(wp??3NOp%I%XX~lu(hs1?`KF zs{KH;wBaXABc-rjQd145-{Y|?Sc5h-VwiBOP5G*O^|-S&pXU29nH_OwYkPO-hVR=O zVaNCFJ5;-IGP38}-uzZ-I7Kz^#BLKCB6+-py49LkU%fubK7+JVUj$znAk+55(JyGf zXLBXAkqeH=7~RaC%t#x2Guue4hJ}Q~{~@OlF4Fd$-IG!skM&04kporw7T6ZU>)Xt&c~Jr$@KL3PUY zPTn8WuhfWzYAZz*wp=YyE&v2o>5aS{8GHd%hDVK&CUCRie1}S93zpP z9=&p&^uss&IGOIdvb)xGT6cfWqT0|ZElrW!eF%-phPcrf{@)-iP4h={)`;aqerYSBBv)M8d5>~HND;H4b1 zE|P!yyqh9P6<+tIP)ZRk#AhW$ew#K`a6HU7N;W<37yya#=#?rnCekm=#7*y+0zr2O z%x=iRZVRLacsA|Ee#|udcU%aPftuP9#Pf{&7s2OLnG^!g$O%|+$zOSWuMH>1GmuTM z*vjz~2VG9<)||_xnPZ5wk?x=RFr`ZhBnxWi44QGzc?jq2L3`-jii_8FT7L|?dK*Fn z7?lS}rzeh7j^m7$0NxU};B3OJfzfD#39J7KeJ=+d1dj&0LP6o1o7+Frx8c-i>d=)2 znDBT6Y{U`jE<-+DZ3c}7+mjcTuZu&Vv8ZM};p`v#kEQgqmXW#;cM1cbgg=S?mkix|Pw@KXpe6JSzhc%8F)$GO!Y{?zzj2s%#y`!Pu9D&By8T!T zH|Jg!EBZNnGJ7q4u?fkWx_{#B;Bmr@u_2-q?cV{m$&X>dU#F5I;HjKY4w?oR&;0RK zaLc_z4r{=z)6`uc^pFnfJ)>1RgQ%2A)^p3E&&Hph6Kp^*tgpEJjBU8c7tdkJvcmqH zfwCDyP7`21#C%&0vdx%(q+G}+SAu%^e!Ssplx`s2)()#N$JQ6`I{BO;IZL^nr=}-@ z3(T|`0{Dm!%0~dx4c%E&$4=+-GU>2E68RH5TKSTgsF~SHyoys@LTv#@Pf{y+v~F2p zgy>Tqv=AjWCW_w&6{c>6kCbaEA$Fyh*?#z!a!e>HYA;Fy(A|@v$iLW{4GcpNUHdf3 z6V!5M%w7;g6rtt9Q)2n#ELwM!h_Z>vNx@M_d%v7=IYBcPG0f5^-gu-mHc$3OewaI4 zaZezzC7{0*%09o5a{!718V==_;q&J96YWZUkcKk3E$@W+<;qOvo5V8eU&UxOmB}}_ z)R;T3n}Slci3fcs?VW~*naQhx7I7St>~L2vm^tJJlqo|&%cmnG{Y2s-Qe~>OZa2dj zinlJkgz~P9wNR!vq_$QeA8?d(_gcn28^>|J#9(KfT_bB&iP_D#>d-Up!ewoK_*$1U zBl3ivPFM0A%#o$;U0Jx&Q7e%Taju)_K{{O~KGcArb<5vqZ0)eRy|*$08gkzLb)?#l z@yXG&#a?X9-Li+c=026-EbVBuNwwidpi*X0Z>2USUA(&zTrp9?XX}?5o(C&G51n>m z_FteAG|H#WHP`T|L)s4wpBzhRYCi~r1*A$%OK^Jc;V!h!HzHU+nVt?IlW*cS6Vo`O znBG8NDsmzGs?$X5PR$SpNddM+T08M1$CP`;WG7x%C>>y&gDY3c>FKv)hd|=QcUN$# zOjAyx&fwx^>yYkMujjcPC_oLv;YiNUQ-fWr??P)#cLkhOJh59#gUGEoaF&0?wUblu zV!Y7ZaHS;g_-O2QMq1+vD5b=k+>hp;GtYw&5cOOg%^LIPn`Y|&O9M=C3dv|b;F(j) z-H8kdhodABLIz3sA@2moPM(Lu*C!r&j>U0@fPovr?Xx}cE zPzXdkkYV zW>+)HHb%A7%f<#I8G)?Lg{+=$0g$sy*@gmUhTFq=9T*F;v zG9a^$_)0`;k(rx5F}kw;1PgWVKWC`V!bFgzx=O(HlK+gyhfwN)YK!1ZGde-Z-At}_ z%k-Q$IN&4uhCN%0opEc|E=al*D{Lbxs|cUhdqtGu@cZ{hlEq`!hCq>>r)g+I+Gq#v z0^csn;d@BzY3N&-ccpxJ2RedTR&b}VUUah0@TZHaoV+o+H>scXg4Sw&oFo>VL1~hO zvqrt>#NveWddb`&f2D~p(#*)=Y=!Ml#x!T$J5FX6cnKk#LX${^)r0w|jth(#Hi+;x zeHd%i8tig)Xa(D3k6xxkgaMeE_t{jHWWZ=$2jzhWQdY{m|IwsKY)anKRT6!3(5x|M zN{Gh^l}HN2(_c=>nhS|?zIo{F>X2G@9zoe++24NC*`qfJ7u@I@6`w}bZS^bD718As zH3+p;NNObO{qC}vE&;yCEzQV`6{gYm;MB}BTnDukatN<;pn|A;qfPRdjal`Z<~8Ib z7XT-Js9#w|!YG3^&DpJA*7}2dg}1DK+P$55jUsmO(sq+bMM5JkOt#TGC5|4 z8-?D};7#*2bVOYD=KTC`Li_&(GWpgT^@{&M#`hn{5d6oy&&J-`z{AAx|0neeQJ%8> z2Q%GQ)M#`t3jRdLIQ?a%fSwSF%eNDZAR5{m!W4=+i4xm|zq*Qz|Bl!mi5xk;GI1rB zW5}R4g$uVZ+w8>C%%xFOimk>ab=EWoKK=@bcdyw=UIr595N0$9X5tMJ-9xKXaDcT_ zSxOg?L>4NdjrJQ6Ml&Il+lRt*jTMUImu{E3V1fJqK>}MY|${4~6vZM|WnxYmd3Atzi#& zCtIeMW8=%=-@?*$d8Z&ZaibXu>+0lfG3&F6e$joghpG5BP?W{W#L@Z$$%|9(F(}!Rod2prFCBcirj0qj;b$U29#`2!pYqz?WpXQGqGO|b% z*3(q4o(Y<~DFG*`wN4zb#7MKHVQuF&K?7dkQoLUf4^{-})pOsESpdfqqQU&&MH^Vo z+lbZ}O)1Pmpk~iySNG>oO?5C5G{VfNB10&2Fbdy2Y!P;pOjOTIEphd@=B|?uZJnQoJ~>I+l$?xK~;Q~ znqzKS9(q8H1O`2X3ItjxvD%Rig|d<4kP&)Gm{CB914{*2JCki-I*aDCV;?c;C3}0h zj!L6p!92h)FuYEco9PcP8Rb|1n#QEXv~UXvg>s@~(=a}wyLxEn{$q6Qx^NtAySf7E zEL-G+BS`ug15rwP^k~rng=9tYagycmA%0<~s?KGj{W+sY9D{IL5rNkjqqLm>qdudckaj_emb`Lx*7* z7HqiL7O?`;49?zhlN1vEHRS5Ki{T!vCn+o9w`g5wjT{L>qGH@i5~u0f49Hl_upR|&(8<@Qu%&;x!utdOMK&m7jXD}2opq)BlKy0JefFs%1%c=^hOK_D{h;i ze|B6ujA$m3`}_?~h)wP(+!KZZF#Y_Px&CH-Z8INOBjUxi;kD4=!Q6F*V6SXhf!HGB z7RicAD}bQ)j}jDGpbYNyindE&?~@&yvu3%nWMhDO9od?VXJ1fQl3XB`(S+SD85r$6 zwh~%e1x2^{5j7p;T;$-S4fTnE4=oX)zdQ91hG?xC09W$m$A`F&M5WNl_gr4o(yFhinlWVP3bUu##1_WDyN5HHIpK$xk!f3YzKqf(YA*5Y337N8F6gZe zWv1=LS_ULY<8D0pmYb0-1PatUJsTEAkK) z*}zVvLum%b8VwC9<~WX*TlE+LWbFi?54X>;7?^YN5THYO&)jB@n z6zW5r9ewb=Jc6$7RoY(@(Wxw$GoQPqojNv_>7;Z@G)nR0C&7ff=+3D6g9v8Hk5 zq)TQ9$s)XXK z2{@^HgosrD`0ey%YUvO8()NHov-gvCt(TE}V}tlSo!X)kN)$i7hJ@Cq&Le_s=j&@8 zi2Dh7xOsfso{zeUhLYTx@J)ds8J5w1Ax6zMIqwmH2)YGhS)F_b8{B-NhMEqmuX5b57@ z$TRv1JL)Qcdu$b}=DVzGF0-X*<OXVRXQIZ!O27N%v@k+CJqX<` z)(+3xP^vb3KM{6)dHMRe%|Uw{`lb9lTC2Il23K zJ3HC?f-;gsfs%#iP^!$noK()HGhNJdOzTtwYD(|A>0T;0nf|aN_78X#a^=cgOpU{_ zMN2w`XUw7P3K7G~WyXB|oMc4-iE7%LaIV1o_=|N#X8jnSg*V^Gl2BZ+l9CM&AtXhw z?l<@zPlk&w85KvHZoWNra6(l(&I0S5$=bvkKoLaO+v2_K3r$W!C*|tVK~Ez7ad^o% zvS)&xIdkAu1@~uDA9s+u}ju#)%8tZs`03aq^gjbtfymw zpO|=07>FADcdDNc8bC*vJ}nc5Q{N2{h=0@w?RXH&@?p~236je4Xy?T8)1&RzHT<47 za-(7g@=A{Ue2^2Itc(?w1RHY5d}U%eO(c~alYmy|v4~1B06wrkF__t7Z!n$%Ibpc5 zW{0a>AF@oLOhhsT1g%sOl}y_cD}<%NuTT4Wbd9v%8U>OTSib?yVz4HrgVfI0?&N6~a4y$_YPdkk>fjo3ovZ=poHsd&^&>3ymC5WK!!DY}k)WL7TY5 z7S6eT`IT)M`~#V`+gSu`IgHW4yKO1vm{nO9_LeO~ZFz)=;h9mi z%CzP#avbBuSGq^Vcc=*{qGe}}QuU?w96B=`1&iv8IyIpxus^pY#zN`twvtP@CzZ4? zFlC2Paf?D_NTQ@@SwMvED*$APPSs?9jLC-bIu}Bg3JZL_^nU?JRFBUg1|2eIMyt|~ zOqwG;0wgta^65}V`wN37R9F0JNel>3zI*VW^Cg8J{48ON{dCRV#y}XNW-`}_l&Zjd z0aJ#ie#C}cF!WA`K>dgu!oAC~3XHMRGz=6ePN^)gu>mz5eQp_4q|UJMZpQ-mi0>3| z%Mp24Y2Jq65G=sN%e?$$0^Co$ZFMl5pb3Qk0B{jh@p7Efi7s7ygnOLt!O$vfmkxHi zE<_9rC**6O8-9zhsany~6kp7QdYJ5%_gh&;BL z_oPQAkQA+@Fogcb2J!ED@b0qm`EmqinFH_cRQMuH9oSN^(A8CK5tUHe%Z1G$nhRWaR;pp zV_P8hm|gM8zqE)UZWFACCI<=pw11yNg&+{c(VhmP>9MbCmJk`W!nwXJVg^6)pDC)j zSbwQbjy8AZ`#u3&py0P8zfvrK1Pj-!pcz4lFzqFXaVaswh$&1o{T9=O_KK@O#um3ef-dCfkfUphR%VkciA{EXMPa8-kzPMW9>~-jx zdqJhz+0Yu9yR*HaCG2X+yaIawsV#`BUZptP9S-_&tdq8KuVZIa)fY9W4gokfk=dA~ z2gLbwnrXt(H}%W{4e0_9oDg5kBb93MfhZ#y6lNJ&+Xs?$#n87}YP->7n20Mdp>fJ| zl=w10s5sd+=`6XQ*b8Qi0goskgA}K0Pp|`w45w?(kZVA9?+|^3{sLfvu+QgV$|q{| zY>iKGa(A)=ECIr)wZOkhU(yNY1;z@YSr(20H;qDq7QMc zDo7(8D9d}hu?B@Ht~S0`)Wn0&`xl!aPM&9IlCsYvA2*=lx5d7WAP=c%jTgAx3uvwv zjGGEOoK$A0yQ3QAdq;ud=v@E9nB9I*C zeBFyHrGI4vYXu1*u_C%?TYZt8+f-Lg9NlN$*qKwi;FA^XGOI1q)DEdY1eM1tKT5Qi z{eIdG{v@_Ek;6J|(S-S0nR>nMGb@t%l@oaD1s#MTqgx`XpuA8e;2xn-R)1o-SUPy> z3>FuK7A!zoH0QR7McJ6fPU1aV`*iV@GHsTB3rQER~?)}jz z(L=#=j5mC(##R-rJpRejs?_mJvT4(?1+PgOF*O~Xh5Slk5q#@CsDjsH`0^7<(1Ww3 z>Z-dlL>fcs{9hKDSQIVn&U_5rnKg3)QJfk%dk0}E;r8;q1*hdr;(S4$5l9!G!KCoz z{ee2XzeuFRc_p_E@5~@yMV&vXd#Z>XvF@lQzevnxtta%48TBwS`3ZJR96sp<2s?!Y zCm`?SDcX$cBxPo{EH3A5QJF4Mn=f%X`*(o869S3nzEOR6Gng?e8~EyADkNc#tM6jr;yKH{FOg?w8P@5g z^USO)0fMXPA3>c+KrcH9F1~ePG~KZCq*3$GCnBi)g{d!%)DpnsuMN`oVYkr zY0o2Ote9eDteL9ji(R)GXgieYS0!9erm?0!EWoNyPttrii1QPe#flD`R^|HkhVHl{ z&ELc|*91cmg)S8|Xxg5s!yQI;l+lD} zCHY?GrZJ7)eZW|KDvi0mOVIdh86ISCAzi?tym#mS1pEmk^N5snEGnNpv73pI1Fa_R zdJk%icv#Qdu&7b%s>t|Tvcdx}lR%KLPedrzVc=|7 zSO!9hZ~~7}IKAAZ1YybDE(stJgR640(I4gkho*d|QkBY0VsCFcGu{enW{e}>Y>}V1 zABOz_)TN&vCMntwApLL&(aRD8@ZBNN;u)A9`#n^gbh}NT5nA}HIu~?*qR4#Q4AkFk zGRKl(XP6PLZYW|x45-^S6`PGzLp9Url@0j>&4dF7kW}Gbya7MzIK4C^5e6VFdmXNv z$!ZJ2hrX4*J;a#jUR{cZhG4HLln!sKvUxh>H#CKw4@n#?kvX-O6wBgw;_irQqdbtK zbN0=pM-w(ZqAskuq?x_UaMne-S3nCs*uxE3CMh2TvNZxh0y0N3_@B`>8{$^#aR&2` zPBLcTgaW@li6hnEv76~n=VR)=&7Vj;BqNjb+(dw6gQJI-{c`0ss( zpmfSp8_L6Ytz)u|TFZ3ZWSC@=RzjKiLVzKyIAEwJhfGn@!5*jrV633rMEpvs21_Si z$7*YpafF%MgA$+nm@XfbAKKAZZlR-b*fAu|3QMK&U9B*Z;DJCTvNE)UbuwFL(0g6F zZt#-xI@g|pYu(rMhy>HZoA`U||Em=*9IPFKS0o9ur5fL_u^ZKH5x9tqn+%h7EUIcV zOO3m4!y|~Cf?_1V+y96?hndW9Iszd^Y1n_Dd=`Fj;r>dtJ=zsYQ#2k7jbwSU%iK{j zlLv+cS$mcG7F2+MfSuj-6w9~?P-cY0za|Cdy&HcV&(nKEGTwe@Pq73Bk9JDoM}?hY zxu{!9lnSZymbJMc*CQUOFK|n(aSoDLOonnJBC;&<*q;*y3I{z(js}B1hYU3Dmo^-) zWwp^MfnN?Ym_ZSg8!{yaH&~Jd@K{Bwk=HZAS##7rr>R)=mc>(|^eAXrwuaym)^!v+ zIX8<;LaaC41?o>sEq~>ne6IQJ0j2QOg(^x~$LCgrmPc23$Cb^L*;nf!%IsnBK$spl z;M|W?cD#=F;Ehe2W?CmX0k}X4CQPSzwLp;DBOpWd#(1Tn!a}4^0#(>8Qv6LhkVjKW z*El!^`Q`8XNP98T+Y-A0iJDmF6~VG~V&#FqPh1(A^W~>2oCWfRGAGSf$LmK*SdF)J z%Nw>V#I;5BCxN%gnFO=ED?ACKricy~)07i^$N(E?$V(#gE6T!8%`W}KhvACuJcgGN z;BAZXe#>zZkB9y@9=HA5=I~{d1m)ZgHq8re4+4(0@Z^N4Fm*EDa$ofP-3t#-cLE2p zyke8mMs9=?1C*ZMC*WO}zIdDBhq3Ocd{-Ev%JLVt;nqt{1zzvf;ff#XFC253Z!d>l-UDBsU4Ihsp7X8; zV{Q}xczo6RJ2@pkm;I249Q{JSzlQjR?0jCf-I8L0=}X8A_wi1Lu}Qy5a{UU<<8u0; z{~StZwmuhy#DHtPB0GH|m0JT=HQk!Ar`Xf0eP{9$azp%Sh~IINN9|W#0om}|1ejG% zhW`cvfID2Auen_vt^LF_z5EQL4`cW8UhCT<-&XrZ%?N$dov8EOFzp18;gx^z*~T#trXj( zA1~|tf|wf`2n=7d9DkNUvPs5Wg0zpZwb2%cjkF87OL&QPN0oub8t9`p`hSKv@YF2P z{0}yHBoIV0&Fx?9nwoRgIUNB@nl#&UQF2nw5z?2hu8_Y+ zJ2W!4x<))*4!-`js;b(GDw;m{_K`=%)Z}BusC0Gb2@<@$@V##~y;efU->f2G=aW^lyKaBwQNV11_?n$u&yfG+NgpLu1M7Q8*x|HV0xkOTMtqV-IC zvZqxRWf@dHD=C*B{OZiOM@4CCrXzNgpvjwBFKdukB;BnH#{E-W;dqC ziHoIBUY;UZN{d_**3Aek@O^)_L^S=at$oOOF{3#D2DXq z=TiilE)iy6UV!D8Vv<5@8$jMQVF&qD(F{)YJKbP^1yqW{6;2Z8fM5A!kVdQAZYqEd zz==;WBly;shYC#%Ce8xVP4fa&s=J{{TNrDq@sF+xYmS?#8=eeWM#7zMsBUj82e+L!Sg1;|h59-^bPt+;b zQ!iH&%*e^(;sxfEHJ}5YpP zc#2BVrSY4<<<~WDK%FiL)o|bmw zj7$t1oz4F%hW?ke!k9#@e=N#|{Q0B`e#hs^a#>SL8V+U+>2FOId?7(AXc=oLx6Vk= zHlz5wNwI54QdH-`m|Nh;GbI&CK^px%sSF;CkdOumQvr!k1(J>o8ZUMA_>F)~W>X8& zFzKWM{ic&pc{PF`7b7_4U^vl2nw3r#ALTx^V2q~{g6XPtBYF`A+Yr`co$Hpj7I!me zEE1o~Xe5af5*30L;-Z5G#JAsr!E74FzvrPK`9&JSx-r>HBht8&R|pq%5G1FyxSi^= z?Y*uk<|%~eO1@;F0#O`HU_X%`bk98QEK8ZpqwRDb3Kf{0#cuU$AbiWB?sq_B#IWvU z5L0F4W4UU;)CC2jFO#06AtOSW8%s2@=@Hk~PHn)GJraE8wa2JMc@ z8g}v2WkmCVdPmT<(SVcvOWBhHYE6$m>g$xqb93nf;8bsTD}!^i4F4FpB+=#4A3R;y zb^8cFDW^2ejrlApB!7u~5~+?o$EWpc!f5GMiB2qO%E(};SGitfVE^Fu^}8{|y)^#~ z9lS?sO-Doa+<|KCXG)K|MG_3bPRE|liI%9tuP{4d|G|9!P{TjZ!-VUqr;?a;_Y#%y z%EHJrXAanWfhH8=H&}L)(^?SB#LnnTI_^zEd(ITsliTBiwnEpIi?*SQ20LeOFX}Si zEGysae*cu2|M9-;d&fIX)ZXc{(kUGlz}MIM;#+UDkf&lno$Slw3^{S0Nas5 z?}n0I#KQLVTT24)Zc8S0!aKD3dSF^ZX8rP5NA|YZ{hMCTD-TRo*4ez^{OkN0x5azT z%~ioUNEVzXrFPY-O>uR_G-XD0abexAt<28{^N-Gs&b$E)1)>qv+03b-H|WQq`<`BR z$8Houv_1nTpI)@=tf-N1H&g;ToSgU{{QA}kd^+IYwBpx35_g5{HGS_=;)NA zzs3Gr;(aI-z?i{0UU<>n!VEv7BA5(Z7sWOOFI+L$IMx{?+=}rZ3pR$YQbu>&N&*SJ4oRBE zgv7u_SRB#rQ2?5A;sX~N3K>(XShn8>0Jiha(SLHa9Kk0u*!9;`CjM#pCF`4+cz1VJ zJR{7UM)8O_h8eu1du2cZUME05hN4fxn3=JA+l_+e4C#~)DFvx*#AxLn40CZ_dK0KF zCLC$;NAI2<Q~$*u}UI_VJ`{& z6F!J?q!g^B}aCT2g-U>|t-T`9R=7s(tO0R+P87W4l4D-D|Y zHUkEiYy!U3Kov!b1}~hEefz5l!Nr!nUBwOU(N#HCe(*=lT#{;wMp=$8mUQKc@*{bT&h3 zzfFfXA6!QPtBnoiXq^9>ZbbR96Q}y8o9sdVe+<$7Id8dGJ3F~q{I`<(f2oOA>RLaE z3)%Oj4*$1FqLx;w^;Bw5sp#r)fw~%U4>WqFV7~CAAyq`6_!vaw*9(rKn_i;<|0?ei zxM2kM%LC3mHXlC$8TF=ieoge~4nC!Oq&MHjq>X?NUIX(V37g#{PoC5q)@4b@0bzYou4#vEOKFrg8f24E(ou-`;QcBTnC+ zS!t(;D5BIRv@2*y6EH-{dRpoYQ2KqUlcdLQPY2jje7$nbbYIk~p2lO7Z-q1G*8EE5Gm8&dT%t?Mh@x?iaj#9Y0ut6Zvo~qM@dS?mH z52uS6VW>srX^1vsTx?EtfhA4^V-~6EL_R1n z*w$z~|EzIJ*DHcWJ8;N_JW35#o4bgDKWF3hJN&6Es)Q>{n-<4xPbRIk ztC{x*>!3fgt|z6g$S-1?98&zSlU;MhR2F=kfXWTD6@d#HXHLThNq81`AAk_;4^qNn zUib$C0!B6eyCs9ub_Y+>iP9YG@c>~q4FI!~^?_ZWcz1S)|M=01@ZlvHp`Wy{;+zw= z-BEmq%*m8~CuBq$;Z%PvEzg)vyj|evx9tZT2Jk@iO)Fu z3`nr{~KrE&wvOkpArA3qkya=FPMIm_LA z)kqU`E6l1K5y|_|&PPEQ-2Ni<8kvE%4vTUUBX)CeH|FuXP#_hG_*X-k|k~BMk}>jG(3&QzJNw2^Ke=dyt9|g<)KTN2 zCm}qt7$|QguKd-R$POe1c9GK>I0L}k&QWKHD;N_`8*1A@iIV4b`uITrg5bQjyB*byi`cl;O5dpnM=Jc`xJ(~4;T5Z*{G?F`T@VLvqZ;}fK zeahe-gp@yn06NB2vgKdumxyl+a&0-d#C-GGTpPT|plKjjEFt1Ev$g?D>IIiI?)HqZ zz&itkgafG^$T4ccNV*FVo`l%W5$GOWj?6Zlml8^8(IKsx{j04_Fm%IYcsLLlnCwTI6CvS+%2zkgJtgtVD5ZHII#A%rdaQbluWjTn>GtLnT(tP+ z61zso$tmsg;1yiOPC%RS@Qkix19I7U!|@?={iQNAvcqitx09WYlaK5rC1t=`E4xQ$ zFxZefs=|ivrMxnkLf~j|$CrunT5nfd(f~;8Rr3Y!7}q__{KDRu*C-pQF=OD`prVYu|QtWPz8z z2kk&6il}Ve{EDuDtagjM6TRwTozy>9-XQ};987!dXkmOp%eAQn4^3ko(_;N#6^lS3 z518FL3LK)-=O@{dr9eHIkEa!aI$#1N_08osq*o-tNvwiGq?fmonB1?DAp-Sh8d^?S zT_j1dk)PBayoFcCgZ)fr&t9F+Tj7wp*?iO0Iky*x9X2O6 zvrdn{(rAd3N1{I>V~nh1)0*zymp2L2Nfu^4!urzK%&H936}@}kA2H^?DR(|ljzhzo zkXemwYI&BGdCidb^KAFjHpHsSjy2#Z%TUgay4GLg`q5*b=b;0mA+)&g*O*cX_a!!4 zX@&%Ycs-irPpfK&8OAEod}dyWQahxg9bp-iJ%dNZkH_zCzRhJ|-aelfX(Z8q?0>dG z2$yPM7Go*S0R5&~=o&@#-}@2?1!{!;E;P^#+B?N6jDn2CiCVnXQr;RJ-#= zq--C>GbIsmWUc&MW+MV};J`lyaRhUTdY~ByLN)tw3EUsZ40=E&Ei)Kp zNl=-!VZ_Fe$;5mKwi$rf9~h(WO_qyN6Yt(w4CS)nydjS@B-mCI)Y ze7J^M>Vooi*M82}fFA67=}CWNU*RQqA3}KKm1A$hAQ`*lKt5x3A-dkM!Pp+LN|ACK z{7tpix-ND5Z*xCs&inZjz*ij4hFr)d>$3ZWSN?Zl`1jr?gAaGu_hd_6 zi$cZ4h3e4@ns+u8SD4SnCi6#aZ zK55Awx~N)5QGsbESSkjEla&JPRwRraBJ8MvfSOd*iWQZ%Jl|F^19|$tr73{_bdal0 zvQ}ETP)`wJq$1{+YDnmR?r(9}FJr8Fo;{r%jcB}$-K3cZQhHS^N#;hs`Z%IO{YrO_ywNUNTZXv*lJZt^!*#gxHJ zd3Qo6W+l^9GLe*CRa`m=iK| zqBqhXyG$AWS7aA_Ot__yFJj2hc-%{}CB=N{$Sb8crGlV|^ptGL+sTcjwLF{-qqFKU zdMo&}lr!m?XHYGAYPH~MA8!i)ykbNOqKU$L{sQ~312SlX91`QA1sP!gINt} zAWrOH1^9;kmm=d_X!^aNj=3*6Md!(Py5(}d`=DVi(V&}Gfy28Fyy0jv5IA#g|F?Z^ zaC>y5=WXWThO`d=7&8>zSQL#Fbhp)hm~IiFEYSKD z2Q-xqT@KdjH7*Vm#WZcoQzZ1mUZa+JE>^w0U%=50VpCm&R17j$0l>0dUZc;-zt{w% z<7?z%d3eQDb)H7M8mJ4nl1PdT23TRWMNkfs)Woua7PkEBrps6i75{wJ%4Rr6=Q~lub#d*i zGcklD4f`!-wc0&n+uUDrP}HAdSDkXL^O39y4!*9K)(N3a9UTuBKeRM2T(G7R1!r!_ zHd~=hhI6)V+S%w@6>K{+D5j*haUSP5!f9SbjbvrtNNVJadNi2tis^6*K9wQxZQx^!D}*+Ng3Aq!N2)&|I>uv$1nZI`|UrpMJ+$P(;_|c&j#f! zlq96hhK>c5sERNiWemjCAn>Mf$DM>x>RQ4<^{?jdS%*YYi`F~;U_8pQllNYyCx{kF z@Dc-CN0?;9gknjoL@5MvSY}jE<|wAI3TRAhvSw^Pd5OZq*!tuGP3sub0EG>QY!P7sz9I6TZ6)VGjnNqXER3}nk`ruNv2I__NOzY zSu@A8H#3x@IEtZhfkA?st8jsS-3K?GwMv!RbhWh#yKZ+Taak8@If;VsNAgp4+G?C) zWo2PtwtaiVAH$Baq~0L?yY|r5&5)x5ryx5`w}0&!GooMb6tW2EbtXmhaG`q8k$8@3)NI|W-g840AGtot8GY%<%bCMRAC~~b#gA>O&(BnRWB#itlM>2TA zmnMB9Rc-;Y!6l?Y4v#B;dr?A75D+T^M^Pm6JTit4@eWw3_B4|zRN=Mi?2=7`CL6!9#zIRyu4*1tm`yD@SM_oZ46rT^4o_V=SGE6bO9-F4BL^$S8*q|oxWueZnz9j@?7bntT98Ca(;fPaMs7F3ts z)j!Z63jF`#Tf9vQ^nJ&86SK+Vf&eV4pdW_VY%f)s?p;^~#jKm_3;S_CMPM#oVA;AW7-M-e6{ zpb)7jn9(Ou!lfeg{z58iE`!3*tY7? zmEy~mj12=%6TDQuKGrC;-R~rX&X^;2%PWsY`aE-_T#YA3!xiY1CcSngGPFm^6TP;u zo9E)<>-%d{EiiDj`Zp?EUuyOCy$p|&v_l4o1sH$PJcbJ;ft;O1*b^9h4%EQUe&-uJ zhzSzyb9n?mKWK--|IfE_7`+aorna8Nu9XnQG!RmCv7(TPsXHq=w$1xH>IgEJ(fjob z_hZXA_9uPDgtub;`-`f&uaQ_eEjL)oP)xzJ4Uv?6EY31-(v^LDCiN(a!S{`BFe8>(_>Yf1a5RaO-M^6B?zFWH6`M0tqG$I zl4Y6@*RRXe?U0j$puwYnks*Q{N&MU++VcR#Z6%4K5pAF*2kMvjYZk3aph|(ny&&N> zA06QR`z{?YZ}IqO7QYfMMh9v9r~-V?6$QIw9=u!FMDgNvh}J1m>@6d*olXdZS`-7>DEEm0DL-R)Cs?>Q!43rW7fQn#E8Ny6#XB^jUxlpJZFSaj zaiNQ@OWi`axNLKDBv{*MIWlylAitZurf|t-$&aEAiBJ5UU=i6>;HU9!8)I0aS`8BJ zt5iq!@zphOPp3YwW^lQ}Q;g%ybstuRh!yBIt4F3UIS@P0C6=dWQgWDZh|h; zvrU@bh)*|JMZZhr*V)GIS%_+NkHct}M~Zafo?T}S(o4H6(s|<6qJma%M>caWRR%>G zkFIVKR3_c?tym;F8mC}ezW#~YD~`GnwzZg=;QvVg=wSaiQt~f8r~gy{?F}3a{(CGi zTr#NikMG|U1U|}}wu}7mJ}+w3fs|as5}FCR_2eogpb8a0AR%Cg;jB9jjg?n2ZmSX< zJpsc)e!;!?19QcXX6QGpy}?tGHQ6~+860M=*TI2z&WQ2SVplw4dlS;)GQ{k%#3F*6 z1>%SaiJR{S%!r>*G#2F{-A|{+nPZkmdmJEgdy8p`;(xYyuJLer!XBWLpL0qN*bSsp z2*a2tD|oNHTDE5Thog0Ia?i!3GQ)&|NdZmWJUT1Rpj% zUJkOE;C0^d5*g^_)*21SzSGGfoCLk58J)_38WixY)cunIT!< zAhc=xaQJ+Bo0>VguT(hxQ1;!K&~_O$E3M4-6UX-zYg87TK10uHsLi96fF@*2c8S8@y{cx7%-a)~|Glq$YE6gks#XKz+O8S~QV#H`SU}pSuW& zUw?`dDT*02ImQ-7S0PJ}xJurpZoabGA3+Wy#z-!+fpMUuMc6e+R1^h1f++y*PG4 zx!{a^O&rMesoxt?^maYw>VPSG$nUxRzbKiNX^h~$Xd!vIR@bN&3(GVZWhvsmbDMNM zVEd7#ANl-M1iNF)OYb7P2vb0ECY)`ej^KF7ODZ<47Xoa2XG~X}7_hBWx8%)TE~wUy zsn4M$5h*tpUSa;VFgNFSa5DWgrAZFef+Rji8ND=S*RG5_~F97KS(?W3hAC% zv=-}_@np#bA*v}^Dw%9r4)|PDT2Yp8;Vc;|Th$IvB-5F*AhGR(Id-ua(KjdfY&qv} zIE{i1L6ug6m@;@l;MQMRv^eX5oJf1#cI?ub(^oi{pRS3za5cL=-0|*ha!tWvwz>U% zZi=l=ufwm;D@YeVR!z}#-_dk)^vJqLmyY^DF%=RORpAYFQm#uAWGnAvBjoVQ@M}Of zH{Fv$)((RP&EDYj?fjEv?Qdb5N72uL)xG4dk%<*us9OWKiaU>VV7uQ=qdRLD{Fm>tr!Z&4>`-A!=OBB{ zY8|wW0-KO*>I$&}*S>(6# z?aZy;vbxlx*F3;i-YMPFrchZrUtiz%LCyQMWE_WU4w&4~qIU4a21khX*d8}|$o@C8fv z$WrVke<~4bJ(fMo>(VKh^8v2@z|>eW3FyZa;WQ%OBrxTrq~x0PIeNeB46w_6{B{Qw zhFEAhjw(+fd(AjckkNr+`pMu4b;UUf>eBP8uKfS;TM^3@!|9o2}-zqWTG-5rFY^&epGsJ{-Hv=egt=< zvwC3Y?{J?&rpI=yaTu~T>77k3O6SVI2qY0z*N&oF;TfLnAzlW7m>Oo>Xz})^9FbCq zIE(wptUi{zA(6OWN9+1;RJ`azgnN_S*DKrRG2Far)w=r5KzU^3V<)Z+^A--O)=Gp= z0zXFvi!X%HZgGmmcmTUZeBBU0s1Xb%jns-cUe2N@vosmemS)qkRN#R)kq7h_ATY)@Xdgi6+(4vMb+)Bdx>>=HlkNR} zwfG6$VBT#PwJ^d7r$8nsuI*OYLQRufr9u|aKX;phSH?mjx~ySeERQsnw8T! z1>RN^dMH^vz#Tq5OfC9(l`WcRWNIcr)K*ilVWz5iT$1RwAgGtmYMTFg!SY?oe9!%( z0og>}KV=h{XDMcBQP4yuM;!GsGW8TX&|dvZCi7b2HV;fnnX5g$swp>}sfDyWk5r)J zdF1RFPkPx7GN;R|&J@SoH;dHSEG~q6r|vp)SOX462v(eE$NBFdmUSlo*sSas(&eQn zzOnb>qMH$bRoK0{LLWl2FzB}f=Gy4-$5KGJ&mvo1MZKbZ#S^7b` zBv6IaEuv$V59sgIcVjdoa78?Zbar?r@&#zZLTCJp^Yvm{SP_}?Pad3*JI28*M3)#5 z`)m#QeonTAE=~4ZMgJ*FCb-kzNKt|*t$)B>j;AeMH|@0A0j%Tat*@ELJAhAFpbjfR zX?x)c)RMQWlWkQ%Qp7vjnYCMRt2hS+hJPE`%tO1 zpLHCCkVa^}sKPwlYcSmxIMTtM47SQTrg=Oug-wapTvDf^#%T4lYAJQGFd-`=r^c>9 z+lMh!u$2q7`h`yT{)qmj9VtBIYX*?%ZUHUGT^=5QOT zpo>EiyU5J4fhoG5Pq9%W-f75x3DNA_xUN_%pm^6w`|Tqpd9M{?@QbuRm7MqGc?(Cb zW8oLEgl^|={X~EA)D3p>6mgf(2xM58wASTHHeQXIOtYXG)$5}JWwa30nA@1ir@wM$ z?&r-F2o7h#%`k+PfI7y+Xz3&?8PQyqt(-NgR4H4U=o!ugxVLIdeHda~Z=6B+UQDvS z7(G}+Qu^J4qZ`v2O>Qi`U0a($UP zs#OwO7%Tfobbi?d2gpMX%--LE#&y@<=(uuu&fwmB*`s`Jp?oWqe9=IC}Ip=uqnH>#&D0c>7F{&LeEXxXDgVO=gpQKB{t_S^}9HwWh;ViTRW zhf6aK#qVI{mmoJMS;7`%)K7|$z^aAVLp5A&+ie z3tmFN{M`>f;bw4W5>eVOeQW!fx!-d1n~nR`+~rzz3qL;-D#Scc{!}6|tk8}e_GY1k zVT&N-sOdd$Xi)#l@prSlsI`95*t~cL{mOd1L7X>gthf8!AWEV*39h*MnYL7gTGBI> z9NCedQkoR+7~0r}%D8;N#2khk-&_o>ifBVkSA`UH#hmj)M>+aEjx-=G#|Ye%BWYE! zd_gdGY1W1YW)2}k@iA+t6+r~eB+}yqU$QHJi_Z6_O}{hl$hV_y_UB71->_)C7v|u% z@21>0*rt!2SKrxG$r88Jhq?J|{Eo%VAw6`=*w*$=uq`8HGfdhQ%X5RuXP8zf2Qg@e zbbTgOf=Gs20PMME@87EVCOKbjeQoVNpa~`sbFW==5>*vKG+S zyNr1BfRAsa@U{4Wae^&ncZm}JeqTeJ4bx8NB?-D7?9FAtZhJ)~j+BKvv^CAW=`_bB z^z+)!4R=i`Pw~qT>t@yVBTM!X@MFC{O@WEmd25fkAvm7w8Mex{u%|(UTJK$fGS9G* zCCP-CuVKW38t$lWeFTNTrDrbl^(a^@93@MMAD^-eSF?0}4Um#eG70s`ZQuHIL5yQTe8ksJ`xza$+~iTd{Vexw?SjxTyS`6DB8>^kiDb zisu_Gr1Km@evBCid+&MQfFPFJ(Dt2$)KyGUWABTPX)ABEsxgb>#9PD&rLbW@=cLGm zTe1A@;s!c}U!E&Dv6NHV+tjpPJSuXZpWC2p>veLy+DpH{m$-3-gFUr^63@L{RyRd7 zrjc`^cX02}=N3e&^X))ZLh9mjENLLmWm{85$5#F+&E7HriEJa$ND}=_#!=rW~;{z`Hr>P-shZrhbosC~K z(H6HOkxbo_UODFK>H4Ft&Q?Yg4b4ogtW=bLo@b4m-wBr(Hvk`uJ0qSzso;qP6|x0% zE}AJN(y2%PfeIzEF$5XMBVnz4y?CqUNMOHe?ZKM`c9}$leQNO8SqtK{S_L`rmh_!? zDxxdYDP%nKD7OGyoyux=<&tcOxX9PF)aW>iSO#BW9g31JX<_(WHwqHsQ&7h`#e$8C zW=$#{1I6CqXH}C@7lN^wF>+5FncbYO2i{I!h!OnCNr)m92kw*Sv%B#3%EeR3CI%D2 zFuHvyYJ0ac@JG$pFfn9>eBX^Zi(B1l!&o18*FIn=E?lnM+w6k#ciV*7C)ev%7q;9B z*Xs@LgkJ1+&+MAz(Vcd7u3okhb&}ppQ!n*KDhrU*m}r7ZFV*T{2N?rIqj7A+Saw~H z*iac*92|El@oBXO@>A$g(B8uBM1fmKAY;72zI{cuM=5s4zQv#da-AvpL?zQ$NMmOf zx*%==Y$5aEXjRagCpP!W6j+#;94=fe=#V|U{`c8#JWj}$0z9wJF}YYM1Q}B7ekOZDgFwREr;Cn&585v zrfZoxIm-^-zT*L%m1rxfVCc~iMKdJa29iOjFh|mUj3@6xbbo!>y=8EfeI@!!A@q(a zPw(L*`C^uAsNvhg&}qAeAj7CIhyc+o3R9+fi~MCk($mo_ruJS!53S4af56tu;tv?P zjiqXl{S-k14YU1@;JSo6&;P5+W!-T|m9vSaa8AeIpPVQ-N&rK_jnH&hD*v$(k~3fC z=zP&q9#B{7i53m1`9!XNf@Bji@0CJ2TgIGO(C0jji_H>;&FU2DLu4x3W~MqSaBh|? z;ev{d)E@U1m-qb5`;f6j2m3x$G_a=!LIW2G#K3B66b&v%$2L_8;hJ;j4a|?_ZwRb^ zQpW%P5%x||qD0-2ZrQeN+qP}nwry*dZQHhOSM9QG-u*vx-_!Sw(`Ss#=X_gh=8T9h zxE%s#4A#Tpp%>nfVe(7}2@q{%vSm**A%$Xz*1HQr<`UFL*K|Pgd3y!%YCyE9dW*|m zX<#tL?$C^hOJyY^AjPqqxwtCyAqN?!_H_(V7!@jjQbV0#p2?DMg!t=(khGZv#c`9E zUeT!v`TMD{`ykwANC#m23_z+m=_)!5;G}hx0Pisn9A^q;2>)V^Fco?!6sL#LbxSBB zP(a3WB5eO+1}&*A)Ck>yG)lNr@37fKDz1Y9nJ(}>JsT{o^gHm~0mwj;bVyOHeuM6$ zQ~DcDw`Z*;Yul(cN}?r064NI_Dj}%BmbmRIKmc~=Rg4blI4=W;ZG?^IYPy~h&8WQ? z6on@a=Wsa^+W)z&*2?dMOrG}r-mnXifG4S2(~-KOGUD4T?&R1t8vITwnLMl0p*=Jz z3`g2xDvDk?ciHA#+(z1HiCE>(Ml?=J<{1<0lq*aD)oaL~ajp7ZL6JpNvw}ty*UR;e za*kVbBj!go7Z>{C{QY~y)k zvx7e%S`=*#X_Oc@T1GN`Y}getaU-fdd3LZyGLMp0Y+Lj@{LMkkII)yW(yWVN3Z=(< z`32Ef(gz}g#Hg@Wc3E6j8&K7I2BU=G@%apvMv1b(GtlTzMm6vcr^Kl#SS4%MrWx}N z_QAr;BC-591&J^fp*#?gmJ#Yy-w6&3c(P{}+o+bOuwcyyC8FT8pl$jfk)5|bHi`}^le zCL23K>F}|Xy(?2s4?uw#!IEdn&fPZV&HyrK*+`^2P{)atp|+g|g0?nEtgCQZYHE9v zUz(w{mR=Dn#MDlg3#Bbx$@L;@pMOzo7%X1TPmIqeSWn_Cs*ITzv^X%QvZkK@mye14zE z4bkdS@P_W@FM4d7cKSiCXHw>(>`&~9HwCSS25Yp}Ryp<(OwdtU1b2SIvr6rgOabH| zbC_I+0ejdwX4$zU{h1;+!CF4?0<0pNjoqYcQ%9s~lbI}eu;n{h-SmO)P#hj)#8|7E zdV^hyaEFa{Cq>l9cAUxp2Vuo~i=8$)w9$~!MPdTk0&G2XAt@WNUa>rO=1thQVxNAQ zj_;0kahU#XwB}Crd}{NzP6P%(Ts&c+rla_uM8yN1ZZ_oP);JdE0)t9RGbSv~;PW`3 zHFZT;Ec0Tu)lrle=SS}6AElZ<>NO`(UDu{66Q{?`EtyzO&j-zTQsiT8J8$xs%yq8P zV_TTw`g^VPmI;p}L#uF|1=HV@3oJ_B^ufz>cF@UJP)15q!z#%yWa!#GtjH>x^Mo># zs>jZ#PUdNQ7hjKKnL4vtNql@Wqp9D(*wO;5_$*O_$=SI`3yZMzYyLa-)8Jdz_4w=UaFpof#h^B4}U-77(Kz~PsB9K;O=S;&HjIdKTE-;NB1iB6NEt!*ZFM;puR zluRLY0Q8sTB{}(0hJjr=BoO0R6JZi)aFggxc`zFyF(T0G1iax?r;J9Mi)LzCIH4cD z{d8Q$gXZv~U`#NZBBEocj``bSfH^#z=fLq~+CIB~DPE9^AY#48V4OVtRAOy+(@SDD zRmWj)zYqP5&nJ$VC|RdnCux|xs{arY(kNj3jY1n%qV*`mS{JBZhzbed4~PV4qu7u< z$lqz*B$5;2qe4l^q^a!Czp(QX!23|euaRSRM*!<{Url}?2hYe<4j6(PH0zVC`zQ3;tBhk0M z_bZ1l9#0+-@j$nq3x^fHj9O-j5~u@9$fwr}S;+Zfu@5d&SE2Ga1Das@g`+6OTm&vxq;cSK4FJDXd0W=y%e|`0%{c+f2B>#cfXTPQZbKt| zg$^L~yv^Oipjw*{dQPa}kdF=nRD{~u;3cELNaUFQg7L6eAdHb7qXb+UvB_D(e)SGU z5qkT}P_$KK;1aw{xq(;|-0;hAE)l9~<%;;{7@3OslJwdX*c2PZzFoOkZ0In-HN8s+ z`uplg>odJ9<;pEUM`wiZH7L*Q5S;{F1!=)x^-=yn-d@3}L`=Z)X(6T|V&_Z3^-}xB zGG6`M#E8+VXRQ?DC=^xA`OS!$DPEo_NmT?egxxzL5I1HB_ms#<#0JYK81pIBm?29N zicL^2$lk3xNEwCAa8b|_SaCd>(Y%(%z$gdrf1_H}ppbEsa8Stxf=a|8;RO>V zLw{vUy7m|{&S9|&J_BnA6h`xNhtaLndkb|%gj^k_#k5X(T1PY!Lc3jfMUl>9jnN#f zs6(mOP4Q-o(L#9d{0L0k)Bt>hBs0f@gkfVOr{Yt<|MYI?C>IVidfC^ZW;^t}@toZ+ z$N+`Bt2CK1@8tEtJ9qSvow_SO{Z01mti>6pL;?uskMS5erPRK&`(cAt zBUX1Wwr%WZs~2Ip4Nld0QClO$^3ZB=UH{XWXNr_XRZ`Nwc_lF$(gk8n`{r6TUTNT{ zMoHA;VNkHgm(MDPLYbs0rLwvyup|Uj^;X|dOIoVtM(bBXd!yr?jL;D7P3lwmfjnk# zxD`WHo(CYwPOmV9t%F1FzzlFR70v3z?B(aRO;>FiW&@O);|9P>r;Auz*~{K9KHs7J z^z|09Nt?o>%5``SprCaMS`|Kw_`;d+EbB>vGG&!z#cS_wA&}LFK*JT=FIX;1!0xh< z?F+=F-@EZ~d0qzZI?$)u8rpfLaxJ|ifX_cawGb7`nWo0;>nlT~_rlX*M=a5tg})C- zBE3zbBg_Y5V)iZwF-A^pvaoGD99~&usseW>H4voaAI$V%_PPXUp;%<7Zbb2_`o1n$ z*8G*JO;vU;J*Z#Ji54d)yRRjZ6PewXSqbk&8jMPkMXPDHEN(S#p8rE3 z630n>AN^BB8!s1-pH6R)#$O8a5yh7KSRV)WP$$T3RWyMIil}6ITe_N%)NZ8<%InYW zOG4=>Qtvu!U-Wm3`SGYRv{YvB0K1AN+DPC_b7(WIwNeMj)&!&GxhP_%+>7HhRFri2 zezID|ZCZ;n^}ZsLpJk^MT=cV06WlPs(hImpu-m#E6Sn|3J~ESkU!tHji=ujf--a_r zX&R^Do+WR1-mwWaggGm`#P2Bw0u2zw#F%Nb5Qu?2BJSF66b<^O0PzGTo=D&TwR%5M zF9DxZ0z-*wFTeY-$z;-_@2sD8y6B&cL%;SYp z;$YXn;+`T@t#36nSnE&M!p6egUK+n}7=uTGxHULP*I9k%-?$Fp=g+=}EV+a7j@OtU z;E5&ni)WD@zc0)rB9}*n@o%oSBr)|%?v0ffz?=?pTUUjCB-iQ|%^K<4Mb`_hp7pa? zARSzIIuk$Pn8}`cK^Vr85&Z{)hUtEzp~#(o#?<*ofNemkGu!uZPL+@8^ax56u$im6G ztUWC(M#;JN8+<>Z-0mP04s1#LkQO{XM~3gL9yxGjGwn;4)u&4P2lw%ONy56Pv_n1$ zWjnPO*e35>&%H5*UcdCXB3eeNz>%}#MR4K9omeJYNOi%S@CEO;6O>O>cgy>g!ByxV z3NgmGSn^gvK3%5XW-JGK{j+w9h06yvwPkrr{Zt@XxvWL|5jb8%g7j+!s!JThw5N`+ zL{Se|KG|cGGTGy{^%HI5ose0hyiuw{)?Dcoa_zgkNVAjos7l#?Him0AF@PO3^QO~K zP!nmpeK==aQp12_?O3hBoo%=yJLLvLjkpp?M~vNUXa{qq1C?r-PJM+ zt8+6t!H%C#)d8KyLZEUHSMCgVE;=w1x$9;)C)qhZJk}!l8Q*Aatf22s%}4h^yBN*! z10lj-7fv4T$cbd>`C$%0aA=OU+0xR~z}LM?+&jBleqMJz?L9q9xjlGWxo^y@psPsn?ATcyqmz zU(9oNY&IVV0>JD?!e{8IkrZ}gblo#;ip;d^3+Tq8elc52DRu#)Nw$2STj0sw*ME0s zUyk6fcC8^;-6slBUPuOt)Z|Fq3nG&eaQ3glfg|7geg{VHS}UMIZ@Q8tg+r|L?`@kj zOICmCFx666 z#3xQ!uV6_s`+!hm6uORHS9mF>fscGZ&yW4c^)G}*6XV-04gDEte6d~xq_{kjZ15Uv{ zc`QKhmvlQj9-;tDUZWN}x+Xk6&9=S0nRz|kZ92WP|FOwyz+E%FC#Wkz~T7> zW(9*kw{O8Bi5T~;0ed$u0rPZ-@j{>{w^xV=D_MQ&e7L)~sedSNa;!FX zY++V=q7yr3>Pb&kR2wXaN0slh&z)g?U*uL!1v|7UsUx4!?>Kvm`O9jTpEk?$Y3lP{ z>|*w9`!eO87BB5kgH-;y_ANM1hF;>n_qm#+fm`YEWp0}HUs*2yAqM=;Q0dbAvlXrV zvoQSk!~j=QJM;fJN8qZuWw*tF;Jc=d;2TjqT7ay-xGG@+H)f&day)}fM_f(dU561b0rf*g8? z0|SLa&W3|E$?`{2xP8W`!)q}rRI3s=C^a*>P|yQz09uoCNw6Yhzl*@UG9ZyvBp_EQ zR}etHbJyxwO-hp0$!E+_Xdo(R+egpTdw93DJJ8tQFmfO*t80rtXztbhD3gMHflEJT zY}ZLqbtUXWS}mx=ewuJJ;f7#yo@atx`ojy;8E|d)VF@*Ux2`Y8M&5VZB}ePc@%b(y z^LK;Yxx)j=T@VXD)`{H4#ab58AARoQ@>tT91)%ssVm(|*<=_ik2k5sC@z+B#(WHIrUk%Q z+rJ;kd7Y0;;Kl%6Q^Z8Z<#TkI`5ieWBq%%ak#hHj5S_;)(^$JYH_(HfNFKv;-Y1XA z|NDOD>fr0}%j~ih&!6l0dmfMx5{1E#tABZkT40zs2$OGlMW+qM#l#gt2iCd>`A z?l0{Jcf0@?k5CxlVo#FkO~%oi9CW2Y+CRi#DO$A2AIOQqeSV*mj zC<7{)I}~q^hZJv9!dqGP6>6`}r@GPSOoK-bYnSTS?w2)vw%h9Kqc1hiA4;^Q9j{rp$*CKCCCeBkpf5;e$xJ(@ zG0-Hxq|6*r+)+5#Mitdie>H1bF{f-00qWYsmZX zgGcZ)4SdN69v#N?ZNmS;c$xNCIBwM{K{@oA_vIkU>f_G@deycVe$S=U&lzhgV;S48 zieoU--BU*j242LC~Gm^pt!*2S9Nmn=5k_pfhW!e0RJpy@URrlI^bq z;Xd3y$(HN?mgX@sv^8>d{vYc`TGalxe`udHiCsMPQu@lkYQDt}A{9auKA8a9jIY^0r`+KUKW!UU1AkHYwa4;E`vO>kJSrqi6id^f{<91I?E7cDlt=FhVBr26siix zX+h3tZ$Lkkf|Y({Yv(RPawQ~v3oI0*5z(PNWlip8NAzev__us?5#rVPVp?WHzh5^G z2f@Fm&!jhy)QXh}r{=+e!5@XVc-3Gp?<;jQUZ12NCF;<Awoi`-8apX5R zVa{Axvto}O+^&{BT)9eXCCe8oMC{S>>=FJfzfZ=70;`yeX6`YoY-2aWIn$$RznFWZ z`1~>vAQGgCoR9&-*}L{1UXd7kiqK-cMh_$=a&)P{4LGoDoOnh63dWO&e;SmL&@!UC7`rXnAs{#29l27BEfc9vCqP7EG8kl)bkeCXCaq_zemL`)u`A z)QgjFMGRSY`7xBeR<{(T9A`bEDq$*&)oA0XG{6Wn+DQ?1B%FlVw8($XK}FwtY^Wop z3`G>@&RlqGu2VthEJIiW)SzAfd_aYmS}d(C9sE!yEqM4`%eeE)azs#6=2h@a3Z&^! zBApU4N;rw2Ay5?|5iT>$r0XSsHihsrgjPK#h(YR@ZCCSGC1(SxH9$P2Z6z91s1#fe zNGLGlWekT??wjzbBJO=yu;n|`lHdKnj(DlRMu}l=#8Mm(ew9`C5QjlJBs<_yzil9S zZjfmnGQ&P3ANQ+HusA4H4UHIPQ^QcdFl~v(o{B=yTvCbXp|#Ui(Tt@KN)U|MRj4?2 z0yrRXwHVCf)uk2kT9m}wDx9tPw~a$SU+eGVjuXMjXnW}5Bjt%H+s}Smq>RY|)loL!RYnPph8>Ond*fgx~hPtPh@pR~= z^^eEzg)?x`*7y!F%~^a2>v{3k41D$mcyVKrULj|g_V@S|X9uMY#L1*-jZUKVd@sLz zcAF4iYd){1-rMpnESE^x#~)Mp>YHUG!^QxDssXbE#O@HrGb=&>V3C#PMkhn%*`ukO z`5b@wgRIK5k64ym!3iBQy^mgQJVBSLspPb^e?~e8VCKxcO&w%-*N1TTo`MluH+seI z!bP$PV!>&m_XjAG4!SF#Zx#D^ubp>M#v6va!qAQEP(;R9U<9T3N4(=s@p?S@hv%}4 zXO&93#SfRGxs((n@jL_jwV)Y?jbR{_&n(d{?G8?L*7665U-4Yw^yU|x|7~}?FV5@u z7}0tzFrFe`WPy6PqI=w&7#QjG(y}iv)@qU4>DNj94PpQ4^uLs(WK==UrkHUV)?}O) zm!;EjWZFusq;8(zVu|{ZnrW{g1ovB=_4$lhR`yvnd3o+t+@4ihG}x1ThLb-OfL&U! zq~nNg!daKegcJ4^ecyDTAzzug(QXsxif=aoqXSi!fA*}{Uau9lkq>e2oE4@5%3_0i zLTRcfBA|asjq2@aap7I*4_j^iSz$)evV>yQ`(Eq6TPbBwr{$&NOulI8S~m=$9ZxaH zr{~#R+7bKsFCg~+Ogp^;CA6#m4AeWQ|CedU$k5Kj*zkXB%W2WjcHU}5`iB|mr;wE> zMKZmhlQoU!z7H<5+qB%y1)n+=Ah8(udkv6)Ogi@4(?#HsY;tNci^C^DRNuA!?bd)U zN+ca|E3VywI{gYM{~$xrDC?OJIvw9(6g2v9G;G5&PDASt?dF6;*oSQ*nN&jhsETEp zmiH$=a5AL8p)G2xvAA9yf~WtF^072&=gezOgfkThH5#>GnvjXWS$1|d2;-lmFPSBV zd`Ul7%QiU|w9JLy%Y%=LoZnOYH518@7DcMG(`dgvU+-S0wJ`V4%Gbnu<2}CLZ}Jh< z>DleJIMwm?jxUEtz&HE83wIxy`8h2FT7=^wNKT^FvBz?~_i%%}-#R^nnla+>#sue45uSv10>;59b^F%N}D>;Qn;*=b_&j1JN@&ipM z^XZ)p3%1(VJS?h@2jaPf+ALV)7zas;NY6pk2_hyAUeZK^n2?P!mRSo5$vgp{3fM>{ z!R4?ODpWtOPVR+0!srNkj96bakziU)99PKpX%SF9$yUGqbOSpf)%pb%J6t+YPth7e zV5cLeThZ1TTj@GY)*15F*>hec)JCZh-zLN0VLQSKGbyS@Ap)IOxJr^vrf?YxZQg*>2wK=@oy=1j*y}p+$h!ur3WVR5 z*|{b3_focVP^Ec%iG`?BOFYB_fLp!Hl4-BNq|_98XpruJu(ChRZx#BiEm z0UOiERIEX-;-GB-?)qJ_+o;P=RdO;sA-KSciJ>M{h+FM99MiNpGd{)|p@DRc}Pd;|I_ zSM@~aNx_`4XLe#{ki_s$iIW0%I*8rmu0nh=EnKGtnV>eE0JDLHwkFxaw-^PnHj&g^ ziml6YoM#ZYBK8~{E0T;ee1g2v1@BCO(GX0w*pL=dt1%2zp4~&MG-i;}sL(r|V#mUJ z*|GWvgj%l;??q&Tpjp zAj(}_7r{wj-S4TGPZ2{wX>UXx-5a+XY>aATJpw)HbHz6S9`Ls>2xq#`t~1rAs@x>N zHG0w_Vz`6!=r5z*-#<11qCL0a!jXZYii(%*b<0i05h`(_&U)U3}5U51%miaHa?FatCjwCwNARc9+h(nFD>1~Qh zL$|rWWPt@;#hZ1OgT58n=uU~c$M4xByGnW7z_}Cp))uX*?`^8D701A|KvX8=SdrN* z4^Dglnp$msGF&D7`#n;Z<^e7B5K8B`8f{$c+dE%j-UZhb^6+%^V*h$0KF&SsN&N_* zs~>GWoz~``*9WA9!E{N99DVN0e8N?#-}vI88R3(!-}@BRy(|4@F6zAMJ$;b7h6DbX zeq$73A!w)Vfybuw%)^BP-=l2Lm(>-{x0Yf?hda9#I3|P!C%y!k1z$Sg!hi+W%@D(5 zk0dgtk(VcbInKansaqmtA|BH0U0QbIZ@uo|#+4T*He{cEydcPcQ$JvG6HCw#8)kC@ z8)SeKQsj!F_|cd742_KWPHW0w@jIv?SBugS@lH(qGIwU(KC&-&>V4H~?UfCcIS$NP zDG>k&$_6e@{^-O|XDyXvo;1Owf5EBSc?3*-;?RdejsDRRqpUw>!P=Onk~tQ0{o7a3 z!&7r+k=5kwYFu-hbuUb(XhB$S05FAh>T}u$*wP(_r{PutPdqJ#)+%%XV~Hay`xcoL zYp}4m3>+kDO4sPKF~H>bGUyL1TX8*c@TTGzyekAe7&GBwY8aeFB@i?3VqVM|5SXgy zPzwH->R`*GMm=!EruMSC=iUCCaKHS;Ubqr07tmz-J(fF_0sp+{w#nQEM>&(vog3!q z4o=64Tv}V5Kf(J6qj53*1f4|uTkA3r_!^(4s(>*)>xK)=5vE2z zhhp*Fqn{3a=O{t%$2ztDUp!v_nHMmx=oHKTRqMr({9jVXMn=ZQ_O90d%jfmqQOPtf z?YB6PeslYR(nJZcPo?CRc&v1^p8j@Ge+V>KdPB2>3P`8SM3X>~n67Qj{Pr?0M|*Kd zHtAmZau~KXuncAVosMS~W=bL=?8QIkO8d{uz(mM8p^O)i@Xoj{Rd>?<%J06 zu+pcXBQB$IR7VA0uOu{@s?v-(eNpt>7er~th>)ikA9X6q) zX^~4=-aMDxi)+hle!9-0 z(&*pwBFn79&cmpfpt|LJd_N*3a!kk(vRF{q&!}b8xvwY~BEIo#*X9-b)ZN<%Q*dU4 z`Exd1Jo|2V>XW{biaF(9Pnlrq-yq4^6#paQb@vVjW-_%L!2YLvaYDWwT(R6TvD_nRrAT&PDxr}Lx3ksxa z51dCANtXWjhzNzo#Pr|*v_{tW4y{C(B)|=a9w4hmRe@t7b&`S#X*!laQPb=OU(S=p zt*)>3fg2l7b)lN#*m3;`)6nY(wGvbkG>fFkA+?5bE`ha@k$?V<&#@d0Mh(XYT`hQ_ z;)#JZ=7GSc|K7U-ubm=P%=@Q?v59rmHrjq*L*x5TO%6IRfYjJX3`@<>v=!w)JT zLKOjaTWf&-&Jt25%P@^7$+A$ycz__N$Pmk+iy_yr4nQ0!2AGC86C}l03TGh*@GJre z2BVI{h*WxJG8cks9`V2>PLeLb7>J{(3Nf$Go# zBmP>uccM;YhEF!pgiZ7I>n76J;b|VsMS~noYjFtj!$44PFCBdSYnMWUd}0X;#B(qe zm*w;wB>&T;2^Ed429J#zh#xX9R~GkqKnvf+GNpkP_W@nwHJJj_`lRkUqb%_l9Rpbn zKFO~D$4Nk(F2?%zzCPfx_EFCXl9@1}u~rKOjhgMOYKvS+&Zxy1tp-yC>{XLiTXTB^ zhOAVMff5Qz<^Ve&PSn-FF^a`xo-_oPWkILTr-Zb20}xZ7hhcb@0Z)kTaN!QhA|gjI zYU24WlQ9JDwWhc3;yp0P$}fMvuZ)zAYED+_5Av2eviBlzy(7YlpV%{02)i?;0Z2jU zkJPQZWr6g`-h3j=pUXn=4$G9WB$!6i>3o;U&Wgl&KC0@OT}T^Rxwx<7p{Akmv7e%w zF8CqcmdLOaVjx51?$O%Ayn1@Gy`84*UYJ_%l0uOIfs61}4n@<|I;KB=;{S<1Bej%! zQgf_&-W)l(m}{z6YZSNu8|qp02}@FSp7(#<15bKC;D&Ik0f?bcSJJH?xh$lc;0Y1&7Fj$*JGs_#X}0Mw#m|J8itWID7M zm#rUA^K02);|aZPE?M(!X%(RA*1F_1yxBR6)$cr@{{DH+fCgEHsZmsj#Qrs6wOcdb z?%wG?2zKeazpNeTnsR5~OBEE7w%O>qD9kb^bc5rbG^(;=7ww7}D@J+PIQVQVib^ZU zKuz2lP!=;)3$q1BCxFw~-_vyoW-(#pcSCi7D2qI)hWw5N#m%eC7YwP--@yBcYYzXc z=C40E!&S%mE}*{omFS~htQa8QiIms+n|#xMng`SwVAey`gzP?Z{>J(4_I=2puz5H1 zQvRo3ZVz**5S^|fwB25b43FWPUIPpm)F80`T=IZEYIq&vrRbLqn0mL7xHQ&KhRvGW36WGJ15-CI*DgV!*m zAHO()-juZSKq7cN9>NvqpXguo{Z%IrqlFPuBtz+cElb=(Gov@QJJ<3jR{deov@UE| zS-Q>dO4-m>4|2uRS6c?7xcn**UonX9K@o|a(Jz@3gIy*pwE&t%xS6(7@{t-}=(h^# z(1=iK$E6*;dX($dHzg>ZVEsc+5Wu>RaoEL`X@llNXzl1{L!Bfs0!PJYD+BfCeGrW; zbJ+a?Bjq5_q~+Xu;kz$@L(pZuMmJfruLHq6Gj%U{00z>sxI7Y*18vuzl?!=}397tT z)?m`NKKV)qHO3=8H0M)tt#Tnuu_CPQ17sC{ie)(FUfE zd)w)6Xhz8*+lsZ;5MKY(JdhMPX-nFx>sNtWbl9Crs=5{^v`)@Me3TmU*j=94JcTQ( z{z?>QXN+rH9Bf4W8K{nJPuOix|9V=LIZ%vyozGFD*_;Bh&$*u`;S6xAIzOlEDIjG6 zl4OpSJE$_yu77sW#*4k;Lpe8C-(-Rbz{rCdKViXU=L6=Tjcx4Oo>gq!V1#|H_6;RV zT%nS6?TMc}&^Y3wx-50ksLGM!x^`YEgty#jqL#%@m+2gd)j)*Mk!eA)fSs1qCl3h) zIC{FQzE}$uv-Mfo<33+uF^ts>l_4#zZ6z=A%38eM=347C+iJmncvh`=-zsRK7pQ5Y z({~=y_`Y&TSv`mpxUcd?)ZlhqeH-qa{>1%1_wuRDmQF|iC|i>M%KQFXb#i6Qhps?#iEkr;;+(vG=-ObJ1EMF6&0V0WSON3eFJung9x!RhA)6tF*}d7N`XKQmfk)Lw1+C}wOqxV5%s&lK3L zjF0=1C1mZ6ZxCqn^IA;zAU~+ch z8s>&UzUV3vXJj@t9NXA(@s>UEbVf1$;T{`*Q@YY)3;k|do4Zy&uLf*aj(4vF;Dbz< zf`HR4gt9dufuR9WrGTQ-Q*?TkO3C`S*xA*&SZ75}@hYLUK2pL*0J50VNGc0kS5U4> zu^U&7G6!)kt+dw3E`!QMobKi{VI*!7vo=n*lVNtAD}x3xr(0{E65V)nbcH$1x!C(p%HD7?W|PeN4v^&K-!>R)AQ9W{Bh%!QI&KizGM+D zMjf71$t1SZJbd5pIZhrInVY}RdYJ!gx|*s@*|;bRxa)_~EP0pt# zPaK#*00GC2bAb%l)FXiDL>8=(RmePqHjJ{z$cnPSG+P%gz&jZ3`9iLMh8UGeMcNvV zbtgC#oYjtel}{-5A6qJvIkJnxnXWn2$^%w*@sfRdi{eVTJ3FtRVG!sl(JRX9-r=v8 z-xXAy@*S(@luI+2(0N{cBj78kN8sZl_}6Qu970>24JkO za9g-=Lv`Dq;1EG&L>~_CC3$5@UDoQMOHy8;zFEfYZoS~aQKX7aI}}9Kz;Ol}IA%vk zl6=C6vv?ySc5X@ehD0kiuC9&p{0!dI_RYUgyUs-p60__@_DylS3BL{0;NO?H07;lc{u)6)QH|+IbC6 z_G%WC)06o9?5I1$Zfl!m;tp~>_h+(~GQJ@e;+#IrFh4AFPpY3R1bo&mB0wZFMZpS1=CAph!v67=U|pBlTvhc063>ELD$Enh}@{M()!cE25G z-nv|DcBkwA^7s6oo)|-~_O!i!r{~%~Rr9|^mKfPs+F5)2ue0;Nsfy|O-yzfi!*PnD zTAQ)jLyV~)7wI4a+qF{5##vWTsbZSeq;f?S9QP^zy~Grnt;Q|C%)mmFThE)g*Hq{d ziGz! zAX1Y^2k4PQoSO8=c5}Vj2$g^F(+J7jqEkkBetw-CZtSm@;?Vumo!p-Gj~Q?GZ=f84 zNPe!eWQhtI{v4Ms2R#}z{OwkI7N7YW7k?gDjaPkdW=rm}I{%ZWwDYm0jbt`9th(7A zb#wYTLEKh~?Z#BQ*}dKVYyK1IUk5^C9zhLk5NCs_78qlQ>6nQu_o%2VhweLQ<+nX~|>AXGybbGX){R8L@Z;Y#iLpfWvg1P1mVK*5s z@!*AokRd&P7J{)J#v;G<+xMTp|FB>=gM==4$ALgb-vHEwTAIffSQ8Q(!KM2o*mlw= z>WoW`YeXl2!hJ}QwW2T+JlYAzY@Opqf)vS_2~|XgPr1ruPPmmj8u3V`Pxvn%!9Rw- znoEHpf+ZxF0UyEliuNow&tBRDlMez9GLDH>y5-Mc8t{Zlh&(@UrdjnWbW^ohC2Z1!T^>?StbyTA&T z&dg-apV1c-VAQ$NPL?Q*V~495D>KdNem_#B*3P7d&<8ggQcf_P!BjczO_f*4 zxKXWmU@Hgv487o~@50M=y*GOHq=Dx@UcvK%O+XS{gN6}VKS{nK53q#~C3atpAUD2{ z8-ntcNdzZdv7NfSnclFi*RWZLJ_-E1(ER;ibcQ-13L zC;c{Bl2?|zt*IfRIoKj9!(VL7+=e&nHd^5>Cn^~pzCSZnkwr*kHLprYEUmQlM`(Dc zeR}#lX^;h%`|a&aGye|O9@%WS^|eB;;D54LUbMF=Hva(spF<~LjyhuSKLRu@-v9mB zbZ~L|U&rQuvvX|Gv{l}cK>AnV!UzhU1Sj2U^CeajPo&8W^ zhIjYe1ex*DC3W0*z2G)naMl5pW@sv$q|^;*6cbb)Ju=H9=2T?uT>!f!k*rodp%NDe zUxTI%aeoamATciSNneS|Lz@{iZ_$6X{e%~zJ^ulPKjQ+@Z@$QRwv^YNnio?8~DTbN#5 zyeLn482++EP?I)yxRpM=GymM}Jd4aymtr`4x;lQHp^vr$RQ|mv@-GU5J}0pdw|s1? z5U7o441d=b18+)qb{YN9iOi4AYqEH*8{qJn(~lrBojr$d<+qFxeb?Tw?}hLW3npxM zao`ed{V8{`_Eg?nSow-2{g{d#9GdKne16QQ4Bi~M4I`_Y`i^~_DaUJ&^vlgDOYqP* zvgD0=e!Dv;pqGH`D15t3vk|a^uS@mYiDQ4gzHbj-S7%Q#xLt_o3G4cFontio1a$+Z zjt;V4G_quCmJFCJ67GP(^;jf!nBkAvGn>}>@DnG7beQRk>-zhM961c&rJO+Hc(a-d z@>=-uQa=!(>AwaRaAiwNhR}vso`kM6;beokf_p48f?d)il+hz@Gza*J8jF306IU(_ zR;2QqssN+Y8+V{*zd#srX2It!4=^y`$s2k& zQDxp4xVWt(4o(Vl|GH|cvOTBh0P9USarph(-$F36G5KV#TJjkukLV_#FNlbNp`Ea* zIAn-bDMwLjlo9X;;~LOG0;V{#?Rw5FlT~aZ;^asNnO!LBx|V@o-sbBIW}d!COB?vdi4*mH`tZtT&q#G|EeB5gs@5FON8XmJfG0Yh9i)_?*C^lU*z}o^B36P#iwCfJjGj#FY!uX-@aEH8bG80mMb0Y_ z7rR!q(`swYlOLK^AQ>%K&f;ifq8TF2l%WYcBQ5JWP7;Z-Mbwmz@Y2y`4^I&|f{jIb z*X9kv>Z&M2w2A@E63MR}2yw3HeH>grRmB0WnY_%fu+%8XO!&742{!B2hH-GmY$gscMlUIE*UP>h zeVnHGy9RVjwqb`C??+9yI5!)-H`S3GJV6Z0LjC?=LR?#N0LXit*NZ)xkFS3Zs@7|C zsS=cP5?%eY>H~_9;@}mzsZ((*-FZVg4zPv?K_P4$Iu;_#qq#6>>^oHJ6MFx3Fpj@} zd^y;`zB+WHmi(fi(eR|xHx3;RLi6Xnj`3jW?-8ZPWK4%I54*~z>MY#3IOzd=M^Grh z)N40wsBC#SWCa*U=!AT9tfww@!;Bj5n9;lqM6a$>WU4!%Qvg<(@*!sHSv$$0QGvx0 z-IsEWPd0&1C^A@+43daSS|Q^)9W&8{R-)<-_X&R41UqvLs5 ze7+}!Zj_>>hHf6si36}Ftl~>!k2~mMRKJC$w&!M=46FCBW7{?jPUF8RNN7;=w6;=Z zb9*;d&MO4qq`r&;lhwolP<&s^pS%Mh*-$p_-QH^=tCX57lXBP0&g8@`&8?mZA(S?o z_8Rh(@C$Sf4Cf=(J{g58rLnl|BH^Y36uk#CkZB4Vg7p|I7alZ)eu1BGn*l-)X{1*2 zR1}hQ6aTy~1S+L(DQa-4v+7RUv#MDOl?>*JYcXqgu6)qnXyD3?6D@}$r%<7B5J}6a zE@Um}Dr*N=&{YI-YrrsZ#*~T0UXQPzTq*eono{>1fZ`vat#;dWg0J!&8#4*M$g{k- z*5|bl@&5e^Co=tUygym&?EQE|GRXvHbaS=r>3V|&PqA^I6`A?@?J^L!2YlA-8DpiU zM8LJ6r4Uc*E_;qGY>D^Q$k$A0sy4j{v}$}u(>%v1agG>xN8}%c{_*_9fD7xWSRT2p zgSt1Nb+LIG=1Nq?!u;lup(Db4vTb~NJ0o89CeBn z!Z51a9{@%MqAwbEcX*)aXZ(3A_+Z3HjN%tuUswzW3!1&jvQJ@;N`^|APYcH9@G)vf zy>q7LP(d(aw@qW&X3g<65zb+1TO)eDj_l+RWB&;3G3>^ftj1sPb273Nzpun4@P#fR z!RJ)pO0Q<8Lu#&>zaJv&m`3*x>Xg78a7WNb)McykR>&-@AS4V{KFkO6y8zm*BmBw4 zf5v*>t{rCtsXdZ^X5Mg4gT8BOWs$npxbkaS!CIj;^kp>HP%pR|)r>2z3*d#^%?Kd++%F z?`Zp7*`DD)iud=wtpMSFho&;JvA4H1GW~zaRR7IVz*kxKUw9ks8CYQsl&L0+C#@EsBq8OWGk!>&h^I$`Y71^Lu`gvd9vM+@Tiv<)@R7#Z) zL?fb=sDdkllqU!#I{-zUu03r915Zh7$%~aBG;OfVM2X6*iy&B)JafgJ3t2m7N>CWf zUD%%Y2)vBpH&AK$c4qj*_xg4Uu!|kcWGcuH2Mk)YXoozOx?Q|s^*Dez@5o=*KoRd4 zd2*jp4b4R2dcrOZx%}%{{4dDc97>#c#8_>GJCC;umN6%Qa8saIP{J_iqWkqCRr;5R z0$Bea!rrkvw5{9L4Q4W9+qRP#+qP}n=8SFIwr$(CZ6`PDmU7PC`;@Zw`(gZp-bQb| zwOXG#DH_Y4Q|Sy${u}$FOp#gRK_Z1&W2OWo=_kQ$O;`#go9p%gjq! zBinTAb>mn+r*yCI+%aNl^~I2tJrL2^yN^ubBxYdrb?|U;aPcM~(l=cgR&7~JvogVYMt(*)h8lUg1YK<9B9GW33C~}%Wm|TzGZdgFrc}xEv#3q zELn_96i&;|*tA>VR^w!eGKi!$S94p^J z=G!yUjrEPyH06Sta9Oyf*XF;|bUM5L=h>y_9koRH;r+az0svtA>)EycKTooMIkc6k z>-Ik~kROjsP91Ckv%jEto}f8%yg0M;Ajha8g|l(fm~$;}9=ZNNIK(e%5BV+H)nU(} zuGirvzBv@9+Dfs!-{}Bturtj8B;Ue)8R3@PgoR-x>!F5O2;0%(O5!(O1an3-$mEQE z_B*8feuiSRr%aFt?2Xbq6Z1^dS4dIyWIS#1ae)-ck%HZd1mssl6EMBoofEMMtrtoT z1Pb0XpH$O1S*i?bzS9z;2_yB|#p|bzeSeWb+&)iVMmAQ;Im#8IqCZ$fNWY0_LvGWw z0+58z0*JE5B1DXu@Nj)0i}Y2|5?j94%b$mBKBlv`@`IT43zG)NS9Nu}GJc3__ukJ& zc+>A#4+H4=KI#iUn3}qEhT-U=CQWz)8)zVQI2M}m_@b$Q&1B~pA z6Q{GIr{EA7N&=tn_TL3Q!sLhsP31hI*B5A-5HPPfz7ff*Sap0*1V&{evwKgBkvXz^ zam0?Ms|I1(h~T2;8p>WrTSr~wE)QK>BX%SiumN;v?gq&o0>j}OqYDt&9(_N93@Kev zPa6KfvGk;cam@f2Y&2=Ep%QGNj40}leYYrq%-I?6mldO_5Gz2HHQPeHNJqA<=CZ%y zyw%?@YQn6PBc+C#Clll+W>8R!DHWrnM!VrZ6Bq|7KmpPv)1z+WK1%sPkw)}}0AmNm ziVWwQigKA?%#LIU!?{uEQ@IkwL8cFh&byjXx|5IcR7oz@P_djE%zbF??aj_gstS{!u%G-FWI1(= z645Ea9{fXnJ5grTFDaxvH9MB6d`Ibo5sz$*tW&76#d=s`p)kFiUzO{Slv_13p5+uz z+__j-P$dJjyd{~q-kge~xB^6IyCO(fwDz&y?|^obj*n0s{|J1d?Xv?(zY2^)_*f{s^OG*_>i$ZF8f1fb1D` zXBaaol%?L&h{bszjI~Q5Dw4D7n62bnp060d>@yww#KD=xEt`ASdUKF1s^U68NWwCx zz$Nc$OxoJCJZkp}e2Y$=Jc7(@g?6M>Gq~gceiLp!3{iS-8TIT=-S!(ef|BiMU(RZg z41n4WaNb>#;0SS@-TU;&(3ggyaq=^P-L&1`r(7OV$ zhM26TO|swh59(B}Caf@Go-CQpcT?8T zFw1E!qbCAUWOOoa0$0J6oxj;?vfAE_Xy^42j;$oHN=xZ9Pt2FDPOiyU%F<@ zFlv->CTM6Il}S)M-!Lw#B!5}t3e!@ zhsNzm5Y28;RSa9aL*{G&Qu2h&!z z`{|Owe;k4Tt~#(c(z7tI`A=cEP6~Q5>vTvTSvq?7_{B3s=cetY80BHSCGw488hUBI zLQw|IK}1oO!TxaHUek8zf1?fs)($o|+c)m_#gE9M+>9s&_s~K+62@}M;1r9frvB=M z8Lr(ofebo-Uo}#3Mr(MB8fA^^i)5i{YIC9smBfzSbEd&p&Zg=g=y~sUmp+l;_)~Ue zQ6C-OE=Gf}3qe#zl9S3E$dLZz+b~~9A&z%8TIGqvGN8Y*_~f70>z z?1~$?`aARIAS@wZ2TrCT_llQD{@x)P832Y483s>c(DVeE zkuPzMHCe(3X&W^az*skjJyw2v^(ZsO8n*jhpVGSHHOa6g5;Nxv@HA#*Z?kWrCk>^w zoKlk+5x{c7KB!vIQ!`*&XsGlSpj{%t%Jju&JJSvh>H?j02rgj|1JL*GPzpbrJ9JVb zXLEv?lwdgMdtq5&Y~i|!#rXF-kwH>+9?!BY3$kI#U*1`On#k1YI8ve3aQgVmxKQ+w|wG-8jJg) z*#n?AXiNyOc!bSz6Niv<(AFi(BvFm_5SWs^sQGeh{qJVOQ&juK&CbzxTp%|awQqDPxQ_-f=E9Cz?%0VEo-@tGH0R6Q83yWCa-ps_*(ZI&}KO(Et zPo39WkbhX2yqN~^;)3Qn7s7I#Q>=|#rOA@UNYJo?{0J5_5U8}HhSInNUcO%^3J+3m zM4hNRK=N_>hU(a)1b`di;qBf44-s_J57g`FmvO9V=AV&fJM9B>MRrKPC+I>hX+H1> zYEAlCjai)sfX@D6Vv33M%oTSBbtQ9ew?|Fo`O<%m=+WHgQMzuyO*qZFXl+ZdWxFbT zpKwEzpuh4l@JAD_gU`dCf%?J9QkxnM`0cMC8t?_gD7g(UJW=iAyd8l?=HXd&u<(Kf zv_Yc$U8wIf4-Fr{H-l2x+fxL5hpVTfaJ19k2c|o$L;hxO(_^XuWejUSR)i zF9Aw4XCmJe9>&Gu&*v)w7M{=RHCaGH1t6SA^7i z`*Lz~qJMoB;_#;`YHBN^53}ZY!>_sYxP$FH!9mKlYLal7%^1a1bf98axdiMHpnAMq zLYHZ;`sFo&YxfwPO}L$Oeq(d<^z%fS#Z2*BVYrU`ra1+7>55zu$rRtI#MpucnqYmN zj0JX)07F$VUtK3ZDo8Mp97(pd?!8h%jrG9~gfuunxOsld?798Xx^rtK%fIqy=8PL_ zGa!2vPSVn&TC}mP!XQVL8rxB&ki%`aD4EI_-(iPpCPGYsNy2S<*k4RCQDYsJwlw{9 zlVE5ll>}|n87H+uH+nnItW#PIDv!d>2ey9OcEE8Gba=I+=x8_F-*?WVK3`AI7SWO= zCJ1ySx1M!iGerm6-%$91g3}_~nJZ>IY2mBSzZ#^;h;naueBOu4Qujg50zg>ZzRxbp z@KFSHb!lbgJi(PslCK=kidLo|*R0Byt<)Zso0m({m!ixPS3IY-xK*+bc4>gW zA5)| zat-l0=ao9Vmmqd}dpNs`r9BEeBwv64dVz^4R3k=y)bzLm7E;uug82ooIbj`5s=oXh z?|wSQX}u8;?gPnZ>A@$M&45pd&XBi3nMWr~u03CqOS~AYNAs_iJM=%%x$DGji5>S= z_%t5|#GDn|qo%VfUn*Hn+r$V#Z{c>p+rl4d1fKwj9rrka-dw5ogH~ZyQ!7@wxrCIx|=~J85 zd`6R6{ybg!qge7%_kpEJXtHN~yO63vp4;9#O8VRiUkZy6;DP#ts$Qr*1zU-T9sa^B zDVi(%!cE#Gz9CaSQG2F83Di2{lqZ&1Mh54ZSJdTZg;Niaob*JX)g$|+d%l8AZZkCL z5wr&Y&--OFh3m@JUh#61o$bBGWBdDSJ1}#*ITnpNM-!tD>UMT#SMl!S$K~sE)1{?M zj<$M$arg4IOM2wn6wCV(A=XO`=^F|KWO=hJ3LBeS-tWdX>Xh{g78mC?g(2rOsI2tJ zp#dP1YK?hXw;4Bm;kxNb(GPOA9Gu3J=5{1QCj#9JvMrQUPB?b~E%Rw=?66%_IK7?< zu?yA>;1reg6_yGVAe#y}=@)udUBW*M_5y zvmR%7T)Li3dV34*QO|de!%GvE`Gy~@^XG-gUMA>r@&s@Hszt?GT7znIepVXa^BY3B z`XhJwR#&T9>Z_PFZqyAfa`!f|x?R^C)KAmlBZeU8Po=sc4$*MR4uJjQkC1c7+C8xe z^;}))20qZl&4{Tl_qrpbiNzX#96-O+vX9`{!yUXUJ9wK0@POf4V{3>pz~px(o{Kej z2jaKEeUQ%j75r^tPgNXNyMp}{dhM!(GU-LRDkT$2A8Iws;QFHXup6cJC$mQUV^jz5 zaL1Ty6@1^s!GY0ZOGLb+d#(#CL?|)Om4VN9>B;yPJ$xgV>x8Ke#MR$$rj-e`gZK7H zm2BN-na!K~@ies0GCbiYAaW>XvYeV37eIModPVZS=hqkjbQvrBgOpV4$$ju?n%)W} zi9WIVj5O>ZdXi@8;zasMmFRWvqTpLWXrxDC)KJ$2qkzd-+Vp+Y^n)aJyC-G0#=fPy z;oPf%yn#*PDsIRR*IZ_b0}wfLUb6F#+r!THw?(J(&&Bd_9Y>r;5{1O%G|)XV+HZjE z#6`n#Ql2s@@6?eyDLi#I?ZW(VFr8S{laB!?!`)*eaUp%S&Oa&rLSz}DrLT&3?b`cI zeMUL0H|aK=TXT2`ONKIt&Hyxe?J`qd(U&MxBc;}U5XJ))1vINFouzT>a$cHhXMRLt zHHfuBr=k*v^Jio&T_jgazoRL2kNf)y)9Oreb)8jmqzFoUAn!)se{iF=ACnv4Y}h;^mfY zzjEn_t!Umvn9=@fqR{0qUl@iD$CLq)!7K+%AiB%zQWjtwGDh(wJQPxq`i3R?^S2X_ zhB>6b+Y-?Y6F_e1dO$g&;xR8T-KE9cs!yT{4Yb;$?@Fbio_jI{i-Mx38Uz|%2^jTQ zK^IW?HoOejDG3wyHqVWH5jl|~1KkonhiR2IR^=PAx+T%l)YH*dDY{RC$;+xCsQ0A_ zf!E#YWM~`v)fZp8+0KXXzlZI+VQa@3lD8ZZ5Wxe2Xz93IbPTfbfWoKTSP>4Nu!*-A zAU-q^2)01rh#tiMjY{{a10vG(;Mb8NLIxzUm;sI9dqkkH3L0)C^fAQ)NEDFso)d8n~htj1H-x8tQ}}LW%k_w41))Uq_uW^G<*i2%aEVp zjAyA}nYGHuJ`4I2y&2f(yJhyF#aIelRL4cF3lrcA5%26%*19lX5+EYnxE@fRU6~yw zLR8~T{;D_mt8_`Z7~V0;L8Fz)-%5t8BCr)`LQ4?FFOTeuuA`brw`HajCYcoD^UnN3 zpA7H*q_d7~DCoFfX-Cb6`+#tynzEG>x62)u8&wyjL$F6}Ie3zpT?)vwzPxIdw()k( zO2yAc$cKJHmYu2`%x@WFDn>R&`_^#Tl|cIbhb-LsJff zaq;c3=8lr*tqhNh0>^+%AAWrAMu0hQD3^6C^=8J&4F{T%Y|>s#n-t6>P~q5GD{T>k z5JJAnrAmvd8<;xsh$Vg08-P3>E9b_!kf}-8CHO*9&)ki6AA1QDG-TFY{MILJkCajCNKpb3xBJM-$1OXINQyO@h zEr|tj4kL#`$pM=*dQmZg@9uL&nr~&bWfveW9`$BpUw)65N|}Eq19|)OU{+N!}0)afi}N4|8q?M6`;uTGSR` zBo2e;7&ToNFl6>h_G(%m*5KGP($Cl9FMuLhKTSOT;*FzsWC#0Q&$BaKx+v z$;9Mx4!&Lu*o4D&iTa3ODaheoUW-HgX>nunAuL+K&G{~bn#RoqJ|1BgssOXuXHzdH zp~xzPxwYAwwjhwfDm3%@NSF{kJM)oi73x6ULU%xe!QpWri!5JPdJb9e>x%4*%r29# z3h|`y83Iu=__O==A$kOc_Q^e-2wmX04E0CTALD=+stC=-;>z*wFu4XLSm$CtunK4< zl3nlpu37g~NH(hDQ+L@EhxQk*Qft9g!5XC`F_ej)mU5U9t;qL>r)iTN`()G}^q#=8d``cP!$; zc*eW-)tDi$i;8g(0y^qdVeX&i(1~Hqa6tC$f0Ocy=!isQBlWwZtO(^WW)&oZlJH0H z3ZnW{|It1Q#N{mV_s8U-Lc8iJ9GvqlR4JUr0=Tf$ZlTq}hMgWEI(QpwVsd;xIj>?(E{yg2Jf0)V1|=bo_AlU~Xw? z^YpTB@_9OXne3{w2LdCmz;wNATYYi0 zLZ_(JHPkO-51H{P>QJh)v1`=*sCkynNEJp$lxzaw6y-&`Mrko}Wl5PvtMECJz6>vA z6?{8*1wrh){$pc+66NAyR44h;RFnqFhjSukmyf@m>t&S@6+;as8Lj{OG>;vPR5V;{ z6KyceX0%0>7EV=%Vq{F`(@Rr|U1mErs)9J2^Lqs`jTF5%s%JCKnPrIOs)D03C4hgjpoi+yAzc`)5){ z(;@SC{xd04{h`-k|Lac9&FMcXB?A>L{@EpePF2@1Cj&|YEIgssL?(w?IU;X`8PHRY2MLr&H%`+YZpZ0AF(*@5TI`9#@?I$B}g z0_&Q%=WB?+-K z5QH6}NjiMB*49d{4hj9yUa>^?1dLD=coCXo%(sV_-o({z@~DBO%QRH(x!8RW8PE7yPiXCeA?@}is^n)>j>AIw3=tJz7nlF3Geqcb;K;*2WkPhnS;YopY?`ExaW* zCZ(kmOJEVRbFFp+K#@Wc#hzJutG!}Lq*m@8e10eL88fGw35Ne3EBj9c_2NSTPW@Dn z($B0J^WQ4S;1BcvS!@4`(%4E->SxT1*7c*sNQ*&~i%W=^Q#L@x6GFXZo7--F!lQVkei<&{LYk?4G{&=5p4~@xG`xl@%$4 zS}Ie=+k=BgC}2QNfE(zOqaqR~1Z5RxjaPK#oNXu-kflCO`DBIKKM9=)^KWq@30zLD zonfk+?j+)~*$^);rG1HL3(}3#h zInB_=qZ(YTRzpti-fGSor%~_T;Hd~j8f4fhArUl?Ps~`lM!wiMa+J?wdTV>t`DyK1 zDiJst!u+H?Ong(l^2q%&Y=0f|>d1I8H|rAg4=Gu-$D+7VR-dlufQc9QKwikkVY%)f z6NCOOs_A$J+J^ECKwMf6qWBDo?fuQgY@KXeo33r2_O5TYKpY#J%*WtrmTzyJ@6Pwz zo6~WId6_^`H7r24&a;%oIt2h4hkN;P9Bybh_=WwyM-b=WhkW3@H$~#*$U~h9g^Yg$ zWS)Z2hp3`>f4K5LPAWr4-r>pq<=-Mw216=o2uA{7$fH;xtk|clDj1k+P%L+#NW5;Y zJXwOAPoDN^1F>BzJBkapY9rZ-N@NzqwRGxkV=5F-9gLBnF25sFWef_C(q*c)@LS7r z<3~f=0~td=8nS%5>t#pt7SycR5)8|JV^d9wAh}3P@1PZfzvmzs$1VV}ub*N}@7&)* z(HS|Sek7N1Bk^Wbgu|eym9Q!59rjD@%*C52{5{NhQ)|aGo271w_qHF>` zn|ODnZrTLV`kK)!n1d!x?wQ4)X9}blCsslgl81E64DlEKozGWB-8*$&P{hIBCv?YJ`8wZT0ZAt!NI=b}t8gxA#&y06{rAj)DNQ@+1)n znUT}Wbu-RFP4}??1WZmwY3c{K3$#0_tt(B;m{)TZ%PIPzuE7j#7iGsG3&`WF3s*@C>S;w2ZW zq?MwVg`|Y0d4OiS>6xZ)tX_#@>ciEM!i?v6r~+syeggR)BjhBadN8c(^}9R5HVnl$T$qQH328p-`zqLF zo@-ytBo9EW-qS03fApN%KGabU5$4N@D%ie*Lr+()8?X_UN|+q)%{OX{nBxzfO{}49 zAF%3==Y6vWvlT3;Gt{UvV+6M;UE)i%Z!>4w`l`D^{##so_Gzt$Gn@D|w=0K{nD@hy zPU>o@_g3p=t1Qz$THD1P-Fl1n^_xY_@5h(6$-5Qp!`_=;{|_~FSHJt&;OFi-`%x3( z{_EZKPhlD`{D=E1QgPOL?MF*Et)eOC1Y?0g29i`eS9a#gdsb$4-j*zy6k6RYkH9z# zSYU?RaJ>>eDQyZg&%6j5I?{Ul^0HwejVGshG!C91oFS4mLjf!j!EWV zb{*m3muj0@rXp}mZ4Sug#vN~m&gjUEkEg`RrWIJr1L=x~i!PD1{2z!w> zebRp!j4tU%QFQ+4DGdya_x}#s)a5!-6O|6p^A_qfFyw*BW zN0$PqX7)nkKsga4al;9yKO)soX)(|$-dwz8p-l7r3T!jT3rGjvUJyo@&kuA0qIVFC zUw@2`3|fL|Xvz=-Jax@INiScwa5JQ%L9SS6otV{XgT-D$vtkvY($EX6s>!Vkt=OZd z`5gqhk}HH!II}iL4R3yQ>?bER(`Ny0lYB$f{%fGYFdWGso0S_p#OAm`V(+Sb$`1Cq z{WovgFBtiXODxh_xev`1izbNi`@W`XRVsm8QaPTpXRwUMpibeUwD_U#F~ieu7``$I z&dVK8hY30sx#PAvpGAXZBGwwsX`SXx(fm)I(Qo$k>CrCNmhaE`1jBn8Y zxfnHRUS}`&!?$dr>@fq&RgA`-=vr2xC7)i%hz8 zaQ$Mmq+kA2ID;3CKbhgHh1CtHE7M&oFyv}U2E{<0xi4BUu+zB@X}lQ535Bo%@*^dT zrb3+mkSPPHSYNpH#Io$f!V>UdK2pSX_^8w?&HV++4_5S&h}7EfUCk0&W#WG4PPhiv zK#uCy@}*Gwqe6&4mCzCu`~7uxiy!`CfQtbI->Ut|T1ETK9}|uTy~j!O_c)CMbV>I9 zgEl{u<;kXs^dQ03fY^v;Dk#bz3wrtdF%#SR#l?95`~4DqO4Dl$xbk%Wj;bZ= zyNsHCI-NX$`WjKZM8JNujEvcQzV3B!4j&M=C?(x$LxgO-m}1h-t=r+M*)4XWhfe#G zd82P4bsX3vQe4pM=yzbSd~Y7sGjA+M4=+}0`GjH_HL}>2$i|F3am#6;>E3t(G`Wu# zPhkf1fVB6{h-636>wtM|R*}zRSqOpys$?n&WIZ4vK$KxwTYkThiWof6h-_PA&uBw#wAPXwU6%$AW94B6;Jza@D-HDi@ z_ypX+cu%=hdJ4Q)jY_*Jg%wpq8s18QP|gS=wuSUhO+yl{kxPY#jA2kh4Y;n#2NbVG zMh2Cs6o<;?K|kp87d;Z1xDe8y@J{h6Fqda1u*ee(|G&6n1JJ+CHEP^*hdBsrSZfpbH zynRXIF|!>-pvGxvXK}c^jJ9T7mMHT(?Q9SQreilfPt}FL)jwr__;Ud(M--6H%l8Qb zN5VB)4l{0=_=;A^av#i@O#LM_BSMSo2na@t_H?3`&0-Ca96usHOw1(e+PRTaGb?AG z_0DZ&3|W+z`5DwjD|V z_nVAr$d6TcEfxm-rhw$B4;G+k4^LkG!k5%yVvm?(vtq7E@!wK~L-5dWLP2^Dq=#;XRqa{~`2$L(%E}Y4s->8ol z;L8m-?f2mp*WzlpMcfRk?|RAw@{EVlJM|9Vkk-(@+=r!=5PGxr>#c*X{-PJ<*EOF|9z6brxpJB z{-6BRNhK>A3=z05?{57x3U<-mDo{)aEAv4ZE2~^2WXooTQM1+cfIlAX%U-*djjz|4 zodE!1ixi&=@w`13_jUEtFsaIHL}Eu3^HgHK$ANPw83&4mRPY-NQh&kyt@!HkMmS0G zD5euP0ILj(grk)a%@bk#eIfLrG_@tGg(LIT9nb){M=#577tarllIc5sVOLd9PrTAa zVIKF_Q60vqJd(~PVXhD0l5F2TyqB#-AS zdo$z8OxdcgOCC@Z8!fS#N3Ok$*jp=$PjT{E%*p_zqnrG)=D>Fg0YJT%Z8gIesU(Hs?U9EImg{PDu@ zT|pJ=wrDbV2`&NY>kjtVtS_WQhytU9a3qNv%isO7SqM6W6m)*0KJoOLi`?<|>&@{~ z(#E0D|J- z!nn!qz3o3OTH5nOMxHX5o{EUR%z}UADE(%Vxw7&UBr#U-*>NESIv(8qo5V6&=1btI zjIrMV?b?zLvk0wceQmtku$uqd(-#NF-%Io+O)kiwC~Oc@xz9$t`Z(854nl#nhLns= zL+^wh^Tgn&46JEqEtHh?ROyu?@(Z6p%W~(NmB8k_HK`5?VKPKil}i>gD6|3uE$veG zQKkw7*1MvPj5MjL?9Z(C-qJWvMHPuwpMs#PZo|SDGIVzMXIdOJM4e$v!O@x(^(qR+ z$jVz!!?2Pv@eB-ww9>Yy)!|BxKodVM*c1iBtyA0KUfetknQ zno~E=jKV7RX8vhYT%7kOvdhsDuO*?3J>G&DIqWe+9_z~yd$%R8S@V6|9i10y%me$^ zZznII+0&17CXe5ZjkuLb1S|xXWJ3&+@z{dYSTPhw$imr_$nSS!`BMg%#uhsB2#!+c z14NEHCGyk5ngr|0nBh5%!zhJdqH*1%MP5%5@l56la zOL1&!Co^oF&m3jk<4kyDYWswUFIY8erSYTnv8Db||Qz64Us2>DRq_ zc5hg}o-`{yWn{PY5IAdctzWeFpgE>C3D{+dtrjR?H|dyev!+CY0{yIlov?vbx3*wC znegb~u*EB~9=@DG9zi2Y^d)`RB|X`)Z~vxkn+|gx$H&Y1h2k#T@X_W^$4VmlS@)R! zld;&H_66fS(9k{MbYXQ)yTG#MrswLPA4uPT$}l?Dre~GkB&XiXX#~le*|*B>S&g(X zdw4sfG+49I2f?SocxY)*G?tRY4#5Q?`6j`+1cY8 zkuM~$`LpXbVVSXwf%yr@aZ?{*obvB_#|$P>Eb=PC1a_6x^1~MWwyk%0GkG)iAm?a2 z7;JlVofTjrp+U3275P0~iV};2UoK{rtGSjzsi)`>!QXL1BR!mEOjP|^CJxkGb;v2c z&2yqg+U6Fw|Pp;AohVEqFfl%h7d{U(|QhMi6DCb{%1@I@l;k3fA z?Cdkj%zQaR#+@qH?|QkUm>k6m=EM(m)~QkYf3k!_0aw++76RYqOY9w!ii-Y_(g%ZO z6Pr-Yk1HH}`+=sMV_tcX&r28}7iPwe8sJEWO)s}OF$_OBd=HsRnmIiA!^Uil-@CGB zdbYeddU2$u&Q|p59NiNz%NXi}{~l?CP?27@@Tdx~Sq*h@dVPAnZFI4-E?2s_Ade}g z-RCiR-Q)bM9mfS5FZWMLMl}+-w7i*+l5#j^yr&o*P;Z~0I2#-~=QnX$s6vYW_2EOX z<#ToLSKVc!^R^-D{dL<*&B)MZ$%8#nu0{LGECJAlwUUDH+~$A&cZEA-GZB6^S5623 z0L1?~zc6yJ&~r4hG;%g`|4;hZLzSNZCgFbqm@Kh>5n;w67_mwJ;t1MDs{~|$wmkG7 zqo^fNSz7Bbav_(H27UluYwkjFGvmh7(K{A-BhJ*)78Gm1Vg-4Vg@_TonqYHS%|zc6 zIBF)bCyWj%#!d*yeHHC0g;qnt8%8G~&>Q$!&FzJNC;UY+4Bc1YLwjKeS zrttpW-rj&cvF`}L&TU<80LM!D7yqz=v=^3qey#>A#!yt(y?(g6j62Wu#yJmNgF3|4 zCeIZPu&oT&*twP+DJ`_-EW7AzQNeviTwRX&%4Fo@QvWcfbGy-yC6;`AEGzoU0~U+= z(_7GHoyO#nd;O|qI_D7nE#R1=NW{>wYWXyy0$9+#oC?5qhumo$>7_caR*$T|Apv|t zE>D#@vf_(iRX2b~HFs{`4$RvJYKrS8pk>Ef$j0n34`qcSns#4JjvN@>xwFH(`Sf^) zjxAIZD2!{P%16df6sp!=@4tlsT1heN{Le8P5ee{7DPa1v;CqQk2*T`-?E1%8Lb*Ib z=F8Vw2rhr4P@I4s}e4<^l@ z4bC2hAvq#?+xTYVGi|d? ztNt)Ck3eMwFCW8I_3!4-JGRfKyIl?&TY0HcV-s9*Z<`OuFgbRor3AH-X0~3? zOR}k@06b9qWhaPFY0>R#+CU=~8Dyf#V?^+~w)Ict@L$M|3!Q3EAkcnsJyW33X80E5 zInC_Q04AHmF!!F8K{>+wFY!RiG2xU_8X{U0A>@fe}icT%Rbuz9~v9Bb<6i z8$YEw=F!^^1bogP8OE5UUB4X<<;BWz)9!jFF24}Zz!(KGYgy${YQ9}|D|N-y?|&%w zr;q-ENCg@FjeY%rJ>~xM@+~<*&s_z9#1_REE(Pbs!k7uiSWt(9}GbL8@ zj^AJVhNZ#~y$Ls6y=e#GUmkx?*R9}iq}|l2h<4N0hrmyJN)3vhb-wQ2c!X#-)$qTDK!Fp+Nhp=^)4&=#k+bj1 zl>jRmVZX&~C=aoFrVIL?7@cLAk9h50!BAoHfPV{2H-g9aPe3be_VSY?D zR9fj!bUiGc4=}6MZWCR(U6a!m$j3~j0NoJsREPCz$g^ou zvMp;gb`!O*As&cKV-Sg|P?Si^Xr+7@0wxK7hw$RFfcQ;C_ZtZ#+1C>~PbwAj-uFkF^7{C)9|GF|?@VT%9?$B)i)n?OYnsv!Jb!?8z*Jkv&S5yRcNI2s4f zN+jTV6#>hWxf4Ws$|Fi9w^s z;Hdv`^1e3-!7cBN=k0x&C*~qXCHtd1+8!;Lw#tX_EZS-7s0pKV?87!MBm(4Zj+gr{ z2I<4cV4m)gRqdi{E64Z$LzarRI9c8Mf$^PF{V&EM15-U~Ya>gx|1dG1#IX2bOWkpF z>xU_d+xus)peb;M5lzt`i?;L_UjwNvs$%F-*A*lh_N0&bbYHoR5SmFsHRDbxp;;7d zZ_dwi5%NTu4A_0Ram%Fc$LJ;vm`NYW?F`{K^x>J1L)S+_v&Gg$LgU)0TXUul#`3d< zez<;7>B#Ig96q1m?%rY7xw?tmEC(QiXr}P^QrT zk@9?TAhxzha)Te6U)$+PRuH}u>Jz<)CyKlVigr6_o-Q63%BBZgASwu_8@U4oXV{~c zwMP*I5Yl3i?!;@ucbhPqRFxhD$uH%w%ACh^4s~pGf41aDK*R6W&dQ8SI8sQ8!xG%9 z@aHth?G_?C$p%K0rV4Z5@AqgM5k)XjqXXxgNpZC+FSr<8abxLnm4FE$o)i!soEYA( zr=KD_9Q=EK`0{X&8IS=hYA$upIU4n}X7z4*{q^CGl3Y$~htsbbq~q4Y~h|e@9?vi<#$@TM)X1HR@?Z zh&ygDTZ3`j;4t*%=n8_T1`;w z`GtOkO79`55WPo-56|^LN;F>s#b_R{w#ircpzs1G4r)>@2-rscjCzEYDPX{N`j|ej;j3!SE0iHH3UL+G^(iRAfMHidd*6-H_ zH=ONyr0l#_On!TF{|z?7N~QDC?nzZ#<%H!+XVR-DTmE3W9h+yD_H|2>XSMTFAJk|> z4F|7N&yjRQe^0RE02wI)wpbBXbmi1#BaWK75}DvH!56JqOIU{+c~UFdWB*d|zn-{FA8u zb5=;(A~2TojAzJ=7PgF){)t0y(h%45*{tL* zJVD~db-toCgE&-w0q`@aUeZU$fO!0-n-A_jv`6L11Nz7aGWBhPFsUp6{W%&H&S5tM z;4g31JfPbzoglwhqA-?MEi(MrDW+knP4BPwkCtt!F_op#%INB|Z;p}pg4E7QB9B9@ zZUHUCNM%rs5H9dT30K}*5Vvwbcy6v4zdj+qyAHOGKRhP7yYH^QJ8HWc{YMO7nUCkw zNNa{yBZ)blcIt>obxc`JI_lm-KT4QH_kv?AFZsc-8kx!vs6*`22|Ea!o9EBtRjMJJ z0NhWV(M@2Kji;Eh1Lq!J6dYdOWwNKEXfvnxb%wr=0^=%L7KXXqO%p($$XV^v7`}Dm z+Zmx@tN%a3z9~2oe_J=6*fu)0Ik7phZQHhO+qP{?Y}?Mn$>e5N-FxmiyXt@TLqGLP zS9N`B{nq-h{;q|Fd&|bGp=ahx3!DoRnAPDQ$oe)z$ff!!c2R-ZV z0mSOvX8#%egD{@EhX6wMz11MWV!ps`&w()-zb*C-O1IMypZs;;frlV1RCUJMBe;W_ z*I&YXJZw}Osr)W4Y|22As?{K(x~IDzYp{{(pT?q>sp^Bo^x@We^2LfIfKQ+z23gJI zCS^SgJN|ql(^CyIknZ0?Kp^!@cVGj_0?OYBXsHSHS~Je|l?vPXOUDHrNL3s#%t|8k z4nR1=cbhPIKiOPLa|Hi}La`KO zFAVf9chhW+$$7%oq}M*qut?ZQFjc>9j#f@gcI3`>FJFI=2~y`NHqOzXl1M*KxCjBW z!|*xu$S&9mD$UYWiW5g|{=Z)qwO9>hQTNprw(#b4Eh-7=)-m3KnWh z73m#G0DWI^44JhJY=t5qcph-h@NN-2Sj7@D;yUfrL|GOqs7YkAgC-^K zlWpDT?`1j%%PtGb{*@$XdzvLicG)z6zkR5w(>3sanpoSTUWsf|t1g@WX-iR3@ z{4fz<3B@f#FowlFE6-0eu{Lb~l@_2FQUuXFC>!d_I%cU55U8X5k35autzWTbKjJ*i4ll_;$fe)8WNLidnU zKjSzYQFer0h;a>M7-TuL)a@+}OtHD&84Bc*9DP>MQ@;lfI&tpPzqV15v1`wP1c6YU z@p9K~$*G&mlN!OnE9)g|V+1Ju588gM9a&a@n~PGC)n(#pCZ`!hAxIe4%?@ogNhb0) z*l_yX5{gj%nIEHF8PcfO0>At#5fSV^4Q(ru9(cMjfP+J!a#*}_gJ#>P;S3U6nSJtp=sNKwNS4(D82VY=V zRJ3?EM674AeDH#nPW2|WQ*OColYX!FnSYD&dsr>8K)w@5=8A;~Lx;upv;bL|_ROWB z+f7Oh>9G9eGT0HVvVQ-l)PHbdY7sy_FQ)xIi-_*PlyS%Z0{1`Qer&>8UG@ zeC&r-keNV2KgrsY2K$m0`1~sam43_|cjq2{KClJBMLl-EIvq?^FT@cvz1`wO(AYD= zp&Y0-$-!8SLMaOykRp?jBX}HZ&x__77QE=u(&r=5T(TV`lj5+5FfU>`FwMI7{N zNIk+FnR~}GLsSh#Jxla5@ar)6IK=>{1gs;dr0*aGf~b`o`^7k96pK_0vmw2vlxwh` z%|Ikm>$-9hVo4(kyK5UOr9NW8SuwKexFXAFM&7irBaP{!p`%LQEZEf8++tW0u2N|& z`7R|{9!`onV}hgjz92+}j+bhVvi1sL%yqI~%7JHlFFJisP+;rvluW z@#u#U#wrX1KyH4-TI&u6M*69#RVx|fvmVUv@Ap(PRWmC?77;DTlT`L)RPLW;be>67 zB8fpFIajQb`{l5YGceD}TEC&kIWkMflqKs!iymUfnu}%q?m}d)SS+QKt;!(vR?%Js zl28trBr^FXoFr5hK2)0B>Jv!Jo zE4w#rOGsC7-3DlP8U`;S-ZDK#C3D!P3Dx;Y_~Gy28|yfn1(gfM_MIa!dDo2yGHryEIxKoamH-dl2MKVi>~>i;$NH*caTP32CgZtXemG23sha zs&JN(t1jmNuP6Sz12g%3jnv{{Lm&zvxOxMw%szZ<6Htn-Yc7PyfJMW~*AuZHOcO&C#vj=UwGQMhVOg(&Ai1uZXM(ZM!EX+O3LqWm_}wEZkzH z+>)vQP{g2r>C0gpw}2l7KELUsUnI97b%v*jx!@kLC6!sQe>Qp7IOV! z_+l%-?&$xxYD`ft?5EAZm}E&_!?j4WcYhnEz{V-3f}&?9o^yn16}SyY$x~-xG@qy1 z#^5TI%r|J9GaG_h%IL}s1H`wxr(nU#ZJ~V}=gmgf?D*j32&?AuCXf_lg)=I8^Q>+- z#{OtryPUSfA7zc>rUz|&roa?W;_xL|y=irA{91qR{LMYXb(oZwT8fd10qOQ`duKyH zt{Tov7z{onW>*`d1sVdY@L^es$k$|^!2j-_VLGaQ667DGD}=o%y1gwH@!!GN!G`c8=V!vjVo{FHP(?UXVyUk;F zhqw&g`zz3T@+FL>CF`f9hcr*_5RPQ|JvzVDw(4bvbd9?E5J7T(ZwNBvxs}T;E=mT0+B(x4O946yOxBcE5LcNsp&y&c z5w>*S$rmT2fyPp_)yAh!B*F_p*f>K{RK;WNr1j;Rl})Nnk>#vLtje^GXoc#eMaaiz zq)Q5iT?uyA7wrTN4d-Y`ZEW^^NRk}aPe{YXQIS4^%=wXnS_gej!9VcbzeCJn;`zBi zTBOr=amLH|e^8@om8(YCDE~3u>qXLzWhg1xG&yO@$YVx6Qp1QLb5HW0|;Y>SX7giQhCj}U)yeU>X3MF{H~7Wek*oX zKdIkCco!dMWnzoGq*xIZw`m>zvuJanmGROV*GqGQu3R5FS>$O8dmE8y?rQ{nU4)?h z*tLgLN>6fX5H{;Ft$9kK`4WlQ%L@M%5MNX`V8F zCr%J8Dj*#J;@z*1(FX&?;q6%NOnh3?@P{``x4Zqe=j$3en=ocY@UX_%-1K^DYinR} zCLkp;cnZ^Krw2YfZ#%Y>y~V!kgTs3`# zv}-9nsEOQs-eA7Jj;WCXxU|EVBiW_Eq!d&2+8vAj{V=nbDd@|U4HJg&xn#&oB=O|s zZu-p096h$Zcx;s5iGy87k-BS@NC+KJOJrfmIym!-i0HpHL*{fr#K%=cmL{K`%9$=4 zgt{vg6EkAl-OFX<$mHP7UNGam%O3m+90wh3Au6b3W-!GbxL7ijm z0LKne729&|x;Qf)5nyx1Hg&B4E=)Sx_u6*U1m#5ST02llATEPjRrtB*(BP?F!a~!U z7bMh;i^0ROmbef`#tZjT{H$p`j){5#gX|AT@fluwF%%pYUEgV zDAD{VrQjZ)ofkKLiZgy8QySU=nx#Jz*WavN{Q=28GI9o#N(6;;N_Bm{nXc zyYn)$4Io2Ql-v=AyU$?;{I*24Pbx!|u$eGW@2on^f}c;Hu3d0X&8V=i9dZWMhR?*x z(TN1xI?df;SfS~fW17LAqtz zD3ytdcr}XUy!DP+i)y1J%!@6r<)rH6ed9uf?bds&DKY1WEGXNqhw*QC9YL9?)j} zH!9XWM|HvAcw?fr;YAFam3xV)b&=YR*1NFUFG3&iZw_jrjTG zCD)1mR*Na1xP%GOB#~ z;^rvVEUWtN?m?DjL-dE8boBTj7WaQoF}*qhA0O3B0wtRBr%z*<;*!pT`IW!)oUw;E{}uk zRGnaksQz8A?q*f($Ga`N8R~IuwnDlVt@err?eqI*pkb}WNT5)^GjG+Vsi;56?uD2r z-zNtijZe;MjrxRjS0^0RC#}z!;W05=>d@iSwmEUmi3Rq|ipl@gstI#uzznQ$*vpA4aD2^; z_h%8qRHB@ES=?%fW=0u$z5cjQa~%Qe9FRUfg>p(?P8<9;NUQ2I3HJQgbU{NIqBZsSowprdz|W8lZR_@%ij(91*>mLuqC z$A=2ydMC|3yN(vU7WfE@0vM-5VVYtUW!(+=wEaRrGN)NSk_z{53a@D6sb3$U{fLr= z8|eV$W0VgXaNganf;(J{jM*G~eF=||DLpWETsJjII82U$r*@WgYCg&)=u@LCA=jlE zIc+Y;Ej~{thp%{fHGQETP`>Es`{%7=3u#l^SY^^$wBQh*B@<|K?kux$9rgLjpQb0) z>PW*P!hWi1r+Dr0^K;Ky)xp}E_1`U;_S7*k{ojaz`$i1$KTe+Ch%s}vaWej|0OEhZ zOmvdA?YGk<<(;j4XR~$%!5TeKr zd6SBH_*PW^Cvb$nLLTlZ(ijL<9;_Ku5=gcG6xjkw7p0mnL_+4HkQ+|l8`3YxLr`s? zEl@mQZJ=iD#Yk??BD0iyImwbp9{Wd}*pKXcut4HhH{l-bttc&hJEeDn+V6Qtb>(2@ za3$8#lnv9+w+$YBxg^kKg8*Koa)|{tWTTFf2Gs|h)w~ZU#Wrewh ze(*ql7a8wwc2_3+O~8ET&>)A z#^$W4EK{|U^3?Yw;fhn|BRuG4s|-UI6}1_+-kpoE1=(6pS<`|Yq;8w%rWHQZIf+)! zW!U(drl9e$j=rlHn8f53B}Y%eI&v^iK~GPQyNR9sSo`l&!%9dxEt4~C$h3#hznbB4 z)MoJW7G=`T7(Q)IN7DVDX>3uuA256lcx7FlE%|?NF^0T zsRC~lTF#ZC`;?G~2#oO3>@5m{xd*dqKeIhByB@O*d>#0PZP-dy;p|93*uhW{3sd&< z%8}wnvnpCE7Po)+VB&TW1DTlT-ufg*q;yM=9!t+}OnmlbANS#zs8(G17OE77R06cP zaCyzrU%tG{2RK`O76s+~g4ieonbuI-<0sO!ZkSWe8rYqWw9AV%I+vNIn`d7agDqeW zwp0e}p5b|Uzo7k>KJK^1fohr7Y-2#DI(aeify1YaMzqD6i6vI z1mb<^F+@_b3HjY;2h!bRA51uc6G#Wz%4Dj642LEpsRAwf9VCDqP56;&3d0p^JvH+Y-$qmO14))cL@k=ZEJ3yYg>rPs-8%z{iQJEhF>zujDx71u31P_O zYjGNZu#rQTUJL}EmyKc{7!esVUfOBJG~wXbDCQ>X@N$v95wR43O&s8Ymy>-aLU-mw z337Kvjq>FV{xf8egfF{b%zBgeGh}9zkSQ2MA3VqqQbdO3b{|r`ICH;4d17ro8GSw> z&1=tl-g+s}^Wuuy533o8jv<>`T{S$>^rCTbH5oF=8QMS%rpLL3gDb$F4xa1hI zK&Om5i8)W*Q0II+VwFS-_Y@PaiF`e|dQ0RknS?xniBSx=z;U@X3~NYu+7cQYiFzgVj*9BxWPR20 zt+zv58(jz8b&X6QmjAf}J7v0juQmSStvjY^i`a=sIlQ?_86IP1RGb`dMe~{C@K8Z& z3m|FG>wQt;_jMk2jlCdO89|{y7LYV+F5ViH9fxjhTSQ8mC&V)ewVgQO$$VVP-k@Mm7ltsQiub7#D1?c&NkWNw9Q z<#f~-zeJFp^$Dbx3Ec&A{nI;TI!S*3u$8yGcmeiP^xxs6294Ei_HD}0_%>zy>O9|`H6ObcakVhrDoJV*Yi22!^G+RIGwEW3xtx6Kg;*_#$ zPC*|z-wZlYjWz8%pzB29PjWo3Lu-17w4l_hON#2<9k32Hk^z(VBW&0WQDY4%>j@ektV0^!m1SzjD4`#A@CLoZ4Ai|HOkY zTytt%D`LsHTjp?n3%Mx*V$JHsqKo;=z$cx%Tyj_BPszb(UTPJU!;c?DqJ_Q%T&HHQ6UU4 zQ&OMuV8Yjpp&!wi*P|~$J(2xBzOZ!W;J~WW@Gv=kY6Zf1K#qZtcx1-Od$3<+OU&q) z9=BPr$BXL=z)g2uVm6=I?Z*l-{yYSGMBAPAvLEBa#N{j|VIl>O)Ai{hf)K~Sx8K`K zXxc-HXDggrGRHVLkqaFHfn8~6QBaQ28T?}m3g-Y#C`AglXZe!)QL-&5I!>!cuR3xb zqG`sWFRUWC&7RAL1iuXO)1$z1D`_%fynw`aAz2}%GU>@P7{B;Wjn2;tBrn(xUr&^{ zL}^fJrdvELEQ)*Je)u!41?^&u?e-op4W`Kz+K_9_pQo^JNG(^wy%Lk-5GgDxgRbOTDl0LACnK#$?mZ67W@JI znNv(~V9WUF?fzrqo=j24rq)%YkfYn0i^uv*6H`>IHi^XqO%)?KmUxBam- zwz)6Z6mR3>t!;g!Z1y3S%39fk&s4H?#Rat0QzV9%UM2>wvu^onSRaf*pN@ck$M0+r zFH}A-5K!KCOZ;b3m9^7<0IzkN?!Qu_hj$(*X`bR#Xc&DZ%`59G>Z~G!*TAsmh0~8# z;qOdFqDB+f(Xkk4S}nv$6+yqB@k1nFi@-M zmv3M8)l6E=k->l!7df5kr{;}jyWvcM@5yDxmJHJKm{FPF7@4^)x5uycnLhb@baXw& zLrD3rj+vt}OVo$Azom;W@(%jAG0!J%3}5#(osxh5UUT>C5Y+4wkeW3gc}pi?Xo+2@ z-?>n@^avarq%AiOHW%RN*Uz@^u5yJA=9LhOp5~>4*~=4^k1HwD~`#p zlo+SwMC_+Tt(+20z|j)J*>hw|-E$Tgx!0q|Dj0&KAb4LoeChAdmv357&RFg$;etB; ziUC7OHm#So5OLjn=gM3e7xQEE;9-B1hc?vUzqM4eZ@y=a1RJU>6Ur&&k4xbr-;fbiDV z!);6###fX>u@15Kt+oMU7%Wxjvc)waM#?LE@*dvnMtK0F0$^B^fAl-fWuz4 zNcg6f&W4VD6aPWa2669%k5}t2me1QWD3=h3sig9~7cXwd$-|?EHxBIdK|+P*)q&kG z@&suaZ;#=)ZRGpj)~W=3Y@1&-c}MbDo=%lHFMrl`IjM*b$}$i_v|MKe;qzm<+L zXwbFpl_Xy1Pb48nsE=YJWog-oc zyceC?%E&sghm~ZTuWQMKi-d%IZ3TtD)*$C-Fbn0#2DBrBCe-RA8FefQGNTF-YT|#w z7jY;Mnw!t^txzDxrISg3>CS;ED-~&>7DZ78fK$2AQi6oeV!WZ+6C;Cx5Cz(H&72cc zK`}p*pMLbT5AObE_zknRIZfkMmePA^a6xqf$R} zc-hxTX6icIMt@blB3v8%DEKQ;6kX?rZ2X+%g> zm(8{}JP>5}JBLrj>H-+X4t(An?>rSO-cb`!uy_Zzy6H)pQ#%^o2fS_ASy(&gz@;j* zvg8vEtBSG}fm^GH5>KJmt#+D!;E`}W`Gu71tXHIh^(O{@Wa5ocU7asYh7lB-K+=hVkxRIyS!*{5s=P*A;4V9qO;G$+ zlxg!fj}ExKbV^SB%^hQUoTXpw>LO5y!r8gQ|Ol>n|H zmmH3if(}Wrv+7LNnz=qkeCp-F0L#OIA1#`5?OZgygf$Y_Z?nTPi0)DbzEM0%HUIhN zo!dz~_xF%Ea8r45(vebX*%{i4jV61Gzr>3^G8_3Z+l}lM6m)OgM0cU9VoK*j?Nz2; zUJnxXVbuqCiTDmmn>U__?A_heWckLsz z%6PIl_U#>oKo*+s&Vdk-tjl%%`se~sK16{DD2!JG5fai+-zy|UG*ZM8iKho8lo&9W zu}NaWA`c&kx~Cj<8Nc);eq1Hem;)Xf^6jX{73LIHK?4vDn8qgkPH?9m1qGyl1+G z9m13A7AI4Dxw}TV(Qk6Od_VtP+NnR%@rq8RH<0<32s5MW_IKidrR2-G}?4zCPv$p-H^(NT92S)DN-o z_p-$Vyn_Imqm(Xce=*H_Dd4O{mJ{s}Okt%4L2%*vubfnKX`5vB=M+MAtRqHJzBw_7 z0AWok@CniOiMbfN%}HofLEgC_LCGe(>-ZK3i!uub#v5xDk&FcnehxFaBxv8gT3D=| z^W5JnL|{TZyL)I@J?DOvPj;!>PW$0nF~L;^yAECYv4kVP>da`M{md?G2b9 zyCnxWn@$s#gZQ(l^K5fzYnOPGOiV2H$nAE5Y(`w9+4YqR>I#5y$ zQeVyz^gyBU@{*6yI63LokhNfxF0JAuSsG~sK{kn>ImpWvitQ@7ZEa1kFS#aau>q+O zt#?#MA^~NP2~6PP&&a}1F|--?+{}IGI9OYhfLG+U3aQu*F75o1dG}k#1Wt2;yFv)t z+dnO622cq`cd_Wsm-Y7dFk*9;H4iCHci)s~cdeV?>52)c@^ao!Tb3MRtrfc#!PzE) zh)4j61ujoEzr~M*Qm>cl}K*iE)PsjISXSL ztH$Ijh1fl+UjU-Pz_{6YFZ<JlbGUC`z$0YV;YJ zXQGU*#nZ@KHJG~eMw!g{1!m+m!g_6j#H-e&mUhTu$Rf_QDQu1KntcY+8R1f-4xz3p z2WgLXK2!3kgWbW}5w?NTmMN#Ve5`sr`FWP)QgKJ;;-ySq)AM3RKl6mGL@sH}|_vS&ZVB|!po^lKtpt>MNmYL8}yyKT-1ktv-vm{<~EG z(5j5?P|@)vi&2$>PN}*M+s>Dct}a_kS}CwrYD2h5Ub7Ifh%rdv&*eICusO~|1EMCr zn0my6i#x`zfW%)BxMa7QqQlD6Anz4Fdrej?Drm^q!Z+W7pO0Gc=){tsfd{J@tCbKN z2IZafmWuSd#qehXIe5?6;#vywc!y)M^_W>hi2Sw^>#6GlSE{A9^_YEe>i9Elul@qM zSr(IU>jF2}?^%A4y3hR60L}mIuqY8{k2WO6Q+OMv)ang{s~=ZZMkjKCAp?cBdXn zEo_Fqg;|n{PqtRVqrSxL9!Tk~4zOAD2}{POp^*S6)4e0;cgu6#X_bf9A>AGq*u}nj z!9I85_}E&;682dON~*j3wCle0{;bClR5AGdpxo!@wU7y+v1aI|StiuZCUC2c}S0;Ka|?!g6ugx@rZs2h`@oSYc* z>0KJg~qY!t4#9(&x3k+@{rP2PxZ^t30(Rsfv)nmc%kh z3zJk}2ZF#Aj@!U`rN;v!vNnRXYm-Zenj6mD$ðWKVpR>`691F9sJy#EX%Ot@POy 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 Ged3%<= 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�BxxNMSV4N0qbm5DL-mf*OX?88F1sK0<;mq_jj; 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≻;eJn@T~uL#CiGi8PTmYV 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 Date: Wed, 6 Aug 2014 20:53:04 +0200 Subject: [PATCH 0507/1761] [downloader/common] Fix possible negative sleep time in slow_down() --- youtube_dl/downloader/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/downloader/common.py b/youtube_dl/downloader/common.py index 6404e1928..33ebbf6b4 100644 --- a/youtube_dl/downloader/common.py +++ b/youtube_dl/downloader/common.py @@ -157,7 +157,7 @@ class FileDownloader(object): return speed = float(byte_counter) / elapsed if speed > rate_limit: - time.sleep((byte_counter / rate_limit) - elapsed) + time.sleep(max((byte_counter / rate_limit) - elapsed, 0)) def temp_name(self, filename): """Returns a temporary filename for the given filename.""" From d42b2d2985f851078226e587fcdc8cdfd7cde435 Mon Sep 17 00:00:00 2001 From: tinybug Date: Thu, 7 Aug 2014 11:24:51 +0800 Subject: [PATCH 0508/1761] Update vube.py fix extractor is broken #3459 --- youtube_dl/extractor/vube.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/youtube_dl/extractor/vube.py b/youtube_dl/extractor/vube.py index f1b9e9a19..109c4b459 100644 --- a/youtube_dl/extractor/vube.py +++ b/youtube_dl/extractor/vube.py @@ -71,12 +71,8 @@ class VubeIE(InfoExtractor): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('id') - webpage = self._download_webpage(url, video_id) - data_json = self._search_regex( - r'(?s)window\["(?:tapiVideoData|vubeOriginalVideoData)"\]\s*=\s*(\{.*?\n});\n', - webpage, 'video data' - ) - data = json.loads(data_json) + json_url = 'http://vube.com/t-api/v1/video/%s?country=US&limit=120®ion=US' % video_id + data = self._download_json(json_url, video_id) video = ( data.get('video') or data) From 5961017202174bf14eda0c0b603e4da44983c884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Thu, 7 Aug 2014 20:04:29 +0700 Subject: [PATCH 0509/1761] [vube] Extract audio and categories --- youtube_dl/extractor/vube.py | 67 +++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/youtube_dl/extractor/vube.py b/youtube_dl/extractor/vube.py index 109c4b459..2544c24bd 100644 --- a/youtube_dl/extractor/vube.py +++ b/youtube_dl/extractor/vube.py @@ -1,10 +1,12 @@ from __future__ import unicode_literals -import json import re from .common import InfoExtractor -from ..utils import int_or_none +from ..utils import ( + int_or_none, + compat_str, +) class VubeIE(InfoExtractor): @@ -29,6 +31,7 @@ class VubeIE(InfoExtractor): 'like_count': int, 'dislike_count': int, 'comment_count': int, + 'categories': ['pop', 'music', 'cover', 'singing', 'jessie j', 'price tag', 'chiara grispo'], } }, { @@ -47,6 +50,7 @@ class VubeIE(InfoExtractor): 'like_count': int, 'dislike_count': int, 'comment_count': int, + 'categories': ['seraina', 'jessica', 'krewella', 'alive'], } }, { 'url': 'http://vube.com/vote/Siren+Gene/0nmsMY5vEq?n=2&t=s', @@ -56,13 +60,15 @@ class VubeIE(InfoExtractor): 'ext': 'mp4', 'title': 'Frozen - Let It Go Cover by Siren Gene', 'description': 'My rendition of "Let It Go" originally sung by Idina Menzel.', - 'uploader': 'Siren Gene', - 'uploader_id': 'Siren', 'thumbnail': 're:^http://frame\.thestaticvube\.com/snap/[0-9x]+/10283ab622a-86c9-4681-51f2-30d1f65774af\.jpg$', + 'uploader': 'Siren', + 'timestamp': 1395448018, + 'upload_date': '20140322', 'duration': 221.788, 'like_count': int, 'dislike_count': int, 'comment_count': int, + 'categories': ['let it go', 'cover', 'idina menzel', 'frozen', 'singing', 'disney', 'siren gene'], } } ] @@ -71,43 +77,40 @@ class VubeIE(InfoExtractor): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('id') - json_url = 'http://vube.com/t-api/v1/video/%s?country=US&limit=120®ion=US' % video_id - data = self._download_json(json_url, video_id) - video = ( - data.get('video') or - data) - assert isinstance(video, dict) + video = self._download_json( + 'http://vube.com/t-api/v1/video/%s' % video_id, video_id, 'Downloading video JSON') public_id = video['public_id'] - formats = [ - { - 'url': 'http://video.thestaticvube.com/video/%s/%s.mp4' % (fmt['media_resolution_id'], public_id), - 'height': int(fmt['height']), - 'abr': int(fmt['audio_bitrate']), - 'vbr': int(fmt['video_bitrate']), - 'format_id': fmt['media_resolution_id'] - } for fmt in video['mtm'] if fmt['transcoding_status'] == 'processed' - ] + formats = [] + + for media in video['media'].get('video', []) + video['media'].get('audio', []): + if media['transcoding_status'] != 'processed': + continue + fmt = { + 'url': 'http://video.thestaticvube.com/video/%s/%s.mp4' % (media['media_resolution_id'], public_id), + 'abr': int(media['audio_bitrate']), + 'format_id': compat_str(media['media_resolution_id']), + } + vbr = int(media['video_bitrate']) + if vbr: + fmt.update({ + 'vbr': vbr, + 'height': int(media['height']), + }) + formats.append(fmt) self._sort_formats(formats) title = video['title'] description = video.get('description') - thumbnail = self._proto_relative_url( - video.get('thumbnail') or video.get('thumbnail_src'), - scheme='http:') - uploader = data.get('user', {}).get('channel', {}).get('name') or video.get('user_alias') - uploader_id = data.get('user', {}).get('name') + thumbnail = self._proto_relative_url(video.get('thumbnail_src'), scheme='http:') + uploader = video.get('user_alias') or video.get('channel') timestamp = int_or_none(video.get('upload_time')) duration = video['duration'] view_count = video.get('raw_view_count') - like_count = video.get('rlikes') - if like_count is None: - like_count = video.get('total_likes') - dislike_count = video.get('rhates') - if dislike_count is None: - dislike_count = video.get('total_hates') + like_count = video.get('total_likes') + dislike_count = video.get('total_hates') comments = video.get('comments') comment_count = None @@ -120,6 +123,8 @@ class VubeIE(InfoExtractor): else: comment_count = len(comments) + categories = [tag['text'] for tag in video['tags']] + return { 'id': video_id, 'formats': formats, @@ -127,11 +132,11 @@ class VubeIE(InfoExtractor): 'description': description, 'thumbnail': thumbnail, 'uploader': uploader, - 'uploader_id': uploader_id, 'timestamp': timestamp, 'duration': duration, 'view_count': view_count, 'like_count': like_count, 'dislike_count': dislike_count, 'comment_count': comment_count, + 'categories': categories, } From 64d02399d8d2acbb55b22f789a5b54e79591b7b3 Mon Sep 17 00:00:00 2001 From: pyed Date: Fri, 8 Aug 2014 09:48:02 +0300 Subject: [PATCH 0510/1761] [xboxclips] Add new extractor --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/xboxclips.py | 34 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 youtube_dl/extractor/xboxclips.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 468c7dc29..23f53ba13 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -384,6 +384,7 @@ from .wistia import WistiaIE from .worldstarhiphop import WorldStarHipHopIE from .wrzuta import WrzutaIE from .xbef import XBefIE +from .xboxclips import XboxClipsIE from .xhamster import XHamsterIE from .xnxx import XNXXIE from .xvideos import XVideosIE diff --git a/youtube_dl/extractor/xboxclips.py b/youtube_dl/extractor/xboxclips.py new file mode 100644 index 000000000..499702d0d --- /dev/null +++ b/youtube_dl/extractor/xboxclips.py @@ -0,0 +1,34 @@ +# encoding: utf-8 +import re + +from .common import InfoExtractor + +class XboxClipsIE(InfoExtractor): + _VALID_URL = r'^https?://(www\.)?xboxclips\.com/video.php\?.*vid=(?P[\w-]*)' + _TEST = { + 'url': 'https://xboxclips.com/video.php?uid=2533274823424419&gamertag=Iabdulelah&vid=074a69a9-5faf-46aa-b93b-9909c1720325', + 'md5': 'fbe1ec805e920aeb8eced3c3e657df5d', + 'info_dict': { + 'id': '074a69a9-5faf-46aa-b93b-9909c1720325', + 'ext': 'mp4', + 'title': 'Iabdulelah playing Upload Studio', + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + video_url = self._search_regex(r'Link.*?"(.*?)"', + webpage, 'video URL') + + video_title = self._html_search_regex(r'.*?\|(.*?)<', + webpage, 'title') + + return { + 'id': video_id, + 'url': video_url, + 'title': video_title, + 'ext': 'mp4', + } From a91cf277672318e942af891d6c962c053abda45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Fri, 8 Aug 2014 18:43:28 +0700 Subject: [PATCH 0511/1761] [nowness] Add support for cn URLs (Closes #3465) --- youtube_dl/extractor/nowness.py | 40 +++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/youtube_dl/extractor/nowness.py b/youtube_dl/extractor/nowness.py index 1c5e9401f..6b2f3f55a 100644 --- a/youtube_dl/extractor/nowness.py +++ b/youtube_dl/extractor/nowness.py @@ -1,3 +1,4 @@ +# encoding: utf-8 from __future__ import unicode_literals import re @@ -8,19 +9,34 @@ from ..utils import ExtractorError class NownessIE(InfoExtractor): - _VALID_URL = r'https?://(?:www\.)?nowness\.com/[^?#]*?/(?P<id>[0-9]+)/(?P<slug>[^/]+?)(?:$|[?#])' + _VALID_URL = r'https?://(?:(?:www|cn)\.)?nowness\.com/[^?#]*?/(?P<id>[0-9]+)/(?P<slug>[^/]+?)(?:$|[?#])' - _TEST = { - 'url': 'http://www.nowness.com/day/2013/6/27/3131/candor--the-art-of-gesticulation', - 'md5': '068bc0202558c2e391924cb8cc470676', - 'info_dict': { - 'id': '2520295746001', - 'ext': 'mp4', - 'description': 'Candor: The Art of Gesticulation', - 'uploader': 'Nowness', - 'title': 'Candor: The Art of Gesticulation', - } - } + _TESTS = [ + { + 'url': 'http://www.nowness.com/day/2013/6/27/3131/candor--the-art-of-gesticulation', + 'md5': '068bc0202558c2e391924cb8cc470676', + 'info_dict': { + 'id': '2520295746001', + 'ext': 'mp4', + 'title': 'Candor: The Art of Gesticulation', + 'description': 'Candor: The Art of Gesticulation', + 'thumbnail': 're:^https?://.*\.jpg', + 'uploader': 'Nowness', + } + }, + { + 'url': 'http://cn.nowness.com/day/2014/8/7/4069/kasper-bj-rke-ft-jaakko-eino-kalevi--tnr', + 'md5': 'e79cf125e387216f86b2e0a5b5c63aa3', + 'info_dict': { + 'id': '3716354522001', + 'ext': 'mp4', + 'title': 'Kasper Bjørke ft. Jaakko Eino Kalevi: TNR', + 'description': 'Kasper Bjørke ft. Jaakko Eino Kalevi: TNR', + 'thumbnail': 're:^https?://.*\.jpg', + 'uploader': 'Nowness', + } + }, + ] def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) From 31bf213032b72069fdd14f5ace3ace33ee46eaf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Fri, 8 Aug 2014 19:21:24 +0700 Subject: [PATCH 0512/1761] [xboxclips] PEP8 and extract more metadata --- youtube_dl/extractor/xboxclips.py | 59 +++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/youtube_dl/extractor/xboxclips.py b/youtube_dl/extractor/xboxclips.py index 499702d0d..a9aa72e73 100644 --- a/youtube_dl/extractor/xboxclips.py +++ b/youtube_dl/extractor/xboxclips.py @@ -1,34 +1,57 @@ # encoding: utf-8 +from __future__ import unicode_literals + import re from .common import InfoExtractor +from ..utils import ( + parse_iso8601, + float_or_none, + int_or_none, +) + class XboxClipsIE(InfoExtractor): - _VALID_URL = r'^https?://(www\.)?xboxclips\.com/video.php\?.*vid=(?P<id>[\w-]*)' + _VALID_URL = r'https?://(?:www\.)?xboxclips\.com/video\.php\?.*vid=(?P<id>[\w-]{36})' _TEST = { - 'url': 'https://xboxclips.com/video.php?uid=2533274823424419&gamertag=Iabdulelah&vid=074a69a9-5faf-46aa-b93b-9909c1720325', - 'md5': 'fbe1ec805e920aeb8eced3c3e657df5d', - 'info_dict': { - 'id': '074a69a9-5faf-46aa-b93b-9909c1720325', - 'ext': 'mp4', - 'title': 'Iabdulelah playing Upload Studio', - } - } + 'url': 'https://xboxclips.com/video.php?uid=2533274823424419&gamertag=Iabdulelah&vid=074a69a9-5faf-46aa-b93b-9909c1720325', + 'md5': 'fbe1ec805e920aeb8eced3c3e657df5d', + 'info_dict': { + 'id': '074a69a9-5faf-46aa-b93b-9909c1720325', + 'ext': 'mp4', + 'title': 'Iabdulelah playing Upload Studio', + 'filesize_approx': 28101836.8, + 'timestamp': 1407388500, + 'upload_date': '20140807', + 'duration': 56, + } + } def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('id') webpage = self._download_webpage(url, video_id) - video_url = self._search_regex(r'Link.*?"(.*?)"', - webpage, 'video URL') - video_title = self._html_search_regex(r'<title>.*?\|(.*?)<', - webpage, 'title') + video_url = self._html_search_regex( + r'>Link: <a href="([^"]+)">', webpage, 'video URL') + title = self._html_search_regex( + r'<title>XboxClips \| ([^<]+)', webpage, 'title') + timestamp = parse_iso8601(self._html_search_regex( + r'>Recorded: ([^<]+)<', webpage, 'upload date', fatal=False)) + filesize = float_or_none(self._html_search_regex( + r'>Size: ([\d\.]+)MB<', webpage, 'file size', fatal=False), invscale=1024 * 1024) + duration = int_or_none(self._html_search_regex( + r'>Duration: (\d+) Seconds<', webpage, 'duration', fatal=False)) + view_count = int_or_none(self._html_search_regex( + r'>Views: (\d+)<', webpage, 'view count', fatal=False)) return { - 'id': video_id, - 'url': video_url, - 'title': video_title, - 'ext': 'mp4', - } + 'id': video_id, + 'url': video_url, + 'title': title, + 'timestamp': timestamp, + 'filesize_approx': filesize, + 'duration': duration, + 'view_count': view_count, + } From fb17b60811ea89fb857ab03a997d193898046466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sat, 9 Aug 2014 05:45:15 +0700 Subject: [PATCH 0513/1761] [arte] Do not filter formats when there are no videos of requested lang code (Closes #3433) --- youtube_dl/extractor/arte.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/youtube_dl/extractor/arte.py b/youtube_dl/extractor/arte.py index 9591bad8a..d86dbba8e 100644 --- a/youtube_dl/extractor/arte.py +++ b/youtube_dl/extractor/arte.py @@ -109,15 +109,19 @@ class ArteTVPlus7IE(InfoExtractor): regexes = [r'VO?%s' % l, r'VO?.-ST%s' % l] return any(re.match(r, f['versionCode']) for r in regexes) # Some formats may not be in the same language as the url + # TODO: Might want not to drop videos that does not match requested language + # but to process those formats with lower precedence formats = filter(_match_lang, all_formats) - formats = list(formats) # in python3 filter returns an iterator + formats = list(formats) # in python3 filter returns an iterator if not formats: # Some videos are only available in the 'Originalversion' # they aren't tagged as being in French or German - if all(f['versionCode'] == 'VO' or f['versionCode'] == 'VA' for f in all_formats): - formats = all_formats - else: - raise ExtractorError(u'The formats list is empty') + # Sometimes there are neither videos of requested lang code + # nor original version videos available + # For such cases we just take all_formats as is + formats = all_formats + if not formats: + raise ExtractorError('The formats list is empty') if re.match(r'[A-Z]Q', formats[0]['quality']) is not None: def sort_key(f): From f5273890eeea6604c23367d91007fb8119768c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 10 Aug 2014 01:04:10 +0700 Subject: [PATCH 0514/1761] [fm4] Remove unused imports and minor changes --- youtube_dl/extractor/fm4.py | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/youtube_dl/extractor/fm4.py b/youtube_dl/extractor/fm4.py index 4eb63ffa9..c1e60774b 100644 --- a/youtube_dl/extractor/fm4.py +++ b/youtube_dl/extractor/fm4.py @@ -1,8 +1,6 @@ # coding: utf-8 from __future__ import unicode_literals -import calendar -import datetime import re from .common import InfoExtractor @@ -13,20 +11,7 @@ from .common import InfoExtractor class FM4IE(InfoExtractor): IE_DESC = 'fm4.orf.at' - _VALID_URL = r'http://fm4\.orf\.at/7tage#(?P[0-9]+)/(?P[\w]+)' - - def _extract_entry_dict(self, info, title, subtitle): - result = { - 'id': info['loopStreamId'].replace('.mp3', ''), - 'url': 'http://loopstream01.apa.at/?channel=fm4&id=%s' % info['loopStreamId'], - 'title': title, - 'description': subtitle, - 'duration': (info['end'] - info['start']) / 1000, - 'timestamp': info['start'] / 1000, - 'ext': 'mp3' - } - - return result + _VALID_URL = r'http://fm4\.orf\.at/7tage/?#(?P[0-9]+)/(?P\w+)' def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) @@ -38,7 +23,18 @@ class FM4IE(InfoExtractor): show_id ) - entries = [ self._extract_entry_dict(t, data['title'], data['subtitle']) for t in data['streams']] + def extract_entry_dict(info, title, subtitle): + return { + 'id': info['loopStreamId'].replace('.mp3', ''), + 'url': 'http://loopstream01.apa.at/?channel=fm4&id=%s' % info['loopStreamId'], + 'title': title, + 'description': subtitle, + 'duration': (info['end'] - info['start']) / 1000, + 'timestamp': info['start'] / 1000, + 'ext': 'mp3' + } + + entries = [extract_entry_dict(t, data['title'], data['subtitle']) for t in data['streams']] return { '_type': 'playlist', From eb3680123a2f451e79e953ede5dd70fb7fb4c0ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 10 Aug 2014 01:21:16 +0700 Subject: [PATCH 0515/1761] [orf] Move all ORF extractors in one place --- youtube_dl/extractor/__init__.py | 8 ++-- youtube_dl/extractor/fm4.py | 45 ------------------- youtube_dl/extractor/oe1.py | 40 ----------------- youtube_dl/extractor/orf.py | 76 +++++++++++++++++++++++++++++++- 4 files changed, 80 insertions(+), 89 deletions(-) delete mode 100644 youtube_dl/extractor/fm4.py delete mode 100644 youtube_dl/extractor/oe1.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 2401940c3..2ea2c73d2 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -96,7 +96,6 @@ from .fktv import ( FKTVPosteckeIE, ) from .flickr import FlickrIE -from .fm4 import FM4IE from .fourtube import FourTubeIE from .franceculture import FranceCultureIE from .franceinter import FranceInterIE @@ -226,9 +225,12 @@ from .nrk import ( from .ntv import NTVIE from .nytimes import NYTimesIE from .nuvid import NuvidIE -from .oe1 import OE1IE from .ooyala import OoyalaIE -from .orf import ORFIE +from .orf import ( + ORFTVthekIE, + ORFOE1IE, + ORFFM4IE, +) from .parliamentliveuk import ParliamentLiveUKIE from .pbs import PBSIE from .photobucket import PhotobucketIE diff --git a/youtube_dl/extractor/fm4.py b/youtube_dl/extractor/fm4.py deleted file mode 100644 index c1e60774b..000000000 --- a/youtube_dl/extractor/fm4.py +++ /dev/null @@ -1,45 +0,0 @@ -# coding: utf-8 -from __future__ import unicode_literals - -import re - -from .common import InfoExtractor - -# audios on fm4.orf.at are only available for 7 days, so we can't -# add tests. - - -class FM4IE(InfoExtractor): - IE_DESC = 'fm4.orf.at' - _VALID_URL = r'http://fm4\.orf\.at/7tage/?#(?P[0-9]+)/(?P\w+)' - - def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - show_date = mobj.group('date') - show_id = mobj.group('show') - - data = self._download_json( - 'http://audioapi.orf.at/fm4/json/2.0/broadcasts/%s/4%s' % (show_date, show_id), - show_id - ) - - def extract_entry_dict(info, title, subtitle): - return { - 'id': info['loopStreamId'].replace('.mp3', ''), - 'url': 'http://loopstream01.apa.at/?channel=fm4&id=%s' % info['loopStreamId'], - 'title': title, - 'description': subtitle, - 'duration': (info['end'] - info['start']) / 1000, - 'timestamp': info['start'] / 1000, - 'ext': 'mp3' - } - - entries = [extract_entry_dict(t, data['title'], data['subtitle']) for t in data['streams']] - - return { - '_type': 'playlist', - 'id': show_id, - 'title': data['title'], - 'description': data['subtitle'], - 'entries': entries - } diff --git a/youtube_dl/extractor/oe1.py b/youtube_dl/extractor/oe1.py deleted file mode 100644 index 38971ab4d..000000000 --- a/youtube_dl/extractor/oe1.py +++ /dev/null @@ -1,40 +0,0 @@ -# coding: utf-8 -from __future__ import unicode_literals - -import calendar -import datetime -import re - -from .common import InfoExtractor - -# audios on oe1.orf.at are only available for 7 days, so we can't -# add tests. - - -class OE1IE(InfoExtractor): - IE_DESC = 'oe1.orf.at' - _VALID_URL = r'http://oe1\.orf\.at/programm/(?P[0-9]+)' - - def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - show_id = mobj.group('id') - - data = self._download_json( - 'http://oe1.orf.at/programm/%s/konsole' % show_id, - show_id - ) - - timestamp = datetime.datetime.strptime('%s %s' % ( - data['item']['day_label'], - data['item']['time'] - ), '%d.%m.%Y %H:%M') - unix_timestamp = calendar.timegm(timestamp.utctimetuple()) - - return { - 'id': show_id, - 'title': data['item']['title'], - 'url': data['item']['url_stream'], - 'ext': 'mp3', - 'description': data['item'].get('info'), - 'timestamp': unix_timestamp - } diff --git a/youtube_dl/extractor/orf.py b/youtube_dl/extractor/orf.py index 03421d1d5..011e6be13 100644 --- a/youtube_dl/extractor/orf.py +++ b/youtube_dl/extractor/orf.py @@ -3,6 +3,8 @@ from __future__ import unicode_literals import json import re +import calendar +import datetime from .common import InfoExtractor from ..utils import ( @@ -12,7 +14,9 @@ from ..utils import ( ) -class ORFIE(InfoExtractor): +class ORFTVthekIE(InfoExtractor): + IE_NAME = 'orf:tvthek' + IE_DESC = 'ORF TVthek' _VALID_URL = r'https?://tvthek\.orf\.at/(?:programs/.+?/episodes|topics/.+?|program/[^/]+)/(?P\d+)' _TEST = { @@ -105,3 +109,73 @@ class ORFIE(InfoExtractor): 'entries': entries, 'id': playlist_id, } + + +# Audios on ORF radio are only available for 7 days, so we can't add tests. + + +class ORFOE1IE(InfoExtractor): + IE_NAME = 'orf:oe1' + IE_DESC = 'Radio Österreich 1' + _VALID_URL = r'http://oe1\.orf\.at/programm/(?P[0-9]+)' + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + show_id = mobj.group('id') + + data = self._download_json( + 'http://oe1.orf.at/programm/%s/konsole' % show_id, + show_id + ) + + timestamp = datetime.datetime.strptime('%s %s' % ( + data['item']['day_label'], + data['item']['time'] + ), '%d.%m.%Y %H:%M') + unix_timestamp = calendar.timegm(timestamp.utctimetuple()) + + return { + 'id': show_id, + 'title': data['item']['title'], + 'url': data['item']['url_stream'], + 'ext': 'mp3', + 'description': data['item'].get('info'), + 'timestamp': unix_timestamp + } + + +class ORFFM4IE(InfoExtractor): + IE_DESC = 'orf:fm4' + IE_DESC = 'radio FM4' + _VALID_URL = r'http://fm4\.orf\.at/7tage/?#(?P[0-9]+)/(?P\w+)' + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + show_date = mobj.group('date') + show_id = mobj.group('show') + + data = self._download_json( + 'http://audioapi.orf.at/fm4/json/2.0/broadcasts/%s/4%s' % (show_date, show_id), + show_id + ) + + def extract_entry_dict(info, title, subtitle): + return { + 'id': info['loopStreamId'].replace('.mp3', ''), + 'url': 'http://loopstream01.apa.at/?channel=fm4&id=%s' % info['loopStreamId'], + 'title': title, + 'description': subtitle, + 'duration': (info['end'] - info['start']) / 1000, + 'timestamp': info['start'] / 1000, + 'ext': 'mp3' + } + + entries = [extract_entry_dict(t, data['title'], data['subtitle']) for t in data['streams']] + + return { + '_type': 'playlist', + 'id': show_id, + 'title': data['title'], + 'description': data['subtitle'], + 'entries': entries + } \ No newline at end of file From 56ca04f662d2c34713d85b0f0dc576e7c51275a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 10 Aug 2014 01:26:23 +0700 Subject: [PATCH 0516/1761] Credit @sehaas for ORF FM4 extractor (#3431) --- youtube_dl/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 9b41587e7..962aedbff 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -68,6 +68,7 @@ __authors__ = ( 'Hassaan Ali', 'Dobrosław Żybort', 'David Fabijan', + 'Sebastian Haas', ) __license__ = 'Public Domain' From c767dc74b8bdfdc75bba14d11b460a95f85ed08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 10 Aug 2014 01:41:01 +0700 Subject: [PATCH 0517/1761] [downloader/common] Fix typo --- youtube_dl/downloader/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/downloader/common.py b/youtube_dl/downloader/common.py index 917f3450e..9ce97f5fe 100644 --- a/youtube_dl/downloader/common.py +++ b/youtube_dl/downloader/common.py @@ -292,7 +292,7 @@ class FileDownloader(object): def real_download(self, filename, info_dict): """Real download process. Redefine in subclasses.""" - raise NotImplementedError(u'This method must be implemented by sublcasses') + raise NotImplementedError(u'This method must be implemented by subclasses') def _hook_progress(self, status): for ph in self._progress_hooks: From 4dc5286e1341adcd8c6b9876b06f8efbe6b9d89e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sun, 10 Aug 2014 10:45:27 +0200 Subject: [PATCH 0518/1761] [reverbnation] Make sure that the thumbnail url contain the protocol They are protocol relative. --- youtube_dl/extractor/reverbnation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/reverbnation.py b/youtube_dl/extractor/reverbnation.py index 49cf427a1..6435beb5c 100644 --- a/youtube_dl/extractor/reverbnation.py +++ b/youtube_dl/extractor/reverbnation.py @@ -17,7 +17,7 @@ class ReverbNationIE(InfoExtractor): "title": "MONA LISA", "uploader": "ALKILADOS", "uploader_id": 216429, - "thumbnail": "//gp1.wac.edgecastcdn.net/802892/production_public/Photo/13761700/image/1366002176_AVATAR_MONA_LISA.jpg" + "thumbnail": "re:^https://gp1\.wac\.edgecastcdn\.net/.*?\.jpg$" }, }] @@ -39,7 +39,8 @@ class ReverbNationIE(InfoExtractor): 'url': api_res.get('url'), 'uploader': api_res.get('artist', {}).get('name'), 'uploader_id': api_res.get('artist', {}).get('id'), - 'thumbnail': api_res.get('image', api_res.get('thumbnail')), + 'thumbnail': self._proto_relative_url( + api_res.get('image', api_res.get('thumbnail'))), 'ext': 'mp3', 'vcodec': 'none', } From 85a699246aa7554e2a88d5a93793dccb9a0b8d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sun, 10 Aug 2014 10:56:37 +0200 Subject: [PATCH 0519/1761] [reverbnation] Modernize test --- youtube_dl/extractor/reverbnation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/reverbnation.py b/youtube_dl/extractor/reverbnation.py index 6435beb5c..c77849336 100644 --- a/youtube_dl/extractor/reverbnation.py +++ b/youtube_dl/extractor/reverbnation.py @@ -11,9 +11,10 @@ class ReverbNationIE(InfoExtractor): _VALID_URL = r'^https?://(?:www\.)?reverbnation\.com/.*?/song/(?P\d+).*?$' _TESTS = [{ 'url': 'http://www.reverbnation.com/alkilados/song/16965047-mona-lisa', - 'file': '16965047.mp3', 'md5': '3da12ebca28c67c111a7f8b262d3f7a7', 'info_dict': { + "id": "16965047", + "ext": "mp3", "title": "MONA LISA", "uploader": "ALKILADOS", "uploader_id": 216429, From 511c4325dc8e3a60d81d3c23e8eb330b3a706883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sun, 10 Aug 2014 10:58:22 +0200 Subject: [PATCH 0520/1761] [reverbnation] Simplify json download We can directly get a json file instead of the jsonp. --- youtube_dl/extractor/reverbnation.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/youtube_dl/extractor/reverbnation.py b/youtube_dl/extractor/reverbnation.py index c77849336..b93adfca5 100644 --- a/youtube_dl/extractor/reverbnation.py +++ b/youtube_dl/extractor/reverbnation.py @@ -1,7 +1,6 @@ from __future__ import unicode_literals import re -import time from .common import InfoExtractor from ..utils import strip_jsonp @@ -27,10 +26,8 @@ class ReverbNationIE(InfoExtractor): song_id = mobj.group('id') api_res = self._download_json( - 'https://api.reverbnation.com/song/%s?callback=api_response_5&_=%d' - % (song_id, int(time.time() * 1000)), + 'https://api.reverbnation.com/song/%s' % song_id, song_id, - transform_source=strip_jsonp, note='Downloading information of song %s' % song_id ) From 40a90862f49f89bdfcd6feea5340538efc2b6a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sun, 10 Aug 2014 11:00:14 +0200 Subject: [PATCH 0521/1761] [reverbnation] The 'uploader_id' field must be a string --- youtube_dl/extractor/reverbnation.py | 6 +++--- youtube_dl/utils.py | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/youtube_dl/extractor/reverbnation.py b/youtube_dl/extractor/reverbnation.py index b93adfca5..ec7e7df7b 100644 --- a/youtube_dl/extractor/reverbnation.py +++ b/youtube_dl/extractor/reverbnation.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import re from .common import InfoExtractor -from ..utils import strip_jsonp +from ..utils import str_or_none class ReverbNationIE(InfoExtractor): @@ -16,7 +16,7 @@ class ReverbNationIE(InfoExtractor): "ext": "mp3", "title": "MONA LISA", "uploader": "ALKILADOS", - "uploader_id": 216429, + "uploader_id": "216429", "thumbnail": "re:^https://gp1\.wac\.edgecastcdn\.net/.*?\.jpg$" }, }] @@ -36,7 +36,7 @@ class ReverbNationIE(InfoExtractor): 'title': api_res.get('name'), 'url': api_res.get('url'), 'uploader': api_res.get('artist', {}).get('name'), - 'uploader_id': api_res.get('artist', {}).get('id'), + 'uploader_id': str_or_none(api_res.get('artist', {}).get('id')), 'thumbnail': self._proto_relative_url( api_res.get('image', api_res.get('thumbnail'))), 'ext': 'mp3', diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index e40b367c2..9b94407f4 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -1275,6 +1275,9 @@ def int_or_none(v, scale=1, default=None, get_attr=None, invscale=1): v = getattr(v, get_attr, None) return default if v is None else (int(v) * invscale // scale) +def str_or_none(v, default=None): + return default if v is None else compat_str(v) + def str_to_int(int_str): if int_str is None: From 173a7026d59bacfbfe7a8eea92e10ef6e89d1798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sun, 10 Aug 2014 11:08:56 +0200 Subject: [PATCH 0522/1761] [test/test_utils] Fix typo in method name --- test/test_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_utils.py b/test/test_utils.py index 51eb0b6b9..e26cc5b0c 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -280,7 +280,7 @@ class TestUtil(unittest.TestCase): d = json.loads(stripped) self.assertEqual(d, [{"id": "532cb", "x": 3}]) - def test_uppercase_escpae(self): + def test_uppercase_escape(self): self.assertEqual(uppercase_escape(u'aä'), u'aä') self.assertEqual(uppercase_escape(u'\\U0001d550'), u'𝕐') From a6da7b6b9657f621a927cb4c7bc46cf7c6c27b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sun, 10 Aug 2014 11:55:24 +0200 Subject: [PATCH 0523/1761] [facebook] Allow '?' before '#!' (fixes #3477) --- test/test_all_urls.py | 1 + youtube_dl/extractor/facebook.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_all_urls.py b/test/test_all_urls.py index 0ff47cf1e..b1ad30bf1 100644 --- a/test/test_all_urls.py +++ b/test/test_all_urls.py @@ -99,6 +99,7 @@ class TestAllURLsMatching(unittest.TestCase): def test_facebook_matching(self): self.assertTrue(FacebookIE.suitable('https://www.facebook.com/Shiniknoh#!/photo.php?v=10153317450565268')) + self.assertTrue(FacebookIE.suitable('https://www.facebook.com/cindyweather?fref=ts#!/photo.php?v=10152183998945793')) def test_no_duplicates(self): ies = gen_extractors() diff --git a/youtube_dl/extractor/facebook.py b/youtube_dl/extractor/facebook.py index f0cd8f156..f7cf700b5 100644 --- a/youtube_dl/extractor/facebook.py +++ b/youtube_dl/extractor/facebook.py @@ -20,7 +20,7 @@ from ..utils import ( class FacebookIE(InfoExtractor): _VALID_URL = r'''(?x) https?://(?:\w+\.)?facebook\.com/ - (?:[^#?]*\#!/)? + (?:[^#]*?\#!/)? (?:video/video\.php|photo\.php|video/embed)\?(?:.*?) (?:v|video_id)=(?P[0-9]+) (?:.*)''' From 3a5beb0ca149cd0b1df5b29984033e20ccb85a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 10 Aug 2014 17:53:17 +0700 Subject: [PATCH 0524/1761] [ard] Show error message for videos that are no longer available (#3422) --- youtube_dl/extractor/ard.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/youtube_dl/extractor/ard.py b/youtube_dl/extractor/ard.py index 957bdefcb..7f0da8ab6 100644 --- a/youtube_dl/extractor/ard.py +++ b/youtube_dl/extractor/ard.py @@ -51,6 +51,9 @@ class ARDIE(InfoExtractor): webpage = self._download_webpage(url, video_id) + if '>Der gewünschte Beitrag ist nicht mehr verfügbar.<' in webpage: + raise ExtractorError('Video %s is no longer available' % video_id, expected=True) + title = self._html_search_regex( [r'(.*?)', r'', From 9572013de9b994e2c20e972f13ce0a54cbd3f886 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 10 Aug 2014 13:04:45 +0200 Subject: [PATCH 0525/1761] [appletrailers] Support height-less videos --- youtube_dl/extractor/appletrailers.py | 5 +++-- youtube_dl/utils.py | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/appletrailers.py b/youtube_dl/extractor/appletrailers.py index dc8657b67..4359b88d1 100644 --- a/youtube_dl/extractor/appletrailers.py +++ b/youtube_dl/extractor/appletrailers.py @@ -6,6 +6,7 @@ import json from .common import InfoExtractor from ..utils import ( compat_urlparse, + int_or_none, ) @@ -110,8 +111,8 @@ class AppleTrailersIE(InfoExtractor): formats.append({ 'url': format_url, 'format': format['type'], - 'width': format['width'], - 'height': int(format['height']), + 'width': int_or_none(format['width']), + 'height': int_or_none(format['height']), }) self._sort_formats(formats) diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 9b94407f4..65b492fb3 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -1273,8 +1273,11 @@ def int_or_none(v, scale=1, default=None, get_attr=None, invscale=1): if get_attr: if v is not None: v = getattr(v, get_attr, None) + if v == '': + v = None return default if v is None else (int(v) * invscale // scale) + def str_or_none(v, default=None): return default if v is None else compat_str(v) From 90e075da3a15052c628c06d4d13ff66e88ff7765 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 10 Aug 2014 19:47:15 +0200 Subject: [PATCH 0526/1761] release 2014.08.10 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 08b5339f6..2ef0d59e3 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.08.05' +__version__ = '2014.08.10' From 6f600ff5d6bda54d8128e6263a468a08edfc3353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Tue, 12 Aug 2014 20:54:08 +0700 Subject: [PATCH 0527/1761] [ooyala] Try mobile player JS URLs for all available devices (Closes #3498) Looks like some videos are only available for particular devices (e.g. http://player.ooyala.com/player.js?embedCode=x1b3lqZDq9y_7kMyC2Op5qo-p077tXD0 is only available for ipad) Working around with fetching URLs for all the devices found starting with 'unknown' until we succeed or eventually fail for each device. --- youtube_dl/extractor/ooyala.py | 66 +++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/youtube_dl/extractor/ooyala.py b/youtube_dl/extractor/ooyala.py index 13f12824c..2044e107e 100644 --- a/youtube_dl/extractor/ooyala.py +++ b/youtube_dl/extractor/ooyala.py @@ -3,23 +3,38 @@ import re import json from .common import InfoExtractor -from ..utils import unescapeHTML +from ..utils import ( + unescapeHTML, + ExtractorError, +) class OoyalaIE(InfoExtractor): _VALID_URL = r'(?:ooyala:|https?://.+?\.ooyala\.com/.*?(?:embedCode|ec)=)(?P.+?)(&|$)' - _TEST = { - # From http://it.slashdot.org/story/13/04/25/178216/recovering-data-from-broken-hard-drives-and-ssds-video - 'url': 'http://player.ooyala.com/player.js?embedCode=pxczE2YjpfHfn1f3M-ykG_AmJRRn0PD8', - 'md5': '3f5cceb3a7bf461d6c29dc466cf8033c', - 'info_dict': { - 'id': 'pxczE2YjpfHfn1f3M-ykG_AmJRRn0PD8', - 'ext': 'mp4', - 'title': 'Explaining Data Recovery from Hard Drives and SSDs', - 'description': 'How badly damaged does a drive have to be to defeat Russell and his crew? Apparently, smashed to bits.', + _TESTS = [ + { + # From http://it.slashdot.org/story/13/04/25/178216/recovering-data-from-broken-hard-drives-and-ssds-video + 'url': 'http://player.ooyala.com/player.js?embedCode=pxczE2YjpfHfn1f3M-ykG_AmJRRn0PD8', + 'md5': '3f5cceb3a7bf461d6c29dc466cf8033c', + 'info_dict': { + 'id': 'pxczE2YjpfHfn1f3M-ykG_AmJRRn0PD8', + 'ext': 'mp4', + 'title': 'Explaining Data Recovery from Hard Drives and SSDs', + 'description': 'How badly damaged does a drive have to be to defeat Russell and his crew? Apparently, smashed to bits.', + }, + }, { + # Only available for ipad + 'url': 'http://player.ooyala.com/player.js?embedCode=x1b3lqZDq9y_7kMyC2Op5qo-p077tXD0', + 'md5': '4b9754921fddb68106e48c142e2a01e6', + 'info_dict': { + 'id': 'x1b3lqZDq9y_7kMyC2Op5qo-p077tXD0', + 'ext': 'mp4', + 'title': 'Simulation Overview - Levels of Simulation', + 'description': '', + }, }, - } + ] @staticmethod def _url_for_embed_code(embed_code): @@ -47,13 +62,30 @@ class OoyalaIE(InfoExtractor): player = self._download_webpage(player_url, embedCode) mobile_url = self._search_regex(r'mobile_player_url="(.+?)&device="', player, 'mobile player url') - mobile_player = self._download_webpage(mobile_url, embedCode) - videos_info = self._search_regex( - r'var streams=window.oo_testEnv\?\[\]:eval\("\((\[{.*?}\])\)"\);', - mobile_player, 'info').replace('\\"','"') - videos_more_info = self._search_regex(r'eval\("\(({.*?\\"promo\\".*?})\)"', mobile_player, 'more info').replace('\\"','"') + # Looks like some videos are only available for particular devices + # (e.g. http://player.ooyala.com/player.js?embedCode=x1b3lqZDq9y_7kMyC2Op5qo-p077tXD0 + # is only available for ipad) + # Working around with fetching URLs for all the devices found starting with 'unknown' + # until we succeed or eventually fail for each device. + devices = re.findall(r'device\s*=\s*"([^"]+)";', player) + devices.remove('unknown') + devices.insert(0, 'unknown') + for device in devices: + mobile_player = self._download_webpage( + '%s&device=%s' % (mobile_url, device), embedCode, + 'Downloading mobile player JS for %s device' % device) + videos_info = self._search_regex( + r'var streams=window.oo_testEnv\?\[\]:eval\("\((\[{.*?}\])\)"\);', + mobile_player, 'info', fatal=False, default=None) + if videos_info: + break + if not videos_info: + raise ExtractorError('Unable to extract info') + videos_info = videos_info.replace('\\"', '"') + videos_more_info = self._search_regex( + r'eval\("\(({.*?\\"promo\\".*?})\)"', mobile_player, 'more info').replace('\\"', '"') videos_info = json.loads(videos_info) - videos_more_info =json.loads(videos_more_info) + videos_more_info = json.loads(videos_more_info) if videos_more_info.get('lineup'): videos = [self._extract_result(info, more_info) for (info, more_info) in zip(videos_info, videos_more_info['lineup'])] From 3cfafc4a9bb7e2fe290ab03f12e9a4fc2af7a404 Mon Sep 17 00:00:00 2001 From: Alexander Kirk Date: Wed, 13 Aug 2014 12:14:44 +0200 Subject: [PATCH 0528/1761] [ellentv] Add new extractor --- youtube_dl/extractor/__init__.py | 4 ++ youtube_dl/extractor/ellentv.py | 79 ++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 youtube_dl/extractor/ellentv.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 2ea2c73d2..381a5d999 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -77,6 +77,10 @@ from .ebaumsworld import EbaumsWorldIE from .ehow import EHowIE from .eighttracks import EightTracksIE from .eitb import EitbIE +from .ellentv import ( + EllenTVIE, + EllenTVClipsIE, +) from .elpais import ElPaisIE from .empflix import EmpflixIE from .engadget import EngadgetIE diff --git a/youtube_dl/extractor/ellentv.py b/youtube_dl/extractor/ellentv.py new file mode 100644 index 000000000..933f36dd8 --- /dev/null +++ b/youtube_dl/extractor/ellentv.py @@ -0,0 +1,79 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re +import json + +from .common import InfoExtractor, ExtractorError + +class EllenTVIE(InfoExtractor): + IE_NAME = u'ellentv' + _VALID_URL = r'https?://(?:www\.)?ellentv\.com/videos/(?P[a-z0-9_-]+)' + _TEST = { + 'url': 'http://www.ellentv.com/videos/0-7jqrsr18/', + 'md5': 'e4af06f3bf0d5f471921a18db5764642', + 'info_dict': { + 'id': '0-7jqrsr18', + 'ext': 'mp4', + 'title': u'What\'s Wrong with These Photos? A Whole Lot', + # TODO more properties, either as: + # * A value + # * MD5 checksum; start the string with md5: + # * A regular expression; start the string with re: + # * Any Python type (for example int or float) + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + id = mobj.group('id') + + webpage = self._download_webpage(url, id) + + return { + 'id': id, + 'title': self._og_search_title(webpage), + 'url': self._html_search_meta('VideoURL', webpage, 'url') + } + +class EllenTVClipsIE(InfoExtractor): + IE_NAME = u'ellentv:clips' + _VALID_URL = r'https?://(?:www\.)?ellentv\.com/episodes/(?P[a-z0-9_-]+)' + _TEST = { + 'url': 'http://www.ellentv.com/episodes/meryl-streep-vanessa-hudgens/', + 'md5': 'TODO: md5 sum of the first 10KiB of the video file', + 'info_dict': { + 'id': '0_wf6pizq7', + 'ext': 'mp4', + 'title': 'Video title goes here', + # TODO more properties, either as: + # * A value + # * MD5 checksum; start the string with md5: + # * A regular expression; start the string with re: + # * Any Python type (for example int or float) + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + playlist_id = mobj.group('id') + + webpage = self._download_webpage(url, playlist_id) + playlist = self._extract_playlist(webpage) + + return { + '_type': 'playlist', + 'id': playlist_id, + 'title': self._og_search_title(webpage), + 'entries': self._extract_entries(playlist) + } + + def _extract_playlist(self, webpage): + json_string = self._search_regex(r'playerView.addClips\(\[\{(.*?)\}\]\);', webpage, 'json') + try: + return json.loads("[{" + json_string + "}]") + except ValueError as ve: + raise ExtractorError('Failed to download JSON', cause=ve) + + def _extract_entries(self, playlist): + return [self.url_result(item[u'url'], 'EllenTV') for item in playlist] From 325826337154b5f7c3df97950b484f370b0c3d81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Wed, 13 Aug 2014 18:24:46 +0700 Subject: [PATCH 0529/1761] [shared] Update test --- youtube_dl/extractor/shared.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/shared.py b/youtube_dl/extractor/shared.py index 8607482be..badba2ac6 100644 --- a/youtube_dl/extractor/shared.py +++ b/youtube_dl/extractor/shared.py @@ -17,11 +17,11 @@ class SharedIE(InfoExtractor): _TEST = { 'url': 'http://shared.sx/0060718775', - 'md5': '53e1c58fc3e777ae1dfe9e57ba2f9c72', + 'md5': '106fefed92a8a2adb8c98e6a0652f49b', 'info_dict': { 'id': '0060718775', 'ext': 'mp4', - 'title': 'Big Buck Bunny Trailer', + 'title': 'Bmp4', }, } From 664718ff63bd8c61380486ce8f1dc96651bbd2e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Thu, 14 Aug 2014 20:17:31 +0700 Subject: [PATCH 0530/1761] [livestream] Improve extraction (Closes #3513) --- youtube_dl/extractor/livestream.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/youtube_dl/extractor/livestream.py b/youtube_dl/extractor/livestream.py index c0c2d9b09..281a0ce40 100644 --- a/youtube_dl/extractor/livestream.py +++ b/youtube_dl/extractor/livestream.py @@ -111,17 +111,28 @@ class LivestreamIE(InfoExtractor): event_name = mobj.group('event_name') webpage = self._download_webpage(url, video_id or event_name) - if video_id is None: - # This is an event page: + og_video = self._og_search_video_url(webpage, 'player url', fatal=False, default=None) + if og_video is None: config_json = self._search_regex( r'window.config = ({.*?});', webpage, 'window config') info = json.loads(config_json)['event'] + + def is_relevant(vdata, vid): + result = vdata['type'] == 'video' + if video_id is not None: + result = result and compat_str(vdata['data']['id']) == vid + return result + videos = [self._extract_video_info(video_data['data']) - for video_data in info['feed']['data'] - if video_data['type'] == 'video'] - return self.playlist_result(videos, info['id'], info['full_name']) + for video_data in info['feed']['data'] + if is_relevant(video_data, video_id)] + if video_id is None: + # This is an event page: + return self.playlist_result(videos, info['id'], info['full_name']) + else: + if videos: + return videos[0] else: - og_video = self._og_search_video_url(webpage, 'player url') query_str = compat_urllib_parse_urlparse(og_video).query query = compat_urlparse.parse_qs(query_str) api_url = query['play_url'][0].replace('.smil', '') From df866e7f2a536e2675af2956b1cff61ea29e145f Mon Sep 17 00:00:00 2001 From: rubicks Date: Thu, 14 Aug 2014 11:01:23 -0400 Subject: [PATCH 0531/1761] envvar overrideable PREFIX, BINDIR, MANDIR, PYTHON --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index c079761ef..088a9320b 100644 --- a/Makefile +++ b/Makefile @@ -6,10 +6,10 @@ clean: cleanall: clean rm -f youtube-dl youtube-dl.exe -PREFIX=/usr/local -BINDIR=$(PREFIX)/bin -MANDIR=$(PREFIX)/man -PYTHON=/usr/bin/env python +PREFIX ?= /usr/local +BINDIR ?= $(PREFIX)/bin +MANDIR ?= $(PREFIX)/man +PYTHON ?= /usr/bin/env python # set SYSCONFDIR to /etc if PREFIX=/usr or PREFIX=/usr/local ifeq ($(PREFIX),/usr) From c990bb36338c422d4da9f092384da1dfbb528d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Fri, 15 Aug 2014 21:38:41 +0700 Subject: [PATCH 0532/1761] [howstuffworks] Add extractor (#3500) Content-length is invalid for final download links. --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/howstuffworks.py | 134 ++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 youtube_dl/extractor/howstuffworks.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 2ea2c73d2..27602e0c0 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -126,6 +126,7 @@ from .helsinki import HelsinkiIE from .hentaistigma import HentaiStigmaIE from .hotnewhiphop import HotNewHipHopIE from .howcast import HowcastIE +from .howstuffworks import HowStuffWorksIE from .huffpost import HuffPostIE from .hypem import HypemIE from .iconosquare import IconosquareIE diff --git a/youtube_dl/extractor/howstuffworks.py b/youtube_dl/extractor/howstuffworks.py new file mode 100644 index 000000000..68684b997 --- /dev/null +++ b/youtube_dl/extractor/howstuffworks.py @@ -0,0 +1,134 @@ +from __future__ import unicode_literals + +import re +import json +import random +import string + +from .common import InfoExtractor +from ..utils import find_xpath_attr + + +class HowStuffWorksIE(InfoExtractor): + _VALID_URL = r'https?://[\da-z-]+\.howstuffworks\.com/(?:[^/]+/)*\d+-(?P.+?)-video\.htm' + _TESTS = [ + { + 'url': 'http://adventure.howstuffworks.com/5266-cool-jobs-iditarod-musher-video.htm', + 'info_dict': { + 'id': '450221', + 'display_id': 'cool-jobs-iditarod-musher', + 'ext': 'flv', + 'title': 'Cool Jobs - Iditarod Musher', + 'description': 'md5:82bb58438a88027b8186a1fccb365f90', + 'thumbnail': 're:^https?://.*\.jpg$', + }, + 'params': { + # md5 is not consistent + 'skip_download': True + } + }, + { + 'url': 'http://adventure.howstuffworks.com/39516-deadliest-catch-jakes-farewell-pots-video.htm', + 'info_dict': { + 'id': '553470', + 'display_id': 'deadliest-catch-jakes-farewell-pots', + 'ext': 'mp4', + 'title': 'Deadliest Catch: Jake\'s Farewell Pots', + 'description': 'md5:9632c346d5e43ee238028c9cefd8dbbc', + 'thumbnail': 're:^https?://.*\.jpg$', + }, + 'params': { + # md5 is not consistent + 'skip_download': True + } + }, + { + 'url': 'http://entertainment.howstuffworks.com/arts/2706-sword-swallowing-1-by-dan-meyer-video.htm', + 'info_dict': { + 'id': '440011', + 'display_id': 'sword-swallowing-1-by-dan-meyer', + 'ext': 'flv', + 'title': 'Sword Swallowing #1 by Dan Meyer', + 'description': 'md5:b2409e88172913e2e7d3d1159b0ef735', + 'thumbnail': 're:^https?://.*\.jpg$', + }, + 'params': { + # md5 is not consistent + 'skip_download': True + } + }, + ] + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + display_id = mobj.group('id') + webpage = self._download_webpage(url, display_id) + + content_id = self._search_regex(r'var siteSectionId="(\d+)";', webpage, 'content id') + + mp4 = self._search_regex( + r'''(?xs)var\s+clip\s*=\s*{\s* + .+?\s* + content_id\s*:\s*%s\s*,\s* + .+?\s* + mp4\s*:\s*\[(.*?),?\]\s* + };\s* + videoData\.push\(clip\);''' % content_id, + webpage, 'mp4', fatal=False, default=None) + + smil = self._download_xml( + 'http://services.media.howstuffworks.com/videos/%s/smil-service.smil' % content_id, + content_id, 'Downloading video SMIL') + + http_base = find_xpath_attr( + smil, + './{0}head/{0}meta'.format('{http://www.w3.org/2001/SMIL20/Language}'), + 'name', + 'httpBase').get('content') + + def random_string(str_len=0): + return ''.join([random.choice(string.ascii_uppercase) for _ in range(str_len)]) + + URL_SUFFIX = '?v=2.11.3&fp=LNX 11,2,202,356&r=%s&g=%s' % (random_string(5), random_string(12)) + + formats = [] + + if mp4: + for video in json.loads('[%s]' % mp4): + bitrate = video['bitrate'] + fmt = { + 'url': video['src'].replace('http://pmd.video.howstuffworks.com', http_base) + URL_SUFFIX, + 'format_id': bitrate, + } + m = re.search(r'(?P\d+)[Kk]', bitrate) + if m: + fmt['vbr'] = int(m.group('vbr')) + formats.append(fmt) + else: + for video in smil.findall( + './/{0}body/{0}switch/{0}video'.format('{http://www.w3.org/2001/SMIL20/Language}')): + vbr = int(video.attrib['system-bitrate']) / 1000 + formats.append({ + 'url': '%s/%s%s' % (http_base, video.attrib['src'], URL_SUFFIX), + 'format_id': '%dk' % vbr, + 'vbr': vbr, + }) + + self._sort_formats(formats) + + title = self._og_search_title(webpage) + TITLE_SUFFIX = ' : HowStuffWorks' + if title.endswith(TITLE_SUFFIX): + title = title[:-len(TITLE_SUFFIX)] + + description = self._og_search_description(webpage) + thumbnail = self._og_search_thumbnail(webpage) + + return { + 'id': content_id, + 'display_id': display_id, + 'title': title, + 'description': description, + 'thumbnail': thumbnail, + 'formats': formats, + } From 49807b4ac6aab2db702afbde20215641210e0413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sat, 16 Aug 2014 13:56:22 +0700 Subject: [PATCH 0533/1761] [yahoo] Add support for embedded videos (Closes #3525) --- youtube_dl/extractor/generic.py | 7 +++++++ youtube_dl/extractor/yahoo.py | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index bcb076594..8e915735e 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -706,6 +706,13 @@ class GenericIE(InfoExtractor): url = unescapeHTML(mobj.group('url')) return self.url_result(url, ie='MTVServicesEmbedded') + # Look for embedded yahoo player + mobj = re.search( + r']+?src=(["\'])(?Phttps?://(?:screen|movies)\.yahoo\.com/.+?\.html\?format=embed)\1', + webpage) + if mobj is not None: + return self.url_result(mobj.group('url'), 'Yahoo') + # Start with something easy: JW Player in SWFObject found = re.findall(r'flashvars: [\'"](?:.*&)?file=(http[^\'"&]*)', webpage) if not found: diff --git a/youtube_dl/extractor/yahoo.py b/youtube_dl/extractor/yahoo.py index d84be2562..0e3b33b16 100644 --- a/youtube_dl/extractor/yahoo.py +++ b/youtube_dl/extractor/yahoo.py @@ -15,7 +15,7 @@ from ..utils import ( class YahooIE(InfoExtractor): IE_DESC = 'Yahoo screen and movies' - _VALID_URL = r'https?://(?:screen|movies)\.yahoo\.com/.*?-(?P[0-9]+)(?:-[a-z]+)?\.html' + _VALID_URL = r'(?Phttps?://(?:screen|movies)\.yahoo\.com/.*?-(?P[0-9]+)(?:-[a-z]+)?\.html)' _TESTS = [ { 'url': 'http://screen.yahoo.com/julian-smith-travis-legg-watch-214727115.html', @@ -46,12 +46,23 @@ class YahooIE(InfoExtractor): 'title': 'The World Loves Spider-Man', 'description': '''People all over the world are celebrating the release of \"The Amazing Spider-Man 2.\" We're taking a look at the enthusiastic response Spider-Man has received from viewers all over the world.''', } - } + }, + { + 'url': 'https://screen.yahoo.com/community/community-sizzle-reel-203225340.html?format=embed', + 'md5': '60e8ac193d8fb71997caa8fce54c6460', + 'info_dict': { + 'id': '4fe78544-8d48-39d8-97cd-13f205d9fcdb', + 'ext': 'mp4', + 'title': "Yahoo Saves 'Community'", + 'description': 'md5:4d4145af2fd3de00cbb6c1d664105053', + } + }, ] def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('id') + url = mobj.group('url') webpage = self._download_webpage(url, video_id) items_json = self._search_regex( From c1d293cfa68031e0ec1a4190041f280d22c2b026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 17 Aug 2014 02:07:04 +0700 Subject: [PATCH 0534/1761] [dfb] Fix f4m manifest URL --- youtube_dl/extractor/dfb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/dfb.py b/youtube_dl/extractor/dfb.py index cb8e06822..8049779b0 100644 --- a/youtube_dl/extractor/dfb.py +++ b/youtube_dl/extractor/dfb.py @@ -30,7 +30,7 @@ class DFBIE(InfoExtractor): video_id) video_info = player_info.find('video') - f4m_info = self._download_xml(video_info.find('url').text, video_id) + f4m_info = self._download_xml(self._proto_relative_url(video_info.find('url').text.strip()), video_id) token_el = f4m_info.find('token') manifest_url = token_el.attrib['url'] + '?' + 'hdnea=' + token_el.attrib['auth'] + '&hdcore=3.2.0' From 83317f693870424c2c769e4d964453401063fdf1 Mon Sep 17 00:00:00 2001 From: riking Date: Sat, 16 Aug 2014 14:28:41 -0700 Subject: [PATCH 0535/1761] [youtube] Add two-factor account signin (TOTP only) Additional work is required to prompt the user for the SMS or phone call codes, as there is no framework currently to prompt the user during an extraction operation. Fixes #3533 --- youtube_dl/__init__.py | 3 ++ youtube_dl/extractor/common.py | 18 ++++++++ youtube_dl/extractor/youtube.py | 74 ++++++++++++++++++++++++++++++++- 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 962aedbff..80de211e7 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -314,6 +314,8 @@ def parseOpts(overrideArguments=None): dest='username', metavar='USERNAME', help='account username') authentication.add_option('-p', '--password', dest='password', metavar='PASSWORD', help='account password') + authentication.add_option('-2', '--twofactor', + dest='twofactor', metavar='TWOFACTOR', help='two-factor auth code') authentication.add_option('-n', '--netrc', action='store_true', dest='usenetrc', help='use .netrc authentication data', default=False) authentication.add_option('--video-password', @@ -748,6 +750,7 @@ def _real_main(argv=None): 'usenetrc': opts.usenetrc, 'username': opts.username, 'password': opts.password, + 'twofactor': opts.twofactor, 'videopassword': opts.videopassword, 'quiet': (opts.quiet or any_printing), 'no_warnings': opts.no_warnings, diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 342bfb8b3..9f6a8a889 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -434,6 +434,24 @@ class InfoExtractor(object): return (username, password) + def _get_tfa_info(self): + """ + Get the two-factor authentication info + TODO - asking the user will be required for sms/phone verify + currently just uses the command line option + If there's no info available, return None + """ + if self._downloader is None: + self.to_screen("no downloader") + return None + downloader_params = self._downloader.params + + if downloader_params.get('twofactor', None) is not None: + return downloader_params['twofactor'] + + self.to_screen("param is None") + return None + # Helper functions for extracting OpenGraph info @staticmethod def _og_regexes(prop): diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index 3c9b0b584..5bfe5e7e5 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -37,6 +37,7 @@ from ..utils import ( class YoutubeBaseInfoExtractor(InfoExtractor): """Provide base functions for Youtube extractors""" _LOGIN_URL = 'https://accounts.google.com/ServiceLogin' + _TWOFACTOR_URL = 'https://accounts.google.com/SecondFactor' _LANG_URL = r'https://www.youtube.com/?hl=en&persist_hl=1&gl=US&persist_gl=1&opt_out_ackd=1' _AGE_URL = 'https://www.youtube.com/verify_age?next_url=/&gl=US&hl=en' _NETRC_MACHINE = 'youtube' @@ -50,12 +51,19 @@ class YoutubeBaseInfoExtractor(InfoExtractor): fatal=False)) def _login(self): + """ + Attempt to log in to YouTube. + True is returned if successful or skipped. + False is returned if login failed. + + If _LOGIN_REQUIRED is set and no authentication was provided, an error is raised. + """ (username, password) = self._get_login_info() # No authentication to be performed if username is None: if self._LOGIN_REQUIRED: raise ExtractorError(u'No login info available, needed for using %s.' % self.IE_NAME, expected=True) - return False + return True login_page = self._download_webpage( self._LOGIN_URL, None, @@ -73,6 +81,7 @@ class YoutubeBaseInfoExtractor(InfoExtractor): u'Email': username, u'GALX': galx, u'Passwd': password, + u'PersistentCookie': u'yes', u'_utf8': u'霱', u'bgresponse': u'js_disabled', @@ -88,6 +97,7 @@ class YoutubeBaseInfoExtractor(InfoExtractor): u'uilel': u'3', u'hl': u'en_US', } + # Convert to UTF-8 *before* urlencode because Python 2.x's urlencode # chokes on unicode login_form = dict((k.encode('utf-8'), v.encode('utf-8')) for k,v in login_form_strs.items()) @@ -99,6 +109,68 @@ class YoutubeBaseInfoExtractor(InfoExtractor): note=u'Logging in', errnote=u'unable to log in', fatal=False) if login_results is False: return False + + if re.search(r'id="errormsg_0_Passwd"', login_results) is not None: + raise ExtractorError(u'Please use your account password and a two-factor code instead of an application-specific password.', expected=True) + + # Two-Factor + # TODO add SMS and phone call support - these require making a request and then prompting the user + + if re.search(r'(?i)]* id="gaia_secondfactorform"', login_results) is not None: + tfa_code = self._get_tfa_info() + + if tfa_code is None: + self._downloader.report_warning(u'Two-factor authentication required. Provide it with --twofactor ') + self._downloader.report_warning(u'(Note that only TOTP (Google Authenticator App) codes work at this time.)') + return False + + # Unlike the first login form, secTok and timeStmp are both required for the TFA form + + match = re.search(r'id="secTok"\n\s+value=\'(.+)\'/>', login_results, re.M | re.U) + if match is None: + self._downloader.report_warning(u'Failed to get secTok - did the page structure change?') + secTok = match.group(1) + match = re.search(r'id="timeStmp"\n\s+value=\'(.+)\'/>', login_results, re.M | re.U) + if match is None: + self._downloader.report_warning(u'Failed to get timeStmp - did the page structure change?') + timeStmp = match.group(1) + + tfa_form_strs = { + u'continue': u'https://www.youtube.com/signin?action_handle_signin=true&feature=sign_in_button&hl=en_US&nomobiletemp=1', + u'smsToken': u'', + u'smsUserPin': tfa_code, + u'smsVerifyPin': u'Verify', + + u'PersistentCookie': u'yes', + u'checkConnection': u'', + u'checkedDomains': u'youtube', + u'pstMsg': u'1', + u'secTok': secTok, + u'timeStmp': timeStmp, + u'service': u'youtube', + u'hl': u'en_US', + } + tfa_form = dict((k.encode('utf-8'), v.encode('utf-8')) for k,v in tfa_form_strs.items()) + tfa_data = compat_urllib_parse.urlencode(tfa_form).encode('ascii') + + tfa_req = compat_urllib_request.Request(self._TWOFACTOR_URL, tfa_data) + tfa_results = self._download_webpage( + tfa_req, None, + note=u'Submitting TFA code', errnote=u'unable to submit tfa', fatal=False) + + if tfa_results is False: + return False + + if re.search(r'(?i)]* id="gaia_secondfactorform"', tfa_results) is not None: + self._downloader.report_warning(u'Two-factor code expired. Please try again, or use a one-use backup code instead.') + return False + if re.search(r'(?i)]* id="gaia_loginform"', tfa_results) is not None: + self._downloader.report_warning(u'unable to log in - did the page structure change?') + return False + if re.search(r'smsauth-interstitial-reviewsettings', tfa_results) is not None: + self._downloader.report_warning(u'Your Google account has a security notice. Please log in on your web browser, resolve the notice, and try again.') + return False + if re.search(r'(?i)]* id="gaia_loginform"', login_results) is not None: self._downloader.report_warning(u'unable to log in: bad username or password') return False From 165250ff5e33d1b246dffaade23b31b4fa3f3b02 Mon Sep 17 00:00:00 2001 From: riking Date: Sat, 16 Aug 2014 14:49:30 -0700 Subject: [PATCH 0536/1761] Remove debug prints --- youtube_dl/extractor/common.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 9f6a8a889..45a17f8ad 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -442,14 +442,12 @@ class InfoExtractor(object): If there's no info available, return None """ if self._downloader is None: - self.to_screen("no downloader") return None downloader_params = self._downloader.params if downloader_params.get('twofactor', None) is not None: return downloader_params['twofactor'] - self.to_screen("param is None") return None # Helper functions for extracting OpenGraph info From 4d9bd478f9d846291c722da002266504fce824ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Mon, 18 Aug 2014 19:20:53 +0700 Subject: [PATCH 0537/1761] [pbs] Extract coveplayerid (Closes #3522) --- youtube_dl/extractor/pbs.py | 42 +++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/youtube_dl/extractor/pbs.py b/youtube_dl/extractor/pbs.py index ec95d0704..09bee6561 100644 --- a/youtube_dl/extractor/pbs.py +++ b/youtube_dl/extractor/pbs.py @@ -20,17 +20,30 @@ class PBSIE(InfoExtractor): ) ''' - _TEST = { - 'url': 'http://www.pbs.org/tpt/constitution-usa-peter-sagal/watch/a-more-perfect-union/', - 'md5': 'ce1888486f0908d555a8093cac9a7362', - 'info_dict': { - 'id': '2365006249', - 'ext': 'mp4', - 'title': 'A More Perfect Union', - 'description': 'md5:ba0c207295339c8d6eced00b7c363c6a', - 'duration': 3190, + _TESTS = [ + { + 'url': 'http://www.pbs.org/tpt/constitution-usa-peter-sagal/watch/a-more-perfect-union/', + 'md5': 'ce1888486f0908d555a8093cac9a7362', + 'info_dict': { + 'id': '2365006249', + 'ext': 'mp4', + 'title': 'A More Perfect Union', + 'description': 'md5:ba0c207295339c8d6eced00b7c363c6a', + 'duration': 3190, + }, }, - } + { + 'url': 'http://www.pbs.org/newshour/bb/education-jan-june12-cyberschools_02-23/', + 'md5': 'b19856d7f5351b17a5ab1dc6a64be633', + 'info_dict': { + 'id': '2201174722', + 'ext': 'mp4', + 'title': 'Cyber Schools Gain Popularity, but Quality Questions Persist', + 'description': 'md5:5871c15cba347c1b3d28ac47a73c7c28', + 'duration': 801, + }, + }, + ] def _extract_ids(self, url): mobj = re.match(self._VALID_URL, url) @@ -40,10 +53,13 @@ class PBSIE(InfoExtractor): if presumptive_id: webpage = self._download_webpage(url, display_id) - # frontline video embed + MEDIA_ID_REGEXES = [ + r"div\s*:\s*'videoembed'\s*,\s*mediaid\s*:\s*'(\d+)'", # frontline video embed + r'class="coveplayerid">([^<]+)<', # coveplayer + ] + media_id = self._search_regex( - r"div\s*:\s*'videoembed'\s*,\s*mediaid\s*:\s*'(\d+)'", - webpage, 'frontline video ID', fatal=False, default=None) + MEDIA_ID_REGEXES, webpage, 'media ID', fatal=False, default=None) if media_id: return media_id, presumptive_id From cd6b48365e29400044b8852226bed41490ef6e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Mon, 18 Aug 2014 19:24:18 +0700 Subject: [PATCH 0538/1761] [pbs] Add frontline video test --- youtube_dl/extractor/pbs.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/youtube_dl/extractor/pbs.py b/youtube_dl/extractor/pbs.py index 09bee6561..dee4af6f1 100644 --- a/youtube_dl/extractor/pbs.py +++ b/youtube_dl/extractor/pbs.py @@ -32,6 +32,17 @@ class PBSIE(InfoExtractor): 'duration': 3190, }, }, + { + 'url': 'http://www.pbs.org/wgbh/pages/frontline/losing-iraq/', + 'md5': '143c98aa54a346738a3d78f54c925321', + 'info_dict': { + 'id': '2365297690', + 'ext': 'mp4', + 'title': 'Losing Iraq', + 'description': 'md5:f5bfbefadf421e8bb8647602011caf8e', + 'duration': 5050, + }, + }, { 'url': 'http://www.pbs.org/newshour/bb/education-jan-june12-cyberschools_02-23/', 'md5': 'b19856d7f5351b17a5ab1dc6a64be633', From 6493f5d7045c90b2a6820b2cda58553d3a2fce8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Mon, 18 Aug 2014 15:39:35 +0200 Subject: [PATCH 0539/1761] [rtlnl] Add extractor for rtlxl.nl (closes #3523) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/rtlnl.py | 52 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 youtube_dl/extractor/rtlnl.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 27602e0c0..d6056ce8d 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -252,6 +252,7 @@ from .ro220 import Ro220IE from .rottentomatoes import RottenTomatoesIE from .roxwel import RoxwelIE from .rtbf import RTBFIE +from .rtlnl import RtlXlIE from .rtlnow import RTLnowIE from .rts import RTSIE from .rtve import RTVEALaCartaIE diff --git a/youtube_dl/extractor/rtlnl.py b/youtube_dl/extractor/rtlnl.py new file mode 100644 index 000000000..14928cd62 --- /dev/null +++ b/youtube_dl/extractor/rtlnl.py @@ -0,0 +1,52 @@ +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor + + +class RtlXlIE(InfoExtractor): + IE_NAME = 'rtlxl.nl' + _VALID_URL = r'https?://www\.rtlxl\.nl/#!/[^/]+/(?P[^/?]+)' + + _TEST = { + 'url': 'http://www.rtlxl.nl/#!/rtl-nieuws-132237/6e4203a6-0a5e-3596-8424-c599a59e0677', + 'info_dict': { + 'id': '6e4203a6-0a5e-3596-8424-c599a59e0677', + 'ext': 'flv', + 'title': 'RTL Nieuws - Laat', + 'description': 'Dagelijks het laatste nieuws uit binnen- en ' + 'buitenland. Voor nog meer nieuws kunt u ook gebruikmaken van ' + 'onze mobiele apps.', + 'timestamp': 1408051800, + 'upload_date': '20140814', + }, + 'params': { + # We download the first bytes of the first fragment, it can't be + # processed by the f4m downloader beacuse it isn't complete + 'skip_download': True, + }, + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + uuid = mobj.group('uuid') + + info = self._download_json( + 'http://www.rtl.nl/system/s4m/vfd/version=2/uuid=%s/fmt=flash/' % uuid, + uuid) + meta = info['meta'] + material = info['material'][0] + episode_info = info['episodes'][0] + + f4m_url = 'http://manifest.us.rtl.nl' + material['videopath'] + progname = info['abstracts'][0]['name'] + subtitle = material['title'] or info['episodes'][0]['name'] + + return { + 'id': uuid, + 'title': '%s - %s' % (progname, subtitle), + 'formats': self._extract_f4m_formats(f4m_url, uuid), + 'timestamp': material['original_date'], + 'description': episode_info['synopsis'], + } From 938dd254e557612b8a6e1f0a2dd1689fca30b9ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Mon, 18 Aug 2014 22:43:35 +0200 Subject: [PATCH 0540/1761] [mitele] Add extractor for mitele.es --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/mitele.py | 60 ++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 youtube_dl/extractor/mitele.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index d6056ce8d..6780f7f99 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -178,6 +178,7 @@ from .mdr import MDRIE from .metacafe import MetacafeIE from .metacritic import MetacriticIE from .mit import TechTVMITIE, MITIE, OCWMITIE +from .mitele import MiTeleIE from .mixcloud import MixcloudIE from .mlb import MLBIE from .mpora import MporaIE diff --git a/youtube_dl/extractor/mitele.py b/youtube_dl/extractor/mitele.py new file mode 100644 index 000000000..979f3d692 --- /dev/null +++ b/youtube_dl/extractor/mitele.py @@ -0,0 +1,60 @@ +from __future__ import unicode_literals + +import re +import json + +from .common import InfoExtractor +from ..utils import ( + compat_urllib_parse, + get_element_by_attribute, + parse_duration, + strip_jsonp, +) + + +class MiTeleIE(InfoExtractor): + IE_NAME = 'mitele.es' + _VALID_URL = r'http://www\.mitele\.es/[^/]+/[^/]+/[^/]+/(?P[^/]+)/' + + _TEST = { + 'url': 'http://www.mitele.es/programas-tv/diario-de/la-redaccion/programa-144/', + 'md5': '6a75fe9d0d3275bead0cb683c616fddb', + 'info_dict': { + 'id': '0fce117d', + 'ext': 'mp4', + 'title': 'Programa 144 - Tor, la web invisible', + 'description': 'md5:3b6fce7eaa41b2d97358726378d9369f', + 'display_id': 'programa-144', + 'duration': 2913, + }, + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + episode = mobj.group('episode') + webpage = self._download_webpage(url, episode) + embed_data_json = self._search_regex( + r'MSV\.embedData\[.*?\]\s*=\s*({.*?});', webpage, 'embed data', + flags=re.DOTALL + ).replace('\'', '"') + embed_data = json.loads(embed_data_json) + + info_url = embed_data['flashvars']['host'] + info_el = self._download_xml(info_url, episode).find('./video/info') + + video_link = info_el.find('videoUrl/link').text + token_query = compat_urllib_parse.urlencode({'id': video_link}) + token_info = self._download_json( + 'http://token.mitele.es/?' + token_query, episode, + transform_source=strip_jsonp + ) + + return { + 'id': embed_data['videoId'], + 'display_id': episode, + 'title': info_el.find('title').text, + 'url': token_info['tokenizedUrl'], + 'description': get_element_by_attribute('class', 'text', webpage), + 'thumbnail': info_el.find('thumb').text, + 'duration': parse_duration(info_el.find('duration').text), + } From fe556f1b0cfd5782ec379a731f4b8879f2a352a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Tue, 19 Aug 2014 20:02:08 +0700 Subject: [PATCH 0541/1761] [jove] Simplify, extract full description and add test for video that requires subscription --- youtube_dl/extractor/jove.py | 76 ++++++++++++++++++++++-------------- youtube_dl/utils.py | 1 + 2 files changed, 47 insertions(+), 30 deletions(-) diff --git a/youtube_dl/extractor/jove.py b/youtube_dl/extractor/jove.py index a7110b683..cf73cd753 100644 --- a/youtube_dl/extractor/jove.py +++ b/youtube_dl/extractor/jove.py @@ -1,64 +1,80 @@ -# coding: utf-8 from __future__ import unicode_literals import re -from datetime import datetime from .common import InfoExtractor -from ..utils import determine_ext, ExtractorError +from ..utils import ( + ExtractorError, + unified_strdate +) class JoveIE(InfoExtractor): _VALID_URL = r'https?://(?:www\.)?jove\.com/video/(?P[0-9]+)' _CHAPTERS_URL = 'http://www.jove.com/video-chapters?videoid={video_id:}' - _TEST = { - 'url': 'http://www.jove.com/video/2744/electrode-positioning-montage-transcranial-direct-current', - 'md5': '93723888d82dbd6ba8b3d7d0cd65dd2b', - 'info_dict': { - 'id': '2744', - 'ext': 'mp4', - 'title': 'Electrode Positioning and Montage in Transcranial Direct Current Stimulation', - 'description': 'Transcranial direct current stimulation (tDCS) is an established technique to modulate cortical excitability1,2. It has been ...', - 'thumbnail': 're:^https?://.*\.png$', - 'upload_date': '20110523', - } - } + _TESTS = [ + { + 'url': 'http://www.jove.com/video/2744/electrode-positioning-montage-transcranial-direct-current', + 'md5': '93723888d82dbd6ba8b3d7d0cd65dd2b', + 'info_dict': { + 'id': '2744', + 'ext': 'mp4', + 'title': 'Electrode Positioning and Montage in Transcranial Direct Current Stimulation', + 'description': 'md5:015dd4509649c0908bc27f049e0262c6', + 'thumbnail': 're:^https?://.*\.png$', + 'upload_date': '20110523', + } + }, + { + 'url': 'http://www.jove.com/video/51796/culturing-caenorhabditis-elegans-axenic-liquid-media-creation', + 'md5': '914aeb356f416811d911996434811beb', + 'info_dict': { + 'id': '51796', + 'ext': 'mp4', + 'title': 'Culturing Caenorhabditis elegans in Axenic Liquid Media and Creation of Transgenic Worms by Microparticle Bombardment', + 'description': 'md5:35ff029261900583970c4023b70f1dc9', + 'thumbnail': 're:^https?://.*\.png$', + 'upload_date': '20140802', + } + }, + + ] def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('id') webpage = self._download_webpage(url, video_id) - title = self._html_search_meta('citation_title', webpage, 'title') - thumbnail = self._og_search_thumbnail(webpage) - description = self._html_search_meta( - 'description', webpage, 'description', fatal=False) - publish_date = self._html_search_meta( - 'citation_publication_date', webpage, 'publish date', fatal=False) - if publish_date: - publish_date = datetime.strptime(publish_date, - '%Y/%m/%d').strftime('%Y%m%d') - # Not the same as video_id. chapters_id = self._html_search_regex( r'/video-chapters\?videoid=([0-9]+)', webpage, 'chapters id') + chapters_xml = self._download_xml( self._CHAPTERS_URL.format(video_id=chapters_id), - video_id, note='Downloading chapter XML', - errnote='Failed to download chapter XML' - ) + video_id, note='Downloading chapters XML', + errnote='Failed to download chapters XML') + video_url = chapters_xml.attrib.get('video') if not video_url: raise ExtractorError('Failed to get the video URL') - ext = determine_ext(video_url) + title = self._html_search_meta('citation_title', webpage, 'title') + thumbnail = self._og_search_thumbnail(webpage) + description = self._html_search_regex( + r'', + webpage, 'duration', fatal=False)) + view_count = int_or_none(self._search_regex( + r'Views:\s*(\d+)', + webpage, 'view count', fatal=False)) return { 'id': video_id, @@ -40,5 +51,6 @@ class HornBunnyIE(InfoExtractor): 'title': title, 'ext': 'flv', 'duration': duration, - 'view_count': int_or_none(view_count), + 'view_count': view_count, + 'age_limit': 18, } From 563f6dea5913e22052f644270cdc19b09f38de84 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 1 Sep 2014 23:07:48 +0200 Subject: [PATCH 0731/1761] [eporner] +age_limit --- youtube_dl/extractor/eporner.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/eporner.py b/youtube_dl/extractor/eporner.py index 4c2c074cb..6926fcda3 100644 --- a/youtube_dl/extractor/eporner.py +++ b/youtube_dl/extractor/eporner.py @@ -21,6 +21,7 @@ class EpornerIE(InfoExtractor): 'title': 'Infamous Tiffany Teen Strip Tease Video', 'duration': 194, 'view_count': int, + 'age_limit': 18, } } @@ -35,9 +36,10 @@ class EpornerIE(InfoExtractor): r'', - webpage, 'info json', flags=re.DOTALL) - info = json.loads(info_json) + video_id = self._match_id(url) + webpage = self._download_webpage( + 'http://www.break.com/embed/%s' % video_id, video_id) + info = json.loads(self._search_regex( + r'var embedVars = ({.*})\s*?', + webpage, 'info json', flags=re.DOTALL)) video_url = info['videoUri'] youtube_id = info.get('youtubeId') if youtube_id: From 146c80e2562dab0f229f13a1fbc0e8ae116d4cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Fri, 3 Oct 2014 19:37:25 +0700 Subject: [PATCH 1025/1761] [utils] Add parse_age_limit --- youtube_dl/utils.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index f8dd9c72d..2615553c1 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -1574,6 +1574,13 @@ US_RATINGS = { } +def parse_age_limit(s): + if s is None: + return 0 + m = re.match(r'^(?P\d{1,2})\+?$', s) + return int(m.group('age')) if m else US_RATINGS.get(s, 0) + + def strip_jsonp(code): return re.sub(r'(?s)^[a-zA-Z0-9_]+\s*\(\s*(.*)\);?\s*?\s*$', r'\1', code) From d397c0b3dd17d17c8235286eb88950d5fda53cee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Fri, 3 Oct 2014 19:37:47 +0700 Subject: [PATCH 1026/1761] [breakcom] Extract all formats --- youtube_dl/extractor/breakcom.py | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/youtube_dl/extractor/breakcom.py b/youtube_dl/extractor/breakcom.py index 9b0aa2b1b..2c0e5eea2 100644 --- a/youtube_dl/extractor/breakcom.py +++ b/youtube_dl/extractor/breakcom.py @@ -4,6 +4,10 @@ import re import json from .common import InfoExtractor +from ..utils import ( + int_or_none, + parse_age_limit, +) class BreakIE(InfoExtractor): @@ -28,15 +32,33 @@ class BreakIE(InfoExtractor): info = json.loads(self._search_regex( r'var embedVars = ({.*})\s*?', webpage, 'info json', flags=re.DOTALL)) - video_url = info['videoUri'] + youtube_id = info.get('youtubeId') if youtube_id: return self.url_result(youtube_id, 'Youtube') - final_url = video_url + '?' + info['AuthToken'] + formats = [{ + 'url': media['uri'] + '?' + info['AuthToken'], + 'tbr': media['bitRate'], + 'width': media['width'], + 'height': media['height'], + } for media in info['media']] + + if not formats: + formats.append({ + 'url': info['videoUri'] + }) + + self._sort_formats(formats) + + duration = int_or_none(info.get('videoLengthInSeconds')) + age_limit = parse_age_limit(info.get('audienceRating')) + return { 'id': video_id, - 'url': final_url, 'title': info['contentName'], 'thumbnail': info['thumbUri'], + 'duration': duration, + 'age_limit': age_limit, + 'formats': formats, } From fe506288bd327d3e7e9a90706ba10f3ff3d36ffe Mon Sep 17 00:00:00 2001 From: Naglis Jonaitis Date: Fri, 3 Oct 2014 19:43:36 +0300 Subject: [PATCH 1027/1761] [planetaplay] Add new extractor (closes #3839) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/planetaplay.py | 60 +++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 youtube_dl/extractor/planetaplay.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index e51ea701f..348f5767a 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -275,6 +275,7 @@ from .parliamentliveuk import ParliamentLiveUKIE from .patreon import PatreonIE from .pbs import PBSIE from .photobucket import PhotobucketIE +from .planetaplay import PlanetaPlayIE from .played import PlayedIE from .playfm import PlayFMIE from .playvid import PlayvidIE diff --git a/youtube_dl/extractor/planetaplay.py b/youtube_dl/extractor/planetaplay.py new file mode 100644 index 000000000..596c621d7 --- /dev/null +++ b/youtube_dl/extractor/planetaplay.py @@ -0,0 +1,60 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ExtractorError + + +class PlanetaPlayIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?planetaplay\.com/\?sng=(?P[0-9]+)' + _API_URL = 'http://planetaplay.com/action/playlist/?sng={0:}' + _THUMBNAIL_URL = 'http://planetaplay.com/img/thumb/{thumb:}' + _TEST = { + 'url': 'http://planetaplay.com/?sng=3586', + 'md5': '9d569dceb7251a4e01355d5aea60f9db', + 'info_dict': { + 'id': '3586', + 'ext': 'flv', + 'title': 'md5:e829428ee28b1deed00de90de49d1da1', + } + } + + _SONG_FORMATS = { + 'lq': (0, 'http://www.planetaplay.com/videoplayback/{med_hash:}'), + 'hq': (1, 'http://www.planetaplay.com/videoplayback/hi/{med_hash:}'), + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + response = self._download_json( + self._API_URL.format(video_id), video_id)['response'] + try: + data = response.get('data')[0] + except IndexError: + raise ExtractorError( + '%s: failed to get the playlist' % self.IE_NAME, expected=True) + + title = '{song_artists:} - {sng_name:}'.format(**data) + thumbnail = self._THUMBNAIL_URL.format(**data) + + formats = [] + for format_id, (quality, url_template) in self._SONG_FORMATS.items(): + formats.append({ + 'format_id': format_id, + 'url': url_template.format(**data), + 'quality': quality, + 'ext': 'flv', + }) + + self._sort_formats(formats) + + return { + 'id': video_id, + 'title': title, + 'formats': formats, + 'thumbnail': thumbnail, + } From d838b1bd4a256484820af7aeb0c2711934cb00ad Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 3 Oct 2014 20:17:10 +0200 Subject: [PATCH 1028/1761] [utils] Default age_limit to None If we can't parse it, it means we don't have any information, not that the content is unrestricted. --- youtube_dl/extractor/common.py | 2 ++ youtube_dl/utils.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 611cf95f1..450c7dfd6 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -138,6 +138,8 @@ class InfoExtractor(object): Unless mentioned otherwise, the fields should be Unicode strings. + Unless mentioned otherwise, None is equivalent to absence of information. + Subclasses of this one should re-define the _real_initialize() and _real_extract() methods and define a _VALID_URL regexp. Probably, they should also be added to the list of extractors. diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 2615553c1..2c9081733 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -1576,9 +1576,9 @@ US_RATINGS = { def parse_age_limit(s): if s is None: - return 0 + return None m = re.match(r'^(?P\d{1,2})\+?$', s) - return int(m.group('age')) if m else US_RATINGS.get(s, 0) + return int(m.group('age')) if m else US_RATINGS.get(s, None) def strip_jsonp(code): From f47754f061abd4615ebcbcfaf3008f0b68d9e525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sat, 4 Oct 2014 18:56:36 +0700 Subject: [PATCH 1029/1761] [globo] Initial extractor implementation (Closes #3823) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/globo.py | 398 +++++++++++++++++++++++++++++++ 2 files changed, 399 insertions(+) create mode 100644 youtube_dl/extractor/globo.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 348f5767a..b59fd65ca 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -134,6 +134,7 @@ from .gamestar import GameStarIE from .gametrailers import GametrailersIE from .gdcvault import GDCVaultIE from .generic import GenericIE +from .globo import GloboIE from .godtube import GodTubeIE from .golem import GolemIE from .googleplus import GooglePlusIE diff --git a/youtube_dl/extractor/globo.py b/youtube_dl/extractor/globo.py new file mode 100644 index 000000000..77c3ad4fc --- /dev/null +++ b/youtube_dl/extractor/globo.py @@ -0,0 +1,398 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import random +import math + +from .common import InfoExtractor +from ..utils import ( + ExtractorError, + float_or_none, + compat_str, + compat_chr, + compat_ord, +) + + +class GloboIE(InfoExtractor): + _VALID_URL = 'https?://.+?\.globo\.com/(?P.+)' + + _API_URL_TEMPLATE = 'http://api.globovideos.com/videos/%s/playlist' + _SECURITY_URL_TEMPLATE = 'http://security.video.globo.com/videos/%s/hash?player=flash&version=2.9.9.50&resource_id=%s' + + _VIDEOID_REGEXES = [ + r'\bdata-video-id="(\d+)"', + r'\bdata-player-videosids="(\d+)"', + r']+\bid="(\d+)"', + ] + + _RESIGN_EXPIRATION = 86400 + + _TESTS = [ + { + 'url': 'http://globotv.globo.com/sportv/futebol-nacional/v/os-gols-de-atletico-mg-3-x-2-santos-pela-24a-rodada-do-brasileirao/3654973/', + 'md5': '03ebf41cb7ade43581608b7d9b71fab0', + 'info_dict': { + 'id': '3654973', + 'ext': 'mp4', + 'title': 'Os gols de Atlético-MG 3 x 2 Santos pela 24ª rodada do Brasileirão', + 'duration': 251.585, + 'uploader': 'SporTV', + 'uploader_id': 698, + 'like_count': int, + } + }, + { + 'url': 'http://g1.globo.com/carros/autoesporte/videos/t/exclusivos-do-g1/v/mercedes-benz-gla-passa-por-teste-de-colisao-na-europa/3607726/', + 'md5': 'b3ccc801f75cd04a914d51dadb83a78d', + 'info_dict': { + 'id': '3607726', + 'ext': 'mp4', + 'title': 'Mercedes-Benz GLA passa por teste de colisão na Europa', + 'duration': 103.204, + 'uploader': 'Globo.com', + 'uploader_id': 265, + 'like_count': int, + } + }, + { + 'url': 'http://g1.globo.com/jornal-nacional/noticia/2014/09/novidade-na-fiscalizacao-de-bagagem-pela-receita-provoca-discussoes.html', + 'md5': '307fdeae4390ccfe6ba1aa198cf6e72b', + 'info_dict': { + 'id': '3652183', + 'ext': 'mp4', + 'title': 'Receita Federal explica como vai fiscalizar bagagens de quem retorna ao Brasil de avião', + 'duration': 110.711, + 'uploader': 'Rede Globo', + 'uploader_id': 196, + 'like_count': int, + } + }, + ] + + class MD5(): + HEX_FORMAT_LOWERCASE = 0 + HEX_FORMAT_UPPERCASE = 1 + BASE64_PAD_CHARACTER_DEFAULT_COMPLIANCE = '' + BASE64_PAD_CHARACTER_RFC_COMPLIANCE = '=' + PADDING = '=0xFF01DD' + hexcase = 0 + b64pad = '' + + def __init__(self): + pass + + class JSArray(list): + def __getitem__(self, y): + try: + return list.__getitem__(self, y) + except IndexError: + return 0 + + def __setitem__(self, i, y): + try: + return list.__setitem__(self, i, y) + except IndexError: + self.extend([0] * (i - len(self) + 1)) + self[-1] = y + + @classmethod + def hex_md5(cls, param1): + return cls.rstr2hex(cls.rstr_md5(cls.str2rstr_utf8(param1))) + + @classmethod + def b64_md5(cls, param1, param2=None): + return cls.rstr2b64(cls.rstr_md5(cls.str2rstr_utf8(param1, param2))) + + @classmethod + def any_md5(cls, param1, param2): + return cls.rstr2any(cls.rstr_md5(cls.str2rstr_utf8(param1)), param2) + + @classmethod + def rstr_md5(cls, param1): + return cls.binl2rstr(cls.binl_md5(cls.rstr2binl(param1), len(param1) * 8)) + + @classmethod + def rstr2hex(cls, param1): + _loc_2 = '0123456789ABCDEF' if cls.hexcase else '0123456789abcdef' + _loc_3 = '' + for _loc_5 in range(0, len(param1)): + _loc_4 = compat_ord(param1[_loc_5]) + _loc_3 += _loc_2[_loc_4 >> 4 & 15] + _loc_2[_loc_4 & 15] + return _loc_3 + + @classmethod + def rstr2b64(cls, param1): + _loc_2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_' + _loc_3 = '' + _loc_4 = len(param1) + for _loc_5 in range(0, _loc_4, 3): + _loc_6_1 = compat_ord(param1[_loc_5]) << 16 + _loc_6_2 = compat_ord(param1[_loc_5 + 1]) << 8 if _loc_5 + 1 < _loc_4 else 0 + _loc_6_3 = compat_ord(param1[_loc_5 + 2]) if _loc_5 + 2 < _loc_4 else 0 + _loc_6 = _loc_6_1 | _loc_6_2 | _loc_6_3 + for _loc_7 in range(0, 4): + if _loc_5 * 8 + _loc_7 * 6 > len(param1) * 8: + _loc_3 += cls.b64pad + else: + _loc_3 += _loc_2[_loc_6 >> 6 * (3 - _loc_7) & 63] + return _loc_3 + + @staticmethod + def rstr2any(param1, param2): + _loc_3 = len(param2) + _loc_4 = [] + _loc_9 = [0] * ((len(param1) >> 2) + 1) + for _loc_5 in range(0, len(_loc_9)): + _loc_9[_loc_5] = compat_ord(param1[_loc_5 * 2]) << 8 | compat_ord(param1[_loc_5 * 2 + 1]) + + while len(_loc_9) > 0: + _loc_8 = [] + _loc_7 = 0 + for _loc_5 in range(0, len(_loc_9)): + _loc_7 = (_loc_7 << 16) + _loc_9[_loc_5] + _loc_6 = math.floor(_loc_7 / _loc_3) + _loc_7 -= _loc_6 * _loc_3 + if len(_loc_8) > 0 or _loc_6 > 0: + _loc_8[len(_loc_8)] = _loc_6 + + _loc_4[len(_loc_4)] = _loc_7 + _loc_9 = _loc_8 + + _loc_10 = '' + _loc_5 = len(_loc_4) - 1 + while _loc_5 >= 0: + _loc_10 += param2[_loc_4[_loc_5]] + _loc_5 -= 1 + + return _loc_10 + + @classmethod + def str2rstr_utf8(cls, param1, param2=None): + _loc_3 = '' + _loc_4 = -1 + if not param2: + param2 = cls.PADDING + param1 = param1 + param2[1:9] + while True: + _loc_4 += 1 + if _loc_4 >= len(param1): + break + _loc_5 = compat_ord(param1[_loc_4]) + _loc_6 = compat_ord(param1[_loc_4 + 1]) if _loc_4 + 1 < len(param1) else 0 + if 55296 <= _loc_5 <= 56319 and 56320 <= _loc_6 <= 57343: + _loc_5 = 65536 + ((_loc_5 & 1023) << 10) + (_loc_6 & 1023) + _loc_4 += 1 + if _loc_5 <= 127: + _loc_3 += compat_chr(_loc_5) + continue + if _loc_5 <= 2047: + _loc_3 += compat_chr(192 | _loc_5 >> 6 & 31) + compat_chr(128 | _loc_5 & 63) + continue + if _loc_5 <= 65535: + _loc_3 += compat_chr(224 | _loc_5 >> 12 & 15) + compat_chr(128 | _loc_5 >> 6 & 63) + compat_chr( + 128 | _loc_5 & 63) + continue + if _loc_5 <= 2097151: + _loc_3 += compat_chr(240 | _loc_5 >> 18 & 7) + compat_chr(128 | _loc_5 >> 12 & 63) + compat_chr( + 128 | _loc_5 >> 6 & 63) + compat_chr(128 | _loc_5 & 63) + return _loc_3 + + @staticmethod + def rstr2binl(param1): + _loc_2 = [0] * ((len(param1) >> 2) + 1) + for _loc_3 in range(0, len(_loc_2)): + _loc_2[_loc_3] = 0 + for _loc_3 in range(0, len(param1) * 8, 8): + _loc_2[_loc_3 >> 5] |= (compat_ord(param1[_loc_3 // 8]) & 255) << _loc_3 % 32 + return _loc_2 + + @staticmethod + def binl2rstr(param1): + _loc_2 = '' + for _loc_3 in range(0, len(param1) * 32, 8): + _loc_2 += compat_chr(param1[_loc_3 >> 5] >> _loc_3 % 32 & 255) + return _loc_2 + + @classmethod + def binl_md5(cls, param1, param2): + param1 = cls.JSArray(param1) + param1[param2 >> 5] |= 128 << param2 % 32 + param1[(param2 + 64 >> 9 << 4) + 14] = param2 + _loc_3 = 1732584193 + _loc_4 = -271733879 + _loc_5 = -1732584194 + _loc_6 = 271733878 + for _loc_7 in range(0, len(param1), 16): + _loc_8 = _loc_3 + _loc_9 = _loc_4 + _loc_10 = _loc_5 + _loc_11 = _loc_6 + _loc_3 = cls.md5_ff(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 0], 7, -680876936) + _loc_6 = cls.md5_ff(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 1], 12, -389564586) + _loc_5 = cls.md5_ff(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 2], 17, 606105819) + _loc_4 = cls.md5_ff(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 3], 22, -1044525330) + _loc_3 = cls.md5_ff(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 4], 7, -176418897) + _loc_6 = cls.md5_ff(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 5], 12, 1200080426) + _loc_5 = cls.md5_ff(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 6], 17, -1473231341) + _loc_4 = cls.md5_ff(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 7], 22, -45705983) + _loc_3 = cls.md5_ff(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 8], 7, 1770035416) + _loc_6 = cls.md5_ff(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 9], 12, -1958414417) + _loc_5 = cls.md5_ff(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 10], 17, -42063) + _loc_4 = cls.md5_ff(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 11], 22, -1990404162) + _loc_3 = cls.md5_ff(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 12], 7, 1804603682) + _loc_6 = cls.md5_ff(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 13], 12, -40341101) + _loc_5 = cls.md5_ff(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 14], 17, -1502002290) + _loc_4 = cls.md5_ff(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 15], 22, 1236535329) + _loc_3 = cls.md5_gg(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 1], 5, -165796510) + _loc_6 = cls.md5_gg(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 6], 9, -1069501632) + _loc_5 = cls.md5_gg(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 11], 14, 643717713) + _loc_4 = cls.md5_gg(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 0], 20, -373897302) + _loc_3 = cls.md5_gg(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 5], 5, -701558691) + _loc_6 = cls.md5_gg(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 10], 9, 38016083) + _loc_5 = cls.md5_gg(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 15], 14, -660478335) + _loc_4 = cls.md5_gg(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 4], 20, -405537848) + _loc_3 = cls.md5_gg(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 9], 5, 568446438) + _loc_6 = cls.md5_gg(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 14], 9, -1019803690) + _loc_5 = cls.md5_gg(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 3], 14, -187363961) + _loc_4 = cls.md5_gg(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 8], 20, 1163531501) + _loc_3 = cls.md5_gg(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 13], 5, -1444681467) + _loc_6 = cls.md5_gg(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 2], 9, -51403784) + _loc_5 = cls.md5_gg(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 7], 14, 1735328473) + _loc_4 = cls.md5_gg(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 12], 20, -1926607734) + _loc_3 = cls.md5_hh(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 5], 4, -378558) + _loc_6 = cls.md5_hh(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 8], 11, -2022574463) + _loc_5 = cls.md5_hh(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 11], 16, 1839030562) + _loc_4 = cls.md5_hh(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 14], 23, -35309556) + _loc_3 = cls.md5_hh(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 1], 4, -1530992060) + _loc_6 = cls.md5_hh(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 4], 11, 1272893353) + _loc_5 = cls.md5_hh(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 7], 16, -155497632) + _loc_4 = cls.md5_hh(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 10], 23, -1094730640) + _loc_3 = cls.md5_hh(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 13], 4, 681279174) + _loc_6 = cls.md5_hh(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 0], 11, -358537222) + _loc_5 = cls.md5_hh(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 3], 16, -722521979) + _loc_4 = cls.md5_hh(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 6], 23, 76029189) + _loc_3 = cls.md5_hh(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 9], 4, -640364487) + _loc_6 = cls.md5_hh(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 12], 11, -421815835) + _loc_5 = cls.md5_hh(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 15], 16, 530742520) + _loc_4 = cls.md5_hh(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 2], 23, -995338651) + _loc_3 = cls.md5_ii(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 0], 6, -198630844) + _loc_6 = cls.md5_ii(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 7], 10, 1126891415) + _loc_5 = cls.md5_ii(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 14], 15, -1416354905) + _loc_4 = cls.md5_ii(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 5], 21, -57434055) + _loc_3 = cls.md5_ii(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 12], 6, 1700485571) + _loc_6 = cls.md5_ii(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 3], 10, -1894986606) + _loc_5 = cls.md5_ii(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 10], 15, -1051523) + _loc_4 = cls.md5_ii(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 1], 21, -2054922799) + _loc_3 = cls.md5_ii(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 8], 6, 1873313359) + _loc_6 = cls.md5_ii(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 15], 10, -30611744) + _loc_5 = cls.md5_ii(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 6], 15, -1560198380) + _loc_4 = cls.md5_ii(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 13], 21, 1309151649) + _loc_3 = cls.md5_ii(_loc_3, _loc_4, _loc_5, _loc_6, param1[_loc_7 + 4], 6, -145523070) + _loc_6 = cls.md5_ii(_loc_6, _loc_3, _loc_4, _loc_5, param1[_loc_7 + 11], 10, -1120210379) + _loc_5 = cls.md5_ii(_loc_5, _loc_6, _loc_3, _loc_4, param1[_loc_7 + 2], 15, 718787259) + _loc_4 = cls.md5_ii(_loc_4, _loc_5, _loc_6, _loc_3, param1[_loc_7 + 9], 21, -343485551) + _loc_3 = cls.safe_add(_loc_3, _loc_8) + _loc_4 = cls.safe_add(_loc_4, _loc_9) + _loc_5 = cls.safe_add(_loc_5, _loc_10) + _loc_6 = cls.safe_add(_loc_6, _loc_11) + return [_loc_3, _loc_4, _loc_5, _loc_6] + + @classmethod + def md5_cmn(cls, param1, param2, param3, param4, param5, param6): + return cls.safe_add( + cls.bit_rol(cls.safe_add(cls.safe_add(param2, param1), cls.safe_add(param4, param6)), param5), param3) + + @classmethod + def md5_ff(cls, param1, param2, param3, param4, param5, param6, param7): + return cls.md5_cmn(param2 & param3 | ~param2 & param4, param1, param2, param5, param6, param7) + + @classmethod + def md5_gg(cls, param1, param2, param3, param4, param5, param6, param7): + return cls.md5_cmn(param2 & param4 | param3 & ~param4, param1, param2, param5, param6, param7) + + @classmethod + def md5_hh(cls, param1, param2, param3, param4, param5, param6, param7): + return cls.md5_cmn(param2 ^ param3 ^ param4, param1, param2, param5, param6, param7) + + @classmethod + def md5_ii(cls, param1, param2, param3, param4, param5, param6, param7): + return cls.md5_cmn(param3 ^ (param2 | ~param4), param1, param2, param5, param6, param7) + + @classmethod + def safe_add(cls, param1, param2): + _loc_3 = (param1 & 65535) + (param2 & 65535) + _loc_4 = (param1 >> 16) + (param2 >> 16) + (_loc_3 >> 16) + return cls.lshift(_loc_4, 16) | _loc_3 & 65535 + + @classmethod + def bit_rol(cls, param1, param2): + return cls.lshift(param1, param2) | (param1 & 0xFFFFFFFF) >> (32 - param2) + + @staticmethod + def lshift(value, count): + r = (0xFFFFFFFF & value) << count + return -(~(r - 1) & 0xFFFFFFFF) if r > 0x7FFFFFFF else r + + def _real_extract(self, url): + video_id = self._match_id(url) + + webpage = self._download_webpage(url, video_id) + video_id = self._search_regex(self._VIDEOID_REGEXES, webpage, 'video id') + + video = self._download_json( + self._API_URL_TEMPLATE % video_id, video_id)['videos'][0] + + title = video['title'] + duration = float_or_none(video['duration'], 1000) + like_count = video['likes'] + uploader = video['channel'] + uploader_id = video['channel_id'] + + formats = [] + + for resource in video['resources']: + resource_id = resource.get('_id') + if not resource_id: + continue + + security = self._download_json( + self._SECURITY_URL_TEMPLATE % (video_id, resource_id), + video_id, 'Downloading security hash for %s' % resource_id) + + security_hash = security.get('hash') + if not security_hash: + message = security.get('message') + if message: + raise ExtractorError( + '%s returned error: %s' % (self.IE_NAME, message), expected=True) + continue + + hash_code = security_hash[:2] + received_time = int(security_hash[2:12]) + received_random = security_hash[12:22] + received_md5 = security_hash[22:] + + sign_time = received_time + self._RESIGN_EXPIRATION + padding = '%010d' % random.randint(1, 10000000000) + + signed_md5 = self.MD5.b64_md5(received_md5 + compat_str(sign_time) + padding) + signed_hash = hash_code + compat_str(received_time) + received_random + compat_str(sign_time) + padding + signed_md5 + + formats.append({ + 'url': '%s?h=%s&k=%s' % (resource['url'], signed_hash, 'flash'), + 'format_id': resource_id, + 'height': resource['height'] + }) + + self._sort_formats(formats) + + return { + 'id': video_id, + 'title': title, + 'duration': duration, + 'uploader': uploader, + 'uploader_id': uploader_id, + 'like_count': like_count, + 'formats': formats + } \ No newline at end of file From e9be9a6acdc47e53dd8292341fa521234ce9dd78 Mon Sep 17 00:00:00 2001 From: Naglis Jonaitis Date: Sat, 4 Oct 2014 22:38:23 +0300 Subject: [PATCH 1030/1761] [utils] Add additional format to unified_strdate --- youtube_dl/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 2c9081733..d7ae5a90a 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -894,6 +894,7 @@ def unified_strdate(date_str): '%Y/%m/%d %H:%M:%S', '%d/%m/%Y %H:%M:%S', '%Y-%m-%d %H:%M:%S', + '%Y-%m-%d %H:%M:%S.%f', '%d.%m.%Y %H:%M', '%d.%m.%Y %H.%M', '%Y-%m-%dT%H:%M:%SZ', From 5e69192ef74f9dd4057905d2ffc2d4afb051fb57 Mon Sep 17 00:00:00 2001 From: Naglis Jonaitis Date: Sat, 4 Oct 2014 22:40:36 +0300 Subject: [PATCH 1031/1761] [thesixtyone] Add new extractor (closes #3781) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/thesixtyone.py | 100 ++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 youtube_dl/extractor/thesixtyone.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index b59fd65ca..d118daa68 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -371,6 +371,7 @@ from .tenplay import TenPlayIE from .testurl import TestURLIE from .tf1 import TF1IE from .theplatform import ThePlatformIE +from .thesixtyone import TheSixtyOneIE from .thisav import ThisAVIE from .tinypic import TinyPicIE from .tlc import TlcIE, TlcDeIE diff --git a/youtube_dl/extractor/thesixtyone.py b/youtube_dl/extractor/thesixtyone.py new file mode 100644 index 000000000..a77c6a2fc --- /dev/null +++ b/youtube_dl/extractor/thesixtyone.py @@ -0,0 +1,100 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import json +import re + +from .common import InfoExtractor +from ..utils import unified_strdate + + +class TheSixtyOneIE(InfoExtractor): + _VALID_URL = r'''(?x)https?://(?:www\.)?thesixtyone\.com/ + (?:.*?/)* + (?: + s| + song/comments/list| + song + )/(?P[A-Za-z0-9]+)/?$''' + _SONG_URL_TEMPLATE = 'http://thesixtyone.com/s/{0:}' + _SONG_FILE_URL_TEMPLATE = 'http://{audio_server:}.thesixtyone.com/thesixtyone_production/audio/{0:}_stream' + _THUMBNAIL_URL_TEMPLATE = '{photo_base_url:}_desktop' + _TESTS = [ + { + 'url': 'http://www.thesixtyone.com/s/SrE3zD7s1jt/', + 'md5': '821cc43b0530d3222e3e2b70bb4622ea', + 'info_dict': { + 'id': 'SrE3zD7s1jt', + 'ext': 'mp3', + 'title': 'CASIO - Unicorn War Mixtape', + 'thumbnail': 're:^https?://.*_desktop$', + 'upload_date': '20071217', + 'duration': 3208, + } + }, + { + 'url': 'http://www.thesixtyone.com/song/comments/list/SrE3zD7s1jt', + 'only_matching': True, + }, + { + 'url': 'http://www.thesixtyone.com/s/ULoiyjuJWli#/s/SrE3zD7s1jt/', + 'only_matching': True, + }, + { + 'url': 'http://www.thesixtyone.com/#/s/SrE3zD7s1jt/', + 'only_matching': True, + }, + { + 'url': 'http://www.thesixtyone.com/song/SrE3zD7s1jt/', + 'only_matching': True, + }, + ] + + _DECODE_MAP = { + "x": "a", + "m": "b", + "w": "c", + "q": "d", + "n": "e", + "p": "f", + "a": "0", + "h": "1", + "e": "2", + "u": "3", + "s": "4", + "i": "5", + "o": "6", + "y": "7", + "r": "8", + "c": "9" + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + song_id = mobj.group('id') + + webpage = self._download_webpage( + self._SONG_URL_TEMPLATE.format(song_id), song_id) + + song_data = json.loads(self._search_regex( + r'"%s":\s(\{.*?\})' % song_id, webpage, 'song_data')) + keys = [self._DECODE_MAP.get(s, s) for s in song_data['key']] + url = self._SONG_FILE_URL_TEMPLATE.format( + "".join(reversed(keys)), **song_data) + + formats = [{ + 'format_id': 'sd', + 'url': url, + 'ext': 'mp3', + }] + + return { + 'id': song_id, + 'title': '{artist:} - {name:}'.format(**song_data), + 'formats': formats, + 'comment_count': song_data.get('comments_count'), + 'duration': song_data.get('play_time'), + 'like_count': song_data.get('score'), + 'thumbnail': self._THUMBNAIL_URL_TEMPLATE.format(**song_data), + 'upload_date': unified_strdate(song_data.get('publish_date')), + } From b81f484b60c5e06e7d30720b104d01245c466e14 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 5 Oct 2014 07:53:02 +0200 Subject: [PATCH 1032/1761] [gorillavid] Add support for movpod.in (Fixes #3881) --- youtube_dl/extractor/gorillavid.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/gorillavid.py b/youtube_dl/extractor/gorillavid.py index ca5f7c417..8c3ad8c7d 100644 --- a/youtube_dl/extractor/gorillavid.py +++ b/youtube_dl/extractor/gorillavid.py @@ -12,10 +12,10 @@ from ..utils import ( class GorillaVidIE(InfoExtractor): - IE_DESC = 'GorillaVid.in and daclips.in' + IE_DESC = 'GorillaVid.in, daclips.in and movpod.in' _VALID_URL = r'''(?x) https?://(?P(?:www\.)? - (?:daclips\.in|gorillavid\.in))/ + (?:daclips\.in|gorillavid\.in|movpod\.in))/ (?:embed-)?(?P[0-9a-zA-Z]+)(?:-[0-9]+x[0-9]+\.html)? ''' @@ -46,6 +46,9 @@ class GorillaVidIE(InfoExtractor): 'title': 'Micro Pig piglets ready on 16th July 2009', 'thumbnail': 're:http://.*\.jpg', }, + }, { + 'url': 'http://movpod.in/0wguyyxi1yca', + 'only_matching': True, }] def _real_extract(self, url): From bb0c206f592b47982753bc63d1ee49868c925cec Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 5 Oct 2014 07:53:25 +0200 Subject: [PATCH 1033/1761] release 2014.10.05 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index b7a60ac24..9f48107a1 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.02' +__version__ = '2014.10.05' From e4b85e35d083fca70d29a751c01071e287b5cdae Mon Sep 17 00:00:00 2001 From: Sergey M Date: Mon, 6 Oct 2014 01:47:22 +0700 Subject: [PATCH 1034/1761] [gorillavid] Fix title extraction and make thumbnail optional (Closes #3884) --- youtube_dl/extractor/gorillavid.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/youtube_dl/extractor/gorillavid.py b/youtube_dl/extractor/gorillavid.py index 8c3ad8c7d..0f0012f1f 100644 --- a/youtube_dl/extractor/gorillavid.py +++ b/youtube_dl/extractor/gorillavid.py @@ -5,6 +5,7 @@ import re from .common import InfoExtractor from ..utils import ( + ExtractorError, determine_ext, compat_urllib_parse, compat_urllib_request, @@ -25,7 +26,7 @@ class GorillaVidIE(InfoExtractor): 'info_dict': { 'id': '06y9juieqpmi', 'ext': 'flv', - 'title': 'Rebecca Black My Moment Official Music Video Reaction', + 'title': 'Rebecca Black My Moment Official Music Video Reaction-6GK87Rc8bzQ', 'thumbnail': 're:http://.*\.jpg', }, }, { @@ -72,14 +73,14 @@ class GorillaVidIE(InfoExtractor): webpage = self._download_webpage(req, video_id, 'Downloading video page') - title = self._search_regex(r'style="z-index: [0-9]+;">([0-9a-zA-Z ]+)(?:-.+)?', webpage, 'title') - thumbnail = self._search_regex(r'image:\'(http[^\']+)\',', webpage, 'thumbnail') - url = self._search_regex(r'file: \'(http[^\']+)\',', webpage, 'file url') + title = self._search_regex(r'style="z-index: [0-9]+;">([^<]+)', webpage, 'title') + video_url = self._search_regex(r'file\s*:\s*\'(http[^\']+)\',', webpage, 'file url') + thumbnail = self._search_regex(r'image\s*:\s*\'(http[^\']+)\',', webpage, 'thumbnail', fatal=False) formats = [{ 'format_id': 'sd', - 'url': url, - 'ext': determine_ext(url), + 'url': video_url, + 'ext': determine_ext(video_url), 'quality': 1, }] From 3ae165aa10e6747173adbcce8da0e2c8d30eed33 Mon Sep 17 00:00:00 2001 From: Sergey M Date: Mon, 6 Oct 2014 01:48:01 +0700 Subject: [PATCH 1035/1761] [gorillavid] Add check for non existing videos --- youtube_dl/extractor/gorillavid.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/youtube_dl/extractor/gorillavid.py b/youtube_dl/extractor/gorillavid.py index 0f0012f1f..45cca1d24 100644 --- a/youtube_dl/extractor/gorillavid.py +++ b/youtube_dl/extractor/gorillavid.py @@ -20,6 +20,8 @@ class GorillaVidIE(InfoExtractor): (?:embed-)?(?P[0-9a-zA-Z]+)(?:-[0-9]+x[0-9]+\.html)? ''' + _FILE_NOT_FOUND_REGEX = r'>(?:404 - )?File Not Found<' + _TESTS = [{ 'url': 'http://gorillavid.in/06y9juieqpmi', 'md5': '5ae4a3580620380619678ee4875893ba', @@ -58,6 +60,9 @@ class GorillaVidIE(InfoExtractor): webpage = self._download_webpage('http://%s/%s' % (mobj.group('host'), video_id), video_id) + if re.search(self._FILE_NOT_FOUND_REGEX, webpage) is not None: + raise ExtractorError('Video %s does not exist' % video_id, expected=True) + fields = dict(re.findall(r'''(?x) Date: Sun, 5 Oct 2014 21:59:53 +0200 Subject: [PATCH 1036/1761] [dailymotion] Alternative title search (Fixes #3882) --- youtube_dl/extractor/dailymotion.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/youtube_dl/extractor/dailymotion.py b/youtube_dl/extractor/dailymotion.py index 66a8f16d9..dbcf5d6a7 100644 --- a/youtube_dl/extractor/dailymotion.py +++ b/youtube_dl/extractor/dailymotion.py @@ -82,11 +82,7 @@ class DailymotionIE(DailymotionBaseInfoExtractor, SubtitlesInfoExtractor): ] def _real_extract(self, url): - # Extract id and simplified title from URL - mobj = re.match(self._VALID_URL, url) - - video_id = mobj.group('id') - + video_id = self._match_id(url) url = 'http://www.dailymotion.com/video/%s' % video_id # Retrieve video webpage to extract further information @@ -147,18 +143,23 @@ class DailymotionIE(DailymotionBaseInfoExtractor, SubtitlesInfoExtractor): self._list_available_subtitles(video_id, webpage) return - view_count = self._search_regex( - r'video_views_count[^>]+>\s+([\d\.,]+)', webpage, 'view count', fatal=False) - if view_count is not None: - view_count = str_to_int(view_count) + view_count = str_to_int(self._search_regex( + r'video_views_count[^>]+>\s+([\d\.,]+)', + webpage, 'view count', fatal=False)) + + title = self._og_search_title(webpage, default=None) + if title is None: + title = self._html_search_regex( + r'(?s)]*>(.*?)', webpage, + 'title') return { - 'id': video_id, + 'id': video_id, 'formats': formats, 'uploader': info['owner.screenname'], - 'upload_date': video_upload_date, - 'title': self._og_search_title(webpage), - 'subtitles': video_subtitles, + 'upload_date': video_upload_date, + 'title': title, + 'subtitles': video_subtitles, 'thumbnail': info['thumbnail_url'], 'age_limit': age_limit, 'view_count': view_count, From 4c4de296d41a1db4642df5f9381d77e7306af3c4 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 5 Oct 2014 22:00:16 +0200 Subject: [PATCH 1037/1761] release 2014.10.05.1 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 9f48107a1..ef2196960 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.05' +__version__ = '2014.10.05.1' From 642b76ac1513f7aaa3469e03078ab2fb3d3187f4 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 5 Oct 2014 22:04:02 +0200 Subject: [PATCH 1038/1761] release 2014.10.05.2 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index ef2196960..4f0d486b9 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.05.1' +__version__ = '2014.10.05.2' From 31d06400ecee79ecf3a0bd38c0702f165fd6d958 Mon Sep 17 00:00:00 2001 From: net Date: Mon, 6 Oct 2014 03:03:05 +0300 Subject: [PATCH 1039/1761] add missed init file --- youtube_dl/extractor/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 079221567..b07c0b4cc 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -427,6 +427,7 @@ from .vporn import VpornIE from .vube import VubeIE from .vuclip import VuClipIE from .vulture import VultureIE +from .walla import WallaIE from .washingtonpost import WashingtonPostIE from .wat import WatIE from .wayofthemaster import WayOfTheMasterIE From 3b700f8d434cbf1b097324a577e4b95325b24d91 Mon Sep 17 00:00:00 2001 From: Xu Cheng Date: Mon, 6 Oct 2014 18:58:25 +0800 Subject: [PATCH 1040/1761] support zsh completion --- devscripts/zsh-completion.in | 28 ++++++++++++++++++++++ devscripts/zsh-completion.py | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 devscripts/zsh-completion.in create mode 100755 devscripts/zsh-completion.py diff --git a/devscripts/zsh-completion.in b/devscripts/zsh-completion.in new file mode 100644 index 000000000..b394a1ae7 --- /dev/null +++ b/devscripts/zsh-completion.in @@ -0,0 +1,28 @@ +#compdef youtube-dl + +__youtube_dl() { + local curcontext="$curcontext" fileopts diropts cur prev + typeset -A opt_args + fileopts="{{fileopts}}" + diropts="{{diropts}}" + cur=$words[CURRENT] + case $cur in + :) + _arguments '*: :(::ytfavorites ::ytrecommended ::ytsubscriptions ::ytwatchlater ::ythistory)' + ;; + *) + prev=$words[CURRENT-1] + if [[ ${prev} =~ ${fileopts} ]]; then + _path_files + elif [[ ${prev} =~ ${diropts} ]]; then + _path_files -/ + elif [[ ${prev} == "--recode-video" ]]; then + _arguments '*: :(mp4 flv ogg webm mkv)' + else + _arguments '*: :({{flags}})' + fi + ;; + esac +} + +__youtube_dl \ No newline at end of file diff --git a/devscripts/zsh-completion.py b/devscripts/zsh-completion.py new file mode 100755 index 000000000..e8d71928a --- /dev/null +++ b/devscripts/zsh-completion.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +import os +from os.path import dirname as dirn +import sys + +sys.path.append(dirn(dirn((os.path.abspath(__file__))))) +import youtube_dl + +ZSH_COMPLETION_FILE = "youtube-dl.zsh" +ZSH_COMPLETION_TEMPLATE = "devscripts/zsh-completion.in" + + +def build_completion(opt_parser): + opts = [opt for group in opt_parser.option_groups + for opt in group.option_list] + opts_file = [opt for opt in opts if opt.metavar == "FILE"] + opts_dir = [opt for opt in opts if opt.metavar == "DIR"] + + fileopts = [] + for opt in opts_file: + if opt._short_opts: + fileopts.extend(opt._short_opts) + if opt._long_opts: + fileopts.extend(opt._long_opts) + + diropts = [] + for opt in opts_dir: + if opt._short_opts: + diropts.extend(opt._short_opts) + if opt._long_opts: + diropts.extend(opt._long_opts) + + flags = [opt.get_opt_string() for opt in opts] + + with open(ZSH_COMPLETION_TEMPLATE) as f: + template = f.read() + + template = template.replace("{{fileopts}}", "|".join(fileopts)) + template = template.replace("{{diropts}}", "|".join(diropts)) + template = template.replace("{{flags}}", " ".join(flags)) + + with open(ZSH_COMPLETION_FILE, "w") as f: + f.write(template) + +parser = youtube_dl.parseOpts()[0] +build_completion(parser) From 24f7fb5e1e2fb1e70f553decf07d14892f87b419 Mon Sep 17 00:00:00 2001 From: Xu Cheng Date: Mon, 6 Oct 2014 19:02:11 +0800 Subject: [PATCH 1041/1761] add zsh completion support into Makefile --- Makefile | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 6272b826c..2da92863f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -all: youtube-dl README.md README.txt youtube-dl.1 youtube-dl.bash-completion youtube-dl.fish +all: youtube-dl README.md README.txt youtube-dl.1 youtube-dl.bash-completion youtube-dl.zsh youtube-dl.fish clean: - rm -rf youtube-dl.1.temp.md youtube-dl.1 youtube-dl.bash-completion README.txt MANIFEST build/ dist/ .coverage cover/ youtube-dl.tar.gz youtube-dl.fish + rm -rf youtube-dl.1.temp.md youtube-dl.1 youtube-dl.bash-completion README.txt MANIFEST build/ dist/ .coverage cover/ youtube-dl.tar.gz youtube-dl.zsh youtube-dl.fish cleanall: clean rm -f youtube-dl youtube-dl.exe @@ -9,6 +9,7 @@ cleanall: clean PREFIX ?= /usr/local BINDIR ?= $(PREFIX)/bin MANDIR ?= $(PREFIX)/man +SHAREDIR ?= $(PREFIX)/share PYTHON ?= /usr/bin/env python # set SYSCONFDIR to /etc if PREFIX=/usr or PREFIX=/usr/local @@ -22,13 +23,15 @@ else endif endif -install: youtube-dl youtube-dl.1 youtube-dl.bash-completion +install: youtube-dl youtube-dl.1 youtube-dl.bash-completion youtube-dl.zsh youtube-dl.fish install -d $(DESTDIR)$(BINDIR) install -m 755 youtube-dl $(DESTDIR)$(BINDIR) install -d $(DESTDIR)$(MANDIR)/man1 install -m 644 youtube-dl.1 $(DESTDIR)$(MANDIR)/man1 install -d $(DESTDIR)$(SYSCONFDIR)/bash_completion.d install -m 644 youtube-dl.bash-completion $(DESTDIR)$(SYSCONFDIR)/bash_completion.d/youtube-dl + install -d $(DESTDIR)$(SHAREDIR)/zsh/site-functions + install -m 644 youtube-dl.zsh $(DESTDIR)$(SHAREDIR)/zsh/site-functions/_youtube-dl install -d $(DESTDIR)$(SYSCONFDIR)/fish/completions install -m 644 youtube-dl.fish $(DESTDIR)$(SYSCONFDIR)/fish/completions/youtube-dl.fish @@ -38,7 +41,7 @@ test: tar: youtube-dl.tar.gz -.PHONY: all clean install test tar bash-completion pypi-files fish-completion +.PHONY: all clean install test tar bash-completion pypi-files zsh-completion fish-completion pypi-files: youtube-dl.bash-completion README.txt youtube-dl.1 youtube-dl.fish @@ -66,12 +69,17 @@ youtube-dl.bash-completion: youtube_dl/*.py youtube_dl/*/*.py devscripts/bash-co bash-completion: youtube-dl.bash-completion +youtube-dl.zsh: youtube_dl/*.py youtube_dl/*/*.py devscripts/zsh-completion.in + python devscripts/zsh-completion.py + +zsh-completion: youtube-dl.zsh + youtube-dl.fish: youtube_dl/*.py youtube_dl/*/*.py devscripts/fish-completion.in python devscripts/fish-completion.py fish-completion: youtube-dl.fish -youtube-dl.tar.gz: youtube-dl README.md README.txt youtube-dl.1 youtube-dl.bash-completion youtube-dl.fish +youtube-dl.tar.gz: youtube-dl README.md README.txt youtube-dl.1 youtube-dl.bash-completion youtube-dl.zsh youtube-dl.fish @tar -czf youtube-dl.tar.gz --transform "s|^|youtube-dl/|" --owner 0 --group 0 \ --exclude '*.DS_Store' \ --exclude '*.kate-swp' \ @@ -86,5 +94,5 @@ youtube-dl.tar.gz: youtube-dl README.md README.txt youtube-dl.1 youtube-dl.bash- bin devscripts test youtube_dl docs \ LICENSE README.md README.txt \ Makefile MANIFEST.in youtube-dl.1 youtube-dl.bash-completion \ - youtube-dl.fish setup.py \ + youtube-dl.zsh youtube-dl.fish setup.py \ youtube-dl From 7bc8780c576505fd87a5c85ff1f50ef2e8841d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Tue, 7 Oct 2014 22:23:05 +0700 Subject: [PATCH 1042/1761] [walla] Fix extractor and add subtitle tests --- test/test_subtitles.py | 28 +++++++++++ youtube_dl/extractor/walla.py | 95 +++++++++++++++++++++-------------- 2 files changed, 85 insertions(+), 38 deletions(-) diff --git a/test/test_subtitles.py b/test/test_subtitles.py index 48c302198..eb5f2f8dd 100644 --- a/test/test_subtitles.py +++ b/test/test_subtitles.py @@ -15,6 +15,7 @@ from youtube_dl.extractor import ( DailymotionIE, TEDIE, VimeoIE, + WallaIE, ) @@ -279,5 +280,32 @@ class TestVimeoSubtitles(BaseTestSubtitles): self.assertTrue(subtitles.get(lang) is not None, u'Subtitles for \'%s\' not extracted' % lang) +class TestWallsSubtitles(BaseTestSubtitles): + url = 'http://vod.walla.co.il/movie/2705958/the-yes-men' + IE = WallaIE + + def test_list_subtitles(self): + self.DL.expect_warning(u'Automatic Captions not supported by this server') + self.DL.params['listsubtitles'] = True + info_dict = self.getInfoDict() + self.assertEqual(info_dict, None) + + def test_allsubtitles(self): + self.DL.expect_warning(u'Automatic Captions not supported by this server') + self.DL.params['writesubtitles'] = True + self.DL.params['allsubtitles'] = True + subtitles = self.getSubtitles() + self.assertEqual(set(subtitles.keys()), set(['heb'])) + self.assertEqual(md5(subtitles['heb']), 'e758c5d7cb982f6bef14f377ec7a3920') + + def test_nosubtitles(self): + self.DL.expect_warning(u'video doesn\'t have subtitles') + self.url = 'http://vod.walla.co.il/movie/2642630/one-direction-all-for-one' + self.DL.params['writesubtitles'] = True + self.DL.params['allsubtitles'] = True + subtitles = self.getSubtitles() + self.assertEqual(len(subtitles), 0) + + if __name__ == '__main__': unittest.main() diff --git a/youtube_dl/extractor/walla.py b/youtube_dl/extractor/walla.py index e687c3af0..672bda7a7 100644 --- a/youtube_dl/extractor/walla.py +++ b/youtube_dl/extractor/walla.py @@ -1,70 +1,89 @@ # coding: utf-8 from __future__ import unicode_literals - import re -from .common import InfoExtractor +from .subtitles import SubtitlesInfoExtractor +from ..utils import ( + xpath_text, + int_or_none, +) -class WallaIE(InfoExtractor): - _VALID_URL = r'http://vod\.walla\.co\.il/\w+/(?P\d+)' +class WallaIE(SubtitlesInfoExtractor): + _VALID_URL = r'http://vod\.walla\.co\.il/[^/]+/(?P\d+)/(?P.+)' _TEST = { 'url': 'http://vod.walla.co.il/movie/2642630/one-direction-all-for-one', 'info_dict': { 'id': '2642630', + 'display_id': 'one-direction-all-for-one', 'ext': 'flv', 'title': 'וואן דיירקשן: ההיסטריה', + 'description': 'md5:de9e2512a92442574cdb0913c49bc4d8', + 'thumbnail': 're:^https?://.*\.jpg', + 'duration': 3600, + }, + 'params': { + # rtmp download + 'skip_download': True, } } + _SUBTITLE_LANGS = { + 'עברית': 'heb', + } + def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') + display_id = mobj.group('display_id') - config_url = 'http://video2.walla.co.il/?w=null/null/%s/@@/video/flv_pl' % video_id - - webpage = self._download_webpage(config_url, video_id, '') + video = self._download_xml( + 'http://video2.walla.co.il/?w=null/null/%s/@@/video/flv_pl' % video_id, + display_id) - media_id = self._html_search_regex(r'(\d+)', webpage, video_id, 'extract media id') + item = video.find('./items/item') - prefix = '0' if len(media_id) == 7 else '' - - series = '%s%s' % (prefix, media_id[0:2]) - session = media_id[2:5] - episode = media_id[5:7] - - title = self._html_search_regex(r'(.*)', webpage, video_id, 'title') - - default_quality = self._html_search_regex(r'', webpage, video_id, 0) - - quality = default_quality if default_quality else '40' - - media_path = '/%s/%s/%s' % (series, session, media_id) #self._html_search_regex(r'.*(.*)' % default_quality ,webpage, '', flags=re.DOTALL) - - playpath = 'mp4:media/%s/%s/%s-%s' % (series, session, media_id, quality) #self._html_search_regex(r'.*(.*)' % default_quality ,webpage, '', flags=re.DOTALL) + title = xpath_text(item, './title', 'title') + description = xpath_text(item, './synopsis', 'description') + thumbnail = xpath_text(item, './preview_pic', 'thumbnail') + duration = int_or_none(xpath_text(item, './duration', 'duration')) subtitles = {} + for subtitle in item.findall('./subtitles/subtitle'): + lang = xpath_text(subtitle, './title') + subtitles[self._SUBTITLE_LANGS.get(lang, lang)] = xpath_text(subtitle, './src') - subtitle_url = self._html_search_regex(r'(.*).*', webpage, video_id, 0) + if self._downloader.params.get('listsubtitles', False): + self._list_available_subtitles(video_id, subtitles) + return - print subtitle_url + subtitles = self.extract_subtitles(video_id, subtitles) - if subtitle_url: - subtitles_page = self._download_webpage(subtitle_url, video_id, '') - subtitles['heb'] = subtitles_page + formats = [] + for quality in item.findall('./qualities/quality'): + format_id = xpath_text(quality, './title') + fmt = { + 'url': 'rtmp://wafla.walla.co.il/vod', + 'play_path': xpath_text(quality, './src'), + 'player_url': 'http://isc.walla.co.il/w9/swf/video_swf/vod/WallaMediaPlayerAvod.swf', + 'page_url': url, + 'ext': 'flv', + 'format_id': xpath_text(quality, './title'), + } + m = re.search(r'^(?P\d+)[Pp]', format_id) + if m: + fmt['height'] = int(m.group('height')) + formats.append(fmt) + self._sort_formats(formats) return { 'id': video_id, + 'display_id': display_id, 'title': title, - 'url': 'rtmp://wafla.walla.co.il:1935/vod', - 'player_url': 'http://isc.walla.co.il/w9/swf/video_swf/vod/WallaMediaPlayerAvod.swf', - 'page_url': url, - 'app': "vod", - 'play_path': playpath, - 'tc_url': 'rtmp://wafla.walla.co.il:1935/vod', - 'rtmp_protocol': 'rtmp', - 'ext': 'flv', + 'description': description, + 'thumbnail': thumbnail, + 'duration': duration, + 'formats': formats, 'subtitles': subtitles, - } \ No newline at end of file + } From 842cca7d56c155f515ba0919d709a412291ef52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Wed, 8 Oct 2014 20:08:29 +0700 Subject: [PATCH 1043/1761] [pornhd] Fix formats extraction (Closes #3898) --- youtube_dl/extractor/pornhd.py | 52 ++++++++++++++-------------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/youtube_dl/extractor/pornhd.py b/youtube_dl/extractor/pornhd.py index 48ce6e730..bac484c67 100644 --- a/youtube_dl/extractor/pornhd.py +++ b/youtube_dl/extractor/pornhd.py @@ -4,19 +4,27 @@ import re import json from .common import InfoExtractor -from ..utils import int_or_none +from ..utils import ( + int_or_none, + js_to_json, + qualities, + determine_ext, +) class PornHdIE(InfoExtractor): - _VALID_URL = r'http://(?:www\.)?pornhd\.com/(?:[a-z]{2,4}/)?videos/(?P\d+)' + _VALID_URL = r'http://(?:www\.)?pornhd\.com/(?:[a-z]{2,4}/)?videos/(?P\d+)(?:/(?P.+))?' _TEST = { 'url': 'http://www.pornhd.com/videos/1962/sierra-day-gets-his-cum-all-over-herself-hd-porn-video', 'md5': '956b8ca569f7f4d8ec563e2c41598441', 'info_dict': { 'id': '1962', + 'display_id': 'sierra-day-gets-his-cum-all-over-herself-hd-porn-video', 'ext': 'mp4', 'title': 'Sierra loves doing laundry', 'description': 'md5:8ff0523848ac2b8f9b065ba781ccf294', + 'thumbnail': 're:^https?://.*\.jpg', + 'view_count': int, 'age_limit': 18, } } @@ -24,8 +32,9 @@ class PornHdIE(InfoExtractor): def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('id') + display_id = mobj.group('display_id') - webpage = self._download_webpage(url, video_id) + webpage = self._download_webpage(url, display_id or video_id) title = self._html_search_regex( r'(.+) porn HD.+?', webpage, 'title') @@ -33,38 +42,21 @@ class PornHdIE(InfoExtractor): r'
([^<]+)
', webpage, 'description', fatal=False) view_count = int_or_none(self._html_search_regex( r'(\d+) views\s*', webpage, 'view count', fatal=False)) + thumbnail = self._search_regex( + r"'poster'\s*:\s*'([^']+)'", webpage, 'thumbnail', fatal=False) - videos = re.findall( - r'var __video([\da-zA-Z]+?)(Low|High)StreamUrl = \'(http://.+?)\?noProxy=1\'', webpage) - - mobj = re.search(r'flashVars = (?P{.+?});', webpage) - if mobj: - flashvars = json.loads(mobj.group('flashvars')) - for key, quality in [('hashlink', 'low'), ('hd', 'high')]: - redirect_url = flashvars.get(key) - if redirect_url: - videos.append(('flv', quality, redirect_url)) - thumbnail = flashvars['urlWallpaper'] - else: - thumbnail = self._og_search_thumbnail(webpage) - - formats = [] - for format_, quality, redirect_url in videos: - format_id = '%s-%s' % (format_.lower(), quality.lower()) - video_url = self._download_webpage( - redirect_url, video_id, 'Downloading %s video link' % format_id, fatal=False) - if not video_url: - continue - formats.append({ - 'url': video_url, - 'ext': format_.lower(), - 'format_id': format_id, - 'quality': 1 if quality.lower() == 'high' else 0, - }) + quality = qualities(['SD', 'HD']) + formats = [{ + 'url': source['file'], + 'format_id': '%s-%s' % (source['label'], determine_ext(source['file'])), + 'quality': quality(source['label']), + } for source in json.loads(js_to_json(self._search_regex( + r"(?s)'sources'\s*:\s*(\[.+?\])", webpage, 'sources')))] self._sort_formats(formats) return { 'id': video_id, + 'display_id': display_id, 'title': title, 'description': description, 'thumbnail': thumbnail, From ced659bb4d066c782a009d370daff0fedb7b1006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Thu, 9 Oct 2014 19:26:23 +0700 Subject: [PATCH 1044/1761] [generic] Ignore some non-video file extensions during generic extraction (Closes #3900) --- youtube_dl/extractor/generic.py | 34 ++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index c16da70f1..dfc2ef4e7 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -847,47 +847,51 @@ class GenericIE(InfoExtractor): if mobj is not None: return self.url_result(mobj.group('url'), 'MLB') + def check_video(vurl): + vpath = compat_urlparse.urlparse(vurl).path + vext = determine_ext(vpath) + return '.' in vpath and vext not in ('swf', 'png', 'jpg', 'srt', 'sbv', 'sub', 'vtt', 'ttml') + + def filter_video(urls): + return list(filter(check_video, urls)) + # Start with something easy: JW Player in SWFObject - found = re.findall(r'flashvars: [\'"](?:.*&)?file=(http[^\'"&]*)', webpage) + found = filter_video(re.findall(r'flashvars: [\'"](?:.*&)?file=(http[^\'"&]*)', webpage)) if not found: # Look for gorilla-vid style embedding - found = re.findall(r'''(?sx) + found = filter_video(re.findall(r'''(?sx) (?: jw_plugins| JWPlayerOptions| jwplayer\s*\(\s*["'][^'"]+["']\s*\)\s*\.setup ) - .*?file\s*:\s*["\'](.*?)["\']''', webpage) + .*?file\s*:\s*["\'](.*?)["\']''', webpage)) if not found: # Broaden the search a little bit - found = re.findall(r'[^A-Za-z0-9]?(?:file|source)=(http[^\'"&]*)', webpage) + found = filter_video(re.findall(r'[^A-Za-z0-9]?(?:file|source)=(http[^\'"&]*)', webpage)) if not found: # Broaden the findall a little bit: JWPlayer JS loader - found = re.findall(r'[^A-Za-z0-9]?file["\']?:\s*["\'](http(?![^\'"]+\.[0-9]+[\'"])[^\'"]+)["\']', webpage) + found = filter_video(re.findall( + r'[^A-Za-z0-9]?file["\']?:\s*["\'](http(?![^\'"]+\.[0-9]+[\'"])[^\'"]+)["\']', webpage)) if not found: # Flow player - found = re.findall(r'''(?xs) + found = filter_video(re.findall(r'''(?xs) flowplayer\("[^"]+",\s* \{[^}]+?\}\s*, \s*{[^}]+? ["']?clip["']?\s*:\s*\{\s* ["']?url["']?\s*:\s*["']([^"']+)["'] - ''', webpage) + ''', webpage)) if not found: # Try to find twitter cards info - found = re.findall(r'.*?]+)? src="([^"]+)"', webpage) From 385009fc443eb81dc8695dd46448950bbe76cce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Thu, 9 Oct 2014 19:56:55 +0700 Subject: [PATCH 1045/1761] [mlb] Fix thumbnails extraction (Closes #3905) --- youtube_dl/extractor/mlb.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/youtube_dl/extractor/mlb.py b/youtube_dl/extractor/mlb.py index bfdb462eb..362c2b5c9 100644 --- a/youtube_dl/extractor/mlb.py +++ b/youtube_dl/extractor/mlb.py @@ -88,8 +88,9 @@ class MLBIE(InfoExtractor): duration = parse_duration(detail.find('./duration').text) timestamp = parse_iso8601(detail.attrib['date'][:-5]) - thumbnail = find_xpath_attr( - detail, './thumbnailScenarios/thumbnailScenario', 'type', '45').text + thumbnails = [{ + 'url': thumbnail.text, + } for thumbnail in detail.findall('./thumbnailScenarios/thumbnailScenario')] formats = [] for media_url in detail.findall('./url'): @@ -116,5 +117,5 @@ class MLBIE(InfoExtractor): 'duration': duration, 'timestamp': timestamp, 'formats': formats, - 'thumbnail': thumbnail, + 'thumbnails': thumbnails, } From b097b5f2469e9df11c120b6338a38b28f951510c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Thu, 9 Oct 2014 20:07:34 +0700 Subject: [PATCH 1046/1761] [mlb] Remove unused import --- youtube_dl/extractor/mlb.py | 1 - 1 file changed, 1 deletion(-) diff --git a/youtube_dl/extractor/mlb.py b/youtube_dl/extractor/mlb.py index 362c2b5c9..42aa2e227 100644 --- a/youtube_dl/extractor/mlb.py +++ b/youtube_dl/extractor/mlb.py @@ -6,7 +6,6 @@ from .common import InfoExtractor from ..utils import ( parse_duration, parse_iso8601, - find_xpath_attr, ) From fc6861b175ec1ad1d7aa322438b095840c437249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Thu, 9 Oct 2014 21:05:39 +0700 Subject: [PATCH 1047/1761] [sportbox] Add extractor (Closes #3906) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/sportbox.py | 81 ++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 youtube_dl/extractor/sportbox.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 76726305a..f96ddfd23 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -347,6 +347,7 @@ from .spiegel import SpiegelIE, SpiegelArticleIE from .spiegeltv import SpiegeltvIE from .spike import SpikeIE from .sport5 import Sport5IE +from .sportbox import SportBoxIE from .sportdeutschland import SportDeutschlandIE from .stanfordoc import StanfordOpenClassroomIE from .steam import SteamIE diff --git a/youtube_dl/extractor/sportbox.py b/youtube_dl/extractor/sportbox.py new file mode 100644 index 000000000..19cc976e3 --- /dev/null +++ b/youtube_dl/extractor/sportbox.py @@ -0,0 +1,81 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ( + parse_duration, + parse_iso8601, + int_or_none, +) + + +class SportBoxIE(InfoExtractor): + _VALID_URL = r'https?://news\.sportbox\.ru/Vidy_sporta/(?:[^/]+/)+spbvideo_NI\d+_(?P.+)' + _TESTS = [ + { + 'url': 'http://news.sportbox.ru/Vidy_sporta/Avtosport/Rossijskij/spbvideo_NI483529_Gonka-2-zaezd-Obyedinenniy-2000-klassi-Turing-i-S', + 'md5': 'ff56a598c2cf411a9a38a69709e97079', + 'info_dict': { + 'id': '80822', + 'ext': 'mp4', + 'title': 'Гонка 2 заезд ««Объединенный 2000»: классы Туринг и Супер-продакшн', + 'description': 'md5:81715fa9c4ea3d9e7915dc8180c778ed', + 'thumbnail': 're:^https?://.*\.jpg$', + 'timestamp': 1411896237, + 'upload_date': '20140928', + 'duration': 4846, + 'view_count': int, + }, + 'params': { + # m3u8 download + 'skip_download': True, + }, + }, { + 'url': 'http://news.sportbox.ru/Vidy_sporta/billiard/spbvideo_NI486287_CHempionat-mira-po-dinamichnoy-piramide-4', + 'only_matching': True, + } + ] + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + display_id = mobj.group('display_id') + + webpage = self._download_webpage(url, display_id) + + video_id = self._search_regex( + r'src="/vdl/player/media/(\d+)"', webpage, 'video id') + + player = self._download_webpage( + 'http://news.sportbox.ru/vdl/player/media/%s' % video_id, + display_id, 'Downloading player webpage') + + hls = self._search_regex( + r"var\s+original_hls_file\s*=\s*'([^']+)'", player, 'hls file') + + formats = self._extract_m3u8_formats(hls, display_id, 'mp4') + + title = self._html_search_regex( + r'

([^<]+)

', webpage, 'title') + description = self._html_search_regex( + r'(?s)
(.+?)
', webpage, 'description', fatal=False) + thumbnail = self._og_search_thumbnail(webpage) + timestamp = parse_iso8601(self._search_regex( + r'([^<]+)', webpage, 'timestamp', fatal=False)) + duration = parse_duration(self._html_search_regex( + r'', webpage, 'duration', fatal=False)) + view_count = int_or_none(self._html_search_regex( + r'Просмотров: (\d+)', player, 'view count', fatal=False)) + + return { + 'id': video_id, + 'display_id': display_id, + 'title': title, + 'description': description, + 'thumbnail': thumbnail, + 'timestamp': timestamp, + 'duration': duration, + 'view_count': view_count, + 'formats': formats, + } From 0ca41c3d9c7405cb79a5f11fcd6e57e7d5e07dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Thu, 9 Oct 2014 21:10:07 +0700 Subject: [PATCH 1048/1761] [walla] Fix typo --- test/test_subtitles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_subtitles.py b/test/test_subtitles.py index eb5f2f8dd..8f4602e5f 100644 --- a/test/test_subtitles.py +++ b/test/test_subtitles.py @@ -280,7 +280,7 @@ class TestVimeoSubtitles(BaseTestSubtitles): self.assertTrue(subtitles.get(lang) is not None, u'Subtitles for \'%s\' not extracted' % lang) -class TestWallsSubtitles(BaseTestSubtitles): +class TestWallaSubtitles(BaseTestSubtitles): url = 'http://vod.walla.co.il/movie/2705958/the-yes-men' IE = WallaIE From 1b725173a5bf3fefcb800222e0c473d65d6cea70 Mon Sep 17 00:00:00 2001 From: George Boyle Date: Thu, 9 Oct 2014 16:00:24 +0100 Subject: [PATCH 1049/1761] Fixed typo --- youtube_dl/YoutubeDL.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 4a9610355..4e2a74624 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -232,7 +232,7 @@ class YoutubeDL(object): # On Python 3, the Unicode filesystem API will throw errors (#1474) self.report_warning( 'Assuming --restrict-filenames since file system encoding ' - 'cannot encode all charactes. ' + 'cannot encode all characters. ' 'Set the LC_ALL environment variable to fix this.') self.params['restrictfilenames'] = True From 53d9009bdb064a43674136d0952a73546b828cd9 Mon Sep 17 00:00:00 2001 From: George Boyle Date: Fri, 10 Oct 2014 09:33:41 +0100 Subject: [PATCH 1050/1761] KeyError on initialising YoutubeDL in python3 #3910 --- youtube_dl/YoutubeDL.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 4e2a74624..dec0e20e7 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -228,7 +228,7 @@ class YoutubeDL(object): if (sys.version_info >= (3,) and sys.platform != 'win32' and sys.getfilesystemencoding() in ['ascii', 'ANSI_X3.4-1968'] - and not params['restrictfilenames']): + and not params.get('restrictfilenames', False)): # On Python 3, the Unicode filesystem API will throw errors (#1474) self.report_warning( 'Assuming --restrict-filenames since file system encoding ' From 762958d5afa04735428cd39c77e78d81c6809672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Fri, 10 Oct 2014 19:50:29 +0700 Subject: [PATCH 1051/1761] [yahoo] Add support for regional subdomains and extract duration (Closes #3915) --- youtube_dl/extractor/yahoo.py | 37 +++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/youtube_dl/extractor/yahoo.py b/youtube_dl/extractor/yahoo.py index 221341c13..ef5ac03f0 100644 --- a/youtube_dl/extractor/yahoo.py +++ b/youtube_dl/extractor/yahoo.py @@ -1,3 +1,4 @@ +# coding: utf-8 from __future__ import unicode_literals import itertools @@ -15,7 +16,7 @@ from ..utils import ( class YahooIE(InfoExtractor): IE_DESC = 'Yahoo screen and movies' - _VALID_URL = r'(?Phttps?://(?:screen|movies)\.yahoo\.com/.*?-(?P[0-9]+)(?:-[a-z]+)?\.html)' + _VALID_URL = r'(?Phttps?://(?:.+?\.)?(?:screen|movies)\.yahoo\.com/.*?-(?P[0-9]+)(?:-[a-z]+)?\.html)' _TESTS = [ { 'url': 'http://screen.yahoo.com/julian-smith-travis-legg-watch-214727115.html', @@ -25,6 +26,7 @@ class YahooIE(InfoExtractor): 'ext': 'mp4', 'title': 'Julian Smith & Travis Legg Watch Julian Smith', 'description': 'Julian and Travis watch Julian Smith', + 'duration': 6863, }, }, { @@ -34,7 +36,8 @@ class YahooIE(InfoExtractor): 'id': 'd1dedf8c-d58c-38c3-8963-e899929ae0a9', 'ext': 'mp4', 'title': 'Codefellas - The Cougar Lies with Spanish Moss', - 'description': 'Agent Topple\'s mustache does its dirty work, and Nicole brokers a deal for peace. But why is the NSA collecting millions of Instagram brunch photos? And if your waffles have nothing to hide, what are they so worried about?', + 'description': 'md5:66b627ab0a282b26352136ca96ce73c1', + 'duration': 151, }, }, { @@ -45,6 +48,29 @@ class YahooIE(InfoExtractor): 'ext': 'mp4', 'title': "Yahoo Saves 'Community'", 'description': 'md5:4d4145af2fd3de00cbb6c1d664105053', + 'duration': 170, + } + }, + { + 'url': 'https://tw.screen.yahoo.com/taipei-opinion-poll/選情站報-街頭民調-台北市篇-102823042.html', + 'md5': '92a7fdd8a08783c68a174d7aa067dde8', + 'info_dict': { + 'id': '7a23b569-7bea-36cb-85b9-bd5301a0a1fb', + 'ext': 'mp4', + 'title': '選情站報 街頭民調 台北市篇', + 'description': '選情站報 街頭民調 台北市篇', + 'duration': 429, + } + }, + { + 'url': 'https://uk.screen.yahoo.com/editor-picks/cute-raccoon-freed-drain-using-091756545.html ', + 'md5': '0b51660361f0e27c9789e7037ef76f4b', + 'info_dict': { + 'id': 'b3affa53-2e14-3590-852b-0e0db6cd1a58', + 'ext': 'mp4', + 'title': 'Cute Raccoon Freed From Drain\u00a0Using Angle Grinder', + 'description': 'md5:f66c890e1490f4910a9953c941dee944', + 'duration': 97, } }, ] @@ -75,9 +101,11 @@ class YahooIE(InfoExtractor): return self._get_info(long_id, video_id, webpage) def _get_info(self, long_id, video_id, webpage): + region = self._search_regex( + r'"region"\s*:\s*"([^"]+)"', webpage, 'region', fatal=False, default='US') query = ('SELECT * FROM yahoo.media.video.streams WHERE id="%s"' - ' AND plrs="86Gj0vCaSzV_Iuf6hNylf2" AND region="US"' - ' AND protocol="http"' % long_id) + ' AND plrs="86Gj0vCaSzV_Iuf6hNylf2" AND region="%s"' + ' AND protocol="http"' % (long_id, region)) data = compat_urllib_parse.urlencode({ 'q': query, 'env': 'prod', @@ -118,6 +146,7 @@ class YahooIE(InfoExtractor): 'formats': formats, 'description': clean_html(meta['description']), 'thumbnail': meta['thumbnail'] if meta.get('thumbnail') else self._og_search_thumbnail(webpage), + 'duration': int_or_none(meta.get('duration')), } From 3c06d3715eac87c945e75fa2f3ad41490d0da1d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Fri, 10 Oct 2014 22:11:30 +0700 Subject: [PATCH 1052/1761] [yahoo] Generalize, support arbitrary subdomains, support iframe videos, capture error message (Closes #2470) --- youtube_dl/extractor/__init__.py | 2 +- youtube_dl/extractor/yahoo.py | 116 +++++++++++++++++++++---------- 2 files changed, 81 insertions(+), 37 deletions(-) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index f96ddfd23..5386ac553 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -463,7 +463,7 @@ from .xvideos import XVideosIE from .xtube import XTubeUserIE, XTubeIE from .yahoo import ( YahooIE, - YahooNewsIE, + #YahooNewsIE, YahooSearchIE, ) from .ynet import YnetIE diff --git a/youtube_dl/extractor/yahoo.py b/youtube_dl/extractor/yahoo.py index ef5ac03f0..117f0856a 100644 --- a/youtube_dl/extractor/yahoo.py +++ b/youtube_dl/extractor/yahoo.py @@ -7,6 +7,7 @@ import re from .common import InfoExtractor, SearchInfoExtractor from ..utils import ( + ExtractorError, compat_urllib_parse, compat_urlparse, clean_html, @@ -16,7 +17,7 @@ from ..utils import ( class YahooIE(InfoExtractor): IE_DESC = 'Yahoo screen and movies' - _VALID_URL = r'(?Phttps?://(?:.+?\.)?(?:screen|movies)\.yahoo\.com/.*?-(?P[0-9]+)(?:-[a-z]+)?\.html)' + _VALID_URL = r'(?P(?Phttps?://(?:[a-zA-Z]{2}\.)?[\da-zA-Z_-]+\.yahoo\.com)/(?:[^/]+/)*(?P.+?)-(?P[0-9]+)(?:-[a-z]+)?\.html)' _TESTS = [ { 'url': 'http://screen.yahoo.com/julian-smith-travis-legg-watch-214727115.html', @@ -63,7 +64,7 @@ class YahooIE(InfoExtractor): } }, { - 'url': 'https://uk.screen.yahoo.com/editor-picks/cute-raccoon-freed-drain-using-091756545.html ', + 'url': 'https://uk.screen.yahoo.com/editor-picks/cute-raccoon-freed-drain-using-091756545.html', 'md5': '0b51660361f0e27c9789e7037ef76f4b', 'info_dict': { 'id': 'b3affa53-2e14-3590-852b-0e0db6cd1a58', @@ -73,13 +74,70 @@ class YahooIE(InfoExtractor): 'duration': 97, } }, + { + 'url': 'https://ca.sports.yahoo.com/video/program-makes-hockey-more-affordable-013127711.html', + 'md5': '57e06440778b1828a6079d2f744212c4', + 'info_dict': { + 'id': 'c9fa2a36-0d4d-3937-b8f6-cc0fb1881e73', + 'ext': 'mp4', + 'title': 'Program that makes hockey more affordable not offered in Manitoba', + 'description': 'md5:c54a609f4c078d92b74ffb9bf1f496f4', + 'duration': 121, + } + }, { + 'url': 'https://ca.finance.yahoo.com/news/20-most-valuable-brands-world-112600775.html', + 'md5': '3e401e4eed6325aa29d9b96125fd5b4f', + 'info_dict': { + 'id': 'c1b4c09c-8ed8-3b65-8b05-169c55358a83', + 'ext': 'mp4', + 'title': "Apple Is The World's Most Valuable Brand", + 'description': 'md5:73eabc1a11c6f59752593b2ceefa1262', + 'duration': 21, + } + }, { + 'url': 'http://news.yahoo.com/video/china-moses-crazy-blues-104538833.html', + 'md5': '67010fdf3a08d290e060a4dd96baa07b', + 'info_dict': { + 'id': 'f885cf7f-43d4-3450-9fac-46ac30ece521', + 'ext': 'mp4', + 'title': 'China Moses Is Crazy About the Blues', + 'description': 'md5:9900ab8cd5808175c7b3fe55b979bed0', + 'duration': 128, + } + }, { + 'url': 'https://in.lifestyle.yahoo.com/video/connect-dots-dark-side-virgo-090247395.html', + 'md5': 'd9a083ccf1379127bf25699d67e4791b', + 'info_dict': { + 'id': '52aeeaa3-b3d1-30d8-9ef8-5d0cf05efb7c', + 'ext': 'mp4', + 'title': 'Connect the Dots: Dark Side of Virgo', + 'description': 'md5:1428185051cfd1949807ad4ff6d3686a', + 'duration': 201, + } + }, { + 'url': 'https://gma.yahoo.com/pizza-delivery-man-surprised-huge-tip-college-kids-195200785.html', + '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') url = mobj.group('url') - webpage = self._download_webpage(url, video_id) + host = mobj.group('host') + webpage = self._download_webpage(url, display_id) + + # Look for iframed media first + iframe_m = re.search(r']+src="(/video/.+?-\d+\.html\?format=embed.*?)"', webpage) + if iframe_m: + iframepage = self._download_webpage( + host + iframe_m.group(1), display_id, 'Downloading iframe webpage') + items_json = self._search_regex( + r'mediaItems: (\[.+?\])$', iframepage, 'items', flags=re.MULTILINE, default=None) + if items_json: + items = json.loads(items_json) + video_id = items[0]['id'] + return self._get_info(video_id, display_id, webpage) items_json = self._search_regex( r'mediaItems: ({.*?})$', webpage, 'items', flags=re.MULTILINE, @@ -90,22 +148,22 @@ class YahooIE(InfoExtractor): r'root\.App\.Cache\.context\.videoCache\.curVideo = \{"([^"]+)"', r'"first_videoid"\s*:\s*"([^"]+)"', ] - long_id = self._search_regex(CONTENT_ID_REGEXES, webpage, 'content ID') - video_id = long_id + video_id = self._search_regex(CONTENT_ID_REGEXES, webpage, 'content ID') else: items = json.loads(items_json) info = items['mediaItems']['query']['results']['mediaObj'][0] # The 'meta' field is not always in the video webpage, we request it # from another page - long_id = info['id'] - return self._get_info(long_id, video_id, webpage) + video_id = info['id'] + return self._get_info(video_id, display_id, webpage) - def _get_info(self, long_id, video_id, webpage): + def _get_info(self, video_id, display_id, webpage): region = self._search_regex( - r'"region"\s*:\s*"([^"]+)"', webpage, 'region', fatal=False, default='US') + r'\\?"region\\?"\s*:\s*\\?"([^"]+?)\\?"', + webpage, 'region', fatal=False, default='US') query = ('SELECT * FROM yahoo.media.video.streams WHERE id="%s"' ' AND plrs="86Gj0vCaSzV_Iuf6hNylf2" AND region="%s"' - ' AND protocol="http"' % (long_id, region)) + ' AND protocol="http"' % (video_id, region)) data = compat_urllib_parse.urlencode({ 'q': query, 'env': 'prod', @@ -113,9 +171,17 @@ class YahooIE(InfoExtractor): }) query_result = self._download_json( 'http://video.query.yahoo.com/v1/public/yql?' + data, - video_id, 'Downloading video info') + display_id, 'Downloading video info') + info = query_result['query']['results']['mediaObj'][0] - meta = info['meta'] + meta = info.get('meta') + + if not meta: + msg = info['status'].get('msg') + if msg: + raise ExtractorError( + '%s returned error: %s' % (self.IE_NAME, msg), expected=True) + raise ExtractorError('Unable to extract media object meta') formats = [] for s in info['streams']: @@ -142,6 +208,7 @@ class YahooIE(InfoExtractor): return { 'id': video_id, + 'display_id': display_id, 'title': meta['title'], 'formats': formats, 'description': clean_html(meta['description']), @@ -150,29 +217,6 @@ class YahooIE(InfoExtractor): } -class YahooNewsIE(YahooIE): - IE_NAME = 'yahoo:news' - _VALID_URL = r'http://news\.yahoo\.com/video/.*?-(?P\d*?)\.html' - - _TESTS = [{ - 'url': 'http://news.yahoo.com/video/china-moses-crazy-blues-104538833.html', - 'md5': '67010fdf3a08d290e060a4dd96baa07b', - 'info_dict': { - 'id': '104538833', - 'ext': 'mp4', - 'title': 'China Moses Is Crazy About the Blues', - 'description': 'md5:9900ab8cd5808175c7b3fe55b979bed0', - }, - }] - - def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') - webpage = self._download_webpage(url, video_id) - long_id = self._search_regex(r'contentId: \'(.+?)\',', webpage, 'long id') - return self._get_info(long_id, video_id, webpage) - - class YahooSearchIE(SearchInfoExtractor): IE_DESC = 'Yahoo screen search' _MAX_RESULTS = 1000 From 823f1e015a8880442f9b9fcf2943f647f5cf8039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Fri, 10 Oct 2014 22:18:37 +0700 Subject: [PATCH 1053/1761] [yahoo] Wipe out yahoo news extractor --- youtube_dl/extractor/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 5386ac553..dd770fdf1 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -463,7 +463,6 @@ from .xvideos import XVideosIE from .xtube import XTubeUserIE, XTubeIE from .yahoo import ( YahooIE, - #YahooNewsIE, YahooSearchIE, ) from .ynet import YnetIE From 3741302a109f28081a9db805a371c744f7bd2a2b Mon Sep 17 00:00:00 2001 From: Ole Ernst Date: Fri, 10 Oct 2014 20:35:34 +0200 Subject: [PATCH 1054/1761] [ard] Add rss support --- youtube_dl/extractor/ard.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/youtube_dl/extractor/ard.py b/youtube_dl/extractor/ard.py index 8de9c11ea..cd9c1d9be 100644 --- a/youtube_dl/extractor/ard.py +++ b/youtube_dl/extractor/ard.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import re from .common import InfoExtractor +from .generic import GenericIE from ..utils import ( determine_ext, ExtractorError, @@ -12,6 +13,7 @@ from ..utils import ( parse_duration, unified_strdate, xpath_text, + parse_xml, ) @@ -54,6 +56,11 @@ class ARDMediathekIE(InfoExtractor): if '>Der gewünschte Beitrag ist nicht mehr verfügbar.<' in webpage: raise ExtractorError('Video %s is no longer available' % video_id, expected=True) + if re.search(r'rss=true', url): + doc = parse_xml(webpage) + if doc.tag == 'rss': + return GenericIE()._extract_rss(url, video_id, doc) + title = self._html_search_regex( [r'(.*?)', r'', From 1409704afa2d076f1d8ea05430d83834b6ffa57a Mon Sep 17 00:00:00 2001 From: dinesh Date: Sat, 11 Oct 2014 12:20:13 +0530 Subject: [PATCH 1055/1761] Fix ndr.de outdated test url --- youtube_dl/extractor/ndr.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/youtube_dl/extractor/ndr.py b/youtube_dl/extractor/ndr.py index 94d5ba982..cf7f0309b 100644 --- a/youtube_dl/extractor/ndr.py +++ b/youtube_dl/extractor/ndr.py @@ -18,16 +18,16 @@ class NDRIE(InfoExtractor): _TESTS = [ { - 'url': 'http://www.ndr.de/fernsehen/media/dienordreportage325.html', - 'md5': '4a4eeafd17c3058b65f0c8f091355855', + 'url': 'http://www.ndr.de/fernsehen/sendungen/nordmagazin/Kartoffeltage-in-der-Lewitz,nordmagazin25866.html', + 'md5': '5bc5f5b92c82c0f8b26cddca34f8bb2c', 'note': 'Video file', 'info_dict': { - 'id': '325', + 'id': '25866', 'ext': 'mp4', - 'title': 'Blaue Bohnen aus Blocken', - 'description': 'md5:190d71ba2ccddc805ed01547718963bc', - 'duration': 1715, - }, + 'title': 'Kartoffeltage in der Lewitz', + 'description': 'md5:16d4d66907f541692e8182c33270f29a', + 'duration': 166, + } }, { 'url': 'http://www.ndr.de/info/audio51535.html', From f4cf848d1d4e0eeec5fedfda79fad50f0b55ec4a Mon Sep 17 00:00:00 2001 From: dinesh Date: Sat, 11 Oct 2014 15:59:42 +0530 Subject: [PATCH 1056/1761] Replace 404 url --- youtube_dl/extractor/howstuffworks.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/youtube_dl/extractor/howstuffworks.py b/youtube_dl/extractor/howstuffworks.py index 68684b997..fccc23884 100644 --- a/youtube_dl/extractor/howstuffworks.py +++ b/youtube_dl/extractor/howstuffworks.py @@ -28,13 +28,13 @@ class HowStuffWorksIE(InfoExtractor): } }, { - 'url': 'http://adventure.howstuffworks.com/39516-deadliest-catch-jakes-farewell-pots-video.htm', + 'url': 'http://adventure.howstuffworks.com/7199-survival-zone-food-and-water-in-the-savanna-video.htm', 'info_dict': { - 'id': '553470', - 'display_id': 'deadliest-catch-jakes-farewell-pots', + 'id': '453464', + 'display_id': 'survival-zone-food-and-water-in-the-savanna', 'ext': 'mp4', - 'title': 'Deadliest Catch: Jake\'s Farewell Pots', - 'description': 'md5:9632c346d5e43ee238028c9cefd8dbbc', + 'title': 'Survival Zone: Food and Water In the Savanna', + 'description': 'md5:7e1c89f6411434970c15fa094170c371', 'thumbnail': 're:^https?://.*\.jpg$', }, 'params': { From 071420e136ea2039d45a26cff0b704104edf533c Mon Sep 17 00:00:00 2001 From: dinesh Date: Sat, 11 Oct 2014 21:10:53 +0530 Subject: [PATCH 1057/1761] Fix download error in GooglePlus --- youtube_dl/extractor/googleplus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/googleplus.py b/youtube_dl/extractor/googleplus.py index 07d994b44..1ab5e9260 100644 --- a/youtube_dl/extractor/googleplus.py +++ b/youtube_dl/extractor/googleplus.py @@ -64,7 +64,7 @@ class GooglePlusIE(InfoExtractor): webpage = self._download_webpage(video_page, video_id, 'Downloading video page') # Extract video links all sizes - pattern = r'\d+,\d+,(\d+),"(http\://redirector\.googlevideo\.com.*?)"' + pattern = r'\d+,\d+,(\d+),"(https\://redirector\.googlevideo\.com.*?)"' mobj = re.findall(pattern, webpage) if len(mobj) == 0: raise ExtractorError('Unable to extract video links') From 4828703f1481dc7a84e49904d90fd9decd8e9e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 12 Oct 2014 01:44:13 +0700 Subject: [PATCH 1058/1761] [googleplus] Modernize and extract all formats --- youtube_dl/extractor/googleplus.py | 75 +++++++++++------------------- 1 file changed, 28 insertions(+), 47 deletions(-) diff --git a/youtube_dl/extractor/googleplus.py b/youtube_dl/extractor/googleplus.py index 1ab5e9260..fcefe54cd 100644 --- a/youtube_dl/extractor/googleplus.py +++ b/youtube_dl/extractor/googleplus.py @@ -1,13 +1,11 @@ # coding: utf-8 from __future__ import unicode_literals -import datetime import re +import codecs from .common import InfoExtractor -from ..utils import ( - ExtractorError, -) +from ..utils import unified_strdate class GooglePlusIE(InfoExtractor): @@ -19,74 +17,57 @@ class GooglePlusIE(InfoExtractor): 'info_dict': { 'id': 'ZButuJc6CtH', 'ext': 'flv', + 'title': '嘆きの天使 降臨', 'upload_date': '20120613', 'uploader': '井上ヨシマサ', - 'title': '嘆きの天使 降臨', } } def _real_extract(self, url): - # Extract id from URL - mobj = re.match(self._VALID_URL, url) - - video_id = mobj.group('id') + video_id = self._match_id(url) # Step 1, Retrieve post webpage to extract further information webpage = self._download_webpage(url, video_id, 'Downloading entry webpage') - self.report_extraction(video_id) - - # Extract update date - upload_date = self._html_search_regex( + title = self._og_search_description(webpage).splitlines()[0] + upload_date = unified_strdate(self._html_search_regex( r'''(?x) ([0-9]{4}-[0-9]{2}-[0-9]{2})''', - webpage, 'upload date', fatal=False, flags=re.VERBOSE) - if upload_date: - # Convert timestring to a format suitable for filename - upload_date = datetime.datetime.strptime(upload_date, "%Y-%m-%d") - upload_date = upload_date.strftime('%Y%m%d') - - # Extract uploader - uploader = self._html_search_regex(r'rel\="author".*?>(.*?)', - webpage, 'uploader', fatal=False) - - # Extract title - # Get the first line for title - video_title = self._og_search_description(webpage).splitlines()[0] + webpage, 'upload date', fatal=False, flags=re.VERBOSE)) + uploader = self._html_search_regex( + r'rel="author".*?>(.*?)', webpage, 'uploader', fatal=False) # Step 2, Simulate clicking the image box to launch video DOMAIN = 'https://plus.google.com/' - video_page = self._search_regex(r' Date: Sat, 11 Oct 2014 22:25:30 +0200 Subject: [PATCH 1059/1761] [vimeo] Make the protocol mandatory in the url (fixes #3926) If it's missing, it will be correctly handled by the generic IE. --- youtube_dl/extractor/vimeo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/vimeo.py b/youtube_dl/extractor/vimeo.py index d2c36b58a..e6a86f18e 100644 --- a/youtube_dl/extractor/vimeo.py +++ b/youtube_dl/extractor/vimeo.py @@ -56,7 +56,7 @@ class VimeoIE(VimeoBaseInfoExtractor, SubtitlesInfoExtractor): # _VALID_URL matches Vimeo URLs _VALID_URL = r'''(?x) - (?P(?:https?:)?//)? + https?:// (?:(?:www|(?Pplayer))\.)? vimeo(?Ppro)?\.com/ (?!channels/[^/?#]+/?(?:$|[?#])|album/) From b1c3a49fffb7109125a2ad215f412f1198e3dffd Mon Sep 17 00:00:00 2001 From: "Ching Yi, Chan" Date: Sun, 12 Oct 2014 08:32:26 +0800 Subject: [PATCH 1060/1761] apply ratelimit to f4m --- youtube_dl/downloader/f4m.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/downloader/f4m.py b/youtube_dl/downloader/f4m.py index b3be16ff1..54dd6ac3f 100644 --- a/youtube_dl/downloader/f4m.py +++ b/youtube_dl/downloader/f4m.py @@ -230,6 +230,7 @@ class F4mFD(FileDownloader): 'continuedl': True, 'quiet': True, 'noprogress': True, + 'ratelimit': self.params.get('ratelimit', None), 'test': self.params.get('test', False), }) From b4c3c8c172d42934b6481a8d62a2260dd86855f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sun, 12 Oct 2014 13:06:31 +0200 Subject: [PATCH 1061/1761] [mixcloud] Fix metadata extraction (fixes #3930) --- youtube_dl/extractor/mixcloud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/mixcloud.py b/youtube_dl/extractor/mixcloud.py index 520f27fca..a4564d3de 100644 --- a/youtube_dl/extractor/mixcloud.py +++ b/youtube_dl/extractor/mixcloud.py @@ -70,7 +70,7 @@ class MixcloudIE(InfoExtractor): raise ExtractorError('Unable to extract track url') PREFIX = ( - r'
Date: Sun, 12 Oct 2014 15:42:35 +0300 Subject: [PATCH 1062/1761] [theonion] Add new extractor (closes #3928) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/theonion.py | 71 ++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 youtube_dl/extractor/theonion.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index dd770fdf1..5e38d2663 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -371,6 +371,7 @@ from .telemb import TeleMBIE from .tenplay import TenPlayIE from .testurl import TestURLIE from .tf1 import TF1IE +from .theonion import TheOnionIE from .theplatform import ThePlatformIE from .thesixtyone import TheSixtyOneIE from .thisav import ThisAVIE diff --git a/youtube_dl/extractor/theonion.py b/youtube_dl/extractor/theonion.py new file mode 100644 index 000000000..8e4c3414b --- /dev/null +++ b/youtube_dl/extractor/theonion.py @@ -0,0 +1,71 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ExtractorError + + +class TheOnionIE(InfoExtractor): + _VALID_URL = r'(?x)https?://(?:www\.)?theonion\.com/video/[^,]+,(?P[0-9]+)/?' + _TEST = { + 'url': 'http://www.theonion.com/video/man-wearing-mm-jacket-gods-image,36918/', + 'md5': '19eaa9a39cf9b9804d982e654dc791ee', + 'info_dict': { + 'id': '2133', + 'ext': 'mp4', + 'title': 'Man Wearing M&M Jacket Apparently Made In God\'s Image', + 'description': 'md5:cc12448686b5600baae9261d3e180910', + 'thumbnail': 're:^https?://.*\.jpg\?\d+$', + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + article_id = mobj.group('article_id') + + webpage = self._download_webpage(url, article_id) + + video_id = self._search_regex( + r'"videoId":\s(\d+),', webpage, 'video ID') + title = self._og_search_title(webpage) + description = self._og_search_description(webpage) + thumbnail = self._og_search_thumbnail(webpage) + + sources = re.findall(r' Date: Sun, 12 Oct 2014 15:47:31 +0300 Subject: [PATCH 1063/1761] [theonion] Fix a small mistake in string formatting --- youtube_dl/extractor/theonion.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/youtube_dl/extractor/theonion.py b/youtube_dl/extractor/theonion.py index 8e4c3414b..b65d8e03f 100644 --- a/youtube_dl/extractor/theonion.py +++ b/youtube_dl/extractor/theonion.py @@ -36,8 +36,7 @@ class TheOnionIE(InfoExtractor): sources = re.findall(r' Date: Sun, 12 Oct 2014 20:09:12 +0530 Subject: [PATCH 1064/1761] Description changed --- youtube_dl/extractor/ndr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/ndr.py b/youtube_dl/extractor/ndr.py index cf7f0309b..add4b3e5d 100644 --- a/youtube_dl/extractor/ndr.py +++ b/youtube_dl/extractor/ndr.py @@ -25,7 +25,7 @@ class NDRIE(InfoExtractor): 'id': '25866', 'ext': 'mp4', 'title': 'Kartoffeltage in der Lewitz', - 'description': 'md5:16d4d66907f541692e8182c33270f29a', + 'description': 'md5:48c4c04dde604c8a9971b3d4e3b9eaa8', 'duration': 166, } }, From 23d83ad4d5d1148f9326a55ff9db8f75bd4ea044 Mon Sep 17 00:00:00 2001 From: Naglis Jonaitis Date: Sun, 12 Oct 2014 23:18:42 +0300 Subject: [PATCH 1065/1761] [niconico] Fix ignored --netrc flag See issue #3753 --- youtube_dl/extractor/niconico.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/youtube_dl/extractor/niconico.py b/youtube_dl/extractor/niconico.py index c0c139b5d..7b85589b7 100644 --- a/youtube_dl/extractor/niconico.py +++ b/youtube_dl/extractor/niconico.py @@ -39,18 +39,17 @@ class NiconicoIE(InfoExtractor): _VALID_URL = r'https?://(?:www\.|secure\.)?nicovideo\.jp/watch/((?:[a-z]{2})?[0-9]+)' _NETRC_MACHINE = 'niconico' - # Determine whether the downloader uses authentication to download video - _AUTHENTICATE = False + # Determine whether the downloader used authentication to download video + _AUTHENTICATED = False def _real_initialize(self): - if self._downloader.params.get('username', None) is not None: - self._AUTHENTICATE = True - - if self._AUTHENTICATE: - self._login() + self._login() def _login(self): (username, password) = self._get_login_info() + # No authentication to be performed + if not username: + return True # Log in login_form_strs = { @@ -68,6 +67,8 @@ class NiconicoIE(InfoExtractor): if re.search(r'(?i)

Log in error

', login_results) is not None: self._downloader.report_warning('unable to log in: bad username or password') return False + # Successful login + self._AUTHENTICATED = True return True def _real_extract(self, url): @@ -82,7 +83,7 @@ class NiconicoIE(InfoExtractor): 'http://ext.nicovideo.jp/api/getthumbinfo/' + video_id, video_id, note='Downloading video info page') - if self._AUTHENTICATE: + if self._AUTHENTICATED: # Get flv info flv_info_webpage = self._download_webpage( 'http://flapi.nicovideo.jp/api/getflv?v=' + video_id, From 2417dc1715c0ca3f229afcd861f59e11360d54ce Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 12 Oct 2014 22:25:18 +0200 Subject: [PATCH 1066/1761] release 2014.10.12 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 4f0d486b9..8b0a704ee 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.05.2' +__version__ = '2014.10.12' From b88b45e46ca960ad4da0474a5b40a45232ab544e Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 12 Oct 2014 22:45:36 +0200 Subject: [PATCH 1067/1761] [options] Mention login in --username documentation (#3753) --- youtube_dl/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/options.py b/youtube_dl/options.py index f651337ad..ad3154a7d 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -205,7 +205,7 @@ def parseOpts(overrideArguments=None): help='Try to download the DASH manifest on YouTube videos (experimental)') authentication.add_option('-u', '--username', - dest='username', metavar='USERNAME', help='account username') + dest='username', metavar='USERNAME', help='login with this account ID') authentication.add_option('-p', '--password', dest='password', metavar='PASSWORD', help='account password') authentication.add_option('-2', '--twofactor', From 8450c15c251f65f72d659bf56fae386e877ab66a Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 12 Oct 2014 23:10:11 +0200 Subject: [PATCH 1068/1761] [options] Consistent formatting and general niceness --- youtube_dl/options.py | 706 +++++++++++++++++++++++++----------------- 1 file changed, 428 insertions(+), 278 deletions(-) diff --git a/youtube_dl/options.py b/youtube_dl/options.py index ad3154a7d..a06850e1c 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -75,7 +75,8 @@ def parseOpts(overrideArguments=None): if len(opts) > 1: opts.insert(1, ', ') - if option.takes_value(): opts.append(' %s' % option.metavar) + if option.takes_value(): + opts.append(' %s' % option.metavar) return "".join(opts) @@ -87,68 +88,69 @@ def parseOpts(overrideArguments=None): for private_opt in ['-p', '--password', '-u', '--username', '--video-password']: try: i = opts.index(private_opt) - opts[i+1] = 'PRIVATE' + opts[i + 1] = 'PRIVATE' except ValueError: pass return opts - max_width = 80 - max_help_position = 80 - # No need to wrap help messages if we're on a wide console columns = get_term_width() - if columns: max_width = columns + max_width = columns if columns else 80 + max_help_position = 80 fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position) fmt.format_option_strings = _format_option_string kw = { - 'version' : __version__, - 'formatter' : fmt, - 'usage' : '%prog [options] url [url...]', - 'conflict_handler' : 'resolve', + 'version': __version__, + 'formatter': fmt, + 'usage': '%prog [options] url [url...]', + 'conflict_handler': 'resolve', } parser = optparse.OptionParser(**kw) - # option groups - general = optparse.OptionGroup(parser, 'General Options') - selection = optparse.OptionGroup(parser, 'Video Selection') - authentication = optparse.OptionGroup(parser, 'Authentication Options') - video_format = optparse.OptionGroup(parser, 'Video Format Options') - subtitles = optparse.OptionGroup(parser, 'Subtitle Options') - downloader = optparse.OptionGroup(parser, 'Download Options') - postproc = optparse.OptionGroup(parser, 'Post-processing Options') - filesystem = optparse.OptionGroup(parser, 'Filesystem Options') - workarounds = optparse.OptionGroup(parser, 'Workarounds') - verbosity = optparse.OptionGroup(parser, 'Verbosity / Simulation Options') - - general.add_option('-h', '--help', - action='help', help='print this help text and exit') - general.add_option('-v', '--version', - action='version', help='print program version and exit') - general.add_option('-U', '--update', - action='store_true', dest='update_self', help='update this program to latest version. Make sure that you have sufficient permissions (run with sudo if needed)') - general.add_option('-i', '--ignore-errors', - action='store_true', dest='ignoreerrors', help='continue on download errors, for example to skip unavailable videos in a playlist', default=False) - general.add_option('--abort-on-error', - action='store_false', dest='ignoreerrors', - help='Abort downloading of further videos (in the playlist or the command line) if an error occurs') - general.add_option('--dump-user-agent', - action='store_true', dest='dump_user_agent', - help='display the current browser identification', default=False) - general.add_option('--list-extractors', - action='store_true', dest='list_extractors', - help='List all supported extractors and the URLs they would handle', default=False) - general.add_option('--extractor-descriptions', - action='store_true', dest='list_extractor_descriptions', - help='Output descriptions of all supported extractors', default=False) + general = optparse.OptionGroup(parser, 'General Options') general.add_option( - '--proxy', dest='proxy', default=None, metavar='URL', + '-h', '--help', + action='help', + help='print this help text and exit') + general.add_option( + '-v', '--version', + action='version', + help='print program version and exit') + general.add_option( + '-U', '--update', + action='store_true', dest='update_self', + help='update this program to latest version. Make sure that you have sufficient permissions (run with sudo if needed)') + general.add_option( + '-i', '--ignore-errors', + action='store_true', dest='ignoreerrors', default=False, + help='continue on download errors, for example to skip unavailable videos in a playlist') + general.add_option( + '--abort-on-error', + action='store_false', dest='ignoreerrors', + help='Abort downloading of further videos (in the playlist or the command line) if an error occurs') + general.add_option( + '--dump-user-agent', + action='store_true', dest='dump_user_agent', default=False, + help='display the current browser identification') + general.add_option( + '--list-extractors', + action='store_true', dest='list_extractors', default=False, + help='List all supported extractors and the URLs they would handle') + general.add_option( + '--extractor-descriptions', + action='store_true', dest='list_extractor_descriptions', default=False, + 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=u'Time to wait before giving up, in seconds') + '--socket-timeout', + dest='socket_timeout', type=float, default=None, + help='Time to wait before giving up, in seconds') general.add_option( '--default-search', dest='default_search', metavar='PREFIX', @@ -158,6 +160,7 @@ def parseOpts(overrideArguments=None): action='store_true', help='Do not read configuration files. When given in the global configuration file /etc/youtube-dl.conf: do not read the user configuration in ~/.config/youtube-dl.conf (%APPDATA%/youtube-dl/config.txt on Windows)') + selection = optparse.OptionGroup(parser, 'Video Selection') selection.add_option( '--playlist-start', dest='playliststart', metavar='NUMBER', default=1, type=int, @@ -166,245 +169,367 @@ def parseOpts(overrideArguments=None): '--playlist-end', dest='playlistend', metavar='NUMBER', default=None, type=int, help='playlist video to end at (default is last)') - selection.add_option('--match-title', dest='matchtitle', metavar='REGEX',help='download only matching titles (regex or caseless sub-string)') - selection.add_option('--reject-title', dest='rejecttitle', metavar='REGEX',help='skip download for matching titles (regex or caseless sub-string)') - selection.add_option('--max-downloads', metavar='NUMBER', - dest='max_downloads', type=int, default=None, - help='Abort after downloading NUMBER files') - selection.add_option('--min-filesize', metavar='SIZE', dest='min_filesize', help="Do not download any videos smaller than SIZE (e.g. 50k or 44.6m)", default=None) - selection.add_option('--max-filesize', metavar='SIZE', dest='max_filesize', help="Do not download any videos larger than SIZE (e.g. 50k or 44.6m)", default=None) - selection.add_option('--date', metavar='DATE', dest='date', help='download only videos uploaded in this date', default=None) selection.add_option( - '--datebefore', metavar='DATE', dest='datebefore', default=None, + '--match-title', + dest='matchtitle', metavar='REGEX', + help='download only matching titles (regex or caseless sub-string)') + selection.add_option( + '--reject-title', + dest='rejecttitle', metavar='REGEX', + help='skip download for matching titles (regex or caseless sub-string)') + selection.add_option( + '--max-downloads', + dest='max_downloads', metavar='NUMBER', type=int, default=None, + help='Abort after downloading NUMBER files') + selection.add_option( + '--min-filesize', + metavar='SIZE', dest='min_filesize', default=None, + help='Do not download any videos smaller than SIZE (e.g. 50k or 44.6m)') + selection.add_option( + '--max-filesize', + metavar='SIZE', dest='max_filesize', default=None, + help='Do not download any videos larger than SIZE (e.g. 50k or 44.6m)') + selection.add_option( + '--date', + metavar='DATE', dest='date', default=None, + help='download only videos uploaded in this date') + selection.add_option( + '--datebefore', + metavar='DATE', dest='datebefore', default=None, help='download only videos uploaded on or before this date (i.e. inclusive)') selection.add_option( - '--dateafter', metavar='DATE', dest='dateafter', default=None, + '--dateafter', + metavar='DATE', dest='dateafter', default=None, help='download only videos uploaded on or after this date (i.e. inclusive)') selection.add_option( - '--min-views', metavar='COUNT', dest='min_views', - default=None, type=int, - help="Do not download any videos with less than COUNT views",) + '--min-views', + metavar='COUNT', dest='min_views', default=None, type=int, + help='Do not download any videos with less than COUNT views',) selection.add_option( - '--max-views', metavar='COUNT', dest='max_views', - default=None, type=int, - help="Do not download any videos with more than COUNT views",) - selection.add_option('--no-playlist', action='store_true', dest='noplaylist', help='download only the currently playing video', default=False) - selection.add_option('--age-limit', metavar='YEARS', dest='age_limit', - help='download only videos suitable for the given age', - default=None, type=int) - selection.add_option('--download-archive', metavar='FILE', - dest='download_archive', - help='Download only videos not listed in the archive file. Record the IDs of all downloaded videos in it.') + '--max-views', + metavar='COUNT', dest='max_views', default=None, type=int, + help='Do not download any videos with more than COUNT views') selection.add_option( - '--include-ads', dest='include_ads', - action='store_true', + '--no-playlist', + action='store_true', dest='noplaylist', default=False, + help='download only the currently playing video') + selection.add_option( + '--age-limit', + metavar='YEARS', dest='age_limit', default=None, type=int, + help='download only videos suitable for the given age') + selection.add_option( + '--download-archive', metavar='FILE', + dest='download_archive', + help='Download only videos not listed in the archive file. Record the IDs of all downloaded videos in it.') + selection.add_option( + '--include-ads', + dest='include_ads', action='store_true', help='Download advertisements as well (experimental)') selection.add_option( - '--youtube-include-dash-manifest', action='store_true', - dest='youtube_include_dash_manifest', default=False, + '--youtube-include-dash-manifest', + action='store_true', dest='youtube_include_dash_manifest', default=False, help='Try to download the DASH manifest on YouTube videos (experimental)') - authentication.add_option('-u', '--username', - dest='username', metavar='USERNAME', help='login with this account ID') - authentication.add_option('-p', '--password', - dest='password', metavar='PASSWORD', help='account password') - authentication.add_option('-2', '--twofactor', - dest='twofactor', metavar='TWOFACTOR', help='two-factor auth code') - authentication.add_option('-n', '--netrc', - action='store_true', dest='usenetrc', help='use .netrc authentication data', default=False) - authentication.add_option('--video-password', - dest='videopassword', metavar='PASSWORD', help='video password (vimeo, smotri)') + authentication = optparse.OptionGroup(parser, 'Authentication Options') + authentication.add_option( + '-u', '--username', + dest='username', metavar='USERNAME', + help='login with this account ID') + authentication.add_option( + '-p', '--password', + dest='password', metavar='PASSWORD', + help='account password') + authentication.add_option( + '-2', '--twofactor', + dest='twofactor', metavar='TWOFACTOR', + help='two-factor auth code') + authentication.add_option( + '-n', '--netrc', + action='store_true', dest='usenetrc', default=False, + help='use .netrc authentication data') + authentication.add_option( + '--video-password', + dest='videopassword', metavar='PASSWORD', + help='video password (vimeo, smotri)') + video_format = optparse.OptionGroup(parser, 'Video Format Options') + video_format.add_option( + '-f', '--format', + action='store', dest='format', metavar='FORMAT', default=None, + help='video format code, specify the order of preference using slashes: -f 22/17/18 . -f mp4 , -f m4a and -f flv are also supported. You can also use the special names "best", "bestvideo", "bestaudio", "worst", "worstvideo" and "worstaudio". By default, youtube-dl will pick the best quality. Use commas to download multiple audio formats, such as -f 136/137/mp4/bestvideo,140/m4a/bestaudio') + video_format.add_option( + '--all-formats', + action='store_const', dest='format', const='all', + help='download all available video formats') + video_format.add_option( + '--prefer-free-formats', + action='store_true', dest='prefer_free_formats', default=False, + help='prefer free video formats unless a specific one is requested') + video_format.add_option( + '--max-quality', + action='store', dest='format_limit', metavar='FORMAT', + help='highest quality format to download') + video_format.add_option( + '-F', '--list-formats', + action='store_true', dest='listformats', + help='list all available formats') - video_format.add_option('-f', '--format', - action='store', dest='format', metavar='FORMAT', default=None, - help='video format code, specify the order of preference using slashes: -f 22/17/18 . -f mp4 , -f m4a and -f flv are also supported. You can also use the special names "best", "bestvideo", "bestaudio", "worst", "worstvideo" and "worstaudio". By default, youtube-dl will pick the best quality. Use commas to download multiple audio formats, such as -f 136/137/mp4/bestvideo,140/m4a/bestaudio') - video_format.add_option('--all-formats', - action='store_const', dest='format', help='download all available video formats', const='all') - video_format.add_option('--prefer-free-formats', - action='store_true', dest='prefer_free_formats', default=False, help='prefer free video formats unless a specific one is requested') - video_format.add_option('--max-quality', - action='store', dest='format_limit', metavar='FORMAT', help='highest quality format to download') - video_format.add_option('-F', '--list-formats', - action='store_true', dest='listformats', help='list all available formats') + subtitles = optparse.OptionGroup(parser, 'Subtitle Options') + subtitles.add_option( + '--write-sub', '--write-srt', + action='store_true', dest='writesubtitles', default=False, + help='write subtitle file') + subtitles.add_option( + '--write-auto-sub', '--write-automatic-sub', + action='store_true', dest='writeautomaticsub', default=False, + help='write automatic subtitle file (youtube only)') + subtitles.add_option( + '--all-subs', + action='store_true', dest='allsubtitles', default=False, + help='downloads all the available subtitles of the video') + subtitles.add_option( + '--list-subs', + action='store_true', dest='listsubtitles', default=False, + help='lists all available subtitles for the video') + subtitles.add_option( + '--sub-format', + action='store', dest='subtitlesformat', metavar='FORMAT', default='srt', + help='subtitle format (default=srt) ([sbv/vtt] youtube only)') + subtitles.add_option( + '--sub-lang', '--sub-langs', '--srt-lang', + action='callback', dest='subtitleslangs', metavar='LANGS', type='str', + default=[], callback=_comma_separated_values_options_callback, + help='languages of the subtitles to download (optional) separated by commas, use IETF language tags like \'en,pt\'') - subtitles.add_option('--write-sub', '--write-srt', - action='store_true', dest='writesubtitles', - help='write subtitle file', default=False) - subtitles.add_option('--write-auto-sub', '--write-automatic-sub', - action='store_true', dest='writeautomaticsub', - help='write automatic subtitle file (youtube only)', default=False) - subtitles.add_option('--all-subs', - action='store_true', dest='allsubtitles', - help='downloads all the available subtitles of the video', default=False) - subtitles.add_option('--list-subs', - action='store_true', dest='listsubtitles', - help='lists all available subtitles for the video', default=False) - subtitles.add_option('--sub-format', - action='store', dest='subtitlesformat', metavar='FORMAT', - help='subtitle format (default=srt) ([sbv/vtt] youtube only)', default='srt') - subtitles.add_option('--sub-lang', '--sub-langs', '--srt-lang', - action='callback', dest='subtitleslangs', metavar='LANGS', type='str', - default=[], callback=_comma_separated_values_options_callback, - help='languages of the subtitles to download (optional) separated by commas, use IETF language tags like \'en,pt\'') - - downloader.add_option('-r', '--rate-limit', - dest='ratelimit', metavar='LIMIT', help='maximum download rate in bytes per second (e.g. 50K or 4.2M)') - downloader.add_option('-R', '--retries', - dest='retries', metavar='RETRIES', help='number of retries (default is %default)', default=10) - downloader.add_option('--buffer-size', - dest='buffersize', metavar='SIZE', help='size of download buffer (e.g. 1024 or 16K) (default is %default)', default="1024") - downloader.add_option('--no-resize-buffer', - action='store_true', dest='noresizebuffer', - help='do not automatically adjust the buffer size. By default, the buffer size is automatically resized from an initial value of SIZE.', default=False) - downloader.add_option('--test', action='store_true', dest='test', default=False, help=optparse.SUPPRESS_HELP) + downloader = optparse.OptionGroup(parser, 'Download Options') + downloader.add_option( + '-r', '--rate-limit', + dest='ratelimit', metavar='LIMIT', + help='maximum download rate in bytes per second (e.g. 50K or 4.2M)') + downloader.add_option( + '-R', '--retries', + dest='retries', metavar='RETRIES', default=10, + help='number of retries (default is %default)') + downloader.add_option( + '--buffer-size', + dest='buffersize', metavar='SIZE', default='1024', + help='size of download buffer (e.g. 1024 or 16K) (default is %default)') + downloader.add_option( + '--no-resize-buffer', + action='store_true', dest='noresizebuffer', default=False, + help='do not automatically adjust the buffer size. By default, the buffer size is automatically resized from an initial value of SIZE.') + downloader.add_option( + '--test', + action='store_true', dest='test', default=False, + help=optparse.SUPPRESS_HELP) + workarounds = optparse.OptionGroup(parser, 'Workarounds') workarounds.add_option( - '--encoding', dest='encoding', metavar='ENCODING', + '--encoding', + dest='encoding', metavar='ENCODING', help='Force the specified encoding (experimental)') workarounds.add_option( - '--no-check-certificate', action='store_true', - dest='no_check_certificate', default=False, + '--no-check-certificate', + action='store_true', dest='no_check_certificate', default=False, help='Suppress HTTPS certificate validation.') workarounds.add_option( - '--prefer-insecure', '--prefer-unsecure', action='store_true', dest='prefer_insecure', + '--prefer-insecure', + '--prefer-unsecure', action='store_true', dest='prefer_insecure', help='Use an unencrypted connection to retrieve information about the video. (Currently supported only for YouTube)') workarounds.add_option( - '--user-agent', metavar='UA', - dest='user_agent', help='specify a custom user agent') + '--user-agent', + metavar='UA', dest='user_agent', + help='specify a custom user agent') workarounds.add_option( - '--referer', metavar='REF', - dest='referer', default=None, + '--referer', + metavar='URL', dest='referer', default=None, help='specify a custom referer, use if the video access is restricted to one domain', ) workarounds.add_option( - '--add-header', metavar='FIELD:VALUE', - dest='headers', action='append', + '--add-header', + metavar='FIELD:VALUE', dest='headers', action='append', help='specify a custom HTTP header and its value, separated by a colon \':\'. You can use this option multiple times', ) workarounds.add_option( - '--bidi-workaround', dest='bidi_workaround', action='store_true', - help=u'Work around terminals that lack bidirectional text support. Requires bidiv or fribidi executable in PATH') + '--bidi-workaround', + dest='bidi_workaround', action='store_true', + help='Work around terminals that lack bidirectional text support. Requires bidiv or fribidi executable in PATH') - verbosity.add_option('-q', '--quiet', - action='store_true', dest='quiet', help='activates quiet mode', default=False) + verbosity = optparse.OptionGroup(parser, 'Verbosity / Simulation Options') + verbosity.add_option( + '-q', '--quiet', + action='store_true', dest='quiet', default=False, + help='activates quiet mode') verbosity.add_option( '--no-warnings', dest='no_warnings', action='store_true', default=False, help='Ignore warnings') - verbosity.add_option('-s', '--simulate', - action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False) - verbosity.add_option('--skip-download', - action='store_true', dest='skip_download', help='do not download the video', default=False) - verbosity.add_option('-g', '--get-url', - action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False) - verbosity.add_option('-e', '--get-title', - action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False) - verbosity.add_option('--get-id', - action='store_true', dest='getid', help='simulate, quiet but print id', default=False) - verbosity.add_option('--get-thumbnail', - action='store_true', dest='getthumbnail', - help='simulate, quiet but print thumbnail URL', default=False) - verbosity.add_option('--get-description', - action='store_true', dest='getdescription', - help='simulate, quiet but print video description', default=False) - verbosity.add_option('--get-duration', - action='store_true', dest='getduration', - help='simulate, quiet but print video length', default=False) - verbosity.add_option('--get-filename', - action='store_true', dest='getfilename', - help='simulate, quiet but print output filename', default=False) - verbosity.add_option('--get-format', - action='store_true', dest='getformat', - help='simulate, quiet but print output format', default=False) - verbosity.add_option('-j', '--dump-json', - action='store_true', dest='dumpjson', - help='simulate, quiet but print JSON information. See --output for a description of available keys.', default=False) - verbosity.add_option('--newline', - action='store_true', dest='progress_with_newline', help='output progress bar as new lines', default=False) - verbosity.add_option('--no-progress', - action='store_true', dest='noprogress', help='do not print progress bar', default=False) - verbosity.add_option('--console-title', - action='store_true', dest='consoletitle', - help='display progress in console titlebar', default=False) - verbosity.add_option('-v', '--verbose', - action='store_true', dest='verbose', help='print various debugging information', default=False) - verbosity.add_option('--dump-intermediate-pages', - action='store_true', dest='dump_intermediate_pages', default=False, - help='print downloaded pages to debug problems (very verbose)') - verbosity.add_option('--write-pages', - action='store_true', dest='write_pages', default=False, - help='Write downloaded intermediary pages to files in the current directory to debug problems') - verbosity.add_option('--youtube-print-sig-code', - action='store_true', dest='youtube_print_sig_code', default=False, - help=optparse.SUPPRESS_HELP) - verbosity.add_option('--print-traffic', - dest='debug_printtraffic', action='store_true', default=False, - help='Display sent and read HTTP traffic') + verbosity.add_option( + '-s', '--simulate', + action='store_true', dest='simulate', default=False, + help='do not download the video and do not write anything to disk',) + verbosity.add_option( + '--skip-download', + action='store_true', dest='skip_download', default=False, + help='do not download the video',) + verbosity.add_option( + '-g', '--get-url', + action='store_true', dest='geturl', default=False, + help='simulate, quiet but print URL') + verbosity.add_option( + '-e', '--get-title', + action='store_true', dest='gettitle', default=False, + help='simulate, quiet but print title') + verbosity.add_option( + '--get-id', + action='store_true', dest='getid', default=False, + help='simulate, quiet but print id') + verbosity.add_option( + '--get-thumbnail', + action='store_true', dest='getthumbnail', default=False, + help='simulate, quiet but print thumbnail URL') + verbosity.add_option( + '--get-description', + action='store_true', dest='getdescription', default=False, + help='simulate, quiet but print video description') + verbosity.add_option( + '--get-duration', + action='store_true', dest='getduration', default=False, + help='simulate, quiet but print video length') + verbosity.add_option( + '--get-filename', + action='store_true', dest='getfilename', default=False, + help='simulate, quiet but print output filename') + verbosity.add_option( + '--get-format', + action='store_true', dest='getformat', default=False, + help='simulate, quiet but print output format') + verbosity.add_option( + '-j', '--dump-json', + action='store_true', dest='dumpjson', default=False, + help='simulate, quiet but print JSON information. See --output for a description of available keys.') + verbosity.add_option( + '--newline', + action='store_true', dest='progress_with_newline', default=False, + help='output progress bar as new lines') + verbosity.add_option( + '--no-progress', + action='store_true', dest='noprogress', default=False, + help='do not print progress bar') + verbosity.add_option( + '--console-title', + action='store_true', dest='consoletitle', default=False, + help='display progress in console titlebar') + verbosity.add_option( + '-v', '--verbose', + action='store_true', dest='verbose', default=False, + help='print various debugging information') + verbosity.add_option( + '--dump-intermediate-pages', + action='store_true', dest='dump_intermediate_pages', default=False, + help='print downloaded pages to debug problems (very verbose)') + verbosity.add_option( + '--write-pages', + action='store_true', dest='write_pages', default=False, + help='Write downloaded intermediary pages to files in the current directory to debug problems') + verbosity.add_option( + '--youtube-print-sig-code', + action='store_true', dest='youtube_print_sig_code', default=False, + help=optparse.SUPPRESS_HELP) + verbosity.add_option( + '--print-traffic', + dest='debug_printtraffic', action='store_true', default=False, + help='Display sent and read HTTP traffic') - - filesystem.add_option('-a', '--batch-file', - dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)') - filesystem.add_option('--id', - action='store_true', dest='useid', help='use only video ID in file name', default=False) - filesystem.add_option('-A', '--auto-number', - action='store_true', dest='autonumber', - help='number downloaded files starting from 00000', default=False) - filesystem.add_option('-o', '--output', - dest='outtmpl', metavar='TEMPLATE', - help=('output filename template. Use %(title)s to get the title, ' - '%(uploader)s for the uploader name, %(uploader_id)s for the uploader nickname if different, ' - '%(autonumber)s to get an automatically incremented number, ' - '%(ext)s for the filename extension, ' - '%(format)s for the format description (like "22 - 1280x720" or "HD"), ' - '%(format_id)s for the unique id of the format (like Youtube\'s itags: "137"), ' - '%(upload_date)s for the upload date (YYYYMMDD), ' - '%(extractor)s for the provider (youtube, metacafe, etc), ' - '%(id)s for the video id, %(playlist)s for the playlist the video is in, ' - '%(playlist_index)s for the position in the playlist and %% for a literal percent. ' - '%(height)s and %(width)s for the width and height of the video format. ' - '%(resolution)s for a textual description of the resolution of the video format. ' - 'Use - to output to stdout. Can also be used to download to a different directory, ' - 'for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .')) - filesystem.add_option('--autonumber-size', - dest='autonumber_size', metavar='NUMBER', - help='Specifies the number of digits in %(autonumber)s when it is present in output filename template or --auto-number option is given') - filesystem.add_option('--restrict-filenames', - action='store_true', dest='restrictfilenames', - help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False) - filesystem.add_option('-t', '--title', - action='store_true', dest='usetitle', help='[deprecated] use title in file name (default)', default=False) - filesystem.add_option('-l', '--literal', - action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False) - filesystem.add_option('-w', '--no-overwrites', - action='store_true', dest='nooverwrites', help='do not overwrite files', default=False) - filesystem.add_option('-c', '--continue', - action='store_true', dest='continue_dl', help='force resume of partially downloaded files. By default, youtube-dl will resume downloads if possible.', default=True) - filesystem.add_option('--no-continue', - action='store_false', dest='continue_dl', - help='do not resume partially downloaded files (restart from beginning)') - filesystem.add_option('--no-part', - action='store_true', dest='nopart', help='do not use .part files', default=False) - filesystem.add_option('--no-mtime', - action='store_false', dest='updatetime', - help='do not use the Last-modified header to set the file modification time', default=True) - filesystem.add_option('--write-description', - action='store_true', dest='writedescription', - help='write video description to a .description file', default=False) - filesystem.add_option('--write-info-json', - action='store_true', dest='writeinfojson', - help='write video metadata to a .info.json file', default=False) - filesystem.add_option('--write-annotations', - action='store_true', dest='writeannotations', - help='write video annotations to a .annotation file', default=False) - filesystem.add_option('--write-thumbnail', - action='store_true', dest='writethumbnail', - help='write thumbnail image to disk', default=False) - filesystem.add_option('--load-info', - dest='load_info_filename', metavar='FILE', - help='json file containing the video information (created with the "--write-json" option)') - filesystem.add_option('--cookies', - dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in') + filesystem = optparse.OptionGroup(parser, 'Filesystem Options') + filesystem.add_option( + '-a', '--batch-file', + dest='batchfile', metavar='FILE', + help='file containing URLs to download (\'-\' for stdin)') + filesystem.add_option( + '--id', default=False, + action='store_true', dest='useid', help='use only video ID in file name') + filesystem.add_option( + '-A', '--auto-number', + action='store_true', dest='autonumber', default=False, + help='number downloaded files starting from 00000') + filesystem.add_option( + '-o', '--output', + dest='outtmpl', metavar='TEMPLATE', + help=('output filename template. Use %(title)s to get the title, ' + '%(uploader)s for the uploader name, %(uploader_id)s for the uploader nickname if different, ' + '%(autonumber)s to get an automatically incremented number, ' + '%(ext)s for the filename extension, ' + '%(format)s for the format description (like "22 - 1280x720" or "HD"), ' + '%(format_id)s for the unique id of the format (like Youtube\'s itags: "137"), ' + '%(upload_date)s for the upload date (YYYYMMDD), ' + '%(extractor)s for the provider (youtube, metacafe, etc), ' + '%(id)s for the video id, %(playlist)s for the playlist the video is in, ' + '%(playlist_index)s for the position in the playlist and %% for a literal percent. ' + '%(height)s and %(width)s for the width and height of the video format. ' + '%(resolution)s for a textual description of the resolution of the video format. ' + 'Use - to output to stdout. Can also be used to download to a different directory, ' + 'for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .')) + filesystem.add_option( + '--autonumber-size', + dest='autonumber_size', metavar='NUMBER', + help='Specifies the number of digits in %(autonumber)s when it is present in output filename template or --auto-number option is given') + filesystem.add_option( + '--restrict-filenames', + action='store_true', dest='restrictfilenames', default=False, + help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames') + filesystem.add_option( + '-t', '--title', + action='store_true', dest='usetitle', default=False, + help='[deprecated] use title in file name (default)') + filesystem.add_option( + '-l', '--literal', default=False, + action='store_true', dest='usetitle', + help='[deprecated] alias of --title') + filesystem.add_option( + '-w', '--no-overwrites', + action='store_true', dest='nooverwrites', default=False, + help='do not overwrite files') + filesystem.add_option( + '-c', '--continue', + action='store_true', dest='continue_dl', default=True, + help='force resume of partially downloaded files. By default, youtube-dl will resume downloads if possible.') + filesystem.add_option( + '--no-continue', + action='store_false', dest='continue_dl', + help='do not resume partially downloaded files (restart from beginning)') + filesystem.add_option( + '--no-part', + action='store_true', dest='nopart', default=False, + help='do not use .part files - write directly into output file') + filesystem.add_option( + '--no-mtime', + action='store_false', dest='updatetime', default=True, + help='do not use the Last-modified header to set the file modification time') + filesystem.add_option( + '--write-description', + action='store_true', dest='writedescription', default=False, + help='write video description to a .description file') + filesystem.add_option( + '--write-info-json', + action='store_true', dest='writeinfojson', default=False, + help='write video metadata to a .info.json file') + filesystem.add_option( + '--write-annotations', + action='store_true', dest='writeannotations', default=False, + help='write video annotations to a .annotation file') + filesystem.add_option( + '--write-thumbnail', + action='store_true', dest='writethumbnail', default=False, + help='write thumbnail image to disk') + filesystem.add_option( + '--load-info', + dest='load_info_filename', metavar='FILE', + help='json file containing the video information (created with the "--write-json" option)') + filesystem.add_option( + '--cookies', + dest='cookiefile', metavar='FILE', + help='file to read cookies from and dump cookie jar in') filesystem.add_option( '--cache-dir', dest='cachedir', default=None, metavar='DIR', help='Location in the filesystem where youtube-dl can store some downloaded information permanently. By default $XDG_CACHE_HOME/youtube-dl or ~/.cache/youtube-dl . At the moment, only YouTube player files (for videos with obfuscated signatures) are cached, but that may change.') @@ -412,36 +537,61 @@ def parseOpts(overrideArguments=None): '--no-cache-dir', action='store_const', const=False, dest='cachedir', help='Disable filesystem caching') filesystem.add_option( - '--rm-cache-dir', action='store_true', dest='rm_cachedir', + '--rm-cache-dir', + action='store_true', dest='rm_cachedir', help='Delete all filesystem cache files') - - postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False, - help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)') - postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best', - help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default') - postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5', - help='ffmpeg/avconv audio quality specification, insert a value between 0 (better) and 9 (worse) for VBR or a specific bitrate like 128K (default 5)') - postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None, - help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm|mkv)') - postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False, - help='keeps the video file on disk after the post-processing; the video is erased by default') - postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False, - help='do not overwrite post-processed files; the post-processed files are overwritten by default') - postproc.add_option('--embed-subs', action='store_true', dest='embedsubtitles', default=False, - help='embed subtitles in the video (only for mp4 videos)') - postproc.add_option('--embed-thumbnail', action='store_true', dest='embedthumbnail', default=False, - help='embed thumbnail in the audio as cover art') - postproc.add_option('--add-metadata', action='store_true', dest='addmetadata', default=False, - help='write metadata to the video file') - postproc.add_option('--xattrs', action='store_true', dest='xattrs', default=False, - help='write metadata to the video file\'s xattrs (using dublin core and xdg standards)') - postproc.add_option('--prefer-avconv', action='store_false', dest='prefer_ffmpeg', + postproc = optparse.OptionGroup(parser, 'Post-processing Options') + postproc.add_option( + '-x', '--extract-audio', + action='store_true', dest='extractaudio', default=False, + help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)') + postproc.add_option( + '--audio-format', metavar='FORMAT', dest='audioformat', default='best', + help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; "%default" by default') + postproc.add_option( + '--audio-quality', metavar='QUALITY', + dest='audioquality', default='5', + help='ffmpeg/avconv audio quality specification, insert a value between 0 (better) and 9 (worse) for VBR or a specific bitrate like 128K (default %default)') + postproc.add_option( + '--recode-video', + metavar='FORMAT', dest='recodevideo', default=None, + help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm|mkv)') + postproc.add_option( + '-k', '--keep-video', + action='store_true', dest='keepvideo', default=False, + help='keeps the video file on disk after the post-processing; the video is erased by default') + postproc.add_option( + '--no-post-overwrites', + action='store_true', dest='nopostoverwrites', default=False, + help='do not overwrite post-processed files; the post-processed files are overwritten by default') + postproc.add_option( + '--embed-subs', + action='store_true', dest='embedsubtitles', default=False, + help='embed subtitles in the video (only for mp4 videos)') + postproc.add_option( + '--embed-thumbnail', + action='store_true', dest='embedthumbnail', default=False, + help='embed thumbnail in the audio as cover art') + postproc.add_option( + '--add-metadata', + action='store_true', dest='addmetadata', default=False, + help='write metadata to the video file') + postproc.add_option( + '--xattrs', + action='store_true', dest='xattrs', default=False, + help='write metadata to the video file\'s xattrs (using dublin core and xdg standards)') + postproc.add_option( + '--prefer-avconv', + action='store_false', dest='prefer_ffmpeg', help='Prefer avconv over ffmpeg for running the postprocessors (default)') - postproc.add_option('--prefer-ffmpeg', action='store_true', dest='prefer_ffmpeg', + postproc.add_option( + '--prefer-ffmpeg', + action='store_true', dest='prefer_ffmpeg', help='Prefer ffmpeg over avconv for running the postprocessors') postproc.add_option( - '--exec', metavar='CMD', dest='exec_cmd', + '--exec', + metavar='CMD', dest='exec_cmd', 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) @@ -458,7 +608,7 @@ def parseOpts(overrideArguments=None): if overrideArguments is not None: opts, args = parser.parse_args(overrideArguments) if opts.verbose: - write_string(u'[debug] Override config: ' + repr(overrideArguments) + '\n') + write_string('[debug] Override config: ' + repr(overrideArguments) + '\n') else: commandLineConf = sys.argv[1:] if '--ignore-config' in commandLineConf: @@ -474,8 +624,8 @@ def parseOpts(overrideArguments=None): opts, args = parser.parse_args(argv) if opts.verbose: - write_string(u'[debug] System config: ' + repr(_hide_login_info(systemConf)) + '\n') - write_string(u'[debug] User config: ' + repr(_hide_login_info(userConf)) + '\n') - write_string(u'[debug] Command-line args: ' + repr(_hide_login_info(commandLineConf)) + '\n') + write_string('[debug] System config: ' + repr(_hide_login_info(systemConf)) + '\n') + write_string('[debug] User config: ' + repr(_hide_login_info(userConf)) + '\n') + write_string('[debug] Command-line args: ' + repr(_hide_login_info(commandLineConf)) + '\n') return parser, opts, args From 4d7b03f1f28760abee5a1326f1c902b081c75976 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 12 Oct 2014 23:31:15 +0200 Subject: [PATCH 1069/1761] [zsh-completion] Ignore generated file (#3890) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e44977ca3..86312d4e4 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ updates_key.pem *.swp test/testdata .tox +youtube-dl.zsh From 203fb43f3602a6363041ee9323ee718e6c71606c Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 13 Oct 2014 00:03:08 +0200 Subject: [PATCH 1070/1761] [youtube] Download DASH manifest by default (Closes #3887) --- youtube_dl/extractor/youtube.py | 2 +- youtube_dl/options.py | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index 9041cfa87..98d7fb5fc 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -938,7 +938,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): raise ExtractorError('no conn, hlsvp or url_encoded_fmt_stream_map information found in video info') # Look for the DASH manifest - if (self._downloader.params.get('youtube_include_dash_manifest', False)): + if self._downloader.params.get('youtube_include_dash_manifest', True): try: # The DASH manifest used needs to be the one from the original video_webpage. # The one found in get_video_info seems to be using different signatures. diff --git a/youtube_dl/options.py b/youtube_dl/options.py index a06850e1c..649361bde 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -225,10 +225,6 @@ def parseOpts(overrideArguments=None): '--include-ads', dest='include_ads', action='store_true', help='Download advertisements as well (experimental)') - selection.add_option( - '--youtube-include-dash-manifest', - action='store_true', dest='youtube_include_dash_manifest', default=False, - help='Try to download the DASH manifest on YouTube videos (experimental)') authentication = optparse.OptionGroup(parser, 'Authentication Options') authentication.add_option( @@ -273,6 +269,14 @@ def parseOpts(overrideArguments=None): '-F', '--list-formats', action='store_true', dest='listformats', help='list all available formats') + video_format.add_option( + '--youtube-include-dash-manifest', + action='store_true', dest='youtube_include_dash_manifest', default=True, + help=optparse.SUPPRESS_HELP) + video_format.add_option( + '--youtube-skip-dash-manifest', + action='store_false', dest='youtube_include_dash_manifest', + help='Do not download the DASH manifest on YouTube videos') subtitles = optparse.OptionGroup(parser, 'Subtitle Options') subtitles.add_option( From 1cc887cbf0371a3de2154bc2b34546d1040d01a8 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 13 Oct 2014 00:09:19 +0200 Subject: [PATCH 1071/1761] [youtube] Add support for format 278 --- youtube_dl/extractor/youtube.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index 98d7fb5fc..cfae2de89 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -286,6 +286,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): '170': {'ext': 'webm', 'height': 1080, 'width': 1920, 'format_note': 'DASH video', 'acodec': 'none', 'container': 'webm', 'vcodec': 'VP8', 'preference': -40}, '218': {'ext': 'webm', 'height': 480, 'width': 854, 'format_note': 'DASH video', 'acodec': 'none', 'container': 'webm', 'vcodec': 'VP8', 'preference': -40}, '219': {'ext': 'webm', 'height': 480, 'width': 854, 'format_note': 'DASH video', 'acodec': 'none', 'container': 'webm', 'vcodec': 'VP8', 'preference': -40}, + '278': {'ext': 'webm', 'height': 144, 'format_note': 'DASH video', 'acodec': 'none', 'preference': -40, 'container': 'webm', 'vcodec': 'VP9'}, '242': {'ext': 'webm', 'height': 240, 'format_note': 'DASH video', 'acodec': 'none', 'preference': -40}, '243': {'ext': 'webm', 'height': 360, 'format_note': 'DASH video', 'acodec': 'none', 'preference': -40}, '244': {'ext': 'webm', 'height': 480, 'format_note': 'DASH video', 'acodec': 'none', 'preference': -40}, From 8a2300a59703da441932f361e4e496bb64e4b502 Mon Sep 17 00:00:00 2001 From: dinesh Date: Mon, 13 Oct 2014 10:03:55 +0530 Subject: [PATCH 1072/1761] [kontrtube] Fix video title extraction --- youtube_dl/extractor/kontrtube.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/kontrtube.py b/youtube_dl/extractor/kontrtube.py index 5341ac773..8a73ecfa0 100644 --- a/youtube_dl/extractor/kontrtube.py +++ b/youtube_dl/extractor/kontrtube.py @@ -34,7 +34,7 @@ class KontrTubeIE(InfoExtractor): video_url = self._html_search_regex(r"video_url: '(.+?)/?',", webpage, 'video URL') thumbnail = self._html_search_regex(r"preview_url: '(.+?)/?',", webpage, 'video thumbnail', fatal=False) title = self._html_search_regex( - r'(.+?) - Труба зовёт - Интересный видеохостинг', webpage, 'video title') + r'(.+?)', webpage, 'video title') description = self._html_search_meta('description', webpage, 'video description') mobj = re.search( From 4c1ce987b03dc9cde1b9f06db117f4f12c1dd6a4 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 13 Oct 2014 10:08:59 +0200 Subject: [PATCH 1073/1761] [huffpost] Modernize --- youtube_dl/extractor/huffpost.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/youtube_dl/extractor/huffpost.py b/youtube_dl/extractor/huffpost.py index 94e7cf790..4ccf6b9b8 100644 --- a/youtube_dl/extractor/huffpost.py +++ b/youtube_dl/extractor/huffpost.py @@ -33,8 +33,7 @@ class HuffPostIE(InfoExtractor): } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') + video_id = self._match_id(url) api_url = 'http://embed.live.huffingtonpost.com/api/segments/%s.json' % video_id data = self._download_json(api_url, video_id)['data'] From 2aefb886faa855518292c4078eb04c40b55d4f90 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 13 Oct 2014 10:12:43 +0200 Subject: [PATCH 1074/1761] [ffmpeg] Improve format merging (Closes #3935) --- youtube_dl/postprocessor/ffmpeg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/postprocessor/ffmpeg.py b/youtube_dl/postprocessor/ffmpeg.py index 8c5f7c43b..6f010a9c7 100644 --- a/youtube_dl/postprocessor/ffmpeg.py +++ b/youtube_dl/postprocessor/ffmpeg.py @@ -487,7 +487,7 @@ class FFmpegMetadataPP(FFmpegPostProcessor): class FFmpegMergerPP(FFmpegPostProcessor): def run(self, info): filename = info['filepath'] - args = ['-c', 'copy'] + args = ['-c', 'copy', '-map', '0:v:0', '-map', '1:a:0', '-shortest'] self._downloader.to_screen(u'[ffmpeg] Merging formats into "%s"' % filename) self.run_ffmpeg_multiple_files(info['__files_to_merge'], filename, args) return True, info From 9b36dcbd6512fb6469b037006c30cedd2cfae3fc Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 13 Oct 2014 10:12:51 +0200 Subject: [PATCH 1075/1761] release 2014.10.13 --- README.md | 13 +++++++------ youtube_dl/version.py | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index cabc5eb9a..90ba928c3 100644 --- a/README.md +++ b/README.md @@ -99,8 +99,6 @@ which means you can modify it, redistribute it or use it however you like. downloaded videos in it. --include-ads Download advertisements as well (experimental) - --youtube-include-dash-manifest Try to download the DASH manifest on - YouTube videos (experimental) ## Download Options: -r, --rate-limit LIMIT maximum download rate in bytes per second @@ -158,7 +156,8 @@ which means you can modify it, redistribute it or use it however you like. downloads if possible. --no-continue do not resume partially downloaded files (restart from beginning) - --no-part do not use .part files + --no-part do not use .part files - write directly + into output file --no-mtime do not use the Last-modified header to set the file modification time --write-description write video description to a .description @@ -216,7 +215,7 @@ which means you can modify it, redistribute it or use it however you like. information about the video. (Currently supported only for YouTube) --user-agent UA specify a custom user agent - --referer REF specify a custom referer, use if the video + --referer URL specify a custom referer, use if the video access is restricted to one domain --add-header FIELD:VALUE specify a custom HTTP header and its value, separated by a colon ':'. You can use this @@ -241,6 +240,8 @@ which means you can modify it, redistribute it or use it however you like. one is requested --max-quality FORMAT highest quality format to download -F, --list-formats list all available formats + --youtube-skip-dash-manifest Do not download the DASH manifest on + YouTube videos ## Subtitle Options: --write-sub write subtitle file @@ -256,7 +257,7 @@ which means you can modify it, redistribute it or use it however you like. language tags like 'en,pt' ## Authentication Options: - -u, --username USERNAME account username + -u, --username USERNAME login with this account ID -p, --password PASSWORD account password -2, --twofactor TWOFACTOR two-factor auth code -n, --netrc use .netrc authentication data @@ -267,7 +268,7 @@ which means you can modify it, redistribute it or use it however you like. (requires ffmpeg or avconv and ffprobe or avprobe) --audio-format FORMAT "best", "aac", "vorbis", "mp3", "m4a", - "opus", or "wav"; best by default + "opus", or "wav"; "best" by default --audio-quality QUALITY ffmpeg/avconv audio quality specification, insert a value between 0 (better) and 9 (worse) for VBR or a specific bitrate like diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 8b0a704ee..416e2fd85 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.12' +__version__ = '2014.10.13' From 1419fafd36a6ab70d769411e779db63f2b4cb1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Mon, 13 Oct 2014 19:59:35 +0700 Subject: [PATCH 1076/1761] [condenast] Add support for embedded videos (Closes #3929) --- youtube_dl/extractor/condenast.py | 2 ++ youtube_dl/extractor/generic.py | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/youtube_dl/extractor/condenast.py b/youtube_dl/extractor/condenast.py index ffbe4903b..7a7e79360 100644 --- a/youtube_dl/extractor/condenast.py +++ b/youtube_dl/extractor/condenast.py @@ -34,6 +34,8 @@ class CondeNastIE(InfoExtractor): _VALID_URL = r'http://(video|www|player)\.(?P%s)\.com/(?Pwatch|series|video|embed)/(?P[^/?#]+)' % '|'.join(_SITES.keys()) IE_DESC = 'Condé Nast media group: %s' % ', '.join(sorted(_SITES.values())) + EMBED_URL = r'(?:https?:)?//player\.(?P%s)\.com/(?Pembed)/.+?' % '|'.join(_SITES.keys()) + _TEST = { 'url': 'http://video.wired.com/watch/3d-printed-speakers-lit-with-led', 'md5': '1921f713ed48aabd715691f774c451f7', diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index dfc2ef4e7..122763a23 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -28,6 +28,7 @@ from .brightcove import BrightcoveIE from .ooyala import OoyalaIE from .rutv import RUTVIE from .smotri import SmotriIE +from .condenast import CondeNastIE class GenericIE(InfoExtractor): @@ -847,6 +848,12 @@ class GenericIE(InfoExtractor): if mobj is not None: return self.url_result(mobj.group('url'), 'MLB') + mobj = re.search( + r']+?src=(["\'])(?P%s)\1' % CondeNastIE.EMBED_URL, + webpage) + if mobj is not None: + return self.url_result(self._proto_relative_url(mobj.group('url'), scheme='http:'), 'CondeNast') + def check_video(vurl): vpath = compat_urlparse.urlparse(vurl).path vext = determine_ext(vpath) From bd4e40df1aaef96dcde64dd64793b5152ae66055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Mon, 13 Oct 2014 16:26:53 +0200 Subject: [PATCH 1077/1761] [brightcove] Add a test for playlists --- youtube_dl/extractor/brightcove.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/youtube_dl/extractor/brightcove.py b/youtube_dl/extractor/brightcove.py index 294670386..ad22cbafd 100644 --- a/youtube_dl/extractor/brightcove.py +++ b/youtube_dl/extractor/brightcove.py @@ -87,6 +87,15 @@ class BrightcoveIE(InfoExtractor): 'description': 'UCI MTB World Cup 2014: Fort William, UK - Downhill Finals', }, }, + { + # playlist test + # from http://support.brightcove.com/en/video-cloud/docs/playlist-support-single-video-players + 'url': 'http://c.brightcove.com/services/viewer/htmlFederated?playerID=3550052898001&playerKey=AQ%7E%7E%2CAAABmA9XpXk%7E%2C-Kp7jNgisre1fG5OdqpAFUTcs0lP_ZoL', + 'info_dict': { + 'title': 'Sealife', + }, + 'playlist_mincount': 7, + }, ] @classmethod From a86c73cf80130e55b676dcf5f5979801f28acaec Mon Sep 17 00:00:00 2001 From: Damon Timm Date: Mon, 13 Oct 2014 14:08:29 -0700 Subject: [PATCH 1078/1761] [glide] Add new extractor Added an extractor for glide.me shared messages. Glide is a movile video messaging services. You can share the link to the messages easily enough and this would allow you to download and save the actual video. --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/glide.py | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 youtube_dl/extractor/glide.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 5e38d2663..c0b26c5b3 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -134,6 +134,7 @@ from .gamestar import GameStarIE from .gametrailers import GametrailersIE from .gdcvault import GDCVaultIE from .generic import GenericIE +from .glide import GlideIE from .globo import GloboIE from .godtube import GodTubeIE from .golem import GolemIE diff --git a/youtube_dl/extractor/glide.py b/youtube_dl/extractor/glide.py new file mode 100644 index 000000000..175d85197 --- /dev/null +++ b/youtube_dl/extractor/glide.py @@ -0,0 +1,33 @@ +# coding: utf-8 +from __future__ import unicode_literals + +from .common import InfoExtractor + + +class GlideIE(InfoExtractor): + IE_DESC = 'Glide mobile video messages (glide.me)' + _VALID_URL = r'https?://share\.glide\.me/(?P[A-Za-z0-9\-=_+]+)' + _TEST = { + 'url': 'http://share.glide.me/UZF8zlmuQbe4mr+7dCiQ0w==', + 'md5': '4466372687352851af2d131cfaa8a4c7', + 'info_dict': { + 'id': 'UZF8zlmuQbe4mr+7dCiQ0w==', + 'ext': 'mp4', + 'title': 'Damon Timm\'s Glide message', + 'thumbnail' : 'http://dk608k4lm7m9j.cloudfront.net/3ee7da5af87065a1eeb8c6c9a864ba5b_2.jpg' + } + } + + def _real_extract(self, url): + video_id = self._match_id(url) + webpage = self._download_webpage(url, video_id) + title = self._html_search_regex(r'(.*?)', webpage, 'title') + video_url = self._search_regex(r'', webpage, 'video_url') + thumbnail_url = self._search_regex(r'Video thumbnail', webpage, 'thumbnail_url') + + return { + 'id': video_id, + 'title': title, + 'url' : 'http:' + video_url, + 'thumbnail' : 'http:' + thumbnail_url + } From 5f58165def551921741b44772c9bf31a237a4ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Tue, 14 Oct 2014 21:43:48 +0700 Subject: [PATCH 1079/1761] [extractor/common] Fix dumping requests with long file abspath on Windows --- youtube_dl/extractor/common.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 450c7dfd6..e8366f7f9 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -281,6 +281,12 @@ class InfoExtractor(object): raw_filename = basen + '.dump' filename = sanitize_filename(raw_filename, restricted=True) self.to_screen('Saving request to ' + filename) + # Working around MAX_PATH limitation on Windows (see + # http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx) + if os.name == 'nt': + absfilepath = os.path.abspath(filename) + if len(absfilepath) > 259: + filename = '\\\\?\\' + absfilepath with open(filename, 'wb') as outf: outf.write(webpage_bytes) From 62a164e71372f126d6d70997adf74fcc4e086b58 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Wed, 15 Oct 2014 00:53:54 +0200 Subject: [PATCH 1080/1761] [mixcloud] Output downloading progress --- youtube_dl/extractor/mixcloud.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/youtube_dl/extractor/mixcloud.py b/youtube_dl/extractor/mixcloud.py index a4564d3de..bb8937c4d 100644 --- a/youtube_dl/extractor/mixcloud.py +++ b/youtube_dl/extractor/mixcloud.py @@ -33,22 +33,22 @@ class MixcloudIE(InfoExtractor): }, } - def check_urls(self, url_list): - """Returns 1st active url from list""" - for url in url_list: + def _get_url(self, track_id, template_url): + server_count = 30 + for i in range(server_count): + url = template_url % i try: # We only want to know if the request succeed # don't download the whole file - self._request_webpage(HEADRequest(url), None, False) + self._request_webpage( + HEADRequest(url), track_id, + 'Checking URL %d/%d ...' % (i + 1, server_count + 1)) return url except ExtractorError: - url = None + pass return None - def _get_url(self, template_url): - return self.check_urls(template_url % i for i in range(30)) - def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) uploader = mobj.group(1) @@ -61,11 +61,11 @@ class MixcloudIE(InfoExtractor): r'\s(?:data-preview-url|m-preview)="(.+?)"', webpage, 'preview url') song_url = preview_url.replace('/previews/', '/c/originals/') template_url = re.sub(r'(stream\d*)', 'stream%d', song_url) - final_song_url = self._get_url(template_url) + final_song_url = self._get_url(track_id, template_url) if final_song_url is None: self.to_screen('Trying with m4a extension') template_url = template_url.replace('.mp3', '.m4a').replace('originals/', 'm4a/64/') - final_song_url = self._get_url(template_url) + final_song_url = self._get_url(track_id, template_url) if final_song_url is None: raise ExtractorError('Unable to extract track url') From a72cbfacf067fc5539b93152d2917f30f44b88c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Wed, 15 Oct 2014 12:24:11 +0200 Subject: [PATCH 1081/1761] [ted] Add support for external videos (fixes #3948) --- youtube_dl/extractor/ted.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/youtube_dl/extractor/ted.py b/youtube_dl/extractor/ted.py index d5e28efad..cd4af96fd 100644 --- a/youtube_dl/extractor/ted.py +++ b/youtube_dl/extractor/ted.py @@ -65,6 +65,22 @@ class TEDIE(SubtitlesInfoExtractor): 'title': 'Who are the hackers?', }, 'playlist_mincount': 6, + }, { + # contains a youtube video + 'url': 'https://www.ted.com/talks/douglas_adams_parrots_the_universe_and_everything', + 'add_ie': ['Youtube'], + 'info_dict': { + 'id': '_ZG8HBuDjgc', + 'ext': 'mp4', + 'title': 'Douglas Adams: Parrots the Universe and Everything', + 'description': 'md5:01ad1e199c49ac640cb1196c0e9016af', + 'uploader': 'University of California Television (UCTV)', + 'uploader_id': 'UCtelevision', + 'upload_date': '20080522', + }, + 'params': { + 'skip_download': True, + }, }] _NATIVE_FORMATS = { @@ -114,6 +130,13 @@ class TEDIE(SubtitlesInfoExtractor): talk_info = self._extract_info(webpage)['talks'][0] + if talk_info.get('external') is not None: + self.to_screen('Found video from %s' % talk_info['external']['service']) + return { + '_type': 'url', + 'url': talk_info['external']['uri'], + } + formats = [{ 'url': format_url, 'format_id': format_id, From df928d500fa2bcbee5a18fae9454e22e0c223624 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Wed, 15 Oct 2014 12:39:30 +0200 Subject: [PATCH 1082/1761] release 2014.10.15 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 416e2fd85..f17c86405 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.13' +__version__ = '2014.10.15' From 09a42738fc5a060208cad5fa5579688225e53464 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Wed, 15 Oct 2014 13:50:53 +0200 Subject: [PATCH 1083/1761] [generic] Correct handling of embedded vimeo players (#3955) --- youtube_dl/extractor/generic.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 122763a23..158dc95a5 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -609,13 +609,13 @@ class GenericIE(InfoExtractor): if mobj: player_url = unescapeHTML(mobj.group('url')) surl = smuggle_url(player_url, {'Referer': url}) - return self.url_result(surl, 'Vimeo') + return self.url_result(surl) # Look for embedded (swf embed) Vimeo player mobj = re.search( - r']+?src="(https?://(?:www\.)?vimeo\.com/moogaloop\.swf.+?)"', webpage) + r']+?src="((?:https?:)?//(?:www\.)?vimeo\.com/moogaloop\.swf.+?)"', webpage) if mobj: - return self.url_result(mobj.group(1), 'Vimeo') + return self.url_result(mobj.group(1)) # Look for embedded YouTube player matches = re.findall(r'''(?x) From 474086450808541954e402dd3d58bad38b75b1d5 Mon Sep 17 00:00:00 2001 From: CkuT Date: Wed, 15 Oct 2014 18:24:32 +0200 Subject: [PATCH 1084/1761] [SexyKarma] Add new extractor --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/sexykarma.py | 43 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 youtube_dl/extractor/sexykarma.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 5e38d2663..92f38dcd0 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -316,6 +316,7 @@ from .sbs import SBSIE from .scivee import SciVeeIE from .screencast import ScreencastIE from .servingsys import ServingSysIE +from .sexykarma import SexyKarmaIE from .shared import SharedIE from .sharesix import ShareSixIE from .sina import SinaIE diff --git a/youtube_dl/extractor/sexykarma.py b/youtube_dl/extractor/sexykarma.py new file mode 100644 index 000000000..cd2668872 --- /dev/null +++ b/youtube_dl/extractor/sexykarma.py @@ -0,0 +1,43 @@ +# coding: utf-8 +from __future__ import unicode_literals + +from .common import InfoExtractor + + +class SexyKarmaIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?sexykarma\.com/gonewild/video/(?P[a-zA-Z0-9\-]+)(.html)' + _TESTS = [{ + 'url': 'http://www.sexykarma.com/gonewild/video/taking-a-quick-pee-yHI70cOyIHt.html', + 'md5': 'b9798e7d1ef1765116a8f516c8091dbd', + 'info_dict': { + 'id': 'taking-a-quick-pee-yHI70cOyIHt', + 'ext': 'mp4', + 'title': 'Taking a quick pee.', + 'uploader': 'wildginger7', + } + }, { + 'url': 'http://www.sexykarma.com/gonewild/video/pot-pixie-tribute-8Id6EZPbuHf.html', + 'md5': 'dd216c68d29b49b12842b9babe762a5d', + 'info_dict': { + 'id': 'pot-pixie-tribute-8Id6EZPbuHf', + 'ext': 'mp4', + 'title': 'pot_pixie tribute', + 'uploader': 'banffite', + } + }] + + def _real_extract(self, url): + video_id = self._match_id(url) + + # TODO more code goes here, for example ... + webpage = self._download_webpage(url, video_id) + title = self._html_search_regex(r'

(.*?)', webpage, 'title') + uploader = self._html_search_regex(r'class="aupa">\n*(.*?)', webpage, 'uploader') + url = self._html_search_regex(r'

Date: Wed, 15 Oct 2014 20:17:07 +0200 Subject: [PATCH 1085/1761] Few improvements --- youtube_dl/extractor/sexykarma.py | 51 +++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/youtube_dl/extractor/sexykarma.py b/youtube_dl/extractor/sexykarma.py index cd2668872..ac7745e74 100644 --- a/youtube_dl/extractor/sexykarma.py +++ b/youtube_dl/extractor/sexykarma.py @@ -2,42 +2,73 @@ from __future__ import unicode_literals from .common import InfoExtractor - +import re +import datetime class SexyKarmaIE(InfoExtractor): - _VALID_URL = r'https?://(?:www\.)?sexykarma\.com/gonewild/video/(?P[a-zA-Z0-9\-]+)(.html)' + _VALID_URL = r'https?://(?:www\.)?sexykarma\.com/gonewild/video/.+\-(?P[a-zA-Z0-9\-]+)(.html)' _TESTS = [{ 'url': 'http://www.sexykarma.com/gonewild/video/taking-a-quick-pee-yHI70cOyIHt.html', 'md5': 'b9798e7d1ef1765116a8f516c8091dbd', 'info_dict': { - 'id': 'taking-a-quick-pee-yHI70cOyIHt', + 'id': 'yHI70cOyIHt', 'ext': 'mp4', 'title': 'Taking a quick pee.', - 'uploader': 'wildginger7', + 'uploader_id': 'wildginger7', + 'thumbnail': 're:^https?://.*\.jpg$', + 'duration': int, + 'view_count': int, + 'upload_date': '20141007', } }, { 'url': 'http://www.sexykarma.com/gonewild/video/pot-pixie-tribute-8Id6EZPbuHf.html', 'md5': 'dd216c68d29b49b12842b9babe762a5d', 'info_dict': { - 'id': 'pot-pixie-tribute-8Id6EZPbuHf', + 'id': '8Id6EZPbuHf', 'ext': 'mp4', 'title': 'pot_pixie tribute', - 'uploader': 'banffite', + 'uploader_id': 'banffite', + 'thumbnail': 're:^https?://.*\.jpg$', + 'duration': int, + 'view_count': int, + 'upload_date': '20141013', } }] def _real_extract(self, url): video_id = self._match_id(url) - # TODO more code goes here, for example ... webpage = self._download_webpage(url, video_id) + title = self._html_search_regex(r'

(.*?)', webpage, 'title') - uploader = self._html_search_regex(r'class="aupa">\n*(.*?)', webpage, 'uploader') + uploader_id = self._html_search_regex(r'class="aupa">\n*(.*?)', webpage, 'uploader') url = self._html_search_regex(r'

[\n\s]*Time: [\n\s]*(.+)\n*', webpage, 'duration') + duration = self._to_seconds(str_duration) + + str_views = self._html_search_regex(r'[\n\s]*Views: [\n\s]*(.+)', webpage, 'view_count') + view_count = int(str_views) + # print view_count + + date = self._html_search_regex(r'class="aup">Added: (.*?)', webpage, 'date') + d = datetime.datetime.strptime(date, '%B %d, %Y') + upload_date = d.strftime('%Y%m%d') return { 'id': video_id, 'title': title, - 'uploader': uploader, - 'url': url + 'uploader_id': uploader_id, + 'url': url, + 'thumbnail': thumbnail, + 'duration': duration, + 'view_count': view_count, + 'upload_date': upload_date, } + + def _to_seconds(self, timestr): + seconds= 0 + for part in timestr.split(':'): + seconds= seconds*60 + int(part) + return seconds From 7da224c907627b5b0233c7eb4eea733f5f97ae90 Mon Sep 17 00:00:00 2001 From: CkuT Date: Wed, 15 Oct 2014 22:34:35 +0200 Subject: [PATCH 1086/1761] Add categories --- youtube_dl/extractor/sexykarma.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/youtube_dl/extractor/sexykarma.py b/youtube_dl/extractor/sexykarma.py index ac7745e74..629499e72 100644 --- a/youtube_dl/extractor/sexykarma.py +++ b/youtube_dl/extractor/sexykarma.py @@ -56,6 +56,8 @@ class SexyKarmaIE(InfoExtractor): d = datetime.datetime.strptime(date, '%B %d, %Y') upload_date = d.strftime('%Y%m%d') + categories = re.findall(r'http://www.sexykarma.com/gonewild/search/video/(?:.+?)">(.*?)', webpage) + return { 'id': video_id, 'title': title, @@ -65,6 +67,7 @@ class SexyKarmaIE(InfoExtractor): 'duration': duration, 'view_count': view_count, 'upload_date': upload_date, + 'categories': categories, } def _to_seconds(self, timestr): From 355d074ff955f7f8b24321e51be44f4431572fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Thu, 16 Oct 2014 22:23:35 +0700 Subject: [PATCH 1087/1761] [twitch] Adapt to new API (Fixes #3946, Fixes #3949, Fixes #3965) Work in progress --- youtube_dl/extractor/justintv.py | 77 ++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/youtube_dl/extractor/justintv.py b/youtube_dl/extractor/justintv.py index 27017e89f..411167d7d 100644 --- a/youtube_dl/extractor/justintv.py +++ b/youtube_dl/extractor/justintv.py @@ -10,6 +10,7 @@ from ..utils import ( compat_str, ExtractorError, formatSeconds, + parse_iso8601, ) @@ -43,6 +44,8 @@ class JustinTVIE(InfoExtractor): } } + _API_BASE = 'https://api.twitch.tv' + # Return count of items, list of *valid* items def _parse_page(self, url, video_id, counter): info_json = self._download_webpage( @@ -74,18 +77,84 @@ class JustinTVIE(InfoExtractor): }) return (len(response), info) + def _handle_error(self, response): + if not isinstance(response, dict): + return + error = response.get('error') + if error: + raise ExtractorError( + '%s returned error: %s - %s' % (self.IE_NAME, error, response.get('message')), + expected=True) + + def _download_json(self, url, video_id, note='Downloading JSON metadata'): + response = super(JustinTVIE, self)._download_json(url, video_id, note) + self._handle_error(response) + return response + + def _extract_media(self, item, item_id): + + ITEMS = { + 'a': 'video', + 'c': 'chapter', + } + + info = self._extract_info(self._download_json( + '%s/kraken/videos/%s%s' % (self._API_BASE, item, item_id), item_id, + 'Downloading %s info JSON' % ITEMS[item])) + + response = self._download_json( + '%s/api/videos/%s%s' % (self._API_BASE, item, item_id), item_id, + 'Downloading %s playlist JSON' % ITEMS[item]) + + entries = [] + chunks = response['chunks'] + qualities = list(chunks.keys()) + for num, fragment in enumerate(zip(*chunks.values()), start=1): + formats = [] + for fmt_num, fragment_fmt in enumerate(fragment): + format_id = qualities[fmt_num] + fmt = { + 'url': fragment_fmt['url'], + 'format_id': format_id, + 'quality': 1 if format_id == 'live' else 0, + } + m = re.search(r'^(?P\d+)[Pp]', format_id) + if m: + fmt['height'] = int(m.group('height')) + formats.append(fmt) + self._sort_formats(formats) + entry = dict(info) + entry['title'] = '%s part %d' % (entry['title'], num) + entry['formats'] = formats + entries.append(entry) + return entries + + def _extract_info(self, info): + return { + 'id': info['_id'], + 'title': info['title'], + 'description': info['description'], + 'duration': info['length'], + 'thumbnail': info['preview'], + 'uploader': info['channel']['display_name'], + 'uploader_id': info['channel']['name'], + 'timestamp': parse_iso8601(info['recorded_at']), + 'view_count': info['views'], + } + def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) - api_base = 'http://api.justin.tv' + api_base = 'http://api.twitch.tv' paged = False if mobj.group('channelid'): paged = True video_id = mobj.group('channelid') api = api_base + '/channel/archives/%s.json' % video_id elif mobj.group('chapterid'): - chapter_id = mobj.group('chapterid') + return self._extract_media('c', mobj.group('chapterid')) + """ webpage = self._download_webpage(url, chapter_id) m = re.search(r'PP\.archive_id = "([0-9]+)";', webpage) if not m: @@ -133,9 +202,9 @@ class JustinTVIE(InfoExtractor): 'uploader_id': chapter_info['channel']['name'], } return info + """ else: - video_id = mobj.group('videoid') - api = api_base + '/broadcast/by_archive/%s.json' % video_id + return self._extract_media('a', mobj.group('videoid')) entries = [] offset = 0 From 4698f0d85839f340fd33a387247efe39828384af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Fri, 17 Oct 2014 15:49:16 +0200 Subject: [PATCH 1088/1761] [vimeo] Improve regex for the config js dict (fixes #3955, fixes #3974) The javascript code contains assignments of empty dicts with the same variable name --- youtube_dl/extractor/vimeo.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/vimeo.py b/youtube_dl/extractor/vimeo.py index e6a86f18e..07959d3fe 100644 --- a/youtube_dl/extractor/vimeo.py +++ b/youtube_dl/extractor/vimeo.py @@ -157,6 +157,18 @@ class VimeoIE(VimeoBaseInfoExtractor, SubtitlesInfoExtractor): 'duration': 62, } }, + { + # from https://www.ouya.tv/game/Pier-Solar-and-the-Great-Architects/ + 'url': 'https://player.vimeo.com/video/98044508', + 'note': 'The js code contains assignments to the same variable as the config', + 'info_dict': { + 'id': '98044508', + 'ext': 'mp4', + 'title': 'Pier Solar OUYA Official Trailer', + 'uploader': 'Tulio Gonçalves', + 'uploader_id': 'user28849593', + }, + }, ] def _verify_video_password(self, url, video_id, webpage): @@ -244,7 +256,7 @@ class VimeoIE(VimeoBaseInfoExtractor, SubtitlesInfoExtractor): # We try to find out to which variable is assigned the config dic m_variable_name = re.search('(\w)\.video\.id', webpage) if m_variable_name is not None: - config_re = r'%s=({.+?});' % re.escape(m_variable_name.group(1)) + config_re = r'%s=({[^}].+?});' % re.escape(m_variable_name.group(1)) else: config_re = [r' = {config:({.+?}),assets:', r'(?:[abc])=({.+?});'] config = self._search_regex(config_re, webpage, 'info section', From 46fd0dd5a5a8d98b76830636a3dcd241ac7bcc7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Fri, 17 Oct 2014 22:58:18 +0700 Subject: [PATCH 1089/1761] [twitch] Rename extractor and support channel videos --- youtube_dl/extractor/__init__.py | 2 +- .../extractor/{justintv.py => twitch.py} | 102 +++++------------- 2 files changed, 28 insertions(+), 76 deletions(-) rename youtube_dl/extractor/{justintv.py => twitch.py} (69%) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 5e38d2663..c29c29c10 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -173,7 +173,6 @@ from .jadorecettepub import JadoreCettePubIE from .jeuxvideo import JeuxVideoIE from .jove import JoveIE from .jukebox import JukeboxIE -from .justintv import JustinTVIE from .jpopsukitv import JpopsukiIE from .kankan import KankanIE from .keezmovies import KeezMoviesIE @@ -395,6 +394,7 @@ from .tutv import TutvIE from .tvigle import TvigleIE from .tvp import TvpIE from .tvplay import TVPlayIE +from .twitch import TwitchIE from .ubu import UbuIE from .udemy import ( UdemyIE, diff --git a/youtube_dl/extractor/justintv.py b/youtube_dl/extractor/twitch.py similarity index 69% rename from youtube_dl/extractor/justintv.py rename to youtube_dl/extractor/twitch.py index 411167d7d..42d38b224 100644 --- a/youtube_dl/extractor/justintv.py +++ b/youtube_dl/extractor/twitch.py @@ -1,26 +1,20 @@ from __future__ import unicode_literals import itertools -import json -import os import re from .common import InfoExtractor from ..utils import ( - compat_str, ExtractorError, - formatSeconds, parse_iso8601, ) -class JustinTVIE(InfoExtractor): - """Information extractor for justin.tv and twitch.tv""" +class TwitchIE(InfoExtractor): # TODO: One broadcast may be split into multiple videos. The key # 'broadcast_id' is the same for all parts, and 'broadcast_part' # starts at 1 and increases. Can we treat all parts as one video? - - _VALID_URL = r"""(?x)^(?:http://)?(?:www\.)?(?:twitch|justin)\.tv/ + _VALID_URL = r"""(?x)^(?:http://)?(?:www\.)?twitch\.tv/ (?: (?P[^/]+)| (?:(?:[^/]+)/b/(?P[^/]+))| @@ -28,9 +22,8 @@ class JustinTVIE(InfoExtractor): ) /?(?:\#.*)?$ """ - _JUSTIN_PAGE_LIMIT = 100 - IE_NAME = 'justin.tv' - IE_DESC = 'justin.tv and twitch.tv' + _PAGE_LIMIT = 100 + _API_BASE = 'https://api.twitch.tv' _TEST = { 'url': 'http://www.twitch.tv/thegamedevhub/b/296128360', 'md5': 'ecaa8a790c22a40770901460af191c9a', @@ -44,39 +37,6 @@ class JustinTVIE(InfoExtractor): } } - _API_BASE = 'https://api.twitch.tv' - - # Return count of items, list of *valid* items - def _parse_page(self, url, video_id, counter): - info_json = self._download_webpage( - url, video_id, - 'Downloading video info JSON on page %d' % counter, - 'Unable to download video info JSON %d' % counter) - - response = json.loads(info_json) - if type(response) != list: - error_text = response.get('error', 'unknown error') - raise ExtractorError('Justin.tv API: %s' % error_text) - info = [] - for clip in response: - video_url = clip['video_file_url'] - if video_url: - video_extension = os.path.splitext(video_url)[1][1:] - video_date = re.sub('-', '', clip['start_time'][:10]) - video_uploader_id = clip.get('user_id', clip.get('channel_id')) - video_id = clip['id'] - video_title = clip.get('title', video_id) - info.append({ - 'id': compat_str(video_id), - 'url': video_url, - 'title': video_title, - 'uploader': clip.get('channel_name', video_uploader_id), - 'uploader_id': video_uploader_id, - 'upload_date': video_date, - 'ext': video_extension, - }) - return (len(response), info) - def _handle_error(self, response): if not isinstance(response, dict): return @@ -87,25 +47,21 @@ class JustinTVIE(InfoExtractor): expected=True) def _download_json(self, url, video_id, note='Downloading JSON metadata'): - response = super(JustinTVIE, self)._download_json(url, video_id, note) + response = super(TwitchIE, self)._download_json(url, video_id, note) self._handle_error(response) return response def _extract_media(self, item, item_id): - ITEMS = { 'a': 'video', 'c': 'chapter', } - info = self._extract_info(self._download_json( '%s/kraken/videos/%s%s' % (self._API_BASE, item, item_id), item_id, 'Downloading %s info JSON' % ITEMS[item])) - response = self._download_json( '%s/api/videos/%s%s' % (self._API_BASE, item, item_id), item_id, 'Downloading %s playlist JSON' % ITEMS[item]) - entries = [] chunks = response['chunks'] qualities = list(chunks.keys()) @@ -144,14 +100,7 @@ class JustinTVIE(InfoExtractor): def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) - - api_base = 'http://api.twitch.tv' - paged = False - if mobj.group('channelid'): - paged = True - video_id = mobj.group('channelid') - api = api_base + '/channel/archives/%s.json' % video_id - elif mobj.group('chapterid'): + if mobj.group('chapterid'): return self._extract_media('c', mobj.group('chapterid')) """ @@ -203,22 +152,25 @@ class JustinTVIE(InfoExtractor): } return info """ - else: + elif mobj.group('videoid'): return self._extract_media('a', mobj.group('videoid')) - - entries = [] - offset = 0 - limit = self._JUSTIN_PAGE_LIMIT - for counter in itertools.count(1): - page_url = api + ('?offset=%d&limit=%d' % (offset, limit)) - page_count, page_info = self._parse_page( - page_url, video_id, counter) - entries.extend(page_info) - if not paged or page_count != limit: - break - offset += limit - return { - '_type': 'playlist', - 'id': video_id, - 'entries': entries, - } + elif mobj.group('channelid'): + channel_id = mobj.group('channelid') + info = self._download_json( + '%s/kraken/channels/%s' % (self._API_BASE, channel_id), + channel_id, 'Downloading channel info JSON') + channel_name = info.get('display_name') or info.get('name') + entries = [] + offset = 0 + limit = self._PAGE_LIMIT + for counter in itertools.count(1): + response = self._download_json( + '%s/kraken/channels/%s/videos/?offset=%d&limit=%d' + % (self._API_BASE, channel_id, offset, limit), + channel_id, 'Downloading channel videos JSON page %d' % counter) + videos = response['videos'] + if not videos: + break + entries.extend([self.url_result(video['url'], 'Twitch') for video in videos]) + offset += limit + return self.playlist_result(entries, channel_id, channel_name) From 013bfdd84c09049cffff365fb81a60fdef51f125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Fri, 17 Oct 2014 23:46:53 +0700 Subject: [PATCH 1090/1761] [twitch] Update tests and minor improvements --- youtube_dl/extractor/twitch.py | 35 ++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/youtube_dl/extractor/twitch.py b/youtube_dl/extractor/twitch.py index 42d38b224..247fc2f64 100644 --- a/youtube_dl/extractor/twitch.py +++ b/youtube_dl/extractor/twitch.py @@ -24,18 +24,28 @@ class TwitchIE(InfoExtractor): """ _PAGE_LIMIT = 100 _API_BASE = 'https://api.twitch.tv' - _TEST = { - 'url': 'http://www.twitch.tv/thegamedevhub/b/296128360', - 'md5': 'ecaa8a790c22a40770901460af191c9a', + _TESTS = [{ + 'url': 'http://www.twitch.tv/riotgames/b/577357806', 'info_dict': { - 'id': '296128360', - 'ext': 'flv', - 'upload_date': '20110927', - 'uploader_id': 25114803, - 'uploader': 'thegamedevhub', - 'title': 'Beginner Series - Scripting With Python Pt.1' - } - } + 'id': 'a577357806', + 'title': 'Worlds Semifinals - Star Horn Royal Club vs. OMG', + }, + 'playlist_mincount': 12, + }, { + 'url': 'http://www.twitch.tv/acracingleague/c/5285812', + 'info_dict': { + 'id': 'c5285812', + 'title': 'ACRL Off Season - Sports Cars @ Nordschleife', + }, + 'playlist_mincount': 3, + }, { + 'url': 'http://www.twitch.tv/vanillatv', + 'info_dict': { + 'id': 'vanillatv', + 'title': 'VanillaTV', + }, + 'playlist_mincount': 412, + }] def _handle_error(self, response): if not isinstance(response, dict): @@ -80,10 +90,11 @@ class TwitchIE(InfoExtractor): formats.append(fmt) self._sort_formats(formats) entry = dict(info) + entry['id'] = '%s_%d' % (entry['id'], num), entry['title'] = '%s part %d' % (entry['title'], num) entry['formats'] = formats entries.append(entry) - return entries + return self.playlist_result(entries, info['id'], info['title']) def _extract_info(self, info): return { From 9471c4440599b02bf648091560097eaab690db50 Mon Sep 17 00:00:00 2001 From: Naglis Jonaitis Date: Sat, 18 Oct 2014 01:52:55 +0300 Subject: [PATCH 1091/1761] [generic] Make sure Wistia embed URLs contain the protocol (Closes #3977) Also, improve detection (Addresses #3662) --- youtube_dl/extractor/generic.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 158dc95a5..9057a6beb 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -654,15 +654,17 @@ class GenericIE(InfoExtractor): match = re.search( r']+?src=(["\'])(?P(?:https?:)?//(?:fast\.)?wistia\.net/embed/iframe/.+?)\1', webpage) if match: + embed_url = self._proto_relative_url( + unescapeHTML(match.group('url'))) return { '_type': 'url_transparent', - 'url': unescapeHTML(match.group('url')), + 'url': embed_url, 'ie_key': 'Wistia', 'uploader': video_uploader, 'title': video_title, 'id': video_id, } - match = re.search(r'(?:id=["\']wistia_|data-wistiaid=["\']|Wistia\.embed\(["\'])(?P[^"\']+)', webpage) + match = re.search(r'(?:id=["\']wistia_|data-wistia-?id=["\']|Wistia\.embed\(["\'])(?P[^"\']+)', webpage) if match: return { '_type': 'url_transparent', From f9befee1f5e96e8b9b7032f33e70290ffd7769f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sat, 18 Oct 2014 18:14:49 +0700 Subject: [PATCH 1092/1761] [arte.tv:+7] Append media type to format_id (Closes #3967) --- youtube_dl/extractor/arte.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/youtube_dl/extractor/arte.py b/youtube_dl/extractor/arte.py index c3d02f85e..3a34d1ecc 100644 --- a/youtube_dl/extractor/arte.py +++ b/youtube_dl/extractor/arte.py @@ -160,6 +160,9 @@ class ArteTVPlus7IE(InfoExtractor): format_id = '%s-%s' % (quality, format_info['versionCode']) else: format_id = quality + media_type = format_info.get('mediaType') + if media_type is not None: + format_id += '-%s' % media_type info = { 'format_id': format_id, 'format_note': format_info.get('versionLibelle'), From 159444a6688172696185404cbfea02945982e968 Mon Sep 17 00:00:00 2001 From: Sergey M Date: Sat, 18 Oct 2014 21:57:24 +0700 Subject: [PATCH 1093/1761] [twitch] Remove superfluous comma --- youtube_dl/extractor/twitch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/twitch.py b/youtube_dl/extractor/twitch.py index 247fc2f64..36aa1ad6e 100644 --- a/youtube_dl/extractor/twitch.py +++ b/youtube_dl/extractor/twitch.py @@ -90,7 +90,7 @@ class TwitchIE(InfoExtractor): formats.append(fmt) self._sort_formats(formats) entry = dict(info) - entry['id'] = '%s_%d' % (entry['id'], num), + entry['id'] = '%s_%d' % (entry['id'], num) entry['title'] = '%s part %d' % (entry['title'], num) entry['formats'] = formats entries.append(entry) From 95fa5fb569c9a29d1dfb7da744022373d279fcb7 Mon Sep 17 00:00:00 2001 From: Sergey M Date: Sun, 19 Oct 2014 00:48:05 +0700 Subject: [PATCH 1094/1761] [sexykarma] Improve and simplify --- youtube_dl/extractor/sexykarma.py | 99 ++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 35 deletions(-) diff --git a/youtube_dl/extractor/sexykarma.py b/youtube_dl/extractor/sexykarma.py index 629499e72..4a6345758 100644 --- a/youtube_dl/extractor/sexykarma.py +++ b/youtube_dl/extractor/sexykarma.py @@ -1,77 +1,106 @@ # coding: utf-8 from __future__ import unicode_literals -from .common import InfoExtractor import re -import datetime + +from .common import InfoExtractor +from ..utils import ( + unified_strdate, + parse_duration, + int_or_none, +) + class SexyKarmaIE(InfoExtractor): - _VALID_URL = r'https?://(?:www\.)?sexykarma\.com/gonewild/video/.+\-(?P[a-zA-Z0-9\-]+)(.html)' + _VALID_URL = r'https?://(?:www\.)?sexykarma\.com/gonewild/video/(?P[^/]+)-(?P[a-zA-Z0-9]+)\.html' _TESTS = [{ 'url': 'http://www.sexykarma.com/gonewild/video/taking-a-quick-pee-yHI70cOyIHt.html', 'md5': 'b9798e7d1ef1765116a8f516c8091dbd', 'info_dict': { 'id': 'yHI70cOyIHt', + 'display_id': 'taking-a-quick-pee', 'ext': 'mp4', 'title': 'Taking a quick pee.', - 'uploader_id': 'wildginger7', + 'description': '', 'thumbnail': 're:^https?://.*\.jpg$', - 'duration': int, - 'view_count': int, + 'uploader': 'wildginger7', 'upload_date': '20141007', + 'duration': 81, + 'view_count': int, + 'comment_count': int, + 'categories': list, } }, { 'url': 'http://www.sexykarma.com/gonewild/video/pot-pixie-tribute-8Id6EZPbuHf.html', 'md5': 'dd216c68d29b49b12842b9babe762a5d', 'info_dict': { 'id': '8Id6EZPbuHf', + 'display_id': 'pot-pixie-tribute', 'ext': 'mp4', 'title': 'pot_pixie tribute', - 'uploader_id': 'banffite', + 'description': 'tribute', 'thumbnail': 're:^https?://.*\.jpg$', - 'duration': int, - 'view_count': int, + 'uploader': 'banffite', 'upload_date': '20141013', + 'duration': 16, + 'view_count': int, + 'comment_count': int, + 'categories': list, } }] def _real_extract(self, url): - video_id = self._match_id(url) + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + display_id = mobj.group('display_id') - webpage = self._download_webpage(url, video_id) - - title = self._html_search_regex(r'

(.*?)', webpage, 'title') - uploader_id = self._html_search_regex(r'class="aupa">\n*(.*?)', webpage, 'uploader') - url = self._html_search_regex(r'

[\n\s]*Time: [\n\s]*(.+)\n*', webpage, 'duration') - duration = self._to_seconds(str_duration) + webpage = self._download_webpage(url, display_id) - str_views = self._html_search_regex(r'[\n\s]*Views: [\n\s]*(.+)', webpage, 'view_count') - view_count = int(str_views) - # print view_count + video_url = self._html_search_regex( + r'

Save this video to your computer:

Added: (.*?)', webpage, 'date') - d = datetime.datetime.strptime(date, '%B %d, %Y') - upload_date = d.strftime('%Y%m%d') + title = self._html_search_regex( + r'

(.*?)', + webpage, 'title') + description = self._html_search_meta( + 'description', webpage, 'description', fatal=False, default='') + thumbnail = self._html_search_regex( + r'(.*?)', webpage) + uploader = self._html_search_regex( + r'class="aupa">\s*(.*?)', + webpage, 'uploader') + upload_date = unified_strdate(self._html_search_regex( + r'Added: (.+?)', webpage, 'upload date', fatal=False)) + + duration = parse_duration(self._search_regex( + r'Time:\s*\s*\s*(.+?)\s*', + webpage, 'duration', fatal=False)) + + view_count = int_or_none(self._search_regex( + r'Views:\s*\s*\s*(\d+)\s*', + webpage, 'view count', fatal=False)) + comment_count = int_or_none(self._search_regex( + r'Comments:\s*\s*\s*(\d+)\s*', + webpage, 'comment count', fatal=False)) + + categories = self._html_search_meta( + 'keywords', webpage, 'categories', + fatal=False, default='').split(',') return { 'id': video_id, + 'display_id': display_id, + 'url': video_url, 'title': title, - 'uploader_id': uploader_id, - 'url': url, + 'description': description, 'thumbnail': thumbnail, + 'uploader': uploader, + 'upload_date': upload_date, 'duration': duration, 'view_count': view_count, - 'upload_date': upload_date, + 'comment_count': comment_count, 'categories': categories, } - - def _to_seconds(self, timestr): - seconds= 0 - for part in timestr.split(':'): - seconds= seconds*60 + int(part) - return seconds From 0f175a932fbc44b404d464e5485460054c697bb0 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 18 Oct 2014 20:22:23 +0200 Subject: [PATCH 1095/1761] release 2014.10.18 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index f17c86405..e7f6adef1 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.15' +__version__ = '2014.10.18' From 4510d14f0ad7e1a7c108bc55526d8b4704420347 Mon Sep 17 00:00:00 2001 From: Sergey M Date: Sun, 19 Oct 2014 01:35:53 +0700 Subject: [PATCH 1096/1761] [twitch] Update tests --- test/test_all_urls.py | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/test/test_all_urls.py b/test/test_all_urls.py index 84b05da39..965e5d8a5 100644 --- a/test/test_all_urls.py +++ b/test/test_all_urls.py @@ -14,7 +14,7 @@ from test.helper import gettestcases from youtube_dl.extractor import ( FacebookIE, gen_extractors, - JustinTVIE, + TwitchIE, YoutubeIE, ) @@ -72,21 +72,17 @@ class TestAllURLsMatching(unittest.TestCase): self.assertMatch('http://www.youtube.com/results?search_query=making+mustard', ['youtube:search_url']) self.assertMatch('https://www.youtube.com/results?baz=bar&search_query=youtube-dl+test+video&filters=video&lclk=video', ['youtube:search_url']) - def test_justin_tv_channelid_matching(self): - self.assertTrue(JustinTVIE.suitable('justin.tv/vanillatv')) - self.assertTrue(JustinTVIE.suitable('twitch.tv/vanillatv')) - self.assertTrue(JustinTVIE.suitable('www.justin.tv/vanillatv')) - self.assertTrue(JustinTVIE.suitable('www.twitch.tv/vanillatv')) - self.assertTrue(JustinTVIE.suitable('http://www.justin.tv/vanillatv')) - self.assertTrue(JustinTVIE.suitable('http://www.twitch.tv/vanillatv')) - self.assertTrue(JustinTVIE.suitable('http://www.justin.tv/vanillatv/')) - self.assertTrue(JustinTVIE.suitable('http://www.twitch.tv/vanillatv/')) + def test_twitch_channelid_matching(self): + self.assertTrue(TwitchIE.suitable('twitch.tv/vanillatv')) + self.assertTrue(TwitchIE.suitable('www.twitch.tv/vanillatv')) + self.assertTrue(TwitchIE.suitable('http://www.twitch.tv/vanillatv')) + self.assertTrue(TwitchIE.suitable('http://www.twitch.tv/vanillatv/')) - def test_justintv_videoid_matching(self): - self.assertTrue(JustinTVIE.suitable('http://www.twitch.tv/vanillatv/b/328087483')) + def test_twitch_videoid_matching(self): + self.assertTrue(TwitchIE.suitable('http://www.twitch.tv/vanillatv/b/328087483')) - def test_justin_tv_chapterid_matching(self): - self.assertTrue(JustinTVIE.suitable('http://www.twitch.tv/tsm_theoddone/c/2349361')) + def test_twitch_chapterid_matching(self): + self.assertTrue(TwitchIE.suitable('http://www.twitch.tv/tsm_theoddone/c/2349361')) def test_youtube_extract(self): assertExtractId = lambda url, id: self.assertEqual(YoutubeIE.extract_id(url), id) From 16efb3695f4e3a07e492a4206cb2901c05ac7c65 Mon Sep 17 00:00:00 2001 From: Sergey M Date: Sun, 19 Oct 2014 01:53:15 +0700 Subject: [PATCH 1097/1761] [sexykarma] Add support for watchindianporn --- youtube_dl/extractor/sexykarma.py | 35 ++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/youtube_dl/extractor/sexykarma.py b/youtube_dl/extractor/sexykarma.py index 4a6345758..c833fc8ee 100644 --- a/youtube_dl/extractor/sexykarma.py +++ b/youtube_dl/extractor/sexykarma.py @@ -12,7 +12,8 @@ from ..utils import ( class SexyKarmaIE(InfoExtractor): - _VALID_URL = r'https?://(?:www\.)?sexykarma\.com/gonewild/video/(?P[^/]+)-(?P[a-zA-Z0-9]+)\.html' + IE_DESC = 'Sexy Karma and Watch Indian Porn' + _VALID_URL = r'https?://(?:www\.)?(?:sexykarma\.com|watchindianporn\.net)/(?:[^/]+/)*video/(?P[^/]+)-(?P[a-zA-Z0-9]+)\.html' _TESTS = [{ 'url': 'http://www.sexykarma.com/gonewild/video/taking-a-quick-pee-yHI70cOyIHt.html', 'md5': 'b9798e7d1ef1765116a8f516c8091dbd', @@ -21,11 +22,10 @@ class SexyKarmaIE(InfoExtractor): 'display_id': 'taking-a-quick-pee', 'ext': 'mp4', 'title': 'Taking a quick pee.', - 'description': '', 'thumbnail': 're:^https?://.*\.jpg$', 'uploader': 'wildginger7', 'upload_date': '20141007', - 'duration': 81, + 'duration': 22, 'view_count': int, 'comment_count': int, 'categories': list, @@ -38,7 +38,6 @@ class SexyKarmaIE(InfoExtractor): 'display_id': 'pot-pixie-tribute', 'ext': 'mp4', 'title': 'pot_pixie tribute', - 'description': 'tribute', 'thumbnail': 're:^https?://.*\.jpg$', 'uploader': 'banffite', 'upload_date': '20141013', @@ -47,6 +46,22 @@ class SexyKarmaIE(InfoExtractor): 'comment_count': int, 'categories': list, } + }, { + 'url': 'http://www.watchindianporn.net/video/desi-dancer-namrata-stripping-completely-nude-and-dancing-on-a-hot-number-dW2mtctxJfs.html', + 'md5': '9afb80675550406ed9a63ac2819ef69d', + 'info_dict': { + 'id': 'dW2mtctxJfs', + 'display_id': 'desi-dancer-namrata-stripping-completely-nude-and-dancing-on-a-hot-number', + 'ext': 'mp4', + 'title': 'Desi dancer namrata stripping completely nude and dancing on a hot number', + 'thumbnail': 're:^https?://.*\.jpg$', + 'uploader': 'Don', + 'upload_date': '20140213', + 'duration': 83, + 'view_count': int, + 'comment_count': int, + 'categories': list, + } }] def _real_extract(self, url): @@ -57,14 +72,11 @@ class SexyKarmaIE(InfoExtractor): webpage = self._download_webpage(url, display_id) video_url = self._html_search_regex( - r'

Save this video to your computer:

(.*?)', webpage, 'title') - description = self._html_search_meta( - 'description', webpage, 'description', fatal=False, default='') thumbnail = self._html_search_regex( r'Comments:\s*\s*\s*(\d+)\s*', webpage, 'comment count', fatal=False)) - categories = self._html_search_meta( - 'keywords', webpage, 'categories', - fatal=False, default='').split(',') + categories = re.findall( + r'([^<]+)', + webpage) return { 'id': video_id, 'display_id': display_id, 'url': video_url, 'title': title, - 'description': description, 'thumbnail': thumbnail, 'uploader': uploader, 'upload_date': upload_date, From ce519b747e1e404f6d15ae68e1b1607a27beff1c Mon Sep 17 00:00:00 2001 From: scheiba Date: Sat, 18 Oct 2014 22:15:47 +0200 Subject: [PATCH 1098/1761] added "bild.de" as extractor --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/bild.py | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 youtube_dl/extractor/bild.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 070f9ff19..e0957987c 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -26,6 +26,7 @@ from .bandcamp import BandcampIE, BandcampAlbumIE from .bbccouk import BBCCoUkIE from .beeg import BeegIE from .behindkink import BehindKinkIE +from .bild import BildIE from .bilibili import BiliBiliIE from .blinkx import BlinkxIE from .bliptv import BlipTVIE, BlipTVUserIE diff --git a/youtube_dl/extractor/bild.py b/youtube_dl/extractor/bild.py new file mode 100644 index 000000000..3a822a5c0 --- /dev/null +++ b/youtube_dl/extractor/bild.py @@ -0,0 +1,46 @@ +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor + + +class BildIE(InfoExtractor): + IE_NAME = 'bild' + _TEST = { + 'url': 'http://www.bild.de/video/clip/apple-ipad-air/das-koennen-die-neuen-ipads-38184146.bild.html', + 'info_dict': { + 'id': '38184146', + 'title': 'BILD hat sie getestet', + 'thumbnail': 'http://bilder.bild.de/fotos/stand-das-koennen-die-neuen-ipads-38184138/Bild/1.bild.jpg', + 'duration': 196, + } + } + + #http://www.bild.de/video/clip/apple-ipad-air/das-koennen-die-neuen-ipads-38184146.bild.html + _VALID_URL = r'http?://(?:www\.)?bild\.de/(?:[^/]+/)+(?P[^/]+)-(?P\d+)(?:,auto=true)?\.bild\.html' + + def _real_extract(self, url): + m = re.match(self._VALID_URL, url) + video_id = m.group('id') + + #webpage = self._download_webpage(url, video_id) + + xml_url = url.split(".bild.html")[0]+",view=xml.bild.xml" + + doc = self._download_xml(xml_url, video_id) + + video_url = doc.attrib['src'] + title = doc.attrib['ueberschrift'] + description = doc.attrib['text'] + thumbnail = doc.attrib['img'] + duration = int(doc.attrib['duration'])/1000 + + return { + 'id': video_id, + 'title': title, + 'description': description, + 'url': video_url, + 'thumbnail': thumbnail, + 'duration': duration, + } From cc98a3f09651423f4405933265c6dcf2ae51011f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sun, 19 Oct 2014 15:14:37 +0200 Subject: [PATCH 1099/1761] [cnn] Fix for urls ending in '.cnn-ap' (fixes #3985) --- youtube_dl/extractor/cnn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/cnn.py b/youtube_dl/extractor/cnn.py index dae40c136..78877b1cf 100644 --- a/youtube_dl/extractor/cnn.py +++ b/youtube_dl/extractor/cnn.py @@ -12,7 +12,7 @@ from ..utils import ( class CNNIE(InfoExtractor): _VALID_URL = r'''(?x)https?://((edition|www)\.)?cnn\.com/video/(data/.+?|\?)/ - (?P.+?/(?P[^/]+?)(?:\.cnn|(?=&)))''' + (?P<path>.+?/(?P<title>[^/]+?)(?:\.cnn(-ap)?|(?=&)))''' _TESTS = [{ 'url': 'http://edition.cnn.com/video/?/video/sports/2013/06/09/nadal-1-on-1.cnn', From 8230018c20595a22e636b834ebb522a6a85d0d8b Mon Sep 17 00:00:00 2001 From: Gabriel Schubiner <gabeos@cs.washington.edu> Date: Sun, 19 Oct 2014 22:47:05 -0700 Subject: [PATCH 1100/1761] Added extractor for crunchyroll 'playlists' i.e. series. so that one can, e.g. download all episodes of a series --- youtube_dl/extractor/__init__.py | 5 ++++- youtube_dl/extractor/crunchyroll.py | 35 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 070f9ff19..0dd763006 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -60,7 +60,10 @@ from .comedycentral import ComedyCentralIE, ComedyCentralShowsIE from .condenast import CondeNastIE from .cracked import CrackedIE from .criterion import CriterionIE -from .crunchyroll import CrunchyrollIE +from .crunchyroll import ( + CrunchyrollIE, + CrunchyrollShowPlaylistIE +) from .cspan import CSpanIE from .d8 import D8IE from .dailymotion import ( diff --git a/youtube_dl/extractor/crunchyroll.py b/youtube_dl/extractor/crunchyroll.py index f99888ecc..414c46b0d 100644 --- a/youtube_dl/extractor/crunchyroll.py +++ b/youtube_dl/extractor/crunchyroll.py @@ -24,6 +24,7 @@ from ..aes import ( aes_cbc_decrypt, inc, ) +from .common import InfoExtractor class CrunchyrollIE(SubtitlesInfoExtractor): @@ -285,3 +286,37 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text 'subtitles': subtitles, 'formats': formats, } + + +class CrunchyrollShowPlaylistIE(InfoExtractor): + IE_NAME = "crunchyroll:playlist" + _VALID_URL = r'https?://(?:(?P<prefix>www|m)\.)?(?P<url>crunchyroll\.com/(?!(?:news|anime-news|library|forum|launchcalendar|lineup|store|comics|freetrial|login))(?P<show>[\w\-]+))/?$' + _TITLE_EXTR = r'<span\s+itemprop="name">\s*(?P<showtitle>[\w\s]+)' + + _TESTS = [{ + 'url' : 'http://www.crunchyroll.com/attack-on-titan', + 'info_dict' : { + 'title' : 'Attack on Titan' + }, + 'playlist_count' : 15 + }] + + def _extract_title_entries(self,id,webpage): + _EPISODE_ID_EXTR = r'id="showview_videos_media_(?P<vidid>\d+)".*?href="/{0}/(?P<vidurl>[\w\-]+-(?P=vidid))"'.format(id) + title = self._html_search_regex(self._TITLE_EXTR,webpage,"title",flags=re.UNICODE|re.MULTILINE) + episode_urls = [self.url_result('http://www.crunchyroll.com/{0}/{1}'.format(id, showmatch[1])) for + showmatch in re.findall(_EPISODE_ID_EXTR, webpage,re.UNICODE|re.MULTILINE|re.DOTALL)] + return title, episode_urls + + + def _real_extract(self, url): + url_match = re.match(self._VALID_URL,url) + show_id = url_match.group('show') + webpage = self._download_webpage(url,show_id) + (title,entries) = self._extract_title_entries(show_id,webpage) + return { + '_type' : 'playlist', + 'id' : show_id, + 'title' : title, + 'entries' : entries + } \ No newline at end of file From d24a2b20b4908b01f9b5bfa88cd293c189fe6475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Mon, 20 Oct 2014 20:27:59 +0700 Subject: [PATCH 1101/1761] [arte.tv:+7] Use original format ids to avoid duplicates --- youtube_dl/extractor/arte.py | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/youtube_dl/extractor/arte.py b/youtube_dl/extractor/arte.py index 3a34d1ecc..a42ebff8e 100644 --- a/youtube_dl/extractor/arte.py +++ b/youtube_dl/extractor/arte.py @@ -12,6 +12,7 @@ from ..utils import ( get_element_by_id, compat_str, get_element_by_attribute, + int_or_none, ) # There are different sources of video in arte.tv, the extraction process @@ -98,7 +99,11 @@ class ArteTVPlus7IE(InfoExtractor): 'thumbnail': player_info.get('programImage') or player_info.get('VTU', {}).get('IUR'), } - all_formats = player_info['VSR'].values() + all_formats = [] + for format_id, format_dict in player_info['VSR'].items(): + fmt = dict(format_dict) + fmt['format_id'] = format_id + all_formats.append(fmt) # Some formats use the m3u8 protocol all_formats = list(filter(lambda f: f.get('videoFormat') != 'M3U8', all_formats)) def _match_lang(f): @@ -149,25 +154,12 @@ class ArteTVPlus7IE(InfoExtractor): ) formats = sorted(formats, key=sort_key) def _format(format_info): - quality = '' - height = format_info.get('height') - if height is not None: - quality = compat_str(height) - bitrate = format_info.get('bitrate') - if bitrate is not None: - quality += '-%d' % bitrate - if format_info.get('versionCode') is not None: - format_id = '%s-%s' % (quality, format_info['versionCode']) - else: - format_id = quality - media_type = format_info.get('mediaType') - if media_type is not None: - format_id += '-%s' % media_type info = { - 'format_id': format_id, - 'format_note': format_info.get('versionLibelle'), - 'width': format_info.get('width'), - 'height': height, + 'format_id': format_info['format_id'], + 'format_note': '%s, %s' % (format_info.get('versionCode'), format_info.get('versionLibelle')), + 'width': int_or_none(format_info.get('width')), + 'height': int_or_none(format_info.get('height')), + 'tbr': int_or_none(format_info.get('bitrate')), } if format_info['mediaType'] == 'rtmp': info['url'] = format_info['streamer'] From 1b10a011ec7544f49159ed60642128720333b8aa Mon Sep 17 00:00:00 2001 From: Gabriel Schubiner <gabeos@cs.washington.edu> Date: Mon, 20 Oct 2014 18:38:42 -0700 Subject: [PATCH 1102/1761] Forgot to reverse extracted video urls so they are in correct order for video selection args --- youtube_dl/extractor/crunchyroll.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/extractor/crunchyroll.py b/youtube_dl/extractor/crunchyroll.py index 414c46b0d..9ac86c2be 100644 --- a/youtube_dl/extractor/crunchyroll.py +++ b/youtube_dl/extractor/crunchyroll.py @@ -306,6 +306,7 @@ class CrunchyrollShowPlaylistIE(InfoExtractor): title = self._html_search_regex(self._TITLE_EXTR,webpage,"title",flags=re.UNICODE|re.MULTILINE) episode_urls = [self.url_result('http://www.crunchyroll.com/{0}/{1}'.format(id, showmatch[1])) for showmatch in re.findall(_EPISODE_ID_EXTR, webpage,re.UNICODE|re.MULTILINE|re.DOTALL)] + episode_urls.reverse() return title, episode_urls From 74214d35c592976ab48b3c89577df586705059e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Tue, 21 Oct 2014 20:08:20 +0700 Subject: [PATCH 1103/1761] [arte.tv:+7] Improve title extraction (Closes #3995) --- youtube_dl/extractor/arte.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/arte.py b/youtube_dl/extractor/arte.py index a42ebff8e..844a8f563 100644 --- a/youtube_dl/extractor/arte.py +++ b/youtube_dl/extractor/arte.py @@ -91,9 +91,14 @@ class ArteTVPlus7IE(InfoExtractor): if not upload_date_str: upload_date_str = player_info.get('VDA', '').split(' ')[0] + title = player_info['VTI'].strip() + subtitle = player_info.get('VSU', '').strip() + if subtitle: + title += ' - %s' % subtitle + info_dict = { 'id': player_info['VID'], - 'title': player_info['VTI'], + 'title': title, 'description': player_info.get('VDE'), 'upload_date': unified_strdate(upload_date_str), 'thumbnail': player_info.get('programImage') or player_info.get('VTU', {}).get('IUR'), From 40bca5f92780586f0de085f718bb2aa9ee94b6fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Tue, 21 Oct 2014 21:06:24 +0700 Subject: [PATCH 1104/1761] [arte.tv] Remove unused import --- youtube_dl/extractor/arte.py | 1 - 1 file changed, 1 deletion(-) diff --git a/youtube_dl/extractor/arte.py b/youtube_dl/extractor/arte.py index 844a8f563..b9a9440c0 100644 --- a/youtube_dl/extractor/arte.py +++ b/youtube_dl/extractor/arte.py @@ -10,7 +10,6 @@ from ..utils import ( unified_strdate, determine_ext, get_element_by_id, - compat_str, get_element_by_attribute, int_or_none, ) From 6bf6962062ff674013d8651e190998b506c681e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Wed, 22 Oct 2014 01:24:04 +0700 Subject: [PATCH 1105/1761] [francetv] Force m3u8 formats extension to mp4 (Closes #3997) --- youtube_dl/extractor/francetv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/francetv.py b/youtube_dl/extractor/francetv.py index 0b3374d97..07165e330 100644 --- a/youtube_dl/extractor/francetv.py +++ b/youtube_dl/extractor/francetv.py @@ -46,7 +46,7 @@ class FranceTVBaseInfoExtractor(InfoExtractor): f4m_format['preference'] = 1 formats.extend(f4m_formats) elif video_url.endswith('.m3u8'): - formats.extend(self._extract_m3u8_formats(video_url, video_id)) + formats.extend(self._extract_m3u8_formats(video_url, video_id, 'mp4')) elif video_url.startswith('rtmp'): formats.append({ 'url': video_url, From bfd91588f3fab0d5a14726810c186e5ec2fdd0f4 Mon Sep 17 00:00:00 2001 From: Ole Ernst <olebowle@gmx.com> Date: Wed, 22 Oct 2014 14:24:53 +0200 Subject: [PATCH 1106/1761] [ard] make rss match more universal --- youtube_dl/extractor/ard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/ard.py b/youtube_dl/extractor/ard.py index cd9c1d9be..630b1faa9 100644 --- a/youtube_dl/extractor/ard.py +++ b/youtube_dl/extractor/ard.py @@ -56,7 +56,7 @@ class ARDMediathekIE(InfoExtractor): if '>Der gewünschte Beitrag ist nicht mehr verfügbar.<' in webpage: raise ExtractorError('Video %s is no longer available' % video_id, expected=True) - if re.search(r'rss=true', url): + if re.search(r'[\?&]rss($|[=&])', url): doc = parse_xml(webpage) if doc.tag == 'rss': return GenericIE()._extract_rss(url, video_id, doc) From 6b445558ffe292c11327862ab510b1abf4e36616 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Thu, 23 Oct 2014 00:44:21 +0200 Subject: [PATCH 1107/1761] [youtube] Only set language when necessary We only need to set the language when we are using a login; otherwise it will always be English. --- youtube_dl/extractor/youtube.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index cfae2de89..4ab56e0ac 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -191,8 +191,9 @@ class YoutubeBaseInfoExtractor(InfoExtractor): def _real_initialize(self): if self._downloader is None: return - if not self._set_language(): - return + if self._get_login_info()[0] is not None: + if not self._set_language(): + return if not self._login(): return self._confirm_age() From 9bbec55255bdf7189f782e42c1acaeb596eb9bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Thu, 23 Oct 2014 20:41:45 +0700 Subject: [PATCH 1108/1761] [pbs] Add support for tabbed frontline videos (Closes #4006) --- youtube_dl/extractor/pbs.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/pbs.py b/youtube_dl/extractor/pbs.py index 8f140d626..6118ed5c2 100644 --- a/youtube_dl/extractor/pbs.py +++ b/youtube_dl/extractor/pbs.py @@ -80,8 +80,14 @@ class PBSIE(InfoExtractor): 'thumbnail': 're:^https?://.*\.jpg$', 'upload_date': '20140122', } + }, + { + 'url': 'http://www.pbs.org/wgbh/pages/frontline/united-states-of-secrets/', + 'info_dict': { + 'id': 'united-states-of-secrets', + }, + 'playlist_count': 2, } - ] def _extract_webpage(self, url): @@ -96,6 +102,12 @@ class PBSIE(InfoExtractor): r'<input type="hidden" id="air_date_[0-9]+" value="([^"]+)"', webpage, 'upload date', default=None)) + # tabbed frontline videos + tabbed_videos = re.findall( + r'<div[^>]+class="videotab[^"]*"[^>]+vid="(\d+)"', webpage) + if tabbed_videos: + return tabbed_videos, presumptive_id, upload_date + MEDIA_ID_REGEXES = [ r"div\s*:\s*'videoembed'\s*,\s*mediaid\s*:\s*'(\d+)'", # frontline video embed r'class="coveplayerid">([^<]+)<', # coveplayer @@ -130,6 +142,12 @@ class PBSIE(InfoExtractor): def _real_extract(self, url): video_id, display_id, upload_date = self._extract_webpage(url) + if isinstance(video_id, list): + entries = [self.url_result( + 'http://video.pbs.org/video/%s' % vid_id, 'PBS', vid_id) + for vid_id in video_id] + return self.playlist_result(entries, display_id) + info_url = 'http://video.pbs.org/videoInfo/%s?format=json' % video_id info = self._download_json(info_url, display_id) From 8f3b5397a761d68122bc1bd66d049fbbe31289a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Thu, 23 Oct 2014 21:35:51 +0700 Subject: [PATCH 1109/1761] [cinemassacre] Fix extraction (Closes #4008) --- youtube_dl/extractor/cinemassacre.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/youtube_dl/extractor/cinemassacre.py b/youtube_dl/extractor/cinemassacre.py index 496271be4..d064a28f9 100644 --- a/youtube_dl/extractor/cinemassacre.py +++ b/youtube_dl/extractor/cinemassacre.py @@ -42,7 +42,7 @@ class CinemassacreIE(InfoExtractor): webpage = self._download_webpage(url, display_id) video_date = mobj.group('date_Y') + mobj.group('date_m') + mobj.group('date_d') - mobj = re.search(r'src="(?P<embed_url>http://player\.screenwavemedia\.com/play/[a-zA-Z]+\.php\?id=(?:Cinemassacre-)?(?P<video_id>.+?))"', webpage) + mobj = re.search(r'src="(?P<embed_url>http://player\.screenwavemedia\.com/play/[a-zA-Z]+\.php\?[^"]*\bid=(?:Cinemassacre-)?(?P<video_id>.+?))"', webpage) if not mobj: raise ExtractorError('Can\'t extract embed url and video id') playerdata_url = mobj.group('embed_url') @@ -53,17 +53,22 @@ class CinemassacreIE(InfoExtractor): video_description = self._html_search_regex( r'<div class="entry-content">(?P<description>.+?)</div>', webpage, 'description', flags=re.DOTALL, fatal=False) + video_thumbnail = self._og_search_thumbnail(webpage) playerdata = self._download_webpage(playerdata_url, video_id, 'Downloading player webpage') - video_thumbnail = self._search_regex( - r'image: \'(?P<thumbnail>[^\']+)\'', playerdata, 'thumbnail', fatal=False) - sd_url = self._search_regex(r'file: \'([^\']+)\', label: \'SD\'', playerdata, 'sd_file') - videolist_url = self._search_regex(r'file: \'([^\']+\.smil)\'}', playerdata, 'videolist_url') + vidurl = self._search_regex( + r'\'vidurl\'\s*:\s*"([^\']+)"', playerdata, 'vidurl').replace('\\/', '/') + vidid = self._search_regex( + r'\'vidid\'\s*:\s*"([^\']+)"', playerdata, 'vidid') + videoserver = self._html_search_regex( + r"'videoserver'\s*:\s*'([^']+)'", playerdata, 'videoserver') + + videolist_url = 'http://%s/vod/smil:%s.smil/jwplayer.smil' % (videoserver, vidid) videolist = self._download_xml(videolist_url, video_id, 'Downloading videolist XML') formats = [] - baseurl = sd_url[:sd_url.rfind('/')+1] + baseurl = vidurl[:vidurl.rfind('/')+1] for video in videolist.findall('.//video'): src = video.get('src') if not src: From 52cffcb186432f9f1b30fba159414aff6a923f59 Mon Sep 17 00:00:00 2001 From: dinesh <dsdiscoverdinesh@gmail.com> Date: Thu, 23 Oct 2014 20:27:13 +0530 Subject: [PATCH 1110/1761] [thoughtworks] wistia support added --- youtube_dl/extractor/generic.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 9057a6beb..877447381 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -380,6 +380,16 @@ class GenericIE(InfoExtractor): 'uploader': 'education-portal.com', }, }, + { + 'url': 'http://thoughtworks.wistia.com/medias/uxjb0lwrcz', + 'md5': 'baf49c2baa8a7de5f3fc145a8506dcd4', + 'info_dict': { + 'id': 'uxjb0lwrcz', + 'ext': 'mp4', + 'title': 'Conversation about Hexagonal Rails Part 1', + 'duration': 1715.0, + }, + }, ] def report_following_redirect(self, new_url): @@ -651,6 +661,10 @@ class GenericIE(InfoExtractor): playlists, lambda p: '//dailymotion.com/playlist/%s' % p) # Look for embedded Wistia player + mobj = re.search(r'<meta content=(["\'])(?P<url>https?://fast\.wistia\.net/embed/iframe/(?P<id>[a-zA-Z0-9_]+)(["\']))', webpage) + if mobj: + return self.url_result(mobj.group('url'), 'Wistia') + match = re.search( r'<iframe[^>]+?src=(["\'])(?P<url>(?:https?:)?//(?:fast\.)?wistia\.net/embed/iframe/.+?)\1', webpage) if match: @@ -664,6 +678,7 @@ class GenericIE(InfoExtractor): 'title': video_title, 'id': video_id, } + match = re.search(r'(?:id=["\']wistia_|data-wistia-?id=["\']|Wistia\.embed\(["\'])(?P<id>[^"\']+)', webpage) if match: return { From 2399535fd1f2ef3125fcf6c1eabf76de53b9b8ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Thu, 23 Oct 2014 22:30:34 +0700 Subject: [PATCH 1111/1761] [francetv] Lower preference of direct links (Closes #4010, closes #3947) Direct links fail with 403, fallback on f4m for now until further investigations. --- youtube_dl/extractor/francetv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/francetv.py b/youtube_dl/extractor/francetv.py index 07165e330..566e20d76 100644 --- a/youtube_dl/extractor/francetv.py +++ b/youtube_dl/extractor/francetv.py @@ -58,7 +58,7 @@ class FranceTVBaseInfoExtractor(InfoExtractor): formats.append({ 'url': video_url, 'format_id': format_id, - 'preference': 2, + 'preference': -1, }) self._sort_formats(formats) From 85d7b7658617895703a3645f14e76a65a1a2f7e6 Mon Sep 17 00:00:00 2001 From: dinesh <dsdiscoverdinesh@gmail.com> Date: Thu, 23 Oct 2014 21:23:56 +0530 Subject: [PATCH 1112/1761] [thoughtworks] wistia regex modified --- youtube_dl/extractor/generic.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 877447381..bf957fa3f 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -386,8 +386,9 @@ class GenericIE(InfoExtractor): 'info_dict': { 'id': 'uxjb0lwrcz', 'ext': 'mp4', - 'title': 'Conversation about Hexagonal Rails Part 1', + 'title': 'Conversation about Hexagonal Rails Part 1 - ThoughtWorks', 'duration': 1715.0, + 'uploader': 'thoughtworks.wistia.com', }, }, ] @@ -661,12 +662,8 @@ class GenericIE(InfoExtractor): playlists, lambda p: '//dailymotion.com/playlist/%s' % p) # Look for embedded Wistia player - mobj = re.search(r'<meta content=(["\'])(?P<url>https?://fast\.wistia\.net/embed/iframe/(?P<id>[a-zA-Z0-9_]+)(["\']))', webpage) - if mobj: - return self.url_result(mobj.group('url'), 'Wistia') - match = re.search( - r'<iframe[^>]+?src=(["\'])(?P<url>(?:https?:)?//(?:fast\.)?wistia\.net/embed/iframe/.+?)\1', webpage) + r'(?:<meta content|<iframe[^>]+?src)=(["\'])(?P<url>(?:https?:)?//(?:fast\.)?wistia\.net/embed/iframe/.+?)\1', webpage) if match: embed_url = self._proto_relative_url( unescapeHTML(match.group('url'))) From 281d3f1d6877a022d51d8d654595c4958dd83d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Thu, 23 Oct 2014 23:03:07 +0700 Subject: [PATCH 1113/1761] [generic/wistia] Improve regex --- youtube_dl/extractor/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index bf957fa3f..e13816c66 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -663,7 +663,7 @@ class GenericIE(InfoExtractor): # Look for embedded Wistia player match = re.search( - r'(?:<meta content|<iframe[^>]+?src)=(["\'])(?P<url>(?:https?:)?//(?:fast\.)?wistia\.net/embed/iframe/.+?)\1', webpage) + r'<(?:meta[^>]+?content|iframe[^>]+?src)=(["\'])(?P<url>(?:https?:)?//(?:fast\.)?wistia\.net/embed/iframe/.+?)\1', webpage) if match: embed_url = self._proto_relative_url( unescapeHTML(match.group('url'))) From 75da98e9e1f55f8fc27200f2b3d56386ead3b56d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Thu, 23 Oct 2014 23:07:58 +0700 Subject: [PATCH 1114/1761] [funnyordie] Fix extraction (Closes #4011) --- youtube_dl/extractor/funnyordie.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/funnyordie.py b/youtube_dl/extractor/funnyordie.py index d966e8403..ec6d96ada 100644 --- a/youtube_dl/extractor/funnyordie.py +++ b/youtube_dl/extractor/funnyordie.py @@ -37,7 +37,7 @@ class FunnyOrDieIE(InfoExtractor): video_id = mobj.group('id') webpage = self._download_webpage(url, video_id) - links = re.findall(r'<source src="([^"]+/v)\d+\.([^"]+)" type=\'video', webpage) + links = re.findall(r'<source src="([^"]+/v)[^"]+\.([^"]+)" type=\'video', webpage) if not links: raise ExtractorError('No media links available for %s' % video_id) From ad5f53ac72d32803819d221b3e9a68331c3002a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= <jaime.marquinez.ferrandiz@gmail.com> Date: Thu, 23 Oct 2014 20:08:55 +0200 Subject: [PATCH 1115/1761] [telecinco] Add extractor (closes #4005) It uses the same extraction process as mitele.es, but with a few small differences. --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/mitele.py | 12 ++++++++++-- youtube_dl/extractor/telecinco.py | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 youtube_dl/extractor/telecinco.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 070f9ff19..0de0b4587 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -367,6 +367,7 @@ from .teachingchannel import TeachingChannelIE from .teamcoco import TeamcocoIE from .techtalks import TechTalksIE from .ted import TEDIE +from .telecinco import TelecincoIE from .telemb import TeleMBIE from .tenplay import TenPlayIE from .testurl import TestURLIE diff --git a/youtube_dl/extractor/mitele.py b/youtube_dl/extractor/mitele.py index 979f3d692..df7fde87c 100644 --- a/youtube_dl/extractor/mitele.py +++ b/youtube_dl/extractor/mitele.py @@ -39,13 +39,21 @@ class MiTeleIE(InfoExtractor): ).replace('\'', '"') embed_data = json.loads(embed_data_json) - info_url = embed_data['flashvars']['host'] + domain = embed_data['mediaUrl'] + if not domain.startswith('http'): + # only happens in telecinco.es videos + domain = 'http://' + domain + info_url = compat_urllib_parse.urljoin( + domain, + compat_urllib_parse.unquote(embed_data['flashvars']['host']) + ) info_el = self._download_xml(info_url, episode).find('./video/info') video_link = info_el.find('videoUrl/link').text token_query = compat_urllib_parse.urlencode({'id': video_link}) token_info = self._download_json( - 'http://token.mitele.es/?' + token_query, episode, + embed_data['flashvars']['ov_tk'] + '?' + token_query, + episode, transform_source=strip_jsonp ) diff --git a/youtube_dl/extractor/telecinco.py b/youtube_dl/extractor/telecinco.py new file mode 100644 index 000000000..161656aa6 --- /dev/null +++ b/youtube_dl/extractor/telecinco.py @@ -0,0 +1,18 @@ +from __future__ import unicode_literals + +from .mitele import MiTeleIE + + +class TelecincoIE(MiTeleIE): + IE_NAME = 'telecinco.es' + _VALID_URL = r'https?://www\.telecinco\.es/[^/]+/[^/]+/[^/]+/(?P<episode>.*?)\.html' + + _TEST = { + 'url': 'http://www.telecinco.es/robinfood/temporada-01/t01xp14/Bacalao-cocochas-pil-pil_0_1876350223.html', + 'info_dict': { + 'id': 'MDSVID20141015_0058', + 'ext': 'mp4', + 'title': 'Con Martín Berasategui, hacer un bacalao al ...', + 'duration': 662, + }, + } From f3cd403c2b0b0819504236946895e8ead9814f1f Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Thu, 23 Oct 2014 20:21:27 +0200 Subject: [PATCH 1116/1761] [telecino] Add coding declaration --- youtube_dl/extractor/telecinco.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/extractor/telecinco.py b/youtube_dl/extractor/telecinco.py index 161656aa6..db9788c18 100644 --- a/youtube_dl/extractor/telecinco.py +++ b/youtube_dl/extractor/telecinco.py @@ -1,3 +1,4 @@ +#coding: utf-8 from __future__ import unicode_literals from .mitele import MiTeleIE From 4661e243f8db0befd0180090874a33dfc375b33c Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Thu, 23 Oct 2014 20:21:38 +0200 Subject: [PATCH 1117/1761] release 2014.10.23 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index e7f6adef1..75da03df1 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.18' +__version__ = '2014.10.23' From f2f2c0c2c642aecc1a8954ad3d8639425036e066 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Thu, 23 Oct 2014 21:13:45 +0200 Subject: [PATCH 1118/1761] [generic] Allow --default-search without colon --- youtube_dl/__init__.py | 2 -- youtube_dl/extractor/generic.py | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 7f2b4dfcc..a53f6a621 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -255,8 +255,6 @@ def _real_main(argv=None): date = DateRange.day(opts.date) else: date = DateRange(opts.dateafter, opts.datebefore) - if opts.default_search not in ('auto', 'auto_warning', 'error', 'fixup_error', None) and ':' not in opts.default_search: - parser.error(u'--default-search invalid; did you forget a colon (:) at the end?') # Do not download videos when there are audio-only formats if opts.extractaudio and not opts.keepvideo and opts.format is None: diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index e13816c66..9b6498894 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -487,7 +487,8 @@ class GenericIE(InfoExtractor): 'Set --default-search "ytsearch" (or run youtube-dl "ytsearch:%s" ) to search YouTube' ) % (url, url), expected=True) else: - assert ':' in default_search + if ':' not in default_search: + default_search += ':' return self.url_result(default_search + url) url, smuggled_data = unsmuggle_url(url) From 2c63ccec78faec092394d4461cb9428504e8c830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= <jaime.marquinez.ferrandiz@gmail.com> Date: Thu, 23 Oct 2014 21:26:48 +0200 Subject: [PATCH 1119/1761] [mitele] Fix on python 2.x --- youtube_dl/extractor/mitele.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/mitele.py b/youtube_dl/extractor/mitele.py index df7fde87c..6691521e5 100644 --- a/youtube_dl/extractor/mitele.py +++ b/youtube_dl/extractor/mitele.py @@ -6,6 +6,7 @@ import json from .common import InfoExtractor from ..utils import ( compat_urllib_parse, + compat_urlparse, get_element_by_attribute, parse_duration, strip_jsonp, @@ -43,7 +44,7 @@ class MiTeleIE(InfoExtractor): if not domain.startswith('http'): # only happens in telecinco.es videos domain = 'http://' + domain - info_url = compat_urllib_parse.urljoin( + info_url = compat_urlparse.urljoin( domain, compat_urllib_parse.unquote(embed_data['flashvars']['host']) ) From b1edd7a48ace472f89cda7503f104a98fc67ee30 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Thu, 23 Oct 2014 23:25:02 +0200 Subject: [PATCH 1120/1761] [crunchyroll] Correct parsing (Fixes #4014) --- youtube_dl/extractor/crunchyroll.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/youtube_dl/extractor/crunchyroll.py b/youtube_dl/extractor/crunchyroll.py index f99888ecc..e3057d900 100644 --- a/youtube_dl/extractor/crunchyroll.py +++ b/youtube_dl/extractor/crunchyroll.py @@ -39,6 +39,7 @@ class CrunchyrollIE(SubtitlesInfoExtractor): 'thumbnail': 'http://img1.ak.crunchyroll.com/i/spire1-tmb/20c6b5e10f1a47b10516877d3c039cae1380951166_full.jpg', 'uploader': 'Yomiuri Telecasting Corporation (YTV)', 'upload_date': '20131013', + 'url': 're:(?!.*&)', }, 'params': { # rtmp @@ -237,12 +238,14 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text streamdata_req.data = 'req=RpcApiVideoEncode%5FGetStreamInfo&video%5Fencode%5Fquality='+stream_quality+'&media%5Fid='+stream_id+'&video%5Fformat='+stream_format streamdata_req.add_header('Content-Type', 'application/x-www-form-urlencoded') streamdata_req.add_header('Content-Length', str(len(streamdata_req.data))) - streamdata = self._download_webpage(streamdata_req, video_id, note='Downloading media info for '+video_format) - video_url = self._search_regex(r'<host>([^<]+)', streamdata, 'video_url') - video_play_path = self._search_regex(r'<file>([^<]+)', streamdata, 'video_play_path') + streamdata = self._download_xml( + streamdata_req, video_id, + note='Downloading media info for %s' % video_format) + video_url = streamdata.find('.//host').text + video_play_path = streamdata.find('.//file').text formats.append({ 'url': video_url, - 'play_path': video_play_path, + 'play_path': video_play_path, 'ext': 'flv', 'format': video_format, 'format_id': video_format, From 67500bf939d7db66cdfb9f742fdedca1b83b8309 Mon Sep 17 00:00:00 2001 From: xavier <xavier.beynon@gmail.com> Date: Thu, 23 Oct 2014 16:55:39 -0500 Subject: [PATCH 1121/1761] Initial version of audiomack.py --- youtube_dl/extractor/audiomack.py | 43 +++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 youtube_dl/extractor/audiomack.py diff --git a/youtube_dl/extractor/audiomack.py b/youtube_dl/extractor/audiomack.py new file mode 100644 index 000000000..c5214f401 --- /dev/null +++ b/youtube_dl/extractor/audiomack.py @@ -0,0 +1,43 @@ +# coding: utf-8 +from __future__ import unicode_literals + +from .common import InfoExtractor +import datetime +import time +import urllib.request +import json + + +class AudiomackIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?audiomack\.com/song/(?P<id>[\w/-]+)' + _TEST = { + 'url': 'https://www.audiomack.com/song/crewneckkramer/story-i-tell', + 'info_dict': { + 'id': 'story-i-tell', + 'ext': 'mp3', + 'title': 'story-i-tell' + } + } + + def _real_extract(self, url): + # TODO more code goes here, for example ... + #webpage = self._download_webpage(url, video_id) + #title = self._html_search_regex(r'<h1>(.*?)</h1>', webpage, 'title') + + assert("/song/" in url) + songurl = url[url.index("/song/")+5:] + title = songurl[songurl.rindex("/")+1:] + video_id = title + t = int(time.mktime(datetime.datetime.now().timetuple())) + s = "http://www.audiomack.com/api/music/url/song"+songurl+"?_="+str(t) + f = urllib.request.urlopen(s) + j = f.read(1000).decode("utf-8") + data = json.loads(j) + + return { + 'id': video_id, + 'title': title, + 'url' : data["url"], + 'ext' : 'mp3' + # TODO more properties (see youtube_dl/extractor/common.py) + } From 5c565ac9e7fed4f6a7123332cbaf35fc44a5a921 Mon Sep 17 00:00:00 2001 From: xavier <xavier.beynon@gmail.com> Date: Thu, 23 Oct 2014 16:58:11 -0500 Subject: [PATCH 1122/1761] Added init.py initializer --- youtube_dl/extractor/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 070f9ff19..29f32cdef 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -20,6 +20,7 @@ from .arte import ( ArteTVDDCIE, ArteTVEmbedIE, ) +from .audiomack import AudiomackIE from .auengine import AUEngineIE from .bambuser import BambuserIE, BambuserChannelIE from .bandcamp import BandcampIE, BandcampAlbumIE From 9e9bc793f3abddc4824cfcb13f569163fb0a4ba7 Mon Sep 17 00:00:00 2001 From: xavier <xavier.beynon@gmail.com> Date: Thu, 23 Oct 2014 23:54:59 -0500 Subject: [PATCH 1123/1761] Finished audiomack extractor --- youtube_dl/extractor/audiomack.py | 82 ++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/youtube_dl/extractor/audiomack.py b/youtube_dl/extractor/audiomack.py index c5214f401..2ececa998 100644 --- a/youtube_dl/extractor/audiomack.py +++ b/youtube_dl/extractor/audiomack.py @@ -1,43 +1,67 @@ +# Xavier Beynon 2014 # coding: utf-8 from __future__ import unicode_literals from .common import InfoExtractor +from .soundcloud import SoundcloudIE import datetime import time -import urllib.request -import json class AudiomackIE(InfoExtractor): _VALID_URL = r'https?://(?:www\.)?audiomack\.com/song/(?P<id>[\w/-]+)' - _TEST = { - 'url': 'https://www.audiomack.com/song/crewneckkramer/story-i-tell', - 'info_dict': { - 'id': 'story-i-tell', - 'ext': 'mp3', - 'title': 'story-i-tell' + IE_NAME = 'audiomack' + _TESTS = [ + #hosted on audiomack + { + 'url': 'http://www.audiomack.com/song/roosh-williams/extraordinary', + 'file': 'Roosh Williams - Extraordinary.mp3', + 'info_dict': + { + 'ext': 'mp3', + 'title': 'Roosh Williams - Extraordinary' + } + }, + #hosted on soundcloud via audiomack + { + 'url': 'http://www.audiomack.com/song/xclusiveszone/take-kare', + 'file': '172419696.mp3', + 'info_dict': + { + 'ext': 'mp3', + 'title': 'Young Thug ft Lil Wayne - Take Kare', + "upload_date": "20141016", + "description": "New track produced by London On Da Track called “Take Kare\"\n\nhttp://instagram.com/theyoungthugworld\nhttps://www.facebook.com/ThuggerThuggerCashMoney\n", + "uploader": "Young Thug World" + } } - } + ] def _real_extract(self, url): - # TODO more code goes here, for example ... - #webpage = self._download_webpage(url, video_id) - #title = self._html_search_regex(r'<h1>(.*?)</h1>', webpage, 'title') - - assert("/song/" in url) - songurl = url[url.index("/song/")+5:] - title = songurl[songurl.rindex("/")+1:] - video_id = title - t = int(time.mktime(datetime.datetime.now().timetuple())) - s = "http://www.audiomack.com/api/music/url/song"+songurl+"?_="+str(t) - f = urllib.request.urlopen(s) - j = f.read(1000).decode("utf-8") - data = json.loads(j) + #id is what follows /song/ in url, usually the uploader name + title + id = url[url.index("/song/")+5:] - return { - 'id': video_id, - 'title': title, - 'url' : data["url"], - 'ext' : 'mp3' - # TODO more properties (see youtube_dl/extractor/common.py) - } + #Call the api, which gives us a json doc with the real url inside + rightnow = int(time.mktime(datetime.datetime.now().timetuple())) + apiresponse = self._download_json("http://www.audiomack.com/api/music/url/song"+id+"?_="+str(rightnow), id) + if not url in apiresponse: + raise Exception("Unable to deduce api url of song") + realurl = apiresponse["url"] + + #Audiomack wraps a lot of soundcloud tracks in their branded wrapper + # - if so, pass the work off to the soundcloud extractor + if SoundcloudIE.suitable(realurl): + sc = SoundcloudIE(downloader=self._downloader) + return sc._real_extract(realurl) + else: + #Pull out metadata + page = self._download_webpage(url, id) + artist = self._html_search_regex(r'<span class="artist">(.*)</span>', page, "artist") + songtitle = self._html_search_regex(r'<h1 class="profile-title song-title"><span class="artist">.*</span>(.*)</h1>', page, "title") + title = artist+" - "+songtitle + return { + 'id': title, # ignore id, which is not useful in song name + 'title': title, + 'url': realurl, + 'ext': 'mp3' + } From 057a5206cc602f2b6b4a622530df5244f1b41782 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Fri, 24 Oct 2014 14:48:12 +0200 Subject: [PATCH 1124/1761] Add --flat-playlist option (Closes #4003) --- youtube_dl/YoutubeDL.py | 11 +++++++++-- youtube_dl/__init__.py | 1 + youtube_dl/options.py | 5 +++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index dec0e20e7..623f9d6fe 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -165,6 +165,8 @@ class YoutubeDL(object): 'auto' for elaborate guessing encoding: Use this encoding instead of the system-specified. extract_flat: Do not resolve URLs, return the immediate result. + Pass in 'in_playlist' to only show this behavior for + playlist items. The following parameters are not used by YoutubeDL itself, they are used by the FileDownloader: @@ -568,8 +570,13 @@ class YoutubeDL(object): result_type = ie_result.get('_type', 'video') - if self.params.get('extract_flat', False): - if result_type in ('url', 'url_transparent'): + if result_type in ('url', 'url_transparent'): + extract_flat = self.params.get('extract_flat', False) + if ((extract_flat == 'in_playlist' and 'playlist' in extra_info) or + extract_flat is True): + self.add_extra_info(ie_result, extra_info) + if self.params.get('forcejson', False): + self.to_stdout(json.dumps(ie_result)) return ie_result if result_type == 'video': diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index a53f6a621..c4e1d32db 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -367,6 +367,7 @@ def _real_main(argv=None): 'youtube_include_dash_manifest': opts.youtube_include_dash_manifest, 'encoding': opts.encoding, 'exec_cmd': opts.exec_cmd, + 'extract_flat': opts.extract_flat, } with YoutubeDL(ydl_opts) as ydl: diff --git a/youtube_dl/options.py b/youtube_dl/options.py index 649361bde..2b1cd7438 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -159,6 +159,11 @@ def parseOpts(overrideArguments=None): '--ignore-config', action='store_true', help='Do not read configuration files. When given in the global configuration file /etc/youtube-dl.conf: do not read the user configuration in ~/.config/youtube-dl.conf (%APPDATA%/youtube-dl/config.txt on Windows)') + general.add_option( + '--flat-playlist', + action='store_const', dest='extract_flat', const='in_playlist', + default=False, + help='Do not extract the videos of a playlist, only list them.') selection = optparse.OptionGroup(parser, 'Video Selection') selection.add_option( From 36f1c9049722fc80154d8ee571b1335286829111 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Fri, 24 Oct 2014 14:48:19 +0200 Subject: [PATCH 1125/1761] release 2014.10.24 --- README.md | 2 ++ youtube_dl/version.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 90ba928c3..e772fc22a 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,8 @@ which means you can modify it, redistribute it or use it however you like. configuration in ~/.config/youtube-dl.conf (%APPDATA%/youtube-dl/config.txt on Windows) + --flat-playlist Do not extract the videos of a playlist, + only list them. ## Video Selection: --playlist-start NUMBER playlist video to start at (default is 1) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 75da03df1..59cb3b1a1 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.23' +__version__ = '2014.10.24' From b5a14350b9909cb9da7e82120fcaf1bf4aa61e43 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Fri, 24 Oct 2014 15:09:43 +0200 Subject: [PATCH 1126/1761] [bild] Simplify (#3983) --- youtube_dl/extractor/bild.py | 85 +++++++++++++++++------------------- 1 file changed, 39 insertions(+), 46 deletions(-) diff --git a/youtube_dl/extractor/bild.py b/youtube_dl/extractor/bild.py index 3a822a5c0..0269d1174 100644 --- a/youtube_dl/extractor/bild.py +++ b/youtube_dl/extractor/bild.py @@ -1,46 +1,39 @@ -from __future__ import unicode_literals - -import re - -from .common import InfoExtractor - - -class BildIE(InfoExtractor): - IE_NAME = 'bild' - _TEST = { - 'url': 'http://www.bild.de/video/clip/apple-ipad-air/das-koennen-die-neuen-ipads-38184146.bild.html', - 'info_dict': { - 'id': '38184146', - 'title': 'BILD hat sie getestet', - 'thumbnail': 'http://bilder.bild.de/fotos/stand-das-koennen-die-neuen-ipads-38184138/Bild/1.bild.jpg', - 'duration': 196, - } - } - - #http://www.bild.de/video/clip/apple-ipad-air/das-koennen-die-neuen-ipads-38184146.bild.html - _VALID_URL = r'http?://(?:www\.)?bild\.de/(?:[^/]+/)+(?P<display_id>[^/]+)-(?P<id>\d+)(?:,auto=true)?\.bild\.html' - - def _real_extract(self, url): - m = re.match(self._VALID_URL, url) - video_id = m.group('id') - - #webpage = self._download_webpage(url, video_id) - - xml_url = url.split(".bild.html")[0]+",view=xml.bild.xml" - - doc = self._download_xml(xml_url, video_id) - - video_url = doc.attrib['src'] - title = doc.attrib['ueberschrift'] - description = doc.attrib['text'] - thumbnail = doc.attrib['img'] - duration = int(doc.attrib['duration'])/1000 - - return { - 'id': video_id, - 'title': title, - 'description': description, - 'url': video_url, - 'thumbnail': thumbnail, - 'duration': duration, - } +#coding: utf-8 +from __future__ import unicode_literals + +from .common import InfoExtractor +from ..utils import int_or_none + + +class BildIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?bild\.de/(?:[^/]+/)+(?P<display_id>[^/]+)-(?P<id>\d+)(?:,auto=true)?\.bild\.html' + IE_DESC = 'Bild.de' + _TEST = { + 'url': 'http://www.bild.de/video/clip/apple-ipad-air/das-koennen-die-neuen-ipads-38184146.bild.html', + 'md5': 'dd495cbd99f2413502a1713a1156ac8a', + 'info_dict': { + 'id': '38184146', + 'ext': 'mp4', + 'title': 'BILD hat sie getestet', + 'thumbnail': 'http://bilder.bild.de/fotos/stand-das-koennen-die-neuen-ipads-38184138/Bild/1.bild.jpg', + 'duration': 196, + 'description': 'Mit dem iPad Air 2 und dem iPad Mini 3 hat Apple zwei neue Tablet-Modelle präsentiert. BILD-Reporter Sven Stein durfte die Geräte bereits testen. ', + } + } + + def _real_extract(self, url): + video_id = self._match_id(url) + + xml_url = url.split(".bild.html")[0] + ",view=xml.bild.xml" + doc = self._download_xml(xml_url, video_id) + + duration = int_or_none(doc.attrib.get('duration'), scale=1000) + + return { + 'id': video_id, + 'title': doc.attrib['ueberschrift'], + 'description': doc.attrib.get('text'), + 'url': doc.attrib['src'], + 'thumbnail': doc.attrib.get('img'), + 'duration': duration, + } From 2acfe95f58e3dc52864a29f1d5b30e44d75d7b38 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Fri, 24 Oct 2014 15:12:29 +0200 Subject: [PATCH 1127/1761] Credit @capital-G for bild.de (#3983) --- youtube_dl/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index c4e1d32db..a1079e596 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -79,6 +79,7 @@ __authors__ = ( 'Carlos Ramos', '5moufl', 'lenaten', + 'Dennis Scheiba', ) __license__ = 'Public Domain' From 95ee84421e57982f208ec00c314abfabaa3418e8 Mon Sep 17 00:00:00 2001 From: winwon <wish4read@gmail.com> Date: Fri, 17 Oct 2014 17:38:16 +0100 Subject: [PATCH 1128/1761] vidzi Add new extractor --- youtube_dl/extractor/__init__.py | 2 +- youtube_dl/extractor/vidzi.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 youtube_dl/extractor/vidzi.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 3023c3095..b52f8c7d1 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -493,7 +493,7 @@ from .youtube import ( ) from .zdf import ZDFIE - +from .vidzi import VidziIE _ALL_CLASSES = [ klass diff --git a/youtube_dl/extractor/vidzi.py b/youtube_dl/extractor/vidzi.py new file mode 100644 index 000000000..7d93dd301 --- /dev/null +++ b/youtube_dl/extractor/vidzi.py @@ -0,0 +1,30 @@ +import re +from .common import InfoExtractor + +class VidziIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?vidzi\.tv/(?P<id>\w+)' + _TEST = { + 'url': 'http://vidzi.tv/m1chxrwq7bx9', + 'md5': '5c4c4a8ca2281a199c8eefe8f411d630', + 'info_dict': { + 'id': 'm1chxrwq7bx9', + 'ext': 'mp4', + 'title': 'Watch Cadbury Dream Factory S01E04 HDTV x264 FiHTV mp4', + }, + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage('http://vidzi.tv/' + video_id, video_id) + video_url = self._html_search_regex(r'{\s*file\s*:\s*"([^"]+)"\s*}', webpage, u'vidzi url') + title = self._html_search_regex(r'<Title>([^<]+)<\/Title>', webpage, u'vidzi title') + + return { + 'id': video_id, + 'title': title, + 'url': video_url, + 'ext': 'mp4', + } + \ No newline at end of file From e65e06fbe28365bf630608bb1d6101074c475e21 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Fri, 24 Oct 2014 15:15:54 +0200 Subject: [PATCH 1129/1761] [vidzi] Correct order in imports (#3989) --- youtube_dl/extractor/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index b52f8c7d1..81b816974 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -423,6 +423,7 @@ from .videopremium import VideoPremiumIE from .videott import VideoTtIE from .videoweed import VideoWeedIE from .vidme import VidmeIE +from .vidzi import VidziIE from .vimeo import ( VimeoIE, VimeoAlbumIE, @@ -491,9 +492,7 @@ from .youtube import ( YoutubeUserIE, YoutubeWatchLaterIE, ) - from .zdf import ZDFIE -from .vidzi import VidziIE _ALL_CLASSES = [ klass From 018e835594f961dfd625abc932451ef3c2c85038 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Fri, 24 Oct 2014 15:17:17 +0200 Subject: [PATCH 1130/1761] [vidzi] Simplify --- youtube_dl/extractor/vidzi.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/youtube_dl/extractor/vidzi.py b/youtube_dl/extractor/vidzi.py index 7d93dd301..82d2179e9 100644 --- a/youtube_dl/extractor/vidzi.py +++ b/youtube_dl/extractor/vidzi.py @@ -1,6 +1,8 @@ -import re +from __future__ import unicode_literals + from .common import InfoExtractor + class VidziIE(InfoExtractor): _VALID_URL = r'https?://(?:www\.)?vidzi\.tv/(?P<id>\w+)' _TEST = { @@ -14,12 +16,13 @@ class VidziIE(InfoExtractor): } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') + video_id = self._match_id(url) - webpage = self._download_webpage('http://vidzi.tv/' + video_id, video_id) - video_url = self._html_search_regex(r'{\s*file\s*:\s*"([^"]+)"\s*}', webpage, u'vidzi url') - title = self._html_search_regex(r'<Title>([^<]+)<\/Title>', webpage, u'vidzi title') + webpage = self._download_webpage(url, video_id) + video_url = self._html_search_regex( + r'{\s*file\s*:\s*"([^"]+)"\s*}', webpage, 'video url') + title = self._html_search_regex( + r'<Title>([^<]+)<\/Title>', webpage, 'title') return { 'id': video_id, From 2c26df763c42433fea30ef46736156c689a74fd9 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Fri, 24 Oct 2014 15:27:02 +0200 Subject: [PATCH 1131/1761] [vidzi] Use proper test case and simplify (#3989) --- youtube_dl/extractor/vidzi.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/youtube_dl/extractor/vidzi.py b/youtube_dl/extractor/vidzi.py index 82d2179e9..669979e13 100644 --- a/youtube_dl/extractor/vidzi.py +++ b/youtube_dl/extractor/vidzi.py @@ -1,3 +1,4 @@ +#coding: utf-8 from __future__ import unicode_literals from .common import InfoExtractor @@ -6,12 +7,12 @@ from .common import InfoExtractor class VidziIE(InfoExtractor): _VALID_URL = r'https?://(?:www\.)?vidzi\.tv/(?P<id>\w+)' _TEST = { - 'url': 'http://vidzi.tv/m1chxrwq7bx9', - 'md5': '5c4c4a8ca2281a199c8eefe8f411d630', + 'url': 'http://vidzi.tv/cghql9yq6emu.html', + 'md5': '4f16c71ca0c8c8635ab6932b5f3f1660', 'info_dict': { - 'id': 'm1chxrwq7bx9', + 'id': 'cghql9yq6emu', 'ext': 'mp4', - 'title': 'Watch Cadbury Dream Factory S01E04 HDTV x264 FiHTV mp4', + 'title': 'youtube-dl test video 1\\\\2\'3/4<5\\\\6ä7↭', }, } @@ -22,12 +23,11 @@ class VidziIE(InfoExtractor): video_url = self._html_search_regex( r'{\s*file\s*:\s*"([^"]+)"\s*}', webpage, 'video url') title = self._html_search_regex( - r'<Title>([^<]+)<\/Title>', webpage, 'title') + r'(?s)<h2 class="video-title">(.*?)</h2>', webpage, 'title') return { 'id': video_id, 'title': title, 'url': video_url, - 'ext': 'mp4', } \ No newline at end of file From 964ae0a1228c9a0853e2b9142452d66e7333bf8c Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Fri, 24 Oct 2014 15:29:44 +0200 Subject: [PATCH 1132/1761] Credit @thornomad for glide (#3944) --- youtube_dl/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index a1079e596..6b0efe059 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -80,6 +80,7 @@ __authors__ = ( '5moufl', 'lenaten', 'Dennis Scheiba', + 'Damon Timm', ) __license__ = 'Public Domain' From 1ede5b2481a271fcfd0e179a494ef84cca2576b7 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Fri, 24 Oct 2014 15:34:19 +0200 Subject: [PATCH 1133/1761] [glide] Simplify --- youtube_dl/extractor/common.py | 2 +- youtube_dl/extractor/glide.py | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index e8366f7f9..8849208de 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -618,7 +618,7 @@ class InfoExtractor(object): formats.sort(key=_formats_key) def http_scheme(self): - """ Either "https:" or "https:", depending on the user's preferences """ + """ Either "http:" or "https:", depending on the user's preferences """ return ( 'http:' if self._downloader.params.get('prefer_insecure', False) diff --git a/youtube_dl/extractor/glide.py b/youtube_dl/extractor/glide.py index 175d85197..9561ed5fb 100644 --- a/youtube_dl/extractor/glide.py +++ b/youtube_dl/extractor/glide.py @@ -14,20 +14,27 @@ class GlideIE(InfoExtractor): 'id': 'UZF8zlmuQbe4mr+7dCiQ0w==', 'ext': 'mp4', 'title': 'Damon Timm\'s Glide message', - 'thumbnail' : 'http://dk608k4lm7m9j.cloudfront.net/3ee7da5af87065a1eeb8c6c9a864ba5b_2.jpg' + 'thumbnail': 're:^https?://.*?\.cloudfront\.net/.*\.jpg$', } } def _real_extract(self, url): video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) - title = self._html_search_regex(r'<title>(.*?)', webpage, 'title') - video_url = self._search_regex(r'', webpage, 'video_url') - thumbnail_url = self._search_regex(r'Video thumbnail', webpage, 'thumbnail_url') + title = self._html_search_regex( + r'(.*?)', webpage, 'title') + video_url = self.http_scheme() + self._search_regex( + r'', webpage, 'video URL') + thumbnail_url = self._search_regex( + r' Date: Fri, 24 Oct 2014 16:13:45 +0200 Subject: [PATCH 1134/1761] [YoutubeDL] Do not apply playlist info to videos when extract_flat is set (#4003) --- youtube_dl/YoutubeDL.py | 1 - 1 file changed, 1 deletion(-) diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 623f9d6fe..6aa1fd105 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -574,7 +574,6 @@ class YoutubeDL(object): extract_flat = self.params.get('extract_flat', False) if ((extract_flat == 'in_playlist' and 'playlist' in extra_info) or extract_flat is True): - self.add_extra_info(ie_result, extra_info) if self.params.get('forcejson', False): self.to_stdout(json.dumps(ie_result)) return ie_result From 5823eda139d851e3ff3cfd1e3fd6b109e1f7c19e Mon Sep 17 00:00:00 2001 From: Filip B Date: Fri, 24 Oct 2014 21:26:32 +0400 Subject: [PATCH 1135/1761] Fix motherless test 0 Apparently motherless no longer serves flv for that video (or maybe even other videos). So I changed expected extension from flv to mp4 and changed expected md5 accordingly. --- youtube_dl/extractor/motherless.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/motherless.py b/youtube_dl/extractor/motherless.py index 6229b2173..55f282966 100644 --- a/youtube_dl/extractor/motherless.py +++ b/youtube_dl/extractor/motherless.py @@ -15,10 +15,10 @@ class MotherlessIE(InfoExtractor): _TESTS = [ { 'url': 'http://motherless.com/AC3FFE1', - 'md5': '5527fef81d2e529215dad3c2d744a7d9', + 'md5': '310f62e325a9fafe64f68c0bccb6e75f', 'info_dict': { 'id': 'AC3FFE1', - 'ext': 'flv', + 'ext': 'mp4', 'title': 'Fucked in the ass while playing PS3', 'categories': ['Gaming', 'anal', 'reluctant', 'rough', 'Wife'], 'upload_date': '20100913', From 7608815cc24e96d3f4895f7c056ee8d769b678d2 Mon Sep 17 00:00:00 2001 From: Filip B Date: Fri, 24 Oct 2014 21:09:55 +0400 Subject: [PATCH 1136/1761] Add another motherless test This test is for videos posted in groups. URL looks like this: motherless.com/g/group_name/ID which is basically the same as motherless.com/ID So far this test fails because I haven't improved the extractor yet. --- youtube_dl/extractor/motherless.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/youtube_dl/extractor/motherless.py b/youtube_dl/extractor/motherless.py index 55f282966..9ce080a30 100644 --- a/youtube_dl/extractor/motherless.py +++ b/youtube_dl/extractor/motherless.py @@ -40,6 +40,20 @@ class MotherlessIE(InfoExtractor): 'thumbnail': 're:http://.*\.jpg', 'age_limit': 18, } + }, + { + 'url': 'http://motherless.com/g/cosplay/633979F', + 'md5': '0b2a43f447a49c3e649c93ad1fafa4a0', + 'info_dict': { + 'id': '633979F', + 'ext': 'mp4', + 'title': 'Turtlette', + 'categories': ['superheroine heroine superher'], + 'upload_date': '20140827', + 'uploader_id': 'shade0230', + 'thumbnail': 're:http://.*\.jpg', + 'age_limit': 18, + } } ] From 7f9ced64cbd33e597287de2f67b7862af123bb7b Mon Sep 17 00:00:00 2001 From: Filip B Date: Fri, 24 Oct 2014 21:44:21 +0400 Subject: [PATCH 1137/1761] Add group videos support for motherless Modified motherless regular expression. Previously it matched only URLs like this: motherless.com/ID Now it also matches this: motherless.com/g/group_name/ID All tests including the newly added one passed. --- youtube_dl/extractor/motherless.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/motherless.py b/youtube_dl/extractor/motherless.py index 9ce080a30..50083bd4a 100644 --- a/youtube_dl/extractor/motherless.py +++ b/youtube_dl/extractor/motherless.py @@ -11,7 +11,7 @@ from ..utils import ( class MotherlessIE(InfoExtractor): - _VALID_URL = r'http://(?:www\.)?motherless\.com/(?P[A-Z0-9]+)' + _VALID_URL = r'http://(?:www\.)?motherless\.com/(?:g/[a-z0-9_]+/)?(?P[A-Z0-9]+)' _TESTS = [ { 'url': 'http://motherless.com/AC3FFE1', From 8efd06aa428df6feed925396f4170a9ad8ca2b4d Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 24 Oct 2014 19:53:48 +0200 Subject: [PATCH 1138/1761] [motherless] Simplify --- youtube_dl/extractor/motherless.py | 36 +++++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/youtube_dl/extractor/motherless.py b/youtube_dl/extractor/motherless.py index 50083bd4a..3621ff99e 100644 --- a/youtube_dl/extractor/motherless.py +++ b/youtube_dl/extractor/motherless.py @@ -5,7 +5,7 @@ import re from .common import InfoExtractor from ..utils import ( - int_or_none, + str_to_int, unified_strdate, ) @@ -57,30 +57,34 @@ class MotherlessIE(InfoExtractor): } ] - def _real_extract(self,url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') - + def _real_extract(self, url): + video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) - title = self._html_search_regex(r'id="view-upload-title">\s+([^<]+)<', webpage, 'title') - - video_url = self._html_search_regex(r'setup\(\{\s+"file".+: "([^"]+)",', webpage, 'video_url') + title = self._html_search_regex( + r'id="view-upload-title">\s+([^<]+)<', webpage, 'title') + video_url = self._html_search_regex( + r'setup\(\{\s+"file".+: "([^"]+)",', webpage, 'video URL') age_limit = self._rta_search(webpage) - - view_count = self._html_search_regex(r'Views\s+([^<]+)<', webpage, 'view_count') + view_count = str_to_int(self._html_search_regex( + r'Views\s+([^<]+)<', + webpage, 'view count', fatal=False)) + like_count = str_to_int(self._html_search_regex( + r'Favorited\s+([^<]+)<', + webpage, 'like count', fatal=False)) - upload_date = self._html_search_regex(r'Uploaded\s+([^<]+)<', webpage, 'upload_date') + upload_date = self._html_search_regex( + r'Uploaded\s+([^<]+)<', webpage, 'upload date') if 'Ago' in upload_date: days = int(re.search(r'([0-9]+)', upload_date).group(1)) upload_date = (datetime.datetime.now() - datetime.timedelta(days=days)).strftime('%Y%m%d') else: upload_date = unified_strdate(upload_date) - like_count = self._html_search_regex(r'Favorited\s+([^<]+)<', webpage, 'like_count') - comment_count = webpage.count('class="media-comment-contents"') - uploader_id = self._html_search_regex(r'"thumb-member-username">\s+\s+ Date: Fri, 24 Oct 2014 22:31:55 +0200 Subject: [PATCH 1139/1761] [hark] Modernize --- youtube_dl/extractor/hark.py | 48 +++++++++++++++++------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/youtube_dl/extractor/hark.py b/youtube_dl/extractor/hark.py index 5bdd08afa..b6cc15b6f 100644 --- a/youtube_dl/extractor/hark.py +++ b/youtube_dl/extractor/hark.py @@ -1,37 +1,33 @@ # -*- coding: utf-8 -*- - -import re -import json +from __future__ import unicode_literals from .common import InfoExtractor -from ..utils import determine_ext + class HarkIE(InfoExtractor): - _VALID_URL = r'https?://www\.hark\.com/clips/(.+?)-.+' + _VALID_URL = r'https?://www\.hark\.com/clips/(?P.+?)-.+' _TEST = { - u'url': u'http://www.hark.com/clips/mmbzyhkgny-obama-beyond-the-afghan-theater-we-only-target-al-qaeda-on-may-23-2013', - u'file': u'mmbzyhkgny.mp3', - u'md5': u'6783a58491b47b92c7c1af5a77d4cbee', - u'info_dict': { - u'title': u"Obama: 'Beyond The Afghan Theater, We Only Target Al Qaeda' on May 23, 2013", - u'description': u'President Barack Obama addressed the nation live on May 23, 2013 in a speech aimed at addressing counter-terrorism policies including the use of drone strikes, detainees at Guantanamo Bay prison facility, and American citizens who are terrorists.', - u'duration': 11, + 'url': 'http://www.hark.com/clips/mmbzyhkgny-obama-beyond-the-afghan-theater-we-only-target-al-qaeda-on-may-23-2013', + 'md5': '6783a58491b47b92c7c1af5a77d4cbee', + 'info_dict': { + 'id': 'mmbzyhkgny', + 'ext': 'mp3', + 'title': 'Obama: \'Beyond The Afghan Theater, We Only Target Al Qaeda\' on May 23, 2013', + 'description': 'President Barack Obama addressed the nation live on May 23, 2013 in a speech aimed at addressing counter-terrorism policies including the use of drone strikes, detainees at Guantanamo Bay prison facility, and American citizens who are terrorists.', + 'duration': 11, } } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group(1) - json_url = "http://www.hark.com/clips/%s.json" %(video_id) - info_json = self._download_webpage(json_url, video_id) - info = json.loads(info_json) - final_url = info['url'] + video_id = self._match_id(url) + data = self._download_json( + 'http://www.hark.com/clips/%s.json' % video_id, video_id) - return {'id': video_id, - 'url' : final_url, - 'title': info['name'], - 'ext': determine_ext(final_url), - 'description': info['description'], - 'thumbnail': info['image_original'], - 'duration': info['duration'], - } + return { + 'id': video_id, + 'url': data['url'], + 'title': data['name'], + 'description': data.get('description'), + 'thumbnail': data.get('image_original'), + 'duration': data.get('duration'), + } From c64ed2a310542a46e79e8969df32d14a5403e53d Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 25 Oct 2014 00:10:11 +0200 Subject: [PATCH 1140/1761] [viddler] Use API --- test/helper.py | 2 +- youtube_dl/extractor/common.py | 5 ++ youtube_dl/extractor/viddler.py | 100 +++++++++++++++++++++----------- 3 files changed, 71 insertions(+), 36 deletions(-) diff --git a/test/helper.py b/test/helper.py index 62cb3ce02..2fa45631a 100644 --- a/test/helper.py +++ b/test/helper.py @@ -145,7 +145,7 @@ def expect_info_dict(self, expected_dict, got_dict): info_dict_str = ''.join( ' %s: %s,\n' % (_repr(k), _repr(v)) for k, v in test_info_dict.items()) - write_string('\n"info_dict": {' + info_dict_str + '}\n', out=sys.stderr) + write_string('\n"info_dict": {\n' + info_dict_str + '}\n', out=sys.stderr) self.assertFalse( missing_keys, 'Missing keys in test definition: %s' % ( diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 8849208de..cf3781cd6 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -89,6 +89,10 @@ class InfoExtractor(object): format, irrespective of the file format. -1 for default (order by other properties), -2 or smaller for less than default. + * source_preference Order number for this video source + (quality takes higher priority) + -1 for default (order by other properties), + -2 or smaller for less than default. * http_referer HTTP Referer header value to set. * http_method HTTP method to use for the download. * http_headers A dictionary of additional HTTP headers @@ -613,6 +617,7 @@ class InfoExtractor(object): audio_ext_preference, f.get('filesize') if f.get('filesize') is not None else -1, f.get('filesize_approx') if f.get('filesize_approx') is not None else -1, + f.get('source_preference') if f.get('source_preference') is not None else -1, f.get('format_id'), ) formats.sort(key=_formats_key) diff --git a/youtube_dl/extractor/viddler.py b/youtube_dl/extractor/viddler.py index 9328ef4a2..0faa729c6 100644 --- a/youtube_dl/extractor/viddler.py +++ b/youtube_dl/extractor/viddler.py @@ -1,55 +1,85 @@ -import json -import re +from __future__ import unicode_literals from .common import InfoExtractor +from ..utils import ( + float_or_none, + int_or_none, +) class ViddlerIE(InfoExtractor): - _VALID_URL = r'(?Phttps?://(?:www\.)?viddler\.com)/(?:v|embed|player)/(?P[a-z0-9]+)' + _VALID_URL = r'https?://(?:www\.)?viddler\.com/(?:v|embed|player)/(?P[a-z0-9]+)' _TEST = { - u"url": u"http://www.viddler.com/v/43903784", - u'file': u'43903784.mp4', - u'md5': u'fbbaedf7813e514eb7ca30410f439ac9', - u'info_dict': { - u"title": u"Video Made Easy", - u"uploader": u"viddler", - u"duration": 100.89, + "url": "http://www.viddler.com/v/43903784", + 'md5': 'ae43ad7cb59431ce043f0ff7fa13cbf4', + 'info_dict': { + 'id': '43903784', + 'ext': 'mp4', + "title": "Video Made Easy", + 'description': 'You don\'t need to be a professional to make high-quality video content. Viddler provides some quick and easy tips on how to produce great video content with limited resources. ', + "uploader": "viddler", + 'timestamp': 1335371429, + 'upload_date': '20120425', + "duration": 100.89, + 'thumbnail': 're:^https?://.*\.jpg$', + 'view_count': int, + 'categories': ['video content', 'high quality video', 'video made easy', 'how to produce video with limited resources', 'viddler'], } } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') + video_id = self._match_id(url) - embed_url = mobj.group('domain') + u'/embed/' + video_id - webpage = self._download_webpage(embed_url, video_id) + json_url = ( + 'http://api.viddler.com/api/v2/viddler.videos.getPlaybackDetails.json?video_id=%s&key=v0vhrt7bg2xq1vyxhkct' % + video_id) + data = self._download_json(json_url, video_id)['video'] - video_sources_code = self._search_regex( - r"(?ms)sources\s*:\s*(\{.*?\})", webpage, u'video URLs') - video_sources = json.loads(video_sources_code.replace("'", '"')) + formats = [] + for filed in data['files']: + if filed.get('status', 'ready') != 'ready': + continue + f = { + 'format_id': filed['profile_id'], + 'format_note': filed['profile_name'], + 'url': self._proto_relative_url(filed['url']), + 'width': int_or_none(filed.get('width')), + 'height': int_or_none(filed.get('height')), + 'filesize': int_or_none(filed.get('size')), + 'ext': filed.get('ext'), + 'source_preference': -1, + } + formats.append(f) - formats = [{ - 'url': video_url, - 'format': format_id, - } for video_url, format_id in video_sources.items()] + if filed.get('cdn_url'): + f = f.copy() + f['url'] = self._proto_relative_url(filed['cdn_url']) + f['format_id'] = filed['profile_id'] + '-cdn' + f['source_preference'] = 1 + formats.append(f) - title = self._html_search_regex( - r"title\s*:\s*'([^']*)'", webpage, u'title') - uploader = self._html_search_regex( - r"authorName\s*:\s*'([^']*)'", webpage, u'uploader', fatal=False) - duration_s = self._html_search_regex( - r"duration\s*:\s*([0-9.]*)", webpage, u'duration', fatal=False) - duration = float(duration_s) if duration_s else None - thumbnail = self._html_search_regex( - r"thumbnail\s*:\s*'([^']*)'", - webpage, u'thumbnail', fatal=False) + if filed.get('html5_video_source'): + f = f.copy() + f['url'] = self._proto_relative_url( + filed['html5_video_source']) + f['format_id'] = filed['profile_id'] + '-html5' + f['source_preference'] = 0 + formats.append(f) + self._sort_formats(formats) + + categories = [ + t.get('text') for t in data.get('tags', []) if 'text' in t] return { '_type': 'video', 'id': video_id, - 'title': title, - 'thumbnail': thumbnail, - 'uploader': uploader, - 'duration': duration, + 'title': data['title'], 'formats': formats, + 'description': data.get('description'), + 'timestamp': int_or_none(data.get('upload_time')), + 'thumbnail': self._proto_relative_url(data.get('thumbnail_url')), + 'uploader': data.get('author'), + 'duration': float_or_none(data.get('length')), + 'view_count': int_or_none(data.get('view_count')), + 'categories': categories, } From 63e0be341571450a2016a29f917e521b70d36020 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 25 Oct 2014 00:30:57 +0200 Subject: [PATCH 1141/1761] New option --dump-single-json (#4003) --- youtube_dl/YoutubeDL.py | 9 ++++++++- youtube_dl/__init__.py | 3 ++- youtube_dl/options.py | 4 ++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 6aa1fd105..75461f19d 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -107,6 +107,8 @@ class YoutubeDL(object): forcefilename: Force printing final filename. forceduration: Force printing duration. forcejson: Force printing info_dict as JSON. + dump_single_json: Force printing the info_dict of the whole playlist + (or video) as a single JSON line. simulate: Do not download the video files. format: Video format code. format_limit: Highest quality format to try. @@ -903,6 +905,8 @@ class YoutubeDL(object): if self.params.get('forcejson', False): info_dict['_filename'] = filename self.to_stdout(json.dumps(info_dict)) + if self.params.get('dump_single_json', False): + info_dict['_filename'] = filename # Do nothing else if in simulate mode if self.params.get('simulate', False): @@ -1070,12 +1074,15 @@ class YoutubeDL(object): for url in url_list: try: #It also downloads the videos - self.extract_info(url) + res = self.extract_info(url) except UnavailableVideoError: self.report_error('unable to download video') except MaxDownloadsReached: self.to_screen('[info] Maximum number of downloaded files reached.') raise + else: + if self.params.get('dump_single_json', False): + self.to_stdout(json.dumps(res)) return self._download_retcode diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 6b0efe059..c8bcc6e46 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -284,7 +284,7 @@ def _real_main(argv=None): u' file! Use "{0}.%(ext)s" instead of "{0}" as the output' u' template'.format(outtmpl)) - any_printing = opts.geturl or opts.gettitle or opts.getid or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat or opts.getduration or opts.dumpjson + any_printing = opts.geturl or opts.gettitle or opts.getid or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat or opts.getduration or opts.dumpjson or opts.dump_single_json download_archive_fn = os.path.expanduser(opts.download_archive) if opts.download_archive is not None else opts.download_archive ydl_opts = { @@ -304,6 +304,7 @@ def _real_main(argv=None): 'forcefilename': opts.getfilename, 'forceformat': opts.getformat, 'forcejson': opts.dumpjson, + 'dump_single_json': opts.dump_single_json, 'simulate': opts.simulate, 'skip_download': (opts.skip_download or opts.simulate or any_printing), 'format': opts.format, diff --git a/youtube_dl/options.py b/youtube_dl/options.py index 2b1cd7438..2ccc63fc5 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -417,6 +417,10 @@ def parseOpts(overrideArguments=None): '-j', '--dump-json', action='store_true', dest='dumpjson', default=False, help='simulate, quiet but print JSON information. See --output for a description of available keys.') + verbosity.add_option( + '-J', '--dump-single-json', + action='store_true', dest='dump_single_json', default=False, + help='simulate, quiet but print JSON information for each command-line argument. If the URL refers to a playlist, dump the whole playlist information in a single line.') verbosity.add_option( '--newline', action='store_true', dest='progress_with_newline', default=False, From 724d03189324920fe5ea4bc9d39cc3e170d376d0 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 25 Oct 2014 00:41:06 +0200 Subject: [PATCH 1142/1761] release 2014.10.25 --- README.md | 4 ++++ youtube_dl/version.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e772fc22a..d62546433 100644 --- a/README.md +++ b/README.md @@ -199,6 +199,10 @@ which means you can modify it, redistribute it or use it however you like. -j, --dump-json simulate, quiet but print JSON information. See --output for a description of available keys. + -J, --dump-single-json simulate, quiet but print JSON information + for each command-line argument. If the URL + refers to a playlist, dump the whole + playlist information in a single line. --newline output progress bar as new lines --no-progress do not print progress bar --console-title display progress in console titlebar diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 59cb3b1a1..d822ae330 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.24' +__version__ = '2014.10.25' From fdfefa1b9c86ef58d943a26a157dc234c2df14d9 Mon Sep 17 00:00:00 2001 From: xavier Date: Fri, 24 Oct 2014 21:07:01 -0500 Subject: [PATCH 1143/1761] Made changes per phihag --- youtube_dl/__init__.py | 1 + youtube_dl/extractor/audiomack.py | 17 +++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 7f2b4dfcc..78cdf14df 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -79,6 +79,7 @@ __authors__ = ( 'Carlos Ramos', '5moufl', 'lenaten', + 'Xavier Beynon' ) __license__ = 'Public Domain' diff --git a/youtube_dl/extractor/audiomack.py b/youtube_dl/extractor/audiomack.py index 2ececa998..bdcc51235 100644 --- a/youtube_dl/extractor/audiomack.py +++ b/youtube_dl/extractor/audiomack.py @@ -1,9 +1,9 @@ -# Xavier Beynon 2014 # coding: utf-8 from __future__ import unicode_literals from .common import InfoExtractor from .soundcloud import SoundcloudIE +from ..utils import ExtractorError import datetime import time @@ -15,9 +15,9 @@ class AudiomackIE(InfoExtractor): #hosted on audiomack { 'url': 'http://www.audiomack.com/song/roosh-williams/extraordinary', - 'file': 'Roosh Williams - Extraordinary.mp3', 'info_dict': { + 'id' : 'roosh-williams/extraordinary', 'ext': 'mp3', 'title': 'Roosh Williams - Extraordinary' } @@ -39,13 +39,14 @@ class AudiomackIE(InfoExtractor): def _real_extract(self, url): #id is what follows /song/ in url, usually the uploader name + title - id = url[url.index("/song/")+5:] + id = self._match_id(url) #Call the api, which gives us a json doc with the real url inside - rightnow = int(time.mktime(datetime.datetime.now().timetuple())) - apiresponse = self._download_json("http://www.audiomack.com/api/music/url/song"+id+"?_="+str(rightnow), id) - if not url in apiresponse: - raise Exception("Unable to deduce api url of song") + rightnow = int(time.time()) + apiresponse = self._download_json("http://www.audiomack.com/api/music/url/song/"+id+"?_="+str(rightnow), id) + + if "url" not in apiresponse: + raise ExtractorError("Unable to deduce api url of song") realurl = apiresponse["url"] #Audiomack wraps a lot of soundcloud tracks in their branded wrapper @@ -60,7 +61,7 @@ class AudiomackIE(InfoExtractor): songtitle = self._html_search_regex(r'

.*(.*)

', page, "title") title = artist+" - "+songtitle return { - 'id': title, # ignore id, which is not useful in song name + 'id': id, # ignore id, which is not useful in song name 'title': title, 'url': realurl, 'ext': 'mp3' From d36cae46d877ebcc656f23a41b53e31731d2b77e Mon Sep 17 00:00:00 2001 From: xavier Date: Fri, 24 Oct 2014 21:11:46 -0500 Subject: [PATCH 1144/1761] Not directly calling soundcloud extractor anymore --- youtube_dl/extractor/audiomack.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/youtube_dl/extractor/audiomack.py b/youtube_dl/extractor/audiomack.py index bdcc51235..2f32253af 100644 --- a/youtube_dl/extractor/audiomack.py +++ b/youtube_dl/extractor/audiomack.py @@ -52,8 +52,7 @@ class AudiomackIE(InfoExtractor): #Audiomack wraps a lot of soundcloud tracks in their branded wrapper # - if so, pass the work off to the soundcloud extractor if SoundcloudIE.suitable(realurl): - sc = SoundcloudIE(downloader=self._downloader) - return sc._real_extract(realurl) + return {'_type': 'url', 'url': realurl, 'ie_key': 'Soundcloud'} else: #Pull out metadata page = self._download_webpage(url, id) From ec9c978481eee1035ac478926a73f729232be204 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 25 Oct 2014 08:42:44 +0200 Subject: [PATCH 1145/1761] Credit @winwon for vidzi (#3989) --- youtube_dl/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index c8bcc6e46..59b851056 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -81,6 +81,7 @@ __authors__ = ( 'lenaten', 'Dennis Scheiba', 'Damon Timm', + 'winwon', ) __license__ = 'Public Domain' From 43d9718fb93ddaafd35e552158ec5bfe61b4c83f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sat, 25 Oct 2014 13:56:21 +0700 Subject: [PATCH 1146/1761] [nhl] Improve video URL extraction (Closes #4013) --- youtube_dl/extractor/nhl.py | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/youtube_dl/extractor/nhl.py b/youtube_dl/extractor/nhl.py index 072d9cf8e..d66c2c6f8 100644 --- a/youtube_dl/extractor/nhl.py +++ b/youtube_dl/extractor/nhl.py @@ -22,21 +22,23 @@ class NHLBaseInfoExtractor(InfoExtractor): self.report_extraction(video_id) initial_video_url = info['publishPoint'] - data = compat_urllib_parse.urlencode({ - 'type': 'fvod', - 'path': initial_video_url.replace('.mp4', '_sd.mp4'), - }) - path_url = 'http://video.nhl.com/videocenter/servlets/encryptvideopath?' + data - path_doc = self._download_xml( - path_url, video_id, 'Downloading final video url') - video_url = path_doc.find('path').text + if info['formats'] == '1': + data = compat_urllib_parse.urlencode({ + 'type': 'fvod', + 'path': initial_video_url.replace('.mp4', '_sd.mp4'), + }) + path_url = 'http://video.nhl.com/videocenter/servlets/encryptvideopath?' + data + path_doc = self._download_xml( + path_url, video_id, 'Downloading final video url') + video_url = path_doc.find('path').text + else: + video_url = initial_video_url join = compat_urlparse.urljoin return { 'id': video_id, 'title': info['name'], 'url': video_url, - 'ext': determine_ext(video_url), 'description': info['description'], 'duration': int(info['duration']), 'thumbnail': join(join(video_url, '/u/'), info['bigImage']), @@ -46,10 +48,11 @@ class NHLBaseInfoExtractor(InfoExtractor): class NHLIE(NHLBaseInfoExtractor): IE_NAME = 'nhl.com' - _VALID_URL = r'https?://video(?P\.[^.]*)?\.nhl\.com/videocenter/console(?:\?(?:.*?[?&])?)id=(?P[0-9]+)' + _VALID_URL = r'https?://video(?P\.[^.]*)?\.nhl\.com/videocenter/console(?:\?(?:.*?[?&])?)id=(?P[0-9a-z-]+)' _TESTS = [{ 'url': 'http://video.canucks.nhl.com/videocenter/console?catid=6?id=453614', + 'md5': 'db704a4ea09e8d3988c85e36cc892d09', 'info_dict': { 'id': '453614', 'ext': 'mp4', @@ -58,6 +61,17 @@ class NHLIE(NHLBaseInfoExtractor): 'duration': 18, 'upload_date': '20131006', }, + }, { + 'url': 'http://video.nhl.com/videocenter/console?id=2014020024-628-h', + 'md5': 'd22e82bc592f52d37d24b03531ee9696', + 'info_dict': { + 'id': '2014020024-628-h', + 'ext': 'mp4', + 'title': 'Alex Galchenyuk Goal on Ray Emery (14:40/3rd)', + 'description': 'Home broadcast - Montreal Canadiens at Philadelphia Flyers - October 11, 2014', + 'duration': 0, + 'upload_date': '20141011', + }, }, { 'url': 'http://video.flames.nhl.com/videocenter/console?id=630616', 'only_matching': True, From d3c72db8945cb979a2505099319071717a525816 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 25 Oct 2014 08:58:03 +0200 Subject: [PATCH 1147/1761] [audiomack] Simplify --- youtube_dl/extractor/audiomack.py | 40 ++++++++++++++++--------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/youtube_dl/extractor/audiomack.py b/youtube_dl/extractor/audiomack.py index 2f32253af..57446fddd 100644 --- a/youtube_dl/extractor/audiomack.py +++ b/youtube_dl/extractor/audiomack.py @@ -38,30 +38,32 @@ class AudiomackIE(InfoExtractor): ] def _real_extract(self, url): - #id is what follows /song/ in url, usually the uploader name + title - id = self._match_id(url) + video_id = self._match_id(url) - #Call the api, which gives us a json doc with the real url inside - rightnow = int(time.time()) - apiresponse = self._download_json("http://www.audiomack.com/api/music/url/song/"+id+"?_="+str(rightnow), id) + api_response = self._download_json( + "http://www.audiomack.com/api/music/url/song/%s?_=%d" % ( + video_id, time.time()), + video_id) - if "url" not in apiresponse: + if "url" not in api_response: raise ExtractorError("Unable to deduce api url of song") - realurl = apiresponse["url"] + realurl = api_response["url"] #Audiomack wraps a lot of soundcloud tracks in their branded wrapper # - if so, pass the work off to the soundcloud extractor if SoundcloudIE.suitable(realurl): return {'_type': 'url', 'url': realurl, 'ie_key': 'Soundcloud'} - else: - #Pull out metadata - page = self._download_webpage(url, id) - artist = self._html_search_regex(r'(.*)', page, "artist") - songtitle = self._html_search_regex(r'

.*(.*)

', page, "title") - title = artist+" - "+songtitle - return { - 'id': id, # ignore id, which is not useful in song name - 'title': title, - 'url': realurl, - 'ext': 'mp3' - } + + webpage = self._download_webpage(url, video_id) + artist = self._html_search_regex( + r'(.*?)', webpage, "artist") + songtitle = self._html_search_regex( + r'

.*?(.*?)

', + webpage, "title") + title = artist + " - " + songtitle + + return { + 'id': video_id, + 'title': title, + 'url': realurl, + } From 9a76f416ce67eaaf9c1cdd9058a4e509950950ef Mon Sep 17 00:00:00 2001 From: Naglis Jonaitis Date: Sat, 25 Oct 2014 13:24:46 +0300 Subject: [PATCH 1148/1761] [lrt] Updated test --- youtube_dl/extractor/lrt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/lrt.py b/youtube_dl/extractor/lrt.py index fca0bfef0..db5df4078 100644 --- a/youtube_dl/extractor/lrt.py +++ b/youtube_dl/extractor/lrt.py @@ -22,7 +22,7 @@ class LRTIE(InfoExtractor): 'id': '54391', 'ext': 'mp4', 'title': 'Septynios Kauno dienos', - 'description': 'Kauno miesto ir apskrities naujienos', + 'description': 'md5:24d84534c7dc76581e59f5689462411a', 'duration': 1783, }, 'params': { From 0eb9fb9f24b3eaf1e1eaa5e4576a06ad7794d944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sat, 25 Oct 2014 22:32:01 +0200 Subject: [PATCH 1149/1761] [soundcloud] Modernize and fix tests --- youtube_dl/extractor/soundcloud.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/youtube_dl/extractor/soundcloud.py b/youtube_dl/extractor/soundcloud.py index 4719ba45c..c77671fd3 100644 --- a/youtube_dl/extractor/soundcloud.py +++ b/youtube_dl/extractor/soundcloud.py @@ -40,14 +40,15 @@ class SoundcloudIE(InfoExtractor): _TESTS = [ { 'url': 'http://soundcloud.com/ethmusic/lostin-powers-she-so-heavy', - 'file': '62986583.mp3', 'md5': 'ebef0a451b909710ed1d7787dddbf0d7', 'info_dict': { - "upload_date": "20121011", - "description": "No Downloads untill we record the finished version this weekend, i was too pumped n i had to post it , earl is prolly gonna b hella p.o'd", - "uploader": "E.T. ExTerrestrial Music", - "title": "Lostin Powers - She so Heavy (SneakPreview) Adrian Ackers Blueprint 1", - "duration": 143, + 'id': '62986583', + 'ext': 'mp3', + 'upload_date': '20121011', + 'description': 'No Downloads untill we record the finished version this weekend, i was too pumped n i had to post it , earl is prolly gonna b hella p.o\'d', + 'uploader': 'E.T. ExTerrestrial Music', + 'title': 'Lostin Powers - She so Heavy (SneakPreview) Adrian Ackers Blueprint 1', + 'duration': 143, } }, # not streamable song @@ -103,7 +104,7 @@ class SoundcloudIE(InfoExtractor): 'id': '128590877', 'ext': 'mp3', 'title': 'Bus Brakes', - 'description': 'md5:0170be75dd395c96025d210d261c784e', + 'description': 'md5:0053ca6396e8d2fd7b7e1595ef12ab66', 'uploader': 'oddsamples', 'upload_date': '20140109', 'duration': 17, From 681b9caa9cec6105707381412b90bfe998aa3e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sat, 25 Oct 2014 22:42:56 +0200 Subject: [PATCH 1150/1761] [tumblr] Fix extraction (fixes #4029) --- youtube_dl/extractor/tumblr.py | 35 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/youtube_dl/extractor/tumblr.py b/youtube_dl/extractor/tumblr.py index 306fe8974..40c53ff17 100644 --- a/youtube_dl/extractor/tumblr.py +++ b/youtube_dl/extractor/tumblr.py @@ -4,9 +4,6 @@ from __future__ import unicode_literals import re from .common import InfoExtractor -from ..utils import ( - ExtractorError, -) class TumblrIE(InfoExtractor): @@ -18,7 +15,7 @@ class TumblrIE(InfoExtractor): 'id': '54196191430', 'ext': 'mp4', 'title': 'tatiana maslany news, Orphan Black || DVD extra - behind the scenes ↳...', - 'description': 'md5:dfac39636969fe6bf1caa2d50405f069', + 'description': 'md5:37db8211e40b50c7c44e95da14f630b7', 'thumbnail': 're:http://.*\.jpg', } }, { @@ -27,7 +24,7 @@ class TumblrIE(InfoExtractor): 'info_dict': { 'id': '90208453769', 'ext': 'mp4', - 'title': '5SOS STRUM ;)', + 'title': '5SOS STRUM ;]', 'description': 'md5:dba62ac8639482759c8eb10ce474586a', 'thumbnail': 're:http://.*\.jpg', } @@ -41,18 +38,12 @@ class TumblrIE(InfoExtractor): url = 'http://%s.tumblr.com/post/%s/' % (blog, video_id) webpage = self._download_webpage(url, video_id) - re_video = r'src=\\x22(?Phttp://%s\.tumblr\.com/video_file/%s/(.*?))\\x22 type=\\x22video/(?P.*?)\\x22' % (blog, video_id) - video = re.search(re_video, webpage) - if video is None: - raise ExtractorError('Unable to extract video') - video_url = video.group('video_url') - ext = video.group('ext') - - video_thumbnail = self._search_regex( - r'posters.*?\[\\x22(.*?)\\x22', - webpage, 'thumbnail', fatal=False) # We pick the first poster - if video_thumbnail: - video_thumbnail = video_thumbnail.replace('\\\\/', '/') + iframe_url = self._search_regex( + r'src=\'(https?://www\.tumblr\.com/video/[^\']+)\'', + webpage, 'iframe url') + iframe = self._download_webpage(iframe_url, video_id) + video_url = self._search_regex(r' Date: Sun, 26 Oct 2014 08:00:01 +0700 Subject: [PATCH 1151/1761] [sportbox] Remove view count --- youtube_dl/extractor/sportbox.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/youtube_dl/extractor/sportbox.py b/youtube_dl/extractor/sportbox.py index 19cc976e3..b9cd35109 100644 --- a/youtube_dl/extractor/sportbox.py +++ b/youtube_dl/extractor/sportbox.py @@ -26,7 +26,6 @@ class SportBoxIE(InfoExtractor): 'timestamp': 1411896237, 'upload_date': '20140928', 'duration': 4846, - 'view_count': int, }, 'params': { # m3u8 download @@ -65,8 +64,6 @@ class SportBoxIE(InfoExtractor): r'([^<]+)', webpage, 'timestamp', fatal=False)) duration = parse_duration(self._html_search_regex( r'', webpage, 'duration', fatal=False)) - view_count = int_or_none(self._html_search_regex( - r'Просмотров: (\d+)', player, 'view count', fatal=False)) return { 'id': video_id, @@ -76,6 +73,5 @@ class SportBoxIE(InfoExtractor): 'thumbnail': thumbnail, 'timestamp': timestamp, 'duration': duration, - 'view_count': view_count, 'formats': formats, } From b13ccb1b87199dcfd10b12ed5c3002ff6f951769 Mon Sep 17 00:00:00 2001 From: dinesh Date: Sun, 26 Oct 2014 13:35:00 +0530 Subject: [PATCH 1152/1761] [BelgianNational] New extractor added --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/belgiannational.py | 64 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 youtube_dl/extractor/belgiannational.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 691fef5ca..ec299b72f 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -27,6 +27,7 @@ from .bandcamp import BandcampIE, BandcampAlbumIE from .bbccouk import BBCCoUkIE from .beeg import BeegIE from .behindkink import BehindKinkIE +from .belgiannational import BelgianNationalIE from .bild import BildIE from .bilibili import BiliBiliIE from .blinkx import BlinkxIE diff --git a/youtube_dl/extractor/belgiannational.py b/youtube_dl/extractor/belgiannational.py new file mode 100644 index 000000000..2367d1f2b --- /dev/null +++ b/youtube_dl/extractor/belgiannational.py @@ -0,0 +1,64 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import int_or_none + +class BelgianNationalIE(InfoExtractor): + _VALID_URL = r'http://(?:deredactie|sporza|cobra)\.be/cm/(.*)/(?P[^\']+)' + _TESTS = [ + # deredactie.be + { + 'url': 'http://deredactie.be/cm/vrtnieuws/videozone/programmas/journaal/EP_141025_JOL', + 'md5': '4cebde1eb60a53782d4f3992cbd46ec8', + 'info_dict': { + 'id': 'EP_141025_JOL', + 'title': 'Het journaal L - 25/10/14', + 'ext': 'mp4', + 'duration': 929, + } + }, + # sporza.be + { + 'url': 'http://sporza.be/cm/sporza/videozone/programmas/extratime/EP_141020_Extra_time', + 'md5': '11f53088da9bf8e7cfc42456697953ff', + 'info_dict': { + 'id': 'EP_141020_Extra_time', + 'title': 'Bekijk Extra Time van 20 oktober', + 'ext': 'mp4', + 'duration': 3238, + } + + }, + # cobra.be + { + 'url': 'http://cobra.be/cm/cobra/videozone/rubriek/film-videozone/141022-mv-ellis-cafecorsari', + 'md5': '78a2b060a5083c4f055449a72477409d', + 'info_dict': { + 'id': '141022-mv-ellis-cafecorsari', + 'title': 'Bret Easton Ellis in Café Corsari', + 'ext': 'mp4', + 'duration': 661, + } + } + ] + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('video_id') + + webpage = self._download_webpage(url, video_id) + title = self._og_search_title(webpage) + + video_url = self._search_regex(r'data-video-src="(.*?)"', webpage, 'Video url') + '/manifest.f4m' + duration = int_or_none(self._search_regex(r'data-video-sitestat-duration="(.*?)"', webpage, 'Duration')) + + return { + 'id': video_id, + 'title': title, + 'url': video_url, + 'ext': 'mp4', + 'duration': duration, + } \ No newline at end of file From 03936f6e6ddf222a9391193f15b3b6e0b75983cd Mon Sep 17 00:00:00 2001 From: dinesh Date: Sun, 26 Oct 2014 13:47:41 +0530 Subject: [PATCH 1153/1761] [BelgianNational] corrected indentation --- youtube_dl/extractor/belgiannational.py | 67 ++++++++++++------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/youtube_dl/extractor/belgiannational.py b/youtube_dl/extractor/belgiannational.py index 2367d1f2b..cabff50f2 100644 --- a/youtube_dl/extractor/belgiannational.py +++ b/youtube_dl/extractor/belgiannational.py @@ -9,40 +9,39 @@ from ..utils import int_or_none class BelgianNationalIE(InfoExtractor): _VALID_URL = r'http://(?:deredactie|sporza|cobra)\.be/cm/(.*)/(?P[^\']+)' _TESTS = [ - # deredactie.be - { - 'url': 'http://deredactie.be/cm/vrtnieuws/videozone/programmas/journaal/EP_141025_JOL', - 'md5': '4cebde1eb60a53782d4f3992cbd46ec8', - 'info_dict': { - 'id': 'EP_141025_JOL', - 'title': 'Het journaal L - 25/10/14', - 'ext': 'mp4', - 'duration': 929, - } - }, - # sporza.be - { - 'url': 'http://sporza.be/cm/sporza/videozone/programmas/extratime/EP_141020_Extra_time', - 'md5': '11f53088da9bf8e7cfc42456697953ff', - 'info_dict': { - 'id': 'EP_141020_Extra_time', - 'title': 'Bekijk Extra Time van 20 oktober', - 'ext': 'mp4', - 'duration': 3238, - } - - }, - # cobra.be - { - 'url': 'http://cobra.be/cm/cobra/videozone/rubriek/film-videozone/141022-mv-ellis-cafecorsari', - 'md5': '78a2b060a5083c4f055449a72477409d', - 'info_dict': { - 'id': '141022-mv-ellis-cafecorsari', - 'title': 'Bret Easton Ellis in Café Corsari', - 'ext': 'mp4', - 'duration': 661, - } - } + # deredactie.be + { + 'url': 'http://deredactie.be/cm/vrtnieuws/videozone/programmas/journaal/EP_141025_JOL', + 'md5': '4cebde1eb60a53782d4f3992cbd46ec8', + 'info_dict': { + 'id': 'EP_141025_JOL', + 'title': 'Het journaal L - 25/10/14', + 'ext': 'mp4', + 'duration': 929, + } + }, + # sporza.be + { + 'url': 'http://sporza.be/cm/sporza/videozone/programmas/extratime/EP_141020_Extra_time', + 'md5': '11f53088da9bf8e7cfc42456697953ff', + 'info_dict': { + 'id': 'EP_141020_Extra_time', + 'title': 'Bekijk Extra Time van 20 oktober', + 'ext': 'mp4', + 'duration': 3238, + } + }, + # cobra.be + { + 'url': 'http://cobra.be/cm/cobra/videozone/rubriek/film-videozone/141022-mv-ellis-cafecorsari', + 'md5': '78a2b060a5083c4f055449a72477409d', + 'info_dict': { + 'id': '141022-mv-ellis-cafecorsari', + 'title': 'Bret Easton Ellis in Café Corsari', + 'ext': 'mp4', + 'duration': 661, + } + }, ] def _real_extract(self, url): From 911344e5aca14d207731148f4862913827c8c871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 26 Oct 2014 16:48:11 +0700 Subject: [PATCH 1154/1761] [vrt] Improve extractor --- youtube_dl/extractor/__init__.py | 2 +- youtube_dl/extractor/belgiannational.py | 63 ---------------- youtube_dl/extractor/vrt.py | 95 +++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 64 deletions(-) delete mode 100644 youtube_dl/extractor/belgiannational.py create mode 100644 youtube_dl/extractor/vrt.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index ec299b72f..5ec9b4745 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -27,7 +27,6 @@ from .bandcamp import BandcampIE, BandcampAlbumIE from .bbccouk import BBCCoUkIE from .beeg import BeegIE from .behindkink import BehindKinkIE -from .belgiannational import BelgianNationalIE from .bild import BildIE from .bilibili import BiliBiliIE from .blinkx import BlinkxIE @@ -446,6 +445,7 @@ from .viki import VikiIE from .vk import VKIE from .vodlocker import VodlockerIE from .vporn import VpornIE +from .vrt import VRTIE from .vube import VubeIE from .vuclip import VuClipIE from .vulture import VultureIE diff --git a/youtube_dl/extractor/belgiannational.py b/youtube_dl/extractor/belgiannational.py deleted file mode 100644 index cabff50f2..000000000 --- a/youtube_dl/extractor/belgiannational.py +++ /dev/null @@ -1,63 +0,0 @@ -# coding: utf-8 -from __future__ import unicode_literals - -import re - -from .common import InfoExtractor -from ..utils import int_or_none - -class BelgianNationalIE(InfoExtractor): - _VALID_URL = r'http://(?:deredactie|sporza|cobra)\.be/cm/(.*)/(?P[^\']+)' - _TESTS = [ - # deredactie.be - { - 'url': 'http://deredactie.be/cm/vrtnieuws/videozone/programmas/journaal/EP_141025_JOL', - 'md5': '4cebde1eb60a53782d4f3992cbd46ec8', - 'info_dict': { - 'id': 'EP_141025_JOL', - 'title': 'Het journaal L - 25/10/14', - 'ext': 'mp4', - 'duration': 929, - } - }, - # sporza.be - { - 'url': 'http://sporza.be/cm/sporza/videozone/programmas/extratime/EP_141020_Extra_time', - 'md5': '11f53088da9bf8e7cfc42456697953ff', - 'info_dict': { - 'id': 'EP_141020_Extra_time', - 'title': 'Bekijk Extra Time van 20 oktober', - 'ext': 'mp4', - 'duration': 3238, - } - }, - # cobra.be - { - 'url': 'http://cobra.be/cm/cobra/videozone/rubriek/film-videozone/141022-mv-ellis-cafecorsari', - 'md5': '78a2b060a5083c4f055449a72477409d', - 'info_dict': { - 'id': '141022-mv-ellis-cafecorsari', - 'title': 'Bret Easton Ellis in Café Corsari', - 'ext': 'mp4', - 'duration': 661, - } - }, - ] - - def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('video_id') - - webpage = self._download_webpage(url, video_id) - title = self._og_search_title(webpage) - - video_url = self._search_regex(r'data-video-src="(.*?)"', webpage, 'Video url') + '/manifest.f4m' - duration = int_or_none(self._search_regex(r'data-video-sitestat-duration="(.*?)"', webpage, 'Duration')) - - return { - 'id': video_id, - 'title': title, - 'url': video_url, - 'ext': 'mp4', - 'duration': duration, - } \ No newline at end of file diff --git a/youtube_dl/extractor/vrt.py b/youtube_dl/extractor/vrt.py new file mode 100644 index 000000000..57ef8dc30 --- /dev/null +++ b/youtube_dl/extractor/vrt.py @@ -0,0 +1,95 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import float_or_none + + +class VRTIE(InfoExtractor): + _VALID_URL = r'https?://(?:deredactie|sporza|cobra)\.be/cm/(?:[^/]+/)+(?P[^/]+)/*' + _TESTS = [ + # deredactie.be + { + 'url': 'http://deredactie.be/cm/vrtnieuws/videozone/programmas/journaal/EP_141025_JOL', + 'md5': '4cebde1eb60a53782d4f3992cbd46ec8', + 'info_dict': { + 'id': '2129880', + 'ext': 'flv', + 'title': 'Het journaal L - 25/10/14', + 'description': None, + 'timestamp': 1414271750.949, + 'upload_date': '20141025', + 'duration': 929, + } + }, + # sporza.be + { + 'url': 'http://sporza.be/cm/sporza/videozone/programmas/extratime/EP_141020_Extra_time', + 'md5': '11f53088da9bf8e7cfc42456697953ff', + 'info_dict': { + 'id': '2124639', + 'ext': 'flv', + 'title': 'Bekijk Extra Time van 20 oktober', + 'description': 'md5:83ac5415a4f1816c6a93f8138aef2426', + 'timestamp': 1413835980.560, + 'upload_date': '20141020', + 'duration': 3238, + } + }, + # cobra.be + { + 'url': 'http://cobra.be/cm/cobra/videozone/rubriek/film-videozone/141022-mv-ellis-cafecorsari', + 'md5': '78a2b060a5083c4f055449a72477409d', + 'info_dict': { + 'id': '2126050', + 'ext': 'flv', + 'title': 'Bret Easton Ellis in Café Corsari', + 'description': 'md5:f699986e823f32fd6036c1855a724ee9', + 'timestamp': 1413967500.494, + 'upload_date': '20141022', + 'duration': 661, + } + }, + ] + + def _real_extract(self, url): + video_id = self._match_id(url) + + webpage = self._download_webpage(url, video_id) + + video_id = self._search_regex( + r'data-video-id="([^"]+)_[^"]+"', webpage, 'video id', fatal=False) + + formats = [] + mobj = re.search( + r'data-video-iphone-server="(?P[^"]+)"\s+data-video-iphone-path="(?P[^"]+)"', + webpage) + if mobj: + formats.extend(self._extract_m3u8_formats( + '%s/%s' % (mobj.group('server'), mobj.group('path')), + video_id, 'mp4')) + mobj = re.search(r'data-video-src="(?P[^"]+)"', webpage) + if mobj: + formats.extend(self._extract_f4m_formats( + '%s/manifest.f4m' % mobj.group('src'), video_id)) + self._sort_formats(formats) + + title = self._og_search_title(webpage) + description = self._og_search_description(webpage, default=None) + thumbnail = self._og_search_thumbnail(webpage) + timestamp = float_or_none(self._search_regex( + r'data-video-sitestat-pubdate="(\d+)"', webpage, 'timestamp', fatal=False), 1000) + duration = float_or_none(self._search_regex( + r'data-video-duration="(\d+)"', webpage, 'duration', fatal=False), 1000) + + return { + 'id': video_id, + 'title': title, + 'description': description, + 'thumbnail': thumbnail, + 'timestamp': timestamp, + 'duration': duration, + 'formats': formats, + } \ No newline at end of file From 1bdeb7be2e5bef703d54d8786fbc6f3c0c23faef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sun, 26 Oct 2014 13:01:57 +0100 Subject: [PATCH 1155/1761] Set '--simulate' if any of the printing options is given (fixes #3036) That's what the help messages say. Previously it would only set '--skip-download', which would write thumbnail, descriptions or subtitles if they were requested (for example you may have set '--write-thumbnail' in the config file). --- youtube_dl/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 4f5ce604f..578ecc4ab 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -307,8 +307,8 @@ def _real_main(argv=None): 'forceformat': opts.getformat, 'forcejson': opts.dumpjson, 'dump_single_json': opts.dump_single_json, - 'simulate': opts.simulate, - 'skip_download': (opts.skip_download or opts.simulate or any_printing), + 'simulate': opts.simulate or any_printing, + 'skip_download': opts.skip_download, 'format': opts.format, 'format_limit': opts.format_limit, 'listformats': opts.listformats, From a7e97f6db17240ae33719550d62df0816ab410ad Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 14:15:48 +0100 Subject: [PATCH 1156/1761] [generic] Allow new SWFObject()-style imports This embed style is used on http://www.bitburger-open.de/ , but that is not included as a test case since the format is likely to be temporary. --- youtube_dl/extractor/generic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 9b6498894..524215408 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -635,7 +635,8 @@ class GenericIE(InfoExtractor): ]+?src=| data-video-url=| ]+?src=| - embedSWF\(?:\s* + embedSWF\(?:\s*| + new\s+SWFObject\( ) (["\']) (?P(?:https?:)?//(?:www\.)?youtube(?:-nocookie)?\.com/ From d28b5171541aaef568372a78384d6a5c862b2369 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 16:31:52 +0100 Subject: [PATCH 1157/1761] [YoutubeDL] Output avconv/ffmpeg versions if -v is given --- youtube_dl/YoutubeDL.py | 16 ++++++++++--- youtube_dl/postprocessor/__init__.py | 12 ++++++---- youtube_dl/postprocessor/ffmpeg.py | 34 +++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 242affb5b..ecf426e37 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -62,7 +62,7 @@ from .utils import ( from .cache import Cache from .extractor import get_info_extractor, gen_extractors from .downloader import get_suitable_downloader -from .postprocessor import FFmpegMergerPP +from .postprocessor import FFmpegMergerPP, FFmpegPostProcessor from .version import __version__ @@ -1311,8 +1311,18 @@ class YoutubeDL(object): sys.exc_clear() except: pass - self._write_string('[debug] Python version %s - %s' % - (platform.python_version(), platform_name()) + '\n') + self._write_string('[debug] Python version %s - %s\n' % ( + platform.python_version(), platform_name())) + + exe_versions = FFmpegPostProcessor.get_versions() + exe_str = ', '.join( + '%s %s' % (exe, v) + for exe, v in sorted(exe_versions.items()) + if v + ) + if not exe_str: + exe_str = 'none' + self._write_string('[debug] exe versions: %s\n' % exe_str) proxy_map = {} for handler in self._opener.handlers: diff --git a/youtube_dl/postprocessor/__init__.py b/youtube_dl/postprocessor/__init__.py index 15aa0daa9..6ac67cbae 100644 --- a/youtube_dl/postprocessor/__init__.py +++ b/youtube_dl/postprocessor/__init__.py @@ -1,24 +1,26 @@ from .atomicparsley import AtomicParsleyPP from .ffmpeg import ( + FFmpegPostProcessor, FFmpegAudioFixPP, + FFmpegEmbedSubtitlePP, + FFmpegExtractAudioPP, FFmpegMergerPP, FFmpegMetadataPP, FFmpegVideoConvertor, - FFmpegExtractAudioPP, - FFmpegEmbedSubtitlePP, ) from .xattrpp import XAttrMetadataPP from .execafterdownload import ExecAfterDownloadPP __all__ = [ 'AtomicParsleyPP', + 'ExecAfterDownloadPP', 'FFmpegAudioFixPP', + 'FFmpegEmbedSubtitlePP', + 'FFmpegExtractAudioPP', 'FFmpegMergerPP', 'FFmpegMetadataPP', + 'FFmpegPostProcessor', 'FFmpegVideoConvertor', - 'FFmpegExtractAudioPP', - 'FFmpegEmbedSubtitlePP', 'XAttrMetadataPP', - 'ExecAfterDownloadPP', ] diff --git a/youtube_dl/postprocessor/ffmpeg.py b/youtube_dl/postprocessor/ffmpeg.py index 6f010a9c7..867e75d80 100644 --- a/youtube_dl/postprocessor/ffmpeg.py +++ b/youtube_dl/postprocessor/ffmpeg.py @@ -1,4 +1,5 @@ import os +import re import subprocess import sys import time @@ -18,6 +19,23 @@ from ..utils import ( ) +def get_version(executable): + """ Returns the version of the specified executable, + or False if the executable is not present """ + try: + out, err = subprocess.Popen( + [executable, '-version'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() + except OSError: + return False + firstline = out.partition(b'\n')[0].decode('ascii', 'ignore') + m = re.search(r'version\s+([0-9._-a-zA-Z]+)', firstline) + if not m: + return u'present' + else: + return m.group(1) + + class FFmpegPostProcessorError(PostProcessingError): pass @@ -25,22 +43,26 @@ class FFmpegPostProcessorError(PostProcessingError): class FFmpegPostProcessor(PostProcessor): def __init__(self, downloader=None, deletetempfiles=False): PostProcessor.__init__(self, downloader) - self._exes = self.detect_executables() + self._versions = self.get_versions() self._deletetempfiles = deletetempfiles @staticmethod - def detect_executables(): + def get_versions(): programs = ['avprobe', 'avconv', 'ffmpeg', 'ffprobe'] - return dict((program, check_executable(program, ['-version'])) for program in programs) + return dict((program, get_version(program)) for program in programs) def _get_executable(self): if self._downloader.params.get('prefer_ffmpeg', False): - return self._exes['ffmpeg'] or self._exes['avconv'] + prefs = ('ffmpeg', 'avconv') else: - return self._exes['avconv'] or self._exes['ffmpeg'] + prefs = ('avconv', 'ffmpeg') + for p in prefs: + if self._versions[p]: + return p + return None def _uses_avconv(self): - return self._get_executable() == self._exes['avconv'] + return self._get_executable() == 'avconv' def run_ffmpeg_multiple_files(self, input_paths, out_path, opts): if not self._get_executable(): From 488447455d3d90e1d83a7ebc2f9ce552e031e0d8 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 16:46:34 +0100 Subject: [PATCH 1158/1761] [ffmpeg] Warn if ffmpeg/avconv version is too old (Fixes #4026) --- youtube_dl/YoutubeDL.py | 2 +- youtube_dl/postprocessor/ffmpeg.py | 28 ++++++++++++++++++++-------- youtube_dl/utils.py | 13 +++++++++++++ 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index ecf426e37..28dcc0195 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -1026,7 +1026,7 @@ class YoutubeDL(object): downloaded = [] success = True merger = FFmpegMergerPP(self, not self.params.get('keepvideo')) - if not merger._get_executable(): + if not merger._executable: postprocessors = [] self.report_warning('You have requested multiple ' 'formats but ffmpeg or avconv are not installed.' diff --git a/youtube_dl/postprocessor/ffmpeg.py b/youtube_dl/postprocessor/ffmpeg.py index 867e75d80..e13deab4b 100644 --- a/youtube_dl/postprocessor/ffmpeg.py +++ b/youtube_dl/postprocessor/ffmpeg.py @@ -12,6 +12,7 @@ from ..utils import ( compat_subprocess_get_DEVNULL, encodeArgument, encodeFilename, + is_outdated_version, PostProcessingError, prepend_extension, shell_quote, @@ -41,17 +42,29 @@ class FFmpegPostProcessorError(PostProcessingError): class FFmpegPostProcessor(PostProcessor): - def __init__(self, downloader=None, deletetempfiles=False): + def __init__(self, downloader, deletetempfiles=False): PostProcessor.__init__(self, downloader) self._versions = self.get_versions() self._deletetempfiles = deletetempfiles + def check_version(self): + if not self._executable: + raise FFmpegPostProcessorError(u'ffmpeg or avconv not found. Please install one.') + + REQUIRED_VERSION = '1.0' + if is_outdated_version( + self._versions[self._executable], REQUIRED_VERSION): + warning = u'Your copy of %s is outdated, update %s to version %s or newer if you encounter any errors.' % ( + self._executable, self._executable, REQUIRED_VERSION) + self._downloader.report_warning(warning) + @staticmethod def get_versions(): programs = ['avprobe', 'avconv', 'ffmpeg', 'ffprobe'] return dict((program, get_version(program)) for program in programs) - def _get_executable(self): + @property + def _executable(self): if self._downloader.params.get('prefer_ffmpeg', False): prefs = ('ffmpeg', 'avconv') else: @@ -62,16 +75,15 @@ class FFmpegPostProcessor(PostProcessor): return None def _uses_avconv(self): - return self._get_executable() == 'avconv' + return self._executable == 'avconv' def run_ffmpeg_multiple_files(self, input_paths, out_path, opts): - if not self._get_executable(): - raise FFmpegPostProcessorError(u'ffmpeg or avconv not found. Please install one.') + self.check_version() files_cmd = [] for path in input_paths: files_cmd.extend(['-i', encodeFilename(path, True)]) - cmd = ([self._get_executable(), '-y'] + files_cmd + cmd = ([self._executable, '-y'] + files_cmd + [encodeArgument(o) for o in opts] + [encodeFilename(self._ffmpeg_filename_argument(out_path), True)]) @@ -204,14 +216,14 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor): if self._nopostoverwrites and os.path.exists(encodeFilename(new_path)): self._downloader.to_screen(u'[youtube] Post-process file %s exists, skipping' % new_path) else: - self._downloader.to_screen(u'[' + self._get_executable() + '] Destination: ' + new_path) + self._downloader.to_screen(u'[' + self._executable + '] Destination: ' + new_path) self.run_ffmpeg(path, new_path, acodec, more_opts) except: etype,e,tb = sys.exc_info() if isinstance(e, AudioConversionError): msg = u'audio conversion failed: ' + e.msg else: - msg = u'error running ' + self._get_executable() + msg = u'error running ' + self._executable raise PostProcessingError(msg) # Try to update the date time for extracted audio file. diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 9287edd8d..6c0c39ca5 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -1723,3 +1723,16 @@ def limit_length(s, length): if len(s) > length: return s[:length - len(ELLIPSES)] + ELLIPSES return s + + +def version_tuple(v): + return [int(e) for e in v.split('.')] + + +def is_outdated_version(version, limit, assume_new=True): + if not version: + return not assume_new + try: + return version_tuple(version) < version_tuple(limit) + except ValueError: + return not assume_new From 23be51d8ce132dbb967f460e1225fdaaa43dff39 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 17:05:44 +0100 Subject: [PATCH 1159/1761] [generic] Handle audio streams that do not implement HEAD (Fixes #4032) --- youtube_dl/extractor/common.py | 7 +++-- youtube_dl/extractor/generic.py | 53 +++++++++++++++++---------------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index cf3781cd6..e1bd6bb49 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -242,7 +242,6 @@ class InfoExtractor(object): def _download_webpage_handle(self, url_or_request, video_id, note=None, errnote=None, fatal=True): """ Returns a tuple (page content as string, URL handle) """ - # Strip hashes from the URL (#1038) if isinstance(url_or_request, (compat_str, str)): url_or_request = url_or_request.partition('#')[0] @@ -251,6 +250,10 @@ class InfoExtractor(object): if urlh is False: assert not fatal return False + content = self._webpage_read_content(urlh, url_or_request, video_id, note, errnote, fatal) + return (content, urlh) + + def _webpage_read_content(self, urlh, url_or_request, video_id, note=None, errnote=None, fatal=True): content_type = urlh.headers.get('Content-Type', '') webpage_bytes = urlh.read() m = re.match(r'[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+\s*;\s*charset=(.+)', content_type) @@ -309,7 +312,7 @@ class InfoExtractor(object): msg += ' Visit %s for more details' % blocked_iframe raise ExtractorError(msg, expected=True) - return (content, urlh) + return content def _download_webpage(self, url_or_request, video_id, note=None, errnote=None, fatal=True): """ Returns the data of the page as a string """ diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 524215408..51dbbc8db 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -503,14 +503,14 @@ class GenericIE(InfoExtractor): self.to_screen('%s: Requesting header' % video_id) head_req = HEADRequest(url) - response = self._request_webpage( + head_response = self._request_webpage( head_req, video_id, note=False, errnote='Could not send HEAD request to %s' % url, fatal=False) - if response is not False: + if head_response is not False: # Check for redirect - new_url = response.geturl() + new_url = head_response.geturl() if url != new_url: self.report_following_redirect(new_url) if force_videoid: @@ -518,34 +518,35 @@ class GenericIE(InfoExtractor): new_url, {'force_videoid': force_videoid}) return self.url_result(new_url) - # Check for direct link to a video - content_type = response.headers.get('Content-Type', '') - m = re.match(r'^(?Paudio|video|application(?=/ogg$))/(?P.+)$', content_type) - if m: - upload_date = response.headers.get('Last-Modified') - if upload_date: - upload_date = unified_strdate(upload_date) - return { - 'id': video_id, - 'title': os.path.splitext(url_basename(url))[0], - 'formats': [{ - 'format_id': m.group('format_id'), - 'url': url, - 'vcodec': 'none' if m.group('type') == 'audio' else None - }], - 'upload_date': upload_date, - } + full_response = None + if head_response is False: + full_response = self._request_webpage(url, video_id) + head_response = full_response + + # Check for direct link to a video + content_type = head_response.headers.get('Content-Type', '') + m = re.match(r'^(?Paudio|video|application(?=/ogg$))/(?P.+)$', content_type) + if m: + upload_date = unified_strdate( + head_response.headers.get('Last-Modified')) + return { + 'id': video_id, + 'title': os.path.splitext(url_basename(url))[0], + 'formats': [{ + 'format_id': m.group('format_id'), + 'url': url, + 'vcodec': 'none' if m.group('type') == 'audio' else None + }], + 'upload_date': upload_date, + } if not self._downloader.params.get('test', False) and not is_intentional: self._downloader.report_warning('Falling back on generic information extractor.') - try: + if full_response: + webpage = _webpage_read_content(url, video_id) + else: webpage = self._download_webpage(url, video_id) - except ValueError: - # since this is the last-resort InfoExtractor, if - # this error is thrown, it'll be thrown here - raise ExtractorError('Failed to download URL: %s' % url) - self.report_extraction(video_id) # Is it an RSS feed? From 09e5d6a6e564ecaa44a174456882bd1998eacbf8 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 17:28:09 +0100 Subject: [PATCH 1160/1761] [crunchyroll:playlist] Simplify (#3988) --- youtube_dl/extractor/crunchyroll.py | 50 +++++++++++++++-------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/youtube_dl/extractor/crunchyroll.py b/youtube_dl/extractor/crunchyroll.py index 2dca52660..05b21e872 100644 --- a/youtube_dl/extractor/crunchyroll.py +++ b/youtube_dl/extractor/crunchyroll.py @@ -293,34 +293,36 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text class CrunchyrollShowPlaylistIE(InfoExtractor): IE_NAME = "crunchyroll:playlist" - _VALID_URL = r'https?://(?:(?Pwww|m)\.)?(?Pcrunchyroll\.com/(?!(?:news|anime-news|library|forum|launchcalendar|lineup|store|comics|freetrial|login))(?P[\w\-]+))/?$' - _TITLE_EXTR = r'\s*(?P[\w\s]+)' + _VALID_URL = r'https?://(?:(?Pwww|m)\.)?(?Pcrunchyroll\.com/(?!(?:news|anime-news|library|forum|launchcalendar|lineup|store|comics|freetrial|login))(?P[\w\-]+))/?$' _TESTS = [{ - 'url' : 'http://www.crunchyroll.com/attack-on-titan', - 'info_dict' : { - 'title' : 'Attack on Titan' + 'url': 'http://www.crunchyroll.com/a-bridge-to-the-starry-skies-hoshizora-e-kakaru-hashi', + 'info_dict': { + 'id': 'a-bridge-to-the-starry-skies-hoshizora-e-kakaru-hashi', + 'title': 'A Bridge to the Starry Skies - Hoshizora e Kakaru Hashi' }, - 'playlist_count' : 15 + 'playlist_count': 13, }] - def _extract_title_entries(self,id,webpage): - _EPISODE_ID_EXTR = r'id="showview_videos_media_(?P\d+)".*?href="/{0}/(?P[\w\-]+-(?P=vidid))"'.format(id) - title = self._html_search_regex(self._TITLE_EXTR,webpage,"title",flags=re.UNICODE|re.MULTILINE) - episode_urls = [self.url_result('http://www.crunchyroll.com/{0}/{1}'.format(id, showmatch[1])) for - showmatch in re.findall(_EPISODE_ID_EXTR, webpage,re.UNICODE|re.MULTILINE|re.DOTALL)] - episode_urls.reverse() - return title, episode_urls - - def _real_extract(self, url): - url_match = re.match(self._VALID_URL,url) - show_id = url_match.group('show') - webpage = self._download_webpage(url,show_id) - (title,entries) = self._extract_title_entries(show_id,webpage) + show_id = self._match_id(url) + + webpage = self._download_webpage(url, show_id) + title = self._html_search_regex( + r'(?s)]*>\s*(.*?)', + webpage, 'title') + episode_paths = re.findall( + r'(?s)
  • ]+>.*? Date: Sun, 26 Oct 2014 17:28:50 +0100 Subject: [PATCH 1161/1761] Credit @gabeos for crunchyroll:playlist (#3988) --- youtube_dl/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index cb4f2e41c..e2c6f38a9 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -82,7 +82,8 @@ __authors__ = ( 'Dennis Scheiba', 'Damon Timm', 'winwon', - 'Xavier Beynon' + 'Xavier Beynon', + 'Gabriel Schubiner', ) __license__ = 'Public Domain' From d481699a7a9bc8769deb9f7b9cdb5754a1fec5ba Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 17:29:27 +0100 Subject: [PATCH 1162/1761] release 2014.10.26 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index d822ae330..f5f60cdc3 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.25' +__version__ = '2014.10.26' From 64269e4d0117a04096696532bccd90ee6b176f25 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 18:00:50 +0100 Subject: [PATCH 1163/1761] Move AUTHORS to root (closes #2985) --- AUTHORS | 82 ++++++++++++++++++++++++++++++++++++++++ youtube_dl/__init__.py | 85 ------------------------------------------ 2 files changed, 82 insertions(+), 85 deletions(-) create mode 100644 AUTHORS diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..a574949b3 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,82 @@ +Ricardo Garcia Gonzalez +Danny Colligan +Benjamin Johnson +Vasyl' Vavrychuk +Witold Baryluk +Paweł Paprota +Gergely Imreh +Rogério Brito +Philipp Hagemeister +Sören Schulze +Kevin Ngo +Ori Avtalion +shizeeg +Filippo Valsorda +Christian Albrecht +Dave Vasilevsky +Jaime Marquínez Ferrándiz +Jeff Crouse +Osama Khalid +Michael Walter +M. Yasoob Ullah Khalid +Julien Fraichard +Johny Mo Swag +Axel Noack +Albert Kim +Pierre Rudloff +Huarong Huo +Ismael Mejía +Steffan 'Ruirize' James +Andras Elso +Jelle van der Waa +Marcin Cieślak +Anton Larionov +Takuya Tsuchida +Sergey M. +Michael Orlitzky +Chris Gahan +Saimadhav Heblikar +Mike Col +Oleg Prutz +pulpe +Andreas Schmitz +Michael Kaiser +Niklas Laxström +David Triendl +Anthony Weems +David Wagner +Juan C. Olivares +Mattias Harrysson +phaer +Sainyam Kapoor +Nicolas Évrard +Jason Normore +Hoje Lee +Adam Thalhammer +Georg Jähnig +Ralf Haring +Koki Takahashi +Ariset Llerena +Adam Malcontenti-Wilson +Tobias Bell +Naglis Jonaitis +Charles Chen +Hassaan Ali +Dobrosław Żybort +David Fabijan +Sebastian Haas +Alexander Kirk +Erik Johnson +Keith Beckman +Ole Ernst +Aaron McDaniel (mcd1992) +Magnus Kolstad +Hari Padmanaban +Carlos Ramos +5moufl +lenaten +Dennis Scheiba +Damon Timm +winwon +Xavier Beynon +Gabriel Schubiner \ No newline at end of file diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index e2c6f38a9..7dc971884 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -1,91 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -__authors__ = ( - 'Ricardo Garcia Gonzalez', - 'Danny Colligan', - 'Benjamin Johnson', - 'Vasyl\' Vavrychuk', - 'Witold Baryluk', - 'Paweł Paprota', - 'Gergely Imreh', - 'Rogério Brito', - 'Philipp Hagemeister', - 'Sören Schulze', - 'Kevin Ngo', - 'Ori Avtalion', - 'shizeeg', - 'Filippo Valsorda', - 'Christian Albrecht', - 'Dave Vasilevsky', - 'Jaime Marquínez Ferrándiz', - 'Jeff Crouse', - 'Osama Khalid', - 'Michael Walter', - 'M. Yasoob Ullah Khalid', - 'Julien Fraichard', - 'Johny Mo Swag', - 'Axel Noack', - 'Albert Kim', - 'Pierre Rudloff', - 'Huarong Huo', - 'Ismael Mejía', - 'Steffan \'Ruirize\' James', - 'Andras Elso', - 'Jelle van der Waa', - 'Marcin Cieślak', - 'Anton Larionov', - 'Takuya Tsuchida', - 'Sergey M.', - 'Michael Orlitzky', - 'Chris Gahan', - 'Saimadhav Heblikar', - 'Mike Col', - 'Oleg Prutz', - 'pulpe', - 'Andreas Schmitz', - 'Michael Kaiser', - 'Niklas Laxström', - 'David Triendl', - 'Anthony Weems', - 'David Wagner', - 'Juan C. Olivares', - 'Mattias Harrysson', - 'phaer', - 'Sainyam Kapoor', - 'Nicolas Évrard', - 'Jason Normore', - 'Hoje Lee', - 'Adam Thalhammer', - 'Georg Jähnig', - 'Ralf Haring', - 'Koki Takahashi', - 'Ariset Llerena', - 'Adam Malcontenti-Wilson', - 'Tobias Bell', - 'Naglis Jonaitis', - 'Charles Chen', - 'Hassaan Ali', - 'Dobrosław Żybort', - 'David Fabijan', - 'Sebastian Haas', - 'Alexander Kirk', - 'Erik Johnson', - 'Keith Beckman', - 'Ole Ernst', - 'Aaron McDaniel (mcd1992)', - 'Magnus Kolstad', - 'Hari Padmanaban', - 'Carlos Ramos', - '5moufl', - 'lenaten', - 'Dennis Scheiba', - 'Damon Timm', - 'winwon', - 'Xavier Beynon', - 'Gabriel Schubiner', -) - __license__ = 'Public Domain' import codecs From 5f82b129e085eb122b6129df36e45925f5b4546a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sun, 26 Oct 2014 18:11:31 +0100 Subject: [PATCH 1164/1761] [ffmpeg] Also look into stderr for extracting the version At least with avconv 11, it will print 'avconv version 11, ..' to stderr, not stdout. --- youtube_dl/postprocessor/ffmpeg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/postprocessor/ffmpeg.py b/youtube_dl/postprocessor/ffmpeg.py index e13deab4b..19fc135dc 100644 --- a/youtube_dl/postprocessor/ffmpeg.py +++ b/youtube_dl/postprocessor/ffmpeg.py @@ -26,7 +26,7 @@ def get_version(executable): try: out, err = subprocess.Popen( [executable, '-version'], - stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() except OSError: return False firstline = out.partition(b'\n')[0].decode('ascii', 'ignore') From 579657ad8726ab0cdefd98fbbb28f09fbcf94e96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sun, 26 Oct 2014 19:08:36 +0100 Subject: [PATCH 1165/1761] [soundcloud] Set the 'webpage_url' field for each track For playlists, YoutubeDL would set it to the playlist url. --- youtube_dl/extractor/soundcloud.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/extractor/soundcloud.py b/youtube_dl/extractor/soundcloud.py index c77671fd3..54256e1a2 100644 --- a/youtube_dl/extractor/soundcloud.py +++ b/youtube_dl/extractor/soundcloud.py @@ -141,6 +141,7 @@ class SoundcloudIE(InfoExtractor): 'description': info['description'], 'thumbnail': thumbnail, 'duration': int_or_none(info.get('duration'), 1000), + 'webpage_url': info.get('permalink_url'), } formats = [] if info.get('downloadable', False): From 70b7e3fbb62e9bec12328bb9d506327fe77a85c0 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 20:49:51 +0100 Subject: [PATCH 1166/1761] [generic] Add a test case for direct links with broken HEAD (#4032) --- test/helper.py | 10 ++++++++++ test/test_download.py | 2 ++ youtube_dl/extractor/generic.py | 17 ++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/test/helper.py b/test/helper.py index 2fa45631a..fb8618120 100644 --- a/test/helper.py +++ b/test/helper.py @@ -171,3 +171,13 @@ def assertGreaterEqual(self, got, expected, msg=None): if msg is None: msg = '%r not greater than or equal to %r' % (got, expected) self.assertTrue(got >= expected, msg) + + +def expect_warnings(ydl, warnings_re): + real_warning = ydl.report_warning + + def _report_warning(w): + if not any(re.search(w_re, w) for w_re in warnings_re): + real_warning(w) + + ydl.report_warning = _report_warning diff --git a/test/test_download.py b/test/test_download.py index 8178015ea..608e4528e 100644 --- a/test/test_download.py +++ b/test/test_download.py @@ -8,6 +8,7 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from test.helper import ( assertGreaterEqual, + expect_warnings, get_params, gettestcases, expect_info_dict, @@ -100,6 +101,7 @@ def generator(test_case): if status['status'] == 'finished': finished_hook_called.add(status['filename']) ydl.add_progress_hook(_hook) + expect_warnings(ydl, test_case.get('expected_warnings', [])) def get_tc_filename(tc): return tc.get('file') or ydl.prepare_filename(tc.get('info_dict', {})) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 51dbbc8db..52f286ac6 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -389,8 +389,23 @@ class GenericIE(InfoExtractor): 'title': 'Conversation about Hexagonal Rails Part 1 - ThoughtWorks', 'duration': 1715.0, 'uploader': 'thoughtworks.wistia.com', - }, + }, }, + # Direct download with broken HEAD + { + 'url': 'http://ai-radio.org:8000/radio.opus', + 'info_dict': { + 'id': 'radio', + 'ext': 'opus', + 'title': 'radio', + }, + 'params': { + 'skip_download': True, # infinite live stream + }, + 'expected_warnings': [ + r'501.*Not Implemented' + ], + } ] def report_following_redirect(self, new_url): From 37d66e7f1e5d325802781c69042571968afa1da0 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 20:58:09 +0100 Subject: [PATCH 1167/1761] [generic] Correct call to _webpage_read_full_content --- youtube_dl/extractor/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 52f286ac6..42284f3d5 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -559,7 +559,7 @@ class GenericIE(InfoExtractor): self._downloader.report_warning('Falling back on generic information extractor.') if full_response: - webpage = _webpage_read_content(url, video_id) + webpage = self._webpage_read_content(full_response, url, video_id) else: webpage = self._download_webpage(url, video_id) self.report_extraction(video_id) From 6194bb1419842e908a5694b8f9a666ba97d3ac9c Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 21:00:42 +0100 Subject: [PATCH 1168/1761] [ffmpeg] Make downloader optional (Fixes #4039) --- youtube_dl/postprocessor/ffmpeg.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/youtube_dl/postprocessor/ffmpeg.py b/youtube_dl/postprocessor/ffmpeg.py index 19fc135dc..4b93556af 100644 --- a/youtube_dl/postprocessor/ffmpeg.py +++ b/youtube_dl/postprocessor/ffmpeg.py @@ -42,7 +42,7 @@ class FFmpegPostProcessorError(PostProcessingError): class FFmpegPostProcessor(PostProcessor): - def __init__(self, downloader, deletetempfiles=False): + def __init__(self, downloader=None, deletetempfiles=False): PostProcessor.__init__(self, downloader) self._versions = self.get_versions() self._deletetempfiles = deletetempfiles @@ -56,7 +56,8 @@ class FFmpegPostProcessor(PostProcessor): self._versions[self._executable], REQUIRED_VERSION): warning = u'Your copy of %s is outdated, update %s to version %s or newer if you encounter any errors.' % ( self._executable, self._executable, REQUIRED_VERSION) - self._downloader.report_warning(warning) + if self._downloader: + self._downloader.report_warning(warning) @staticmethod def get_versions(): From 1a253e134ce1f30dd640ba47ffb8fb8a74fe8bed Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 21:03:16 +0100 Subject: [PATCH 1169/1761] [ffmpeg] Fix call to ffprobe (Fixes #4041) --- youtube_dl/postprocessor/ffmpeg.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/youtube_dl/postprocessor/ffmpeg.py b/youtube_dl/postprocessor/ffmpeg.py index 4b93556af..bd2d749f9 100644 --- a/youtube_dl/postprocessor/ffmpeg.py +++ b/youtube_dl/postprocessor/ffmpeg.py @@ -75,6 +75,17 @@ class FFmpegPostProcessor(PostProcessor): return p return None + @property + def _probe_executable(self): + if self._downloader.params.get('prefer_ffmpeg', False): + prefs = ('ffproe', 'avprobe') + else: + prefs = ('avprobe', 'ffprobe') + for p in prefs: + if self._versions[p]: + return p + return None + def _uses_avconv(self): return self._executable == 'avconv' @@ -120,11 +131,12 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor): self._nopostoverwrites = nopostoverwrites def get_audio_codec(self, path): - if not self._exes['ffprobe'] and not self._exes['avprobe']: + + if not self._probe_executable: raise PostProcessingError(u'ffprobe or avprobe not found. Please install one.') try: cmd = [ - self._exes['avprobe'] or self._exes['ffprobe'], + self._probe_executable, '-show_streams', encodeFilename(self._ffmpeg_filename_argument(path), True)] handle = subprocess.Popen(cmd, stderr=compat_subprocess_get_DEVNULL(), stdout=subprocess.PIPE) From 3d6eed9b5224cbcd0f57044f8e09a52a4a7eabfd Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 21:03:38 +0100 Subject: [PATCH 1170/1761] release 2014.10.26.1 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index f5f60cdc3..8eb60c1e2 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.26' +__version__ = '2014.10.26.1' From 50b51830fbeea2e9b2a3235e0c8b6b146f28eb3a Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 21:31:51 +0100 Subject: [PATCH 1171/1761] [ffmpeg] Fix typo --- youtube_dl/postprocessor/ffmpeg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/postprocessor/ffmpeg.py b/youtube_dl/postprocessor/ffmpeg.py index bd2d749f9..4963ffc92 100644 --- a/youtube_dl/postprocessor/ffmpeg.py +++ b/youtube_dl/postprocessor/ffmpeg.py @@ -78,7 +78,7 @@ class FFmpegPostProcessor(PostProcessor): @property def _probe_executable(self): if self._downloader.params.get('prefer_ffmpeg', False): - prefs = ('ffproe', 'avprobe') + prefs = ('ffprobe', 'avprobe') else: prefs = ('avprobe', 'ffprobe') for p in prefs: From 83855f3a1fdf9d344e0b25c757e3eccd9246c2bf Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 21:44:23 +0100 Subject: [PATCH 1172/1761] [livestream:original] Fix RTMP parameters (Fixes #4040) --- youtube_dl/extractor/livestream.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/livestream.py b/youtube_dl/extractor/livestream.py index 516147417..363a12ad0 100644 --- a/youtube_dl/extractor/livestream.py +++ b/youtube_dl/extractor/livestream.py @@ -190,7 +190,8 @@ class LivestreamOriginalIE(InfoExtractor): 'id': video_id, 'title': item.find('title').text, 'url': 'rtmp://extondemand.livestream.com/ondemand', - 'play_path': 'mp4:trans/dv15/mogulus-{0}.mp4'.format(path), + 'play_path': 'trans/dv15/mogulus-{0}'.format(path), + 'player_url': 'http://static.livestream.com/chromelessPlayer/v21/playerapi.swf?hash=5uetk&v=0803&classid=D27CDB6E-AE6D-11cf-96B8-444553540000&jsEnabled=false&wmode=opaque', 'ext': 'flv', 'thumbnail': thumbnail_url, } From bfc2bedcfcbfd531b6f452cae3b7af654ceaab1a Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 21:49:29 +0100 Subject: [PATCH 1173/1761] [youtube] Make confirm_age non-fatal (#4042) --- youtube_dl/extractor/youtube.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index 4ab56e0ac..382d20c5a 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -185,8 +185,8 @@ class YoutubeBaseInfoExtractor(InfoExtractor): self._download_webpage( req, None, - note='Confirming age', errnote='Unable to confirm age') - return True + note='Confirming age', errnote='Unable to confirm age', + fatal=False) def _real_initialize(self): if self._downloader is None: From 77ec444d9a20fb0e3aa1be2941979189d53ebdb3 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 21:49:52 +0100 Subject: [PATCH 1174/1761] release 2014.10.26.2 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 8eb60c1e2..8e5a642a8 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.26.1' +__version__ = '2014.10.26.2' From 526b276fd7199414d199f2913bc794677d0933ac Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 23:11:15 +0100 Subject: [PATCH 1175/1761] [faz] Modernize --- youtube_dl/extractor/faz.py | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/youtube_dl/extractor/faz.py b/youtube_dl/extractor/faz.py index c6ab6952e..f3d45b2be 100644 --- a/youtube_dl/extractor/faz.py +++ b/youtube_dl/extractor/faz.py @@ -1,5 +1,5 @@ # encoding: utf-8 -import re +from __future__ import unicode_literals from .common import InfoExtractor from ..utils import ( @@ -8,42 +8,44 @@ from ..utils import ( class FazIE(InfoExtractor): - IE_NAME = u'faz.net' + IE_NAME = 'faz.net' _VALID_URL = r'https?://www\.faz\.net/multimedia/videos/.*?-(?P\d+)\.html' _TEST = { - u'url': u'http://www.faz.net/multimedia/videos/stockholm-chemie-nobelpreis-fuer-drei-amerikanische-forscher-12610585.html', - u'file': u'12610585.mp4', - u'info_dict': { - u'title': u'Stockholm: Chemie-Nobelpreis für drei amerikanische Forscher', - u'description': u'md5:1453fbf9a0d041d985a47306192ea253', + 'url': 'http://www.faz.net/multimedia/videos/stockholm-chemie-nobelpreis-fuer-drei-amerikanische-forscher-12610585.html', + 'info_dict': { + 'id': '12610585', + 'ext': 'mp4', + 'title': 'Stockholm: Chemie-Nobelpreis für drei amerikanische Forscher', + 'description': 'md5:1453fbf9a0d041d985a47306192ea253', }, } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') - self.to_screen(video_id) + video_id = self._match_id(url) + webpage = self._download_webpage(url, video_id) - config_xml_url = self._search_regex(r'writeFLV\(\'(.+?)\',', webpage, - u'config xml url') - config = self._download_xml(config_xml_url, video_id, - u'Downloading config xml') + config_xml_url = self._search_regex( + r'writeFLV\(\'(.+?)\',', webpage, 'config xml url') + config = self._download_xml( + config_xml_url, video_id, 'Downloading config xml') encodings = config.find('ENCODINGS') formats = [] - for code in ['LOW', 'HIGH', 'HQ']: + for pref, code in enumerate(['LOW', 'HIGH', 'HQ']): encoding = encodings.find(code) if encoding is None: continue encoding_url = encoding.find('FILENAME').text formats.append({ 'url': encoding_url, - 'ext': determine_ext(encoding_url), 'format_id': code.lower(), + 'quality': pref, }) + self._sort_formats(formats) - descr = self._html_search_regex(r'

    (.*?)

    ', webpage, u'description') + descr = self._html_search_regex( + r'

    (.*?)

    ', webpage, 'description', fatal=False) return { 'id': video_id, 'title': self._og_search_title(webpage), From c9f08154a3dbf7272b1373c8e6aeea4a8d92b190 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 23:13:42 +0100 Subject: [PATCH 1176/1761] Remove unused imports --- youtube_dl/extractor/audiomack.py | 2 +- youtube_dl/extractor/br.py | 2 -- youtube_dl/extractor/cliphunter.py | 5 +---- youtube_dl/extractor/faz.py | 3 --- youtube_dl/extractor/nhl.py | 1 - youtube_dl/extractor/sportbox.py | 1 - youtube_dl/extractor/vimeo.py | 2 -- youtube_dl/postprocessor/ffmpeg.py | 1 - 8 files changed, 2 insertions(+), 15 deletions(-) diff --git a/youtube_dl/extractor/audiomack.py b/youtube_dl/extractor/audiomack.py index 57446fddd..6232d2cd0 100644 --- a/youtube_dl/extractor/audiomack.py +++ b/youtube_dl/extractor/audiomack.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals from .common import InfoExtractor from .soundcloud import SoundcloudIE from ..utils import ExtractorError -import datetime + import time diff --git a/youtube_dl/extractor/br.py b/youtube_dl/extractor/br.py index 2e277c8c3..45ba51732 100644 --- a/youtube_dl/extractor/br.py +++ b/youtube_dl/extractor/br.py @@ -1,8 +1,6 @@ # coding: utf-8 from __future__ import unicode_literals -import re - from .common import InfoExtractor from ..utils import ( ExtractorError, diff --git a/youtube_dl/extractor/cliphunter.py b/youtube_dl/extractor/cliphunter.py index d4227e6eb..2edab90a3 100644 --- a/youtube_dl/extractor/cliphunter.py +++ b/youtube_dl/extractor/cliphunter.py @@ -4,7 +4,6 @@ import json import re from .common import InfoExtractor -from ..utils import int_or_none _translation_table = { @@ -39,9 +38,7 @@ class CliphunterIE(InfoExtractor): } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') - + video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) video_title = self._search_regex( diff --git a/youtube_dl/extractor/faz.py b/youtube_dl/extractor/faz.py index f3d45b2be..3c39ca451 100644 --- a/youtube_dl/extractor/faz.py +++ b/youtube_dl/extractor/faz.py @@ -2,9 +2,6 @@ from __future__ import unicode_literals from .common import InfoExtractor -from ..utils import ( - determine_ext, -) class FazIE(InfoExtractor): diff --git a/youtube_dl/extractor/nhl.py b/youtube_dl/extractor/nhl.py index d66c2c6f8..82af6e330 100644 --- a/youtube_dl/extractor/nhl.py +++ b/youtube_dl/extractor/nhl.py @@ -7,7 +7,6 @@ from .common import InfoExtractor from ..utils import ( compat_urlparse, compat_urllib_parse, - determine_ext, unified_strdate, ) diff --git a/youtube_dl/extractor/sportbox.py b/youtube_dl/extractor/sportbox.py index b9cd35109..becdf658f 100644 --- a/youtube_dl/extractor/sportbox.py +++ b/youtube_dl/extractor/sportbox.py @@ -7,7 +7,6 @@ from .common import InfoExtractor from ..utils import ( parse_duration, parse_iso8601, - int_or_none, ) diff --git a/youtube_dl/extractor/vimeo.py b/youtube_dl/extractor/vimeo.py index 07959d3fe..5839c550d 100644 --- a/youtube_dl/extractor/vimeo.py +++ b/youtube_dl/extractor/vimeo.py @@ -8,13 +8,11 @@ import itertools from .common import InfoExtractor from .subtitles import SubtitlesInfoExtractor from ..utils import ( - clean_html, compat_HTTPError, compat_urllib_parse, compat_urllib_request, compat_urlparse, ExtractorError, - get_element_by_attribute, InAdvancePagedList, int_or_none, RegexNotFoundError, diff --git a/youtube_dl/postprocessor/ffmpeg.py b/youtube_dl/postprocessor/ffmpeg.py index 4963ffc92..083c79592 100644 --- a/youtube_dl/postprocessor/ffmpeg.py +++ b/youtube_dl/postprocessor/ffmpeg.py @@ -8,7 +8,6 @@ import time from .common import AudioConversionError, PostProcessor from ..utils import ( - check_executable, compat_subprocess_get_DEVNULL, encodeArgument, encodeFilename, From 2bcae58d46b88200a2247a7e2bee999f459f75c4 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 23:23:10 +0100 Subject: [PATCH 1177/1761] [srmediathek] New extractor --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/srmediathek.py | 43 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 youtube_dl/extractor/srmediathek.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 8e31de93d..17ab49283 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -355,6 +355,7 @@ from .spike import SpikeIE from .sport5 import Sport5IE from .sportbox import SportBoxIE from .sportdeutschland import SportDeutschlandIE +from .srmediathek import SRMediathekIE from .stanfordoc import StanfordOpenClassroomIE from .steam import SteamIE from .streamcloud import StreamcloudIE diff --git a/youtube_dl/extractor/srmediathek.py b/youtube_dl/extractor/srmediathek.py new file mode 100644 index 000000000..26bf9e34c --- /dev/null +++ b/youtube_dl/extractor/srmediathek.py @@ -0,0 +1,43 @@ +# encoding: utf-8 +from __future__ import unicode_literals + +import json + +from .common import InfoExtractor +from ..utils import js_to_json + + +class SRMediathekIE(InfoExtractor): + IE_NAME = 'Süddeutscher Rundfunk' + _VALID_URL = r'https?://sr-mediathek\.sr-online\.de/index\.php\?.*?&id=(?P[0-9]+)' + + _TEST = { + 'url': 'http://sr-mediathek.sr-online.de/index.php?seite=7&id=28455', + 'info_dict': { + 'id': '28455', + 'ext': 'mp4', + 'title': 'sportarena (26.10.2014)', + 'description': 'Ringen: KSV Köllerbach gegen Aachen-Walheim; Frauen-Fußball: 1. FC Saarbrücken gegen Sindelfingen; Motorsport: Rallye in Losheim; dazu: Interview mit Timo Bernhard; Turnen: TG Saar; Reitsport: Deutscher Voltigier-Pokal; Badminton: Interview mit Michael Fuchs ', + 'thumbnail': 're:^https?://.*\.jpg$', + }, + } + + def _real_extract(self, url): + video_id = self._match_id(url) + webpage = self._download_webpage(url, video_id) + + urls = json.loads(js_to_json(self._search_regex( + r'var mediaURLs\s*=\s*(.*?);\n', webpage, 'video URLs'))) + formats = [{'url': url} for url in urls] + self._sort_formats(formats) + + title = json.loads(js_to_json(self._search_regex( + r'var mediaTitles\s*=\s*(.*?);\n', webpage, 'title')))[0] + + return { + 'id': video_id, + 'title': title, + 'formats': formats, + 'description': self._og_search_description(webpage), + 'thumbnail': self._og_search_thumbnail(webpage), + } From cf501a23d29e13e8bcfac5f8ce10ac96d097f6e0 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 26 Oct 2014 23:23:53 +0100 Subject: [PATCH 1178/1761] [srmediathek] Correct IE_NAME/IE_DESC --- youtube_dl/extractor/srmediathek.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/srmediathek.py b/youtube_dl/extractor/srmediathek.py index 26bf9e34c..d92d14d65 100644 --- a/youtube_dl/extractor/srmediathek.py +++ b/youtube_dl/extractor/srmediathek.py @@ -8,7 +8,7 @@ from ..utils import js_to_json class SRMediathekIE(InfoExtractor): - IE_NAME = 'Süddeutscher Rundfunk' + IE_DESC = 'Süddeutscher Rundfunk' _VALID_URL = r'https?://sr-mediathek\.sr-online\.de/index\.php\?.*?&id=(?P[0-9]+)' _TEST = { From 8d11b59bbb2cc4cdf10b2659c04589fd81b9c6f9 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:05:34 +0100 Subject: [PATCH 1179/1761] [ynet] Remove test md5sums These fluctuate regularly. --- youtube_dl/extractor/ynet.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/youtube_dl/extractor/ynet.py b/youtube_dl/extractor/ynet.py index 944d7da38..9cd7989cc 100644 --- a/youtube_dl/extractor/ynet.py +++ b/youtube_dl/extractor/ynet.py @@ -13,7 +13,6 @@ class YnetIE(InfoExtractor): _TESTS = [ { 'url': 'http://hot.ynet.co.il/home/0,7340,L-11659-99244,00.html', - 'md5': '4b29cb57c3dddd57642b3f051f535b07', 'info_dict': { 'id': 'L-11659-99244', 'ext': 'flv', @@ -22,7 +21,6 @@ class YnetIE(InfoExtractor): } }, { 'url': 'http://hot.ynet.co.il/home/0,7340,L-8859-84418,00.html', - 'md5': '8194c2ea221e9a639cac96b6b0753dc5', 'info_dict': { 'id': 'L-8859-84418', 'ext': 'flv', From f46a8702ccfcb221b3e01ca95553be92af3f8f4e Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:06:47 +0100 Subject: [PATCH 1180/1761] [youtube:playlist] Fix test title --- youtube_dl/extractor/youtube.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index 382d20c5a..40fe4662a 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -1057,7 +1057,7 @@ class YoutubePlaylistIE(YoutubeBaseInfoExtractor): 'note': 'issue #673', 'url': 'PLBB231211A4F62143', 'info_dict': { - 'title': 'Team Fortress 2 (Class-based LP)', + 'title': '[OLD]Team Fortress 2 (Class-based LP)', }, 'playlist_mincount': 26, }, { From 3adba6fa2ae1af3c90e9c6623161b223697cc874 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:08:37 +0100 Subject: [PATCH 1181/1761] [xtube] Fix test description --- youtube_dl/extractor/xtube.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/xtube.py b/youtube_dl/extractor/xtube.py index 273d93d9e..c3bb9b2cf 100644 --- a/youtube_dl/extractor/xtube.py +++ b/youtube_dl/extractor/xtube.py @@ -20,7 +20,7 @@ class XTubeIE(InfoExtractor): 'id': 'kVTUy_G222_', 'ext': 'mp4', 'title': 'strange erotica', - 'description': 'surreal gay themed erotica...almost an ET kind of thing', + 'description': 'http://www.xtube.com an ET kind of thing', 'uploader': 'greenshowers', 'duration': 450, 'age_limit': 18, From 7706927370f7b2ec9b759961ce5bf34b24ef5ce5 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:11:34 +0100 Subject: [PATCH 1182/1761] [vine:user] Adapt test to changed list size --- youtube_dl/extractor/vine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/vine.py b/youtube_dl/extractor/vine.py index e7754158d..42995226e 100644 --- a/youtube_dl/extractor/vine.py +++ b/youtube_dl/extractor/vine.py @@ -70,7 +70,7 @@ class VineUserIE(InfoExtractor): 'info_dict': { 'id': 'Visa', }, - 'playlist_mincount': 47, + 'playlist_mincount': 46, } def _real_extract(self, url): From 9dec99303d589bdf78493ee124f3ae230d8cd606 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:13:40 +0100 Subject: [PATCH 1183/1761] [vimeo:review] Fix test title --- youtube_dl/extractor/vimeo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/vimeo.py b/youtube_dl/extractor/vimeo.py index 5839c550d..d9cad0ea5 100644 --- a/youtube_dl/extractor/vimeo.py +++ b/youtube_dl/extractor/vimeo.py @@ -512,7 +512,7 @@ class VimeoReviewIE(InfoExtractor): 'info_dict': { 'id': '91613211', 'ext': 'mp4', - 'title': 'Death by dogma versus assembling agile - Sander Hoogendoorn', + 'title': 're:(?i)^Death by dogma versus assembling agile . Sander Hoogendoorn', 'uploader': 'DevWeek Events', 'duration': 2773, 'thumbnail': 're:^https?://.*\.jpg$', From 3d6047113ceade1c3588b46fa6a65ee360643b02 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:14:52 +0100 Subject: [PATCH 1184/1761] [vgtv] Simplify --- youtube_dl/extractor/vgtv.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/youtube_dl/extractor/vgtv.py b/youtube_dl/extractor/vgtv.py index 964470070..bb6cc83b5 100644 --- a/youtube_dl/extractor/vgtv.py +++ b/youtube_dl/extractor/vgtv.py @@ -67,9 +67,7 @@ class VGTVIE(InfoExtractor): ] def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') - + video_id = self._match_id(url) data = self._download_json( 'http://svp.vg.no/svp/api/v1/vgtv/assets/%s?appName=vgtv-website' % video_id, video_id, 'Downloading media JSON') From 6009b69f81ce7320a69baf1172a61e7e36ea8096 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:15:42 +0100 Subject: [PATCH 1185/1761] [vgtv] Fix test title --- youtube_dl/extractor/vgtv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/vgtv.py b/youtube_dl/extractor/vgtv.py index bb6cc83b5..d3fa70e0e 100644 --- a/youtube_dl/extractor/vgtv.py +++ b/youtube_dl/extractor/vgtv.py @@ -17,7 +17,7 @@ class VGTVIE(InfoExtractor): 'info_dict': { 'id': '84196', 'ext': 'mp4', - 'title': 'Hevnen er søt episode 10: Abu', + 'title': 'Hevnen er søt episode 1:10 - Abu', 'description': 'md5:e25e4badb5f544b04341e14abdc72234', 'thumbnail': 're:^https?://.*\.jpg', 'duration': 648.000, From 446a03bd96d99d99b36f1dbfe0617033327f463f Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:18:10 +0100 Subject: [PATCH 1186/1761] [ustream:channel] Change test playlist size (Seems to have been limited that way on the website as well) --- youtube_dl/extractor/ustream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/ustream.py b/youtube_dl/extractor/ustream.py index 994b60a76..cee1ea8f6 100644 --- a/youtube_dl/extractor/ustream.py +++ b/youtube_dl/extractor/ustream.py @@ -72,7 +72,7 @@ class UstreamChannelIE(InfoExtractor): 'info_dict': { 'id': '10874166', }, - 'playlist_mincount': 54, + 'playlist_mincount': 17, } def _real_extract(self, url): From 94f052cbf458ba816e95c1f73cae7bcd63c9e549 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:19:10 +0100 Subject: [PATCH 1187/1761] [syfy] Remove test checksum We have the minsize test now. --- youtube_dl/extractor/syfy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/youtube_dl/extractor/syfy.py b/youtube_dl/extractor/syfy.py index f76b6e2b2..5ca079f88 100644 --- a/youtube_dl/extractor/syfy.py +++ b/youtube_dl/extractor/syfy.py @@ -10,7 +10,6 @@ class SyfyIE(InfoExtractor): _TESTS = [{ 'url': 'http://www.syfy.com/videos/Robot%20Combat%20League/Behind%20the%20Scenes/vid:2631458', - 'md5': 'e07de1d52c7278adbb9b9b1c93a66849', 'info_dict': { 'id': 'NmqMrGnXvmO1', 'ext': 'flv', From 8d32abff9e3d56bf74eb6eec8284623a94f4551f Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:20:54 +0100 Subject: [PATCH 1188/1761] [ruhd] Simplify --- youtube_dl/extractor/ruhd.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/youtube_dl/extractor/ruhd.py b/youtube_dl/extractor/ruhd.py index 55b58e5e6..0e470e73f 100644 --- a/youtube_dl/extractor/ruhd.py +++ b/youtube_dl/extractor/ruhd.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -import re - from .common import InfoExtractor @@ -21,19 +19,20 @@ class RUHDIE(InfoExtractor): } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') - + video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) video_url = self._html_search_regex( r'([^<]+)   RUHD.ru - Видео Высокого качества №1 в России!', webpage, 'title') + r'([^<]+)   RUHD.ru - Видео Высокого качества №1 в России!', + webpage, 'title') description = self._html_search_regex( - r'(?s)
    (.+?)', webpage, 'description', fatal=False) + r'(?s)
    (.+?)', + webpage, 'description', fatal=False) thumbnail = self._html_search_regex( - r' Date: Mon, 27 Oct 2014 00:33:35 +0100 Subject: [PATCH 1189/1761] [pornhub] Modernize and fix test definition --- youtube_dl/extractor/pornhub.py | 13 ++++++------- youtube_dl/extractor/rtlnow.py | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/youtube_dl/extractor/pornhub.py b/youtube_dl/extractor/pornhub.py index 4118ee956..618e8f5dd 100644 --- a/youtube_dl/extractor/pornhub.py +++ b/youtube_dl/extractor/pornhub.py @@ -16,13 +16,14 @@ from ..aes import ( class PornHubIE(InfoExtractor): - _VALID_URL = r'^(?:https?://)?(?:www\.)?(?Ppornhub\.com/view_video\.php\?viewkey=(?P[0-9a-f]+))' + _VALID_URL = r'^https?://(?:www\.)?pornhub\.com/view_video\.php\?viewkey=(?P[0-9a-f]+)' _TEST = { 'url': 'http://www.pornhub.com/view_video.php?viewkey=648719015', - 'file': '648719015.mp4', 'md5': '882f488fa1f0026f023f33576004a2ed', 'info_dict': { - "uploader": "BABES-COM", + 'id': '648719015', + 'ext': 'mp4', + "uploader": "Babes", "title": "Seductive Indian beauty strips down and fingers her pink pussy", "age_limit": 18 } @@ -35,9 +36,7 @@ class PornHubIE(InfoExtractor): return count def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('videoid') - url = 'http://www.' + mobj.group('url') + video_id = self._match_id(url) req = compat_urllib_request.Request(url) req.add_header('Cookie', 'age_verified=1') @@ -45,7 +44,7 @@ class PornHubIE(InfoExtractor): video_title = self._html_search_regex(r'

    ]+>([^<]+)', webpage, 'title') video_uploader = self._html_search_regex( - r'(?s)From: .+?<(?:a href="/users/|]+>(.+?)<', webpage, 'uploader', fatal=False) thumbnail = self._html_search_regex(r'"image_url":"([^"]+)', webpage, 'thumbnail', fatal=False) if thumbnail: diff --git a/youtube_dl/extractor/rtlnow.py b/youtube_dl/extractor/rtlnow.py index a45884b25..1a41cbe40 100644 --- a/youtube_dl/extractor/rtlnow.py +++ b/youtube_dl/extractor/rtlnow.py @@ -81,7 +81,7 @@ class RTLnowIE(InfoExtractor): 'id': '99205', 'ext': 'flv', 'title': 'Medicopter 117 - Angst!', - 'description': 'md5:895b1df01639b5f61a04fc305a5cb94d', + 'description': 're:^Im Therapiezentrum \'Sonnalm\' kommen durch eine Unachtsamkeit die für die B.handlung mit Phobikern gehaltenen Voglespinnen frei\. Eine Ausreißerin', 'thumbnail': 'http://autoimg.static-fra.de/superrtlnow/287529/1500x1500/image2.jpg', 'upload_date': '20080928', 'duration': 2691, From f744c0f3984cb8bb09f16bc4ef1d3c9c356b1b33 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:39:39 +0100 Subject: [PATCH 1190/1761] [test_download] Improve error message --- test/test_download.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/test_download.py b/test/test_download.py index 608e4528e..75e0bb289 100644 --- a/test/test_download.py +++ b/test/test_download.py @@ -185,7 +185,9 @@ def generator(test_case): md5_for_file = _file_md5(tc_filename) self.assertEqual(md5_for_file, tc['md5']) info_json_fn = os.path.splitext(tc_filename)[0] + '.info.json' - self.assertTrue(os.path.exists(info_json_fn)) + self.assertTrue( + os.path.exists(info_json_fn), + 'Missing info file %s' % info_json_fn) with io.open(info_json_fn, encoding='utf-8') as infof: info_dict = json.load(infof) From 640743233389714dda8a3ccb01cf7335e7b43c37 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:40:07 +0100 Subject: [PATCH 1191/1761] [Makefile] remove temporary files in clean target --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2da92863f..3e1debc7e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ all: youtube-dl README.md README.txt youtube-dl.1 youtube-dl.bash-completion youtube-dl.zsh youtube-dl.fish clean: - rm -rf youtube-dl.1.temp.md youtube-dl.1 youtube-dl.bash-completion README.txt MANIFEST build/ dist/ .coverage cover/ youtube-dl.tar.gz youtube-dl.zsh youtube-dl.fish + rm -rf youtube-dl.1.temp.md youtube-dl.1 youtube-dl.bash-completion README.txt MANIFEST build/ dist/ .coverage cover/ youtube-dl.tar.gz youtube-dl.zsh youtube-dl.fish *.dump *.part cleanall: clean rm -f youtube-dl youtube-dl.exe From 2e9ff8f36284c43d9f98e19fa58e10ce5bd5eece Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:44:27 +0100 Subject: [PATCH 1192/1761] [gorillavid] Fix test title --- youtube_dl/extractor/gorillavid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/gorillavid.py b/youtube_dl/extractor/gorillavid.py index 45cca1d24..e21e57510 100644 --- a/youtube_dl/extractor/gorillavid.py +++ b/youtube_dl/extractor/gorillavid.py @@ -46,9 +46,9 @@ class GorillaVidIE(InfoExtractor): 'info_dict': { 'id': '3rso4kdn6f9m', 'ext': 'mp4', - 'title': 'Micro Pig piglets ready on 16th July 2009', + 'title': 'Micro Pig piglets ready on 16th July 2009-bG0PdrCdxUc', 'thumbnail': 're:http://.*\.jpg', - }, + } }, { 'url': 'http://movpod.in/0wguyyxi1yca', 'only_matching': True, From d6d9186f0d12e226ab1b908c66d67e14adb88aea Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:45:15 +0100 Subject: [PATCH 1193/1761] [generic] Fix test title --- youtube_dl/extractor/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 42284f3d5..35a7664b2 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -325,7 +325,7 @@ class GenericIE(InfoExtractor): 'ext': 'mp4', 'age_limit': 18, 'uploader': 'www.handjobhub.com', - 'title': 'Busty Blonde Siri Tit Fuck While Wank at Handjob Hub', + 'title': 'Busty Blonde Siri Tit Fuck While Wank at HandjobHub.com', } }, # RSS feed From 586f7082ef279049bf8a774836556b0a72be7a62 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:46:34 +0100 Subject: [PATCH 1194/1761] [francetv] Remove changing md5sum --- youtube_dl/extractor/francetv.py | 1 - 1 file changed, 1 deletion(-) diff --git a/youtube_dl/extractor/francetv.py b/youtube_dl/extractor/francetv.py index 566e20d76..35d7d15e1 100644 --- a/youtube_dl/extractor/francetv.py +++ b/youtube_dl/extractor/francetv.py @@ -93,7 +93,6 @@ class FranceTvInfoIE(FranceTVBaseInfoExtractor): _TESTS = [{ 'url': 'http://www.francetvinfo.fr/replay-jt/france-3/soir-3/jt-grand-soir-3-lundi-26-aout-2013_393427.html', - 'md5': '9cecf35f99c4079c199e9817882a9a1c', 'info_dict': { 'id': '84981923', 'ext': 'flv', From 15956b5aa1867e9511d5edeebc5d4e9e70ed39c0 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 00:50:22 +0100 Subject: [PATCH 1195/1761] [promptfile] Fix check for deleted videos --- youtube_dl/extractor/promptfile.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/youtube_dl/extractor/promptfile.py b/youtube_dl/extractor/promptfile.py index 463e85501..7fcde086c 100644 --- a/youtube_dl/extractor/promptfile.py +++ b/youtube_dl/extractor/promptfile.py @@ -14,7 +14,6 @@ from ..utils import ( class PromptFileIE(InfoExtractor): _VALID_URL = r'https?://(?:www\.)?promptfile\.com/l/(?P[0-9A-Z\-]+)' - _FILE_NOT_FOUND_REGEX = r'.+

    [^-]' _TEST = { 'url': 'http://www.promptfile.com/l/D21B4746E9-F01462F0FF', 'md5': 'd1451b6302da7215485837aaea882c4c', @@ -27,11 +26,10 @@ class PromptFileIE(InfoExtractor): } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') + video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) - if re.search(self._FILE_NOT_FOUND_REGEX, webpage) is not None: + if re.search(r'(?!We are).+
    [^-]', webpage) is not None: raise ExtractorError('Video %s does not exist' % video_id, expected=True) From 10e3d734723def2d91bdd3d02b85a149c056dcfb Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 01:14:17 +0100 Subject: [PATCH 1196/1761] [nbc] Fix ThePlatform embedded videos --- youtube_dl/extractor/nbc.py | 7 +++--- youtube_dl/extractor/theplatform.py | 34 +++++++++++++++-------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/youtube_dl/extractor/nbc.py b/youtube_dl/extractor/nbc.py index e75ab7c39..7b5449031 100644 --- a/youtube_dl/extractor/nbc.py +++ b/youtube_dl/extractor/nbc.py @@ -26,8 +26,7 @@ class NBCIE(InfoExtractor): } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') + video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) theplatform_url = self._search_regex('class="video-player video-player-full" data-mpx-url="(.*?)"', webpage, 'theplatform url') if theplatform_url.startswith('//'): @@ -57,7 +56,7 @@ class NBCNewsIE(InfoExtractor): 'md5': 'b2421750c9f260783721d898f4c42063', 'info_dict': { 'id': 'I1wpAI_zmhsQ', - 'ext': 'flv', + 'ext': 'mp4', 'title': 'How Twitter Reacted To The Snowden Interview', 'description': 'md5:65a0bd5d76fe114f3c2727aa3a81fe64', }, @@ -97,6 +96,8 @@ class NBCNewsIE(InfoExtractor): ] for base_url in base_urls: + if not base_url: + continue playlist_url = base_url + '?form=MPXNBCNewsAPI' all_videos = self._download_json(playlist_url, title)['videos'] diff --git a/youtube_dl/extractor/theplatform.py b/youtube_dl/extractor/theplatform.py index 0be793b1c..a04925633 100644 --- a/youtube_dl/extractor/theplatform.py +++ b/youtube_dl/extractor/theplatform.py @@ -6,6 +6,7 @@ import json from .common import InfoExtractor from ..utils import ( compat_str, + determine_ext, ExtractorError, xpath_with_ns, ) @@ -34,10 +35,21 @@ class ThePlatformIE(InfoExtractor): 'skip_download': True, }, } + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + if mobj.group('config'): + config_url = url+ '&form=json' + config_url = config_url.replace('swf/', 'config/') + config_url = config_url.replace('onsite/', 'onsite/config/') + config = self._download_json(config_url, video_id, 'Downloading config') + smil_url = config['releaseUrl'] + '&format=SMIL&formats=MPEG4&manifest=f4m' + else: + smil_url = ('http://link.theplatform.com/s/dJ5BDC/{0}/meta.smil?' + 'format=smil&mbr=true'.format(video_id)) + - def _get_info(self, video_id, smil_url): meta = self._download_xml(smil_url, video_id) - try: error_msg = next( n.attrib['abstract'] @@ -89,10 +101,14 @@ class ThePlatformIE(InfoExtractor): for f in switch.findall(_x('smil:video')): attr = f.attrib vbr = int(attr['system-bitrate']) // 1000 + ext = determine_ext(attr['src']) + if ext == 'once': + ext = 'mp4' formats.append({ 'format_id': compat_str(vbr), 'url': attr['src'], 'vbr': vbr, + 'ext': ext, }) self._sort_formats(formats) @@ -104,17 +120,3 @@ class ThePlatformIE(InfoExtractor): 'thumbnail': info['defaultThumbnailUrl'], 'duration': info['duration']//1000, } - - def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') - if mobj.group('config'): - config_url = url+ '&form=json' - config_url = config_url.replace('swf/', 'config/') - config_url = config_url.replace('onsite/', 'onsite/config/') - config = self._download_json(config_url, video_id, 'Downloading config') - smil_url = config['releaseUrl'] + '&format=SMIL&formats=MPEG4&manifest=f4m' - else: - smil_url = ('http://link.theplatform.com/s/dJ5BDC/{0}/meta.smil?' - 'format=smil&mbr=true'.format(video_id)) - return self._get_info(video_id, smil_url) From 4a6c94288ae42402f4a61a924318cedc5d1bb511 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 01:16:18 +0100 Subject: [PATCH 1197/1761] [kickstarter] Simplify and fix test case --- youtube_dl/extractor/kickstarter.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/youtube_dl/extractor/kickstarter.py b/youtube_dl/extractor/kickstarter.py index 56a76380c..827091e60 100644 --- a/youtube_dl/extractor/kickstarter.py +++ b/youtube_dl/extractor/kickstarter.py @@ -1,8 +1,6 @@ # encoding: utf-8 from __future__ import unicode_literals -import re - from .common import InfoExtractor @@ -21,22 +19,17 @@ class KickStarterIE(InfoExtractor): }, { 'note': 'Embedded video (not using the native kickstarter video service)', 'url': 'https://www.kickstarter.com/projects/597507018/pebble-e-paper-watch-for-iphone-and-android/posts/659178', - 'playlist': [ - { - 'info_dict': { - 'id': '78704821', - 'ext': 'mp4', - 'uploader_id': 'pebble', - 'uploader': 'Pebble Technology', - 'title': 'Pebble iOS Notifications', - } - } - ], + 'info_dict': { + 'id': '78704821', + 'ext': 'mp4', + 'uploader_id': 'pebble', + 'uploader': 'Pebble Technology', + 'title': 'Pebble iOS Notifications', + } }] def _real_extract(self, url): - m = re.match(self._VALID_URL, url) - video_id = m.group('id') + video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) title = self._html_search_regex( From ecfe623422f61df886b83e6eae98a0e4a297802e Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 01:33:49 +0100 Subject: [PATCH 1198/1761] [heise] Fix extraction Now they use an XML format instead of JSON. --- youtube_dl/extractor/heise.py | 48 +++++++++++++++-------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/youtube_dl/extractor/heise.py b/youtube_dl/extractor/heise.py index f97b1e085..d41c0413f 100644 --- a/youtube_dl/extractor/heise.py +++ b/youtube_dl/extractor/heise.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals from .common import InfoExtractor from ..utils import ( get_meta_content, + int_or_none, parse_iso8601, ) @@ -28,20 +29,26 @@ class HeiseIE(InfoExtractor): 'timestamp': 1411812600, 'upload_date': '20140927', 'description': 'In uplink-Episode 3.3 geht es darum, wie man sich von Cloud-Anbietern emanzipieren kann, worauf man beim Kauf einer Tastatur achten sollte und was Smartphones über uns verraten.', + 'thumbnail': 're:https?://.*\.jpg$', } } def _real_extract(self, url): video_id = self._match_id(url) - webpage = self._download_webpage(url, video_id) - json_url = self._search_regex( - r'json_url:\s*"([^"]+)"', webpage, 'json URL') - config = self._download_json(json_url, video_id) + + container_id = self._search_regex( + r'
    Date: Mon, 27 Oct 2014 02:14:07 +0100 Subject: [PATCH 1199/1761] [zdf] Simplify --- youtube_dl/extractor/zdf.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/youtube_dl/extractor/zdf.py b/youtube_dl/extractor/zdf.py index 3b1ac4e9f..52b066ce3 100644 --- a/youtube_dl/extractor/zdf.py +++ b/youtube_dl/extractor/zdf.py @@ -11,7 +11,7 @@ from ..utils import ( class ZDFIE(InfoExtractor): - _VALID_URL = r'^https?://www\.zdf\.de/ZDFmediathek(?P#)?/(.*beitrag/(?:video/)?)(?P[0-9]+)(?:/[^/?]+)?(?:\?.*)?' + _VALID_URL = r'^https?://www\.zdf\.de/ZDFmediathek(?P#)?/(.*beitrag/(?:video/)?)(?P[0-9]+)(?:/[^/?]+)?(?:\?.*)?' _TEST = { 'url': 'http://www.zdf.de/ZDFmediathek/beitrag/video/2037704/ZDFspezial---Ende-des-Machtpokers--?bc=sts;stt', @@ -29,8 +29,7 @@ class ZDFIE(InfoExtractor): } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('video_id') + video_id = self._match_id(url) xml_url = 'http://www.zdf.de/ZDFmediathek/xmlservice/web/beitragsDetails?ak=web&id=%s' % video_id doc = self._download_xml( From bf7aa6301b30156d3badbd67a5a12bdb500a8366 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 02:26:05 +0100 Subject: [PATCH 1200/1761] [fktv] Modernize --- youtube_dl/extractor/fktv.py | 42 +++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/youtube_dl/extractor/fktv.py b/youtube_dl/extractor/fktv.py index d7048c8c1..990bee8ba 100644 --- a/youtube_dl/extractor/fktv.py +++ b/youtube_dl/extractor/fktv.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import re import random import json @@ -11,15 +13,16 @@ from ..utils import ( class FKTVIE(InfoExtractor): - IE_NAME = u'fernsehkritik.tv' - _VALID_URL = r'(?:http://)?(?:www\.)?fernsehkritik\.tv/folge-(?P[0-9]+)(?:/.*)?' + IE_NAME = 'fernsehkritik.tv' + _VALID_URL = r'http://(?:www\.)?fernsehkritik\.tv/folge-(?P[0-9]+)(?:/.*)?' _TEST = { - u'url': u'http://fernsehkritik.tv/folge-1', - u'file': u'00011.flv', - u'info_dict': { - u'title': u'Folge 1 vom 10. April 2007', - u'description': u'md5:fb4818139c7cfe6907d4b83412a6864f', + 'url': 'http://fernsehkritik.tv/folge-1', + 'info_dict': { + 'id': '00011', + 'ext': 'flv', + 'title': 'Folge 1 vom 10. April 2007', + 'description': 'md5:fb4818139c7cfe6907d4b83412a6864f', }, } @@ -32,7 +35,7 @@ class FKTVIE(InfoExtractor): start_webpage = self._download_webpage('http://fernsehkritik.tv/folge-%d/Start' % episode, episode) playlist = self._search_regex(r'playlist = (\[.*?\]);', start_webpage, - u'playlist', flags=re.DOTALL) + 'playlist', flags=re.DOTALL) files = json.loads(re.sub('{[^{}]*?}', '{}', playlist)) # TODO: return a single multipart video videos = [] @@ -42,7 +45,6 @@ class FKTVIE(InfoExtractor): videos.append({ 'id': video_id, 'url': video_url, - 'ext': determine_ext(video_url), 'title': clean_html(get_element_by_id('eptitle', start_webpage)), 'description': clean_html(get_element_by_id('contentlist', start_webpage)), 'thumbnail': video_thumbnail @@ -51,14 +53,15 @@ class FKTVIE(InfoExtractor): class FKTVPosteckeIE(InfoExtractor): - IE_NAME = u'fernsehkritik.tv:postecke' - _VALID_URL = r'(?:http://)?(?:www\.)?fernsehkritik\.tv/inline-video/postecke\.php\?(.*&)?ep=(?P[0-9]+)(&|$)' + IE_NAME = 'fernsehkritik.tv:postecke' + _VALID_URL = r'http://(?:www\.)?fernsehkritik\.tv/inline-video/postecke\.php\?(.*&)?ep=(?P[0-9]+)(&|$)' _TEST = { - u'url': u'http://fernsehkritik.tv/inline-video/postecke.php?iframe=true&width=625&height=440&ep=120', - u'file': u'0120.flv', - u'md5': u'262f0adbac80317412f7e57b4808e5c4', - u'info_dict': { - u"title": u"Postecke 120" + 'url': 'http://fernsehkritik.tv/inline-video/postecke.php?iframe=true&width=625&height=440&ep=120', + 'md5': '262f0adbac80317412f7e57b4808e5c4', + 'info_dict': { + 'id': '0120', + 'ext': 'flv', + 'title': 'Postecke 120', } } @@ -71,8 +74,7 @@ class FKTVPosteckeIE(InfoExtractor): video_url = 'http://dl%d.fernsehkritik.tv/postecke/postecke%d.flv' % (server, episode) video_title = 'Postecke %d' % episode return { - 'id': video_id, - 'url': video_url, - 'ext': determine_ext(video_url), - 'title': video_title, + 'id': video_id, + 'url': video_url, + 'title': video_title, } From 8112d4b28429a4319bc3d9d111b69fa62e514de3 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 02:27:49 +0100 Subject: [PATCH 1201/1761] [lrt] Modernize --- youtube_dl/extractor/lrt.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/youtube_dl/extractor/lrt.py b/youtube_dl/extractor/lrt.py index db5df4078..d72d470aa 100644 --- a/youtube_dl/extractor/lrt.py +++ b/youtube_dl/extractor/lrt.py @@ -32,9 +32,7 @@ class LRTIE(InfoExtractor): } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') - + video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) title = remove_end(self._og_search_title(webpage), ' - LRT') From 81515ad9f674597e0d41be6acfcb8592f2230f32 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 02:28:37 +0100 Subject: [PATCH 1202/1761] [extractor/common] Improve m3u8 output --- youtube_dl/extractor/common.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index e1bd6bb49..b77db52f7 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -689,7 +689,10 @@ class InfoExtractor(object): if re.match(r'^https?://', u) else compat_urlparse.urljoin(m3u8_url, u)) - m3u8_doc = self._download_webpage(m3u8_url, video_id) + m3u8_doc = self._download_webpage( + m3u8_url, video_id, + note='Downloading m3u8 information', + errnote='Failed to download m3u8 information') last_info = None kv_rex = re.compile( r'(?P[a-zA-Z_-]+)=(?P"[^"]+"|[^",]+)(?:,|$)') From b0fb6d4db1ed19dfa3a38ee5fd1d38e6227c3d93 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 02:32:44 +0100 Subject: [PATCH 1203/1761] [ku6] Modernize --- youtube_dl/extractor/ku6.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/youtube_dl/extractor/ku6.py b/youtube_dl/extractor/ku6.py index 484239b19..89013e522 100644 --- a/youtube_dl/extractor/ku6.py +++ b/youtube_dl/extractor/ku6.py @@ -1,7 +1,5 @@ from __future__ import unicode_literals -import re - from .common import InfoExtractor @@ -18,11 +16,11 @@ class Ku6IE(InfoExtractor): } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') - + video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) - title = self._search_regex(r'

    (.*?)

    ', webpage, 'title') + + title = self._html_search_regex( + r'

    (.*?)

    ', webpage, 'title') dataUrl = 'http://v.ku6.com/fetchVideo4Player/%s.html' % video_id jsonData = self._download_json(dataUrl, video_id) downloadUrl = jsonData['data']['f'] From 8cc3eba79ae19cf5ec4780356b75ccb9813916f0 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 02:43:59 +0100 Subject: [PATCH 1204/1761] [phoenix] Add new extractor (Fixes #4036) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/phoenix.py | 31 +++++++ youtube_dl/extractor/zdf.py | 151 ++++++++++++++++--------------- 3 files changed, 109 insertions(+), 74 deletions(-) create mode 100644 youtube_dl/extractor/phoenix.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 17ab49283..3979b8270 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -280,6 +280,7 @@ from .orf import ( from .parliamentliveuk import ParliamentLiveUKIE from .patreon import PatreonIE from .pbs import PBSIE +from .phoenix import PhoenixIE from .photobucket import PhotobucketIE from .planetaplay import PlanetaPlayIE from .played import PlayedIE diff --git a/youtube_dl/extractor/phoenix.py b/youtube_dl/extractor/phoenix.py new file mode 100644 index 000000000..a20672c0c --- /dev/null +++ b/youtube_dl/extractor/phoenix.py @@ -0,0 +1,31 @@ +from __future__ import unicode_literals + +from .common import InfoExtractor +from .zdf import extract_from_xml_url + + +class PhoenixIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?phoenix\.de/content/(?P[0-9]+)' + _TEST = { + 'url': 'http://www.phoenix.de/content/884301', + 'md5': 'ed249f045256150c92e72dbb70eadec6', + 'info_dict': { + 'id': '884301', + 'ext': 'mp4', + 'title': 'Michael Krons mit Hans-Werner Sinn', + 'description': 'Im Dialog - Sa. 25.10.14, 00.00 - 00.35 Uhr', + 'upload_date': '20141025', + 'uploader': 'Im Dialog', + } + } + + def _real_extract(self, url): + video_id = self._match_id(url) + webpage = self._download_webpage(url, video_id) + + internal_id = self._search_regex( + r'
    [^_]+)_(?P[^_]+)_(?P[^_]+)_ + (?P[^_]+)_(?P[^_]+)_(?P[^_]+) + ''', format_id) + + ext = format_m.group('container') + proto = format_m.group('proto').lower() + + quality = fnode.find('./quality').text + abr = int(fnode.find('./audioBitrate').text) // 1000 + vbr_node = fnode.find('./videoBitrate') + vbr = None if vbr_node is None else int(vbr_node.text) // 1000 + + width_node = fnode.find('./width') + width = None if width_node is None else int_or_none(width_node.text) + height_node = fnode.find('./height') + height = None if height_node is None else int_or_none(height_node.text) + + format_note = '' + if not format_note: + format_note = None + + return { + 'format_id': format_id + '-' + quality, + 'url': video_url, + 'ext': ext, + 'acodec': format_m.group('acodec'), + 'vcodec': format_m.group('vcodec'), + 'abr': abr, + 'vbr': vbr, + 'width': width, + 'height': height, + 'filesize': int_or_none(fnode.find('./filesize').text), + 'format_note': format_note, + 'protocol': proto, + '_available': is_available, + } + + format_nodes = doc.findall('.//formitaeten/formitaet') + formats = list(filter( + lambda f: f['_available'], + map(xml_to_format, format_nodes))) + ie._sort_formats(formats) + + return { + 'id': video_id, + 'title': title, + 'description': description, + 'duration': duration, + 'uploader': uploader, + 'uploader_id': uploader_id, + 'upload_date': upload_date, + 'formats': formats, + } + + class ZDFIE(InfoExtractor): _VALID_URL = r'^https?://www\.zdf\.de/ZDFmediathek(?P#)?/(.*beitrag/(?:video/)?)(?P[0-9]+)(?:/[^/?]+)?(?:\?.*)?' @@ -32,77 +108,4 @@ class ZDFIE(InfoExtractor): video_id = self._match_id(url) xml_url = 'http://www.zdf.de/ZDFmediathek/xmlservice/web/beitragsDetails?ak=web&id=%s' % video_id - doc = self._download_xml( - xml_url, video_id, - note='Downloading video info', - errnote='Failed to download video info') - - title = doc.find('.//information/title').text - description = doc.find('.//information/detail').text - duration = int(doc.find('.//details/lengthSec').text) - uploader_node = doc.find('.//details/originChannelTitle') - uploader = None if uploader_node is None else uploader_node.text - uploader_id_node = doc.find('.//details/originChannelId') - uploader_id = None if uploader_id_node is None else uploader_id_node.text - upload_date = unified_strdate(doc.find('.//details/airtime').text) - - def xml_to_format(fnode): - video_url = fnode.find('url').text - is_available = 'http://www.metafilegenerator' not in video_url - - format_id = fnode.attrib['basetype'] - format_m = re.match(r'''(?x) - (?P[^_]+)_(?P[^_]+)_(?P[^_]+)_ - (?P[^_]+)_(?P[^_]+)_(?P[^_]+) - ''', format_id) - - ext = format_m.group('container') - proto = format_m.group('proto').lower() - - quality = fnode.find('./quality').text - abr = int(fnode.find('./audioBitrate').text) // 1000 - vbr_node = fnode.find('./videoBitrate') - vbr = None if vbr_node is None else int(vbr_node.text) // 1000 - - width_node = fnode.find('./width') - width = None if width_node is None else int_or_none(width_node.text) - height_node = fnode.find('./height') - height = None if height_node is None else int_or_none(height_node.text) - - format_note = '' - if not format_note: - format_note = None - - return { - 'format_id': format_id + '-' + quality, - 'url': video_url, - 'ext': ext, - 'acodec': format_m.group('acodec'), - 'vcodec': format_m.group('vcodec'), - 'abr': abr, - 'vbr': vbr, - 'width': width, - 'height': height, - 'filesize': int_or_none(fnode.find('./filesize').text), - 'format_note': format_note, - 'protocol': proto, - '_available': is_available, - } - - format_nodes = doc.findall('.//formitaeten/formitaet') - formats = list(filter( - lambda f: f['_available'], - map(xml_to_format, format_nodes))) - - self._sort_formats(formats) - - return { - 'id': video_id, - 'title': title, - 'description': description, - 'duration': duration, - 'uploader': uploader, - 'uploader_id': uploader_id, - 'upload_date': upload_date, - 'formats': formats, - } \ No newline at end of file + return extract_from_xml_url(self, video_id, xml_url) From b2e6a1c14c142eab299266641a72101f7d679443 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 27 Oct 2014 02:44:07 +0100 Subject: [PATCH 1205/1761] release 2014.10.27 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 8e5a642a8..b1f0316ee 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.10.26.2' +__version__ = '2014.10.27' From aaa399d2f6cf8efff6e63f05be947c6ee4de4d34 Mon Sep 17 00:00:00 2001 From: Naglis Jonaitis Date: Mon, 27 Oct 2014 18:49:48 +0200 Subject: [PATCH 1206/1761] [sphinx] Fix version import --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 4a04ad779..594ca61a6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -44,8 +44,8 @@ copyright = u'2014, Ricardo Garcia Gonzalez' # built documents. # # The short X.Y version. -import youtube_dl -version = youtube_dl.__version__ +from youtube_dl.version import __version__ +version = __version__ # The full version, including alpha/beta/rc tags. release = version From 27c542c06f816100a64a2e3dbc5396df033aa025 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 28 Oct 2014 09:12:28 +0100 Subject: [PATCH 1207/1761] [iconosquare] Simplify --- youtube_dl/extractor/iconosquare.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/youtube_dl/extractor/iconosquare.py b/youtube_dl/extractor/iconosquare.py index 1d5a10a3b..370e86e5a 100644 --- a/youtube_dl/extractor/iconosquare.py +++ b/youtube_dl/extractor/iconosquare.py @@ -1,7 +1,5 @@ from __future__ import unicode_literals -import re - from .common import InfoExtractor @@ -20,13 +18,11 @@ class IconosquareIE(InfoExtractor): } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') + video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) - html_title = self._html_search_regex( - r'(.+?)', + title = self._html_search_regex( + r'(.+?)(?: *\(Videos?\))? \| (?:Iconosquare|Statigram)', webpage, 'title') - title = re.sub(r'(?: *\(Videos?\))? \| (?:Iconosquare|Statigram)$', '', html_title) uploader_id = self._html_search_regex( r'@([^ ]+)', title, 'uploader name', fatal=False) From 48a24ab7465a41822a0fd40bba249520b3a85124 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 28 Oct 2014 10:41:24 +0100 Subject: [PATCH 1208/1761] [generic] Fix HTML5 video regexp --- youtube_dl/extractor/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 35a7664b2..47580328a 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -933,7 +933,7 @@ class GenericIE(InfoExtractor): found = filter_video(re.findall(r'.*?]+)? src="([^"]+)"', webpage) + found = re.findall(r'(?s).*?]*)?\s+src="([^"]+)"', webpage) if not found: found = re.search( r'(?i) Date: Tue, 28 Oct 2014 10:41:37 +0100 Subject: [PATCH 1209/1761] [quickvid] Add new extractor --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/quickvid.py | 51 ++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 youtube_dl/extractor/quickvid.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 3979b8270..c3799da67 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -294,6 +294,7 @@ from .pornoxo import PornoXOIE from .promptfile import PromptFileIE from .prosiebensat1 import ProSiebenSat1IE from .pyvideo import PyvideoIE +from .quickvid import QuickVidIE from .radiofrance import RadioFranceIE from .rai import RaiIE from .rbmaradio import RBMARadioIE diff --git a/youtube_dl/extractor/quickvid.py b/youtube_dl/extractor/quickvid.py new file mode 100644 index 000000000..3bc78060d --- /dev/null +++ b/youtube_dl/extractor/quickvid.py @@ -0,0 +1,51 @@ +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ( + compat_urlparse, + determine_ext, + int_or_none, +) + + +class QuickVidIE(InfoExtractor): + _VALID_URL = r'https?://(www\.)?quickvid\.org/watch\.php\?v=(?P[a-zA-Z_0-9-]+)' + _TEST = { + 'url': 'http://quickvid.org/watch.php?v=sUQT3RCG8dx', + 'md5': 'c0c72dd473f260c06c808a05d19acdc5', + 'info_dict': { + 'id': 'sUQT3RCG8dx', + 'ext': 'mp4', + 'title': 'Nick Offerman\'s Summer Reading Recap', + 'thumbnail': 're:^https?://.*\.(?:png|jpg|gif)$', + 'view_count': int, + }, + } + + def _real_extract(self, url): + video_id = self._match_id(url) + webpage = self._download_webpage(url, video_id) + + title = self._html_search_regex(r'

    (.*?)

    ', webpage, 'title') + view_count = int_or_none(self._html_search_regex( + r'(?s)
    (.*?)
    ', + webpage, 'view count', fatal=False)) + video_code = self._search_regex( + r'(?s)', webpage, 'video code') + formats = [ + { + 'url': compat_urlparse.urljoin(url, src), + 'format_id': determine_ext(src, None), + } for src in re.findall(' Date: Tue, 28 Oct 2014 10:44:17 +0100 Subject: [PATCH 1210/1761] [fktv] Remove unused import --- youtube_dl/extractor/fktv.py | 1 - 1 file changed, 1 deletion(-) diff --git a/youtube_dl/extractor/fktv.py b/youtube_dl/extractor/fktv.py index 990bee8ba..21b89142c 100644 --- a/youtube_dl/extractor/fktv.py +++ b/youtube_dl/extractor/fktv.py @@ -6,7 +6,6 @@ import json from .common import InfoExtractor from ..utils import ( - determine_ext, get_element_by_id, clean_html, ) From 9fdece5d340f24ab3c16770f71fd26943f4996c2 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 28 Oct 2014 10:44:47 +0100 Subject: [PATCH 1211/1761] [srmediathek] Choose variable name more wisely --- youtube_dl/extractor/srmediathek.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/srmediathek.py b/youtube_dl/extractor/srmediathek.py index d92d14d65..666a7dcc8 100644 --- a/youtube_dl/extractor/srmediathek.py +++ b/youtube_dl/extractor/srmediathek.py @@ -26,9 +26,9 @@ class SRMediathekIE(InfoExtractor): video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) - urls = json.loads(js_to_json(self._search_regex( + murls = json.loads(js_to_json(self._search_regex( r'var mediaURLs\s*=\s*(.*?);\n', webpage, 'video URLs'))) - formats = [{'url': url} for url in urls] + formats = [{'url': murl} for murl in murls] self._sort_formats(formats) title = json.loads(js_to_json(self._search_regex( From 3511266bc39976a926a9f33a0762aa40212431ee Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 28 Oct 2014 12:54:29 +0100 Subject: [PATCH 1212/1761] [YoutubeDL] Simplify API of YoutubeDL Calling add_default_extractors twice should be harmless since the first set of extractors will match. --- youtube_dl/YoutubeDL.py | 6 +++++- youtube_dl/__init__.py | 3 --- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 28dcc0195..fd775b9fd 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -189,7 +189,7 @@ class YoutubeDL(object): _num_downloads = None _screen_file = None - def __init__(self, params=None): + def __init__(self, params=None, auto_init=True): """Create a FileDownloader object with the given options.""" if params is None: params = {} @@ -246,6 +246,10 @@ class YoutubeDL(object): self._setup_opener() + if auto_init: + self.print_debug_header() + self.add_default_info_extractors() + def add_info_extractor(self, ie): """Add an InfoExtractor object to the end of the list.""" self._ies.append(ie) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 7dc971884..3c968082c 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -293,9 +293,6 @@ def _real_main(argv=None): } with YoutubeDL(ydl_opts) as ydl: - ydl.print_debug_header() - ydl.add_default_info_extractors() - # PostProcessors # Add the metadata pp first, the other pps will copy it if opts.addmetadata: From 03df7baa6a8dc5cab41f5ce2f0be8cd439a6195d Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 28 Oct 2014 12:54:39 +0100 Subject: [PATCH 1213/1761] Start documentation on how to embed youtube-dl --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index d62546433..230c12a88 100644 --- a/README.md +++ b/README.md @@ -511,6 +511,20 @@ If you want to add support for a new site, you can follow this quick list (assum In any case, thank you very much for your contributions! +# EMBEDDING YOUTUBE-DL + +youtube-dl makes the best effort to be a good command-line program, and thus should be callable from any programming language. If you encounter any problems parsing its output, feel free to [create a report](https://github.com/rg3/youtube-dl/issues/new). + +From a Python program, you can embed youtube-dl in a more powerful fashion, like this: + + import youtube_dl + + ydl_opts = {} + with youtube_dl.YoutubeDL(ydl_opts) as ydl: + ydl.download(['http://www.youtube.com/watch?v=BaW_jenozKc']) + +Most likely, you'll want to use various options. For a list of what can be done, have a look at [youtube_dl/YoutubeDL.py](https://github.com/rg3/youtube-dl/blob/master/youtube_dl/YoutubeDL.py#L69). For a start, if you want to intercept youtube-dl's output, set a `logger` object. + # BUGS Bugs and suggestions should be reported at: . Unless you were prompted so or there is another pertinent reason (e.g. GitHub fails to accept the bug report), please do not send bug reports via personal email. From 632256d9ecd86f17b370b2cbe3f50acdf961d6cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Tue, 28 Oct 2014 20:35:02 +0700 Subject: [PATCH 1214/1761] [wimp] Update video URL regex --- youtube_dl/extractor/wimp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/wimp.py b/youtube_dl/extractor/wimp.py index c27dda944..3377a543e 100644 --- a/youtube_dl/extractor/wimp.py +++ b/youtube_dl/extractor/wimp.py @@ -37,7 +37,7 @@ class WimpIE(InfoExtractor): video_id = mobj.group(1) webpage = self._download_webpage(url, video_id) video_url = self._search_regex( - r's1\.addVariable\("file",\s*"([^"]+)"\);', webpage, 'video URL') + r"'file'\s*:\s*'([^']+)'", webpage, 'video URL') if YoutubeIE.suitable(video_url): self.to_screen('Found YouTube video') return { From 9334f8f17a0e6a2b97d4e20b12a9ede52e4c0b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Tue, 28 Oct 2014 21:06:07 +0700 Subject: [PATCH 1215/1761] [vk] Handle deleted videos --- youtube_dl/extractor/vk.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/youtube_dl/extractor/vk.py b/youtube_dl/extractor/vk.py index 918bd1098..837c3167e 100644 --- a/youtube_dl/extractor/vk.py +++ b/youtube_dl/extractor/vk.py @@ -142,6 +142,10 @@ class VKIE(InfoExtractor): raise ExtractorError('This video is only available for registered users, ' 'use --username and --password options to provide account credentials.', expected=True) + if 'Unknown error' in info_page: + raise ExtractorError( + 'Video %s does not exist' % video_id, expected=True) + m_yt = re.search(r'src="(http://www.youtube.com/.*?)"', info_page) if m_yt is not None: self.to_screen('Youtube video detected') From e0c51cdadc838a67870f5c22c48bb0b9f1951afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Tue, 28 Oct 2014 21:35:25 +0700 Subject: [PATCH 1216/1761] [vk] Generalize errors --- youtube_dl/extractor/vk.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/youtube_dl/extractor/vk.py b/youtube_dl/extractor/vk.py index 837c3167e..36cd7e52e 100644 --- a/youtube_dl/extractor/vk.py +++ b/youtube_dl/extractor/vk.py @@ -138,13 +138,19 @@ class VKIE(InfoExtractor): info_url = 'http://vk.com/al_video.php?act=show&al=1&video=%s' % video_id info_page = self._download_webpage(info_url, video_id) - if re.search(r'Please log in or <', info_page): - raise ExtractorError('This video is only available for registered users, ' - 'use --username and --password options to provide account credentials.', expected=True) + ERRORS = { + r'>Видеозапись .*? была изъята из публичного доступа в связи с обращением правообладателя.<': + 'Video %s has been removed from public access due to rightholder complaint.', + r'Please log in or <': + 'Video %s is only available for registered users, ' + 'use --username and --password options to provide account credentials.', + 'Unknown error': + 'Video %s does not exist.' + } - if 'Unknown error' in info_page: - raise ExtractorError( - 'Video %s does not exist' % video_id, expected=True) + for error_re, error_msg in ERRORS.items(): + if re.search(error_re, info_page): + raise ExtractorError(error_msg % video_id, expected=True) m_yt = re.search(r'src="(http://www.youtube.com/.*?)"', info_page) if m_yt is not None: From 01d663bca35e138cb95f5d156bcf396dcae54f73 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 28 Oct 2014 15:51:15 +0100 Subject: [PATCH 1217/1761] [auengine] Simplify --- youtube_dl/extractor/auengine.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/youtube_dl/extractor/auengine.py b/youtube_dl/extractor/auengine.py index 20bf12550..1c765532a 100644 --- a/youtube_dl/extractor/auengine.py +++ b/youtube_dl/extractor/auengine.py @@ -24,8 +24,7 @@ class AUEngineIE(InfoExtractor): } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') + video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) title = self._html_search_regex(r'(?P<title>.+?)', webpage, 'title') From e5193599ecca2d4437d066e9fed95db74b8562c7 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 28 Oct 2014 16:51:32 +0100 Subject: [PATCH 1218/1761] [laola1tv] Add new extractor The extractor works fine, but the f4m downloader cannot handle the resulting bootstrap information. --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/laola1tv.py | 75 ++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 youtube_dl/extractor/laola1tv.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index c3799da67..615018c09 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -189,6 +189,7 @@ from .kontrtube import KontrTubeIE from .krasview import KrasViewIE from .ku6 import Ku6IE from .la7 import LA7IE +from .laola1tv import Laola1TvIE from .lifenews import LifeNewsIE from .liveleak import LiveLeakIE from .livestream import ( diff --git a/youtube_dl/extractor/laola1tv.py b/youtube_dl/extractor/laola1tv.py new file mode 100644 index 000000000..45ab86b03 --- /dev/null +++ b/youtube_dl/extractor/laola1tv.py @@ -0,0 +1,75 @@ +from __future__ import unicode_literals + +import random +import re + +from .common import InfoExtractor + + +class Laola1TvIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?laola1\.tv/(?P[a-z]+)-(?P[a-z]+)/.*?/(?P[0-9]+)\.html' + _TEST = { + 'url': 'http://www.laola1.tv/de-de/live/bwf-bitburger-open-grand-prix-gold-court-1/250019.html', + 'info_dict': { + 'id': '250019', + 'ext': 'mp4', + 'title': 'Bitburger Open Grand Prix Gold - Court 1', + 'categories': ['Badminton'], + 'uploader': 'BWF - Badminton World Federation', + 'is_live': True, + }, + 'params': { + 'skip_download': True, + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + lang = mobj.group('lang') + portal = mobj.group('portal') + + webpage = self._download_webpage(url, video_id) + iframe_url = self._search_regex( + r']*?class="main_tv_player"[^>]*?src="([^"]+)"', + webpage, 'iframe URL') + + iframe = self._download_webpage( + iframe_url, video_id, note='Downloading iframe') + flashvars_m = re.findall( + r'flashvars\.([_a-zA-Z0-9]+)\s*=\s*"([^"]*)";', iframe) + flashvars = dict((m[0], m[1]) for m in flashvars_m) + + xml_url = ('http://www.laola1.tv/server/hd_video.php?' + + 'play=%s&partner=1&portal=%s&v5ident=&lang=%s' % ( + video_id, portal, lang)) + hd_doc = self._download_xml(xml_url, video_id) + + title = hd_doc.find('.//video/title').text + flash_url = hd_doc.find('.//video/url').text + categories = hd_doc.find('.//video/meta_sports').text.split(',') + uploader = hd_doc.find('.//video/meta_organistation').text + + ident = random.randint(10000000, 99999999) + token_url = '%s&ident=%s&klub=0&unikey=0×tamp=%s&auth=%s' % ( + flash_url, ident, flashvars['timestamp'], flashvars['auth']) + + token_doc = self._download_xml( + token_url, video_id, note='Downloading token') + token_attrib = token_doc.find('.//token').attrib + if token_attrib.get('auth') == 'blocked': + raise ExtractorError('Token error: ' % token_attrib.get('comment')) + + video_url = '%s?hdnea=%s&hdcore=3.2.0' % ( + token_attrib['url'], token_attrib['auth']) + + return { + 'id': video_id, + 'is_live': True, + 'title': title, + 'url': video_url, + 'uploader': uploader, + 'categories': categories, + 'ext': 'mp4', + } + From ee966928af5f35123c4c7417bb052ae5aea345c9 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 28 Oct 2014 17:27:41 +0100 Subject: [PATCH 1219/1761] [f4m] Support bootstrap URLs --- youtube_dl/downloader/f4m.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/youtube_dl/downloader/f4m.py b/youtube_dl/downloader/f4m.py index b3be16ff1..b607f6485 100644 --- a/youtube_dl/downloader/f4m.py +++ b/youtube_dl/downloader/f4m.py @@ -244,9 +244,16 @@ class F4mFD(FileDownloader): lambda f: int(f[0]) == requested_bitrate, formats))[0] base_url = compat_urlparse.urljoin(man_url, media.attrib['url']) - bootstrap = base64.b64decode(doc.find(_add_ns('bootstrapInfo')).text) + bootstrap_node = doc.find(_add_ns('bootstrapInfo')) + if bootstrap_node.text is None: + bootstrap_url = compat_urlparse.urljoin( + base_url, bootstrap_node.attrib['url']) + bootstrap = self.ydl.urlopen(bootstrap_url).read() + else: + bootstrap = base64.b64decode(bootstrap_node.text) metadata = base64.b64decode(media.find(_add_ns('metadata')).text) boot_info = read_bootstrap_info(bootstrap) + fragments_list = build_fragments_list(boot_info) if self.params.get('test', False): # We only download the first fragment From 00edd4f9bef7cf0708d1c4da128477d76115fdec Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Tue, 28 Oct 2014 17:29:25 +0100 Subject: [PATCH 1220/1761] [laola1tv] Mark as broken When the f4m downloader gets live stream support, I expect this to work magically or with very minor changes. --- youtube_dl/extractor/laola1tv.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/youtube_dl/extractor/laola1tv.py b/youtube_dl/extractor/laola1tv.py index 45ab86b03..263f68773 100644 --- a/youtube_dl/extractor/laola1tv.py +++ b/youtube_dl/extractor/laola1tv.py @@ -23,6 +23,8 @@ class Laola1TvIE(InfoExtractor): } } + _BROKEN = True # Not really - extractor works fine, but f4m downloader does not support live streams yet. + def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('id') From a9bad429b309e614b4b8905c085ef425350ceeb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Wed, 29 Oct 2014 11:04:48 +0100 Subject: [PATCH 1221/1761] [niconico] Add extractor for playlists (closes #4043) --- youtube_dl/extractor/__init__.py | 2 +- youtube_dl/extractor/niconico.py | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 615018c09..32236f0fa 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -252,7 +252,7 @@ from .newstube import NewstubeIE from .nfb import NFBIE from .nfl import NFLIE from .nhl import NHLIE, NHLVideocenterIE -from .niconico import NiconicoIE +from .niconico import NiconicoIE, NiconicoPlaylistIE from .ninegag import NineGagIE from .noco import NocoIE from .normalboots import NormalbootsIE diff --git a/youtube_dl/extractor/niconico.py b/youtube_dl/extractor/niconico.py index 7b85589b7..62d5707fe 100644 --- a/youtube_dl/extractor/niconico.py +++ b/youtube_dl/extractor/niconico.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import re +import json from .common import InfoExtractor from ..utils import ( @@ -146,3 +147,36 @@ class NiconicoIE(InfoExtractor): 'duration': duration, 'webpage_url': webpage_url, } + + +class NiconicoPlaylistIE(InfoExtractor): + _VALID_URL = r'https?://www\.nicovideo\.jp/mylist/(?P\d+)' + + _TEST = { + 'url': 'http://www.nicovideo.jp/mylist/27411728', + 'info_dict': { + 'id': '27411728', + 'title': 'AKB48のオールナイトニッポン', + }, + 'playlist_mincount': 225, + } + + def _real_extract(self, url): + list_id = self._match_id(url) + webpage = self._download_webpage(url, list_id) + + entries_json = self._search_regex(r'Mylist\.preload\(\d+, (\[.*\])\);', + webpage, 'entries') + entries = json.loads(entries_json) + entries = [{ + '_type': 'url', + 'ie_key': NiconicoIE.ie_key(), + 'url': 'http://www.nicovideo.jp/watch/%s' % entry['item_id'], + } for entry in entries] + + return { + '_type': 'playlist', + 'title': self._search_regex(r'\s+name: "(.*?)"', webpage, 'title'), + 'id': list_id, + 'entries': entries, + } From 8abec2c8bb2ff1051af63420711706497faf6de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Wed, 29 Oct 2014 11:13:34 +0100 Subject: [PATCH 1222/1761] [test_utils] Fix compat_getenv and compat_expanduser tests on python 3.x --- test/test_utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/test_utils.py b/test/test_utils.py index 19f9fce20..febba411e 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -360,12 +360,14 @@ class TestUtil(unittest.TestCase): def test_compat_getenv(self): test_str = 'тест' - os.environ['YOUTUBE-DL-TEST'] = test_str.encode(get_filesystem_encoding()) + os.environ['YOUTUBE-DL-TEST'] = (test_str if sys.version_info >= (3, 0) + else test_str.encode(get_filesystem_encoding())) self.assertEqual(compat_getenv('YOUTUBE-DL-TEST'), test_str) def test_compat_expanduser(self): test_str = 'C:\Documents and Settings\тест\Application Data' - os.environ['HOME'] = test_str.encode(get_filesystem_encoding()) + os.environ['HOME'] = (test_str if sys.version_info >= (3, 0) + else test_str.encode(get_filesystem_encoding())) self.assertEqual(compat_expanduser('~'), test_str) if __name__ == '__main__': From c451d4f5533de9bacba5ad7c186b7bbb3fb0b6cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Wed, 29 Oct 2014 21:16:10 +0700 Subject: [PATCH 1223/1761] [trutube] Fix extraction --- youtube_dl/extractor/trutube.py | 38 +++++++++++++++------------------ 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/youtube_dl/extractor/trutube.py b/youtube_dl/extractor/trutube.py index 57f956683..a73f3c43a 100644 --- a/youtube_dl/extractor/trutube.py +++ b/youtube_dl/extractor/trutube.py @@ -1,13 +1,12 @@ from __future__ import unicode_literals -import re - from .common import InfoExtractor +from ..utils import xpath_text class TruTubeIE(InfoExtractor): - _VALID_URL = r'https?://(?:www\.)?trutube\.tv/video/(?P[0-9]+)/.*' - _TEST = { + _VALID_URL = r'https?://(?:www\.)?trutube\.tv/(?:video/|nuevo/player/embed\.php\?v=)(?P[0-9]+)' + _TESTS = [{ 'url': 'http://trutube.tv/video/14880/Ramses-II-Proven-To-Be-A-Red-Headed-Caucasoid-', 'md5': 'c5b6e301b0a2040b074746cbeaa26ca1', 'info_dict': { @@ -16,29 +15,26 @@ class TruTubeIE(InfoExtractor): 'title': 'Ramses II - Proven To Be A Red Headed Caucasoid', 'thumbnail': 're:^http:.*\.jpg$', } - } + }, { + 'url': 'https://trutube.tv/nuevo/player/embed.php?v=14880', + 'only_matching': True, + }] def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') + video_id = self._match_id(url) - webpage = self._download_webpage(url, video_id) - video_title = self._og_search_title(webpage).strip() - thumbnail = self._search_regex( - r"var splash_img = '([^']+)';", webpage, 'thumbnail', fatal=False) + config = self._download_xml( + 'https://trutube.tv/nuevo/player/config.php?v=%s' % video_id, + video_id, transform_source=lambda s: s.strip()) - all_formats = re.finditer( - r"var (?P[a-z]+)_video_file\s*=\s*'(?P[^']+)';", webpage) - formats = [{ - 'format_id': m.group('key'), - 'quality': -i, - 'url': m.group('url'), - } for i, m in enumerate(all_formats)] - self._sort_formats(formats) + # filehd is always 404 + video_url = xpath_text(config, './file', 'video URL', fatal=True) + title = xpath_text(config, './title', 'title') + thumbnail = xpath_text(config, './image', ' thumbnail') return { 'id': video_id, - 'title': video_title, - 'formats': formats, + 'url': video_url, + 'title': title, 'thumbnail': thumbnail, } From dbd1283d31aa1df43bf9b3255dc27a1c8bfed4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Wed, 29 Oct 2014 21:50:37 +0700 Subject: [PATCH 1224/1761] [naver] Capture and output error message (#4057) --- youtube_dl/extractor/naver.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/youtube_dl/extractor/naver.py b/youtube_dl/extractor/naver.py index c0231c197..cb1af9ecc 100644 --- a/youtube_dl/extractor/naver.py +++ b/youtube_dl/extractor/naver.py @@ -7,6 +7,7 @@ from .common import InfoExtractor from ..utils import ( compat_urllib_parse, ExtractorError, + clean_html, ) @@ -31,6 +32,11 @@ class NaverIE(InfoExtractor): m_id = re.search(r'var rmcPlayer = new nhn.rmcnmv.RMCVideoPlayer\("(.+?)", "(.+?)"', webpage) if m_id is None: + m_error = re.search( + r'(?s)
    \s*(?:)?\s*

    (?P.+?)

    \s*
    ', + webpage) + if m_error: + raise ExtractorError(clean_html(m_error.group('msg')), expected=True) raise ExtractorError('couldn\'t extract vid and key') vid = m_id.group(1) key = m_id.group(2) From 6ad4013d40e839211e2896129eed05ccd40ee963 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Wed, 29 Oct 2014 20:10:00 +0100 Subject: [PATCH 1225/1761] [drtv] Allow fractional timestamps (Fixes #4059) --- test/test_utils.py | 1 + youtube_dl/extractor/drtv.py | 7 ++----- youtube_dl/utils.py | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/test/test_utils.py b/test/test_utils.py index 19f9fce20..1c2b57609 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -289,6 +289,7 @@ class TestUtil(unittest.TestCase): self.assertEqual(parse_iso8601('2014-03-23T23:04:26+0100'), 1395612266) self.assertEqual(parse_iso8601('2014-03-23T22:04:26+0000'), 1395612266) self.assertEqual(parse_iso8601('2014-03-23T22:04:26Z'), 1395612266) + self.assertEqual(parse_iso8601('2014-03-23T22:04:26.1234Z'), 1395612266) def test_strip_jsonp(self): stripped = strip_jsonp('cb ([ {"id":"532cb",\n\n\n"x":\n3}\n]\n);') diff --git a/youtube_dl/extractor/drtv.py b/youtube_dl/extractor/drtv.py index 9d6ce1f48..93b3c9f36 100644 --- a/youtube_dl/extractor/drtv.py +++ b/youtube_dl/extractor/drtv.py @@ -1,7 +1,5 @@ from __future__ import unicode_literals -import re - from .subtitles import SubtitlesInfoExtractor from .common import ExtractorError from ..utils import parse_iso8601 @@ -25,8 +23,7 @@ class DRTVIE(SubtitlesInfoExtractor): } def _real_extract(self, url): - mobj = re.match(self._VALID_URL, url) - video_id = mobj.group('id') + video_id = self._match_id(url) programcard = self._download_json( 'http://www.dr.dk/mu/programcard/expanded/%s' % video_id, video_id, 'Downloading video JSON') @@ -35,7 +32,7 @@ class DRTVIE(SubtitlesInfoExtractor): title = data['Title'] description = data['Description'] - timestamp = parse_iso8601(data['CreatedTime'][:-5]) + timestamp = parse_iso8601(data['CreatedTime']) thumbnail = None duration = None diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 6c0c39ca5..2864e5142 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -925,7 +925,7 @@ def parse_iso8601(date_str, delimiter='T'): return None m = re.search( - r'Z$| ?(?P\+|-)(?P[0-9]{2}):?(?P[0-9]{2})$', + r'(\.[0-9]+)?(?:Z$| ?(?P\+|-)(?P[0-9]{2}):?(?P[0-9]{2})$)', date_str) if not m: timezone = datetime.timedelta() @@ -938,7 +938,7 @@ def parse_iso8601(date_str, delimiter='T'): timezone = datetime.timedelta( hours=sign * int(m.group('hours')), minutes=sign * int(m.group('minutes'))) - date_format = '%Y-%m-%d{0}%H:%M:%S'.format(delimiter) + date_format = '%Y-%m-%d{0}%H:%M:%S'.format(delimiter) dt = datetime.datetime.strptime(date_str, date_format) - timezone return calendar.timegm(dt.timetuple()) From ac645ac7d0ce240e17f5e26f525e22e2aa71407a Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Wed, 29 Oct 2014 20:27:58 +0100 Subject: [PATCH 1226/1761] [generic] Allow soundcloud embeds with additional attributes --- youtube_dl/extractor/generic.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 47580328a..a27ec342e 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -405,6 +405,18 @@ class GenericIE(InfoExtractor): 'expected_warnings': [ r'501.*Not Implemented' ], + }, + # Soundcloud embed + { + 'url': 'http://nakedsecurity.sophos.com/2014/10/29/sscc-171-are-you-sure-that-1234-is-a-bad-password-podcast/', + 'info_dict': { + 'id': '174391317', + 'ext': 'mp3', + 'description': 'md5:ff867d6b555488ad3c52572bb33d432c', + 'uploader': 'Sophos Security', + 'title': 'Chet Chat 171 - Oct 29, 2014', + 'upload_date': '20141029', + } } ] @@ -838,7 +850,7 @@ class GenericIE(InfoExtractor): # Look for embeded soundcloud player mobj = re.search( - r'
  • (.+?)

    ', + webpage, 'description', fatal=False) + publish_date = unified_strdate(self._html_search_meta( + 'citation_publication_date', webpage, 'publish date', fatal=False)) + comment_count = self._html_search_regex( + r' Date: Wed, 20 Aug 2014 20:30:29 +0700 Subject: [PATCH 0542/1761] [teamcoco] Update video id regex --- youtube_dl/extractor/teamcoco.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/teamcoco.py b/youtube_dl/extractor/teamcoco.py index f8dd7e955..fa796ce72 100644 --- a/youtube_dl/extractor/teamcoco.py +++ b/youtube_dl/extractor/teamcoco.py @@ -37,7 +37,7 @@ class TeamcocoIE(InfoExtractor): video_id = mobj.group("video_id") if not video_id: video_id = self._html_search_regex( - r'
    Date: Thu, 21 Aug 2014 11:52:07 +0200 Subject: [PATCH 0543/1761] Allow playlist test definitions in test_download. This moves playlist tests where they belong, i.e. to the extractors themselves. Additionally, all our network interaction configuration for tests in test_download now applies to playlist tests as well. --- test/helper.py | 5 +++-- test/test_download.py | 32 +++++++++++++++++++++++++++----- youtube_dl/YoutubeDL.py | 8 +++++++- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/test/helper.py b/test/helper.py index b7299fb82..22d763860 100644 --- a/test/helper.py +++ b/test/helper.py @@ -117,8 +117,9 @@ def expect_info_dict(self, expected_dict, got_dict): u'invalid value for field %s, expected %r, got %r' % (info_field, expected, got)) # Check for the presence of mandatory fields - for key in ('id', 'url', 'title', 'ext'): - self.assertTrue(got_dict.get(key), 'Missing mandatory field %s' % key) + if got_dict.get('_type') != 'playlist': + for key in ('id', 'url', 'title', 'ext'): + self.assertTrue(got_dict.get(key), 'Missing mandatory field %s' % key) # Check for mandatory fields that are automatically set by YoutubeDL for key in ['webpage_url', 'extractor', 'extractor_key']: self.assertTrue(got_dict.get(key), u'Missing field: %s' % key) diff --git a/test/test_download.py b/test/test_download.py index d6540588c..c8d4ec2c8 100644 --- a/test/test_download.py +++ b/test/test_download.py @@ -63,15 +63,21 @@ def generator(test_case): def test_template(self): ie = youtube_dl.extractor.get_info_extractor(test_case['name']) other_ies = [get_info_extractor(ie_key) for ie_key in test_case.get('add_ie', [])] + is_playlist = any(k.startswith('playlist') for k in test_case) + test_cases = test_case.get( + 'playlist', [] if is_playlist else [test_case]) + def print_skipping(reason): print('Skipping %s: %s' % (test_case['name'], reason)) if not ie.working(): print_skipping('IE marked as not _WORKING') return - if 'playlist' not in test_case: - info_dict = test_case.get('info_dict', {}) - if not test_case.get('file') and not (info_dict.get('id') and info_dict.get('ext')): + + for tc in test_cases: + info_dict = tc.get('info_dict', {}) + if not tc.get('file') and not (info_dict.get('id') and info_dict.get('ext')): raise Exception('Test definition incorrect. The output file cannot be known. Are both \'id\' and \'ext\' keys present?') + if 'skip' in test_case: print_skipping(test_case['skip']) return @@ -81,6 +87,9 @@ def generator(test_case): return params = get_params(test_case.get('params', {})) + if is_playlist and 'playlist' not in test_case: + params.setdefault('extract_flat', True) + params.setdefault('skip_download', True) ydl = YoutubeDL(params) ydl.add_default_info_extractors() @@ -93,7 +102,6 @@ def generator(test_case): def get_tc_filename(tc): return tc.get('file') or ydl.prepare_filename(tc.get('info_dict', {})) - test_cases = test_case.get('playlist', [test_case]) def try_rm_tcs_files(): for tc in test_cases: tc_filename = get_tc_filename(tc) @@ -105,7 +113,10 @@ def generator(test_case): try_num = 1 while True: try: - ydl.download([test_case['url']]) + # We're not using .download here sine that is just a shim + # for outside error handling, and returns the exit code + # instead of the result dict. + res_dict = ydl.extract_info(test_case['url']) except (DownloadError, ExtractorError) as err: # Check if the exception is not a network related one if not err.exc_info[0] in (compat_urllib_error.URLError, socket.timeout, UnavailableVideoError, compat_http_client.BadStatusLine) or (err.exc_info[0] == compat_HTTPError and err.exc_info[1].code == 503): @@ -121,6 +132,17 @@ def generator(test_case): else: break + if is_playlist: + self.assertEqual(res_dict['_type'], 'playlist') + expect_info_dict(self, test_case.get('info_dict', {}), res_dict) + if 'playlist_mincount' in test_case: + self.assertGreaterEqual( + len(res_dict['entries']), + test_case['playlist_mincount'], + 'Expected at least %d in playlist %s, but got only %d' % ( + test_case['playlist_mincount'], test_case['url'], + len(res_dict['entries']))) + for tc in test_cases: tc_filename = get_tc_filename(tc) if not test_case.get('params', {}).get('skip_download', False): diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 14a1d06ab..e7194f3e3 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -162,6 +162,7 @@ class YoutubeDL(object): default_search: Prepend this string if an input url is not valid. 'auto' for elaborate guessing encoding: Use this encoding instead of the system-specified. + extract_flat: Do not resolve URLs, return the immediate result. The following parameters are not used by YoutubeDL itself, they are used by the FileDownloader: @@ -558,7 +559,12 @@ class YoutubeDL(object): Returns the resolved ie_result. """ - result_type = ie_result.get('_type', 'video') # If not given we suppose it's a video, support the default old system + result_type = ie_result.get('_type', 'video') + + if self.params.get('extract_flat', False): + if result_type in ('url', 'url_transparent'): + return ie_result + if result_type == 'video': self.add_extra_info(ie_result, extra_info) return self.process_video_result(ie_result, download=download) From 266c71f97190d5516d72bb9e5fbe0e8946bbb465 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Thu, 21 Aug 2014 11:56:49 +0200 Subject: [PATCH 0544/1761] Deprecate test_playlists --- test/test_playlists.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/test_playlists.py b/test/test_playlists.py index 4f188345b..6448fea38 100644 --- a/test/test_playlists.py +++ b/test/test_playlists.py @@ -1,6 +1,17 @@ #!/usr/bin/env python # encoding: utf-8 +## DEPRECATED FILE! +# Add new tests to the extractors themselves, like this: +# _TEST = { +# 'url': 'http://example.com/playlist/42', +# 'playlist_mincount': 99, +# 'info_dict': { +# 'id': '42', +# 'title': 'Playlist number forty-two', +# } +# } + from __future__ import unicode_literals # Allow direct execution From 1d01f26ab122258e06828ed411522af9fae80fe4 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Thu, 21 Aug 2014 11:57:03 +0200 Subject: [PATCH 0545/1761] [ellentv] Simplify and correct tests --- youtube_dl/extractor/ellentv.py | 48 ++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/youtube_dl/extractor/ellentv.py b/youtube_dl/extractor/ellentv.py index 933f36dd8..3e7923648 100644 --- a/youtube_dl/extractor/ellentv.py +++ b/youtube_dl/extractor/ellentv.py @@ -4,10 +4,14 @@ from __future__ import unicode_literals import re import json -from .common import InfoExtractor, ExtractorError +from .common import InfoExtractor +from ..utils import ( + ExtractorError, + parse_iso8601, +) + class EllenTVIE(InfoExtractor): - IE_NAME = u'ellentv' _VALID_URL = r'https?://(?:www\.)?ellentv\.com/videos/(?P[a-z0-9_-]+)' _TEST = { 'url': 'http://www.ellentv.com/videos/0-7jqrsr18/', @@ -15,43 +19,39 @@ class EllenTVIE(InfoExtractor): 'info_dict': { 'id': '0-7jqrsr18', 'ext': 'mp4', - 'title': u'What\'s Wrong with These Photos? A Whole Lot', - # TODO more properties, either as: - # * A value - # * MD5 checksum; start the string with md5: - # * A regular expression; start the string with re: - # * Any Python type (for example int or float) + 'title': 'What\'s Wrong with These Photos? A Whole Lot', + 'timestamp': 1406876400, + 'upload_date': '20140801', } } def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) - id = mobj.group('id') + video_id = mobj.group('id') - webpage = self._download_webpage(url, id) + webpage = self._download_webpage(url, video_id) + timestamp = parse_iso8601(self._search_regex( + r'', webpage, u'title') + + return { + 'id': video_id, + 'title': title, + 'url': video_url, + 'ext': 'flv', + 'thumbnail': thumb, + } From 83d35817f5e0960ffa750043a2add1247a3206ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=2EYasoob=20Ullah=20Khalid=20=E2=98=BA?= Date: Fri, 22 Aug 2014 01:31:12 +0500 Subject: [PATCH 0560/1761] Added test for dump.com --- youtube_dl/extractor/dump.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/youtube_dl/extractor/dump.py b/youtube_dl/extractor/dump.py index cfa71bd38..4b756b20a 100644 --- a/youtube_dl/extractor/dump.py +++ b/youtube_dl/extractor/dump.py @@ -11,6 +11,15 @@ from ..utils import ( class DumpIE(InfoExtractor): _VALID_URL = r'^https?://(?:www\.)?dump\.com/(?P[a-zA-Z0-9]+)/' + _TEST = { + u'url': u'http://www.dump.com/oneus/', + u'file': u'oneus.flv', + u'md5': u'ad71704d1e67dfd9e81e3e8b42d69d99', + u'info_dict': { + u"title": u"He's one of us.", + }, + } + def _real_extract(self, url): m = re.match(self._VALID_URL, url) video_id = m.group('id') From ea6e8d545430ebd8cf622c5c04571f180452360e Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 01:36:07 +0200 Subject: [PATCH 0561/1761] [metacafe] Add support for movieclips videos (Fixes #3555) --- youtube_dl/extractor/metacafe.py | 66 +++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/youtube_dl/extractor/metacafe.py b/youtube_dl/extractor/metacafe.py index 96a4f1018..1a896b536 100644 --- a/youtube_dl/extractor/metacafe.py +++ b/youtube_dl/extractor/metacafe.py @@ -9,6 +9,7 @@ from ..utils import ( compat_urllib_request, determine_ext, ExtractorError, + int_or_none, ) @@ -83,6 +84,21 @@ class MetacafeIE(InfoExtractor): 'skip_download': True, }, }, + # Movieclips.com video + { + 'url': 'http://www.metacafe.com/watch/mv-Wy7ZU/my_week_with_marilyn_do_you_love_me/', + 'info_dict': { + 'id': 'mv-Wy7ZU', + 'ext': 'mp4', + 'title': 'My Week with Marilyn - Do You Love Me?', + 'description': 'From the movie My Week with Marilyn - Colin (Eddie Redmayne) professes his love to Marilyn (Michelle Williams) and gets her to promise to return to set and finish the movie.', + 'uploader': 'movie_trailers', + 'duration': 176, + }, + 'params': { + 'skip_download': 'requires rtmpdump', + } + } ] def report_disclaimer(self): @@ -167,7 +183,36 @@ class MetacafeIE(InfoExtractor): mediaURL = mobj.group('mediaURL').replace('\\/', '/') video_url = '%s?__gda__=%s' % (mediaURL, mobj.group('key')) video_ext = determine_ext(video_url) + if video_url is None: + player_url = self._search_regex( + r"swfobject\.embedSWF\('([^']+)'", + webpage, 'config URL', default=None) + if player_url: + config_url = self._search_regex( + r'config=(.+)$', player_url, 'config URL') + config_doc = self._download_xml( + config_url, video_id, + note='Downloading video config') + smil_url = config_doc.find('.//properties').attrib['smil_file'] + smil_doc = self._download_xml( + smil_url, video_id, + note='Downloading SMIL document') + base_url = smil_doc.find('./head/meta').attrib['base'] + video_url = [] + for vn in smil_doc.findall('.//video'): + br = int(vn.attrib['system-bitrate']) + play_path = vn.attrib['src'] + video_url.append({ + 'format_id': 'smil-%d' % br, + 'url': base_url, + 'play_path': play_path, + 'page_url': url, + 'player_url': player_url, + 'ext': play_path.partition(':')[0], + }) + if video_url is None: + raise ExtractorError('Unsupported video type') video_title = self._html_search_regex( r'(?im)(.*) - Video', webpage, 'title') @@ -176,19 +221,30 @@ class MetacafeIE(InfoExtractor): video_uploader = self._html_search_regex( r'submitter=(.*?);|googletag\.pubads\(\)\.setTargeting\("(?:channel|submiter)","([^"]+)"\);', webpage, 'uploader nickname', fatal=False) + duration = int_or_none( + self._html_search_meta('video:duration', webpage)) - if re.search(r'"contentRating":"restricted"', webpage) is not None: - age_limit = 18 + age_limit = ( + 18 + if re.search(r'"contentRating":"restricted"', webpage) + else 0) + + if isinstance(video_url, list): + formats = video_url else: - age_limit = 0 + formats = [{ + 'url': video_url, + 'ext': video_ext, + }] + self._sort_formats(formats) return { 'id': video_id, - 'url': video_url, 'description': description, 'uploader': video_uploader, 'title': video_title, 'thumbnail': thumbnail, - 'ext': video_ext, 'age_limit': age_limit, + 'formats': formats, + 'duration': duration, } From 91dff03217fabf34b04f2ee811dfd98149739678 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 01:43:19 +0200 Subject: [PATCH 0562/1761] [dump] Modernize (#3565) --- youtube_dl/extractor/dump.py | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/youtube_dl/extractor/dump.py b/youtube_dl/extractor/dump.py index 4b756b20a..6b651778a 100644 --- a/youtube_dl/extractor/dump.py +++ b/youtube_dl/extractor/dump.py @@ -4,19 +4,19 @@ from __future__ import unicode_literals import re from .common import InfoExtractor -from ..utils import ( - ExtractorError, -) + class DumpIE(InfoExtractor): _VALID_URL = r'^https?://(?:www\.)?dump\.com/(?P[a-zA-Z0-9]+)/' _TEST = { - u'url': u'http://www.dump.com/oneus/', - u'file': u'oneus.flv', - u'md5': u'ad71704d1e67dfd9e81e3e8b42d69d99', - u'info_dict': { - u"title": u"He's one of us.", + 'url': 'http://www.dump.com/oneus/', + 'md5': 'ad71704d1e67dfd9e81e3e8b42d69d99', + 'info_dict': { + 'id': 'oneus', + 'ext': 'flv', + 'title': "He's one of us.", + 'thumbnail': 're:^https?://.*\.jpg$', }, } @@ -24,25 +24,16 @@ class DumpIE(InfoExtractor): m = re.match(self._VALID_URL, url) video_id = m.group('id') - # Note: There is an easier-to-parse configuration at - # http://www.aparat.com/video/video/config/videohash/%video_id - # but the URL in there does not work - webpage = self._download_webpage(url, video_id) + video_url = self._search_regex( + r's1.addVariable\("file",\s*"([^"]+)"', webpage, 'video URL') - try: - video_url = re.findall(r'file","(.+?.flv)"', webpage)[-1] - except IndexError: - raise ExtractorError(u'No video URL found') - - thumb = re.findall('([^"]+)', webpage, u'title') + thumb = self._og_search_thumbnail(webpage) + title = self._search_regex(r'([^"]+)', webpage, 'title') return { 'id': video_id, 'title': title, 'url': video_url, - 'ext': 'flv', 'thumbnail': thumb, } From 5fcf2dbed0f704c96d9d14fadcbe1c3bf4f7f2cc Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 01:44:35 +0200 Subject: [PATCH 0563/1761] [aparat] modernize --- youtube_dl/extractor/aparat.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/youtube_dl/extractor/aparat.py b/youtube_dl/extractor/aparat.py index 7e93bc4df..748608826 100644 --- a/youtube_dl/extractor/aparat.py +++ b/youtube_dl/extractor/aparat.py @@ -1,5 +1,7 @@ #coding: utf-8 +from __future__ import unicode_literals + import re from .common import InfoExtractor @@ -13,13 +15,14 @@ class AparatIE(InfoExtractor): _VALID_URL = r'^https?://(?:www\.)?aparat\.com/(?:v/|video/video/embed/videohash/)(?P[a-zA-Z0-9]+)' _TEST = { - u'url': u'http://www.aparat.com/v/wP8On', - u'file': u'wP8On.mp4', - u'md5': u'6714e0af7e0d875c5a39c4dc4ab46ad1', - u'info_dict': { - u"title": u"تیم گلکسی 11 - زومیت", + 'url': 'http://www.aparat.com/v/wP8On', + 'md5': '6714e0af7e0d875c5a39c4dc4ab46ad1', + 'info_dict': { + 'id': 'wP8On', + 'ext': 'mp4', + 'title': 'تیم گلکسی 11 - زومیت', }, - #u'skip': u'Extremely unreliable', + # 'skip': 'Extremely unreliable', } def _real_extract(self, url): @@ -29,8 +32,8 @@ class AparatIE(InfoExtractor): # Note: There is an easier-to-parse configuration at # http://www.aparat.com/video/video/config/videohash/%video_id # but the URL in there does not work - embed_url = (u'http://www.aparat.com/video/video/embed/videohash/' + - video_id + u'/vt/frame') + embed_url = ('http://www.aparat.com/video/video/embed/videohash/' + + video_id + '/vt/frame') webpage = self._download_webpage(embed_url, video_id) video_urls = re.findall(r'fileList\[[0-9]+\]\s*=\s*"([^"]+)"', webpage) From e62e150f6403b992baa2a094a602e30f1375c111 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 01:47:42 +0200 Subject: [PATCH 0564/1761] [README] brevity is the soul of wit These instructions are overly long as it is. Leave out the _TESTS example; most developers will not need it in their first IE. --- README.md | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/README.md b/README.md index efd8a3d06..3a622cf0c 100644 --- a/README.md +++ b/README.md @@ -453,34 +453,7 @@ If you want to add support for a new site, you can follow this quick list (assum ``` 5. Add an import in [`youtube_dl/extractor/__init__.py`](https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/__init__.py). 6. Run `python test/test_download.py TestDownload.test_YourExtractor`. This *should fail* at first, but you can continually re-run it until you're done. - * If you decide to add more than one test, then rename the ``_TEST`` variable to ``_TESTS`` and make it into a list of dictionaries, like the example below. The tests will be then respectfully be named `TestDownload.test_YourExtractor`, `TestDownload.test_YourExtractor_1`, `TestDownload.test_YourExtractor_2`, etc. - ```python - _TESTS = [ - { - 'url': 'http://yourextractor.com/watch/42', - 'md5': 'TODO: md5 sum of the first 10KiB of the video file', - 'info_dict': { - 'id': '42', - 'ext': 'mp4', - 'title': 'Video title goes here', - # TODO more properties, either as: - # * A value - # * MD5 checksum; start the string with md5: - # * A regular expression; start the string with re: - # * Any Python type (for example int or float) - } - }, - { - 'url': 'http://yourextractor.com/watch/43', - 'md5': 'TODO: md5 sum of the first 10KiB of the video file', - 'info_dict': { - 'id': '43', - 'ext': 'mp4', - 'title': 'Video title goes here', - } - } - ] - ``` + * If you decide to add more than one test, then rename the ``_TEST`` variable to ``_TESTS`` and make it into a list of dictionaries. The tests will be then be named `TestDownload.test_YourExtractor`, `TestDownload.test_YourExtractor_1`, `TestDownload.test_YourExtractor_2`, etc. 7. Have a look at [`youtube_dl/common/extractor/common.py`](https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/common.py) for possible helper methods and a [detailed description of what your extractor should return](https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/common.py#L38). Add tests and code for as many as you want. 8. If you can, check the code with [pyflakes](https://pypi.python.org/pypi/pyflakes) (a good idea) and [pep8](https://pypi.python.org/pypi/pep8) (optional, ignore E501). 9. When the tests pass, [add](https://www.kernel.org/pub/software/scm/git/docs/git-add.html) the new files and [commit](https://www.kernel.org/pub/software/scm/git/docs/git-commit.html) them and [push](https://www.kernel.org/pub/software/scm/git/docs/git-push.html) the result, like this: From ace52c5713459cd176017f49a265f1d0cd58311d Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 01:51:26 +0200 Subject: [PATCH 0565/1761] [README] format --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 3a622cf0c..ba350b905 100644 --- a/README.md +++ b/README.md @@ -452,8 +452,7 @@ If you want to add support for a new site, you can follow this quick list (assum } ``` 5. Add an import in [`youtube_dl/extractor/__init__.py`](https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/__init__.py). -6. Run `python test/test_download.py TestDownload.test_YourExtractor`. This *should fail* at first, but you can continually re-run it until you're done. - * If you decide to add more than one test, then rename the ``_TEST`` variable to ``_TESTS`` and make it into a list of dictionaries. The tests will be then be named `TestDownload.test_YourExtractor`, `TestDownload.test_YourExtractor_1`, `TestDownload.test_YourExtractor_2`, etc. +6. Run `python test/test_download.py TestDownload.test_YourExtractor`. This *should fail* at first, but you can continually re-run it until you're done. If you decide to add more than one test, then rename ``_TEST`` to ``_TESTS`` and make it into a list of dictionaries. The tests will be then be named `TestDownload.test_YourExtractor`, `TestDownload.test_YourExtractor_1`, `TestDownload.test_YourExtractor_2`, etc. 7. Have a look at [`youtube_dl/common/extractor/common.py`](https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/common.py) for possible helper methods and a [detailed description of what your extractor should return](https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/common.py#L38). Add tests and code for as many as you want. 8. If you can, check the code with [pyflakes](https://pypi.python.org/pypi/pyflakes) (a good idea) and [pep8](https://pypi.python.org/pypi/pep8) (optional, ignore E501). 9. When the tests pass, [add](https://www.kernel.org/pub/software/scm/git/docs/git-add.html) the new files and [commit](https://www.kernel.org/pub/software/scm/git/docs/git-commit.html) them and [push](https://www.kernel.org/pub/software/scm/git/docs/git-push.html) the result, like this: From e05f693942b0dacecc60b987a79859ee62b58ab9 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 02:33:29 +0200 Subject: [PATCH 0566/1761] [patreon] Simplify (#3390) --- youtube_dl/extractor/patreon.py | 112 ++++++++++---------------------- youtube_dl/utils.py | 28 ++++++++ 2 files changed, 61 insertions(+), 79 deletions(-) diff --git a/youtube_dl/extractor/patreon.py b/youtube_dl/extractor/patreon.py index 4ddff42e6..707a54e3a 100644 --- a/youtube_dl/extractor/patreon.py +++ b/youtube_dl/extractor/patreon.py @@ -1,81 +1,19 @@ # encoding: utf-8 from __future__ import unicode_literals +import json import re from .common import InfoExtractor from ..utils import ( - ExtractorError, - compat_html_parser, - #compat_urllib_request, - #compat_urllib_parse, + compat_urlparse, + js_to_json, ) -class PatreonHTMLParser(compat_html_parser.HTMLParser): - _PREFIX = 'http://www.patreon.com' - _ATTACH_TAGS = 5 * ['div'] - _ATTACH_CLASSES = [ - 'fancyboxhidden', 'box photo', 'boxwrapper', - 'hiddendisplay shareinfo', 'attach' - ] - _INFO_TAGS = 4 * ['div'] - _INFO_CLASSES = [ - 'fancyboxhidden', 'box photo', 'boxwrapper', - 'hiddendisplay shareinfo' - ] - - def _match(self, attrs_classes, desired): - if attrs_classes == desired: - return True - elif len(attrs_classes) == len(desired): - return all( - x.startswith(y) - for x, y in zip(attrs_classes, desired) - ) - return False - - def get_creation_info(self, html_data): - self.tag_stack = [] - self.attrs_stack = [] - self.creation_info = {} - self.feed(html_data) - - def handle_starttag(self, tag, attrs): - self.tag_stack.append(tag.lower()) - self.attrs_stack.append(dict(attrs)) - - def handle_endtag(self, tag): - self.tag_stack.pop() - self.attrs_stack.pop() - - def handle_data(self, data): - # Check first if this is a creation attachment - if self.tag_stack[-6:-1] == self._ATTACH_TAGS: - attrs_classes = [ - x.get('class', '').lower() for x in self.attrs_stack[-6:-1] - ] - if self._match(attrs_classes, self._ATTACH_CLASSES): - if self.tag_stack[-1] == 'a': - url = self._PREFIX + self.attrs_stack[-1].get('href') - self.creation_info['url'] = url - if '.' in data: - self.creation_info['ext'] = data.rsplit('.')[-1] - # Next, check if this is within the div containing the creation info - if self.tag_stack[-5:-1] == self._INFO_TAGS: - attrs_classes = [ - x.get('class', '').lower() for x in self.attrs_stack[-5:-1] - ] - if self._match(attrs_classes, self._INFO_CLASSES): - if self.attrs_stack[-1].get('class') == 'utitle': - self.creation_info['title'] = data.strip() - - class PatreonIE(InfoExtractor): - IE_NAME = 'patreon' _VALID_URL = r'https?://(?:www\.)?patreon\.com/creation\?hid=(.+)' _TESTS = [ - # CSS names with "double" in the name, i.e. "boxwrapper double" { 'url': 'http://www.patreon.com/creation?hid=743933', 'md5': 'e25505eec1053a6e6813b8ed369875cc', @@ -84,6 +22,7 @@ class PatreonIE(InfoExtractor): 'ext': 'mp3', 'title': 'Episode 166: David Smalley of Dogma Debate', 'uploader': 'Cognitive Dissonance Podcast', + 'thumbnail': 're:^https?://.*$', }, }, { @@ -94,6 +33,7 @@ class PatreonIE(InfoExtractor): 'ext': 'mp3', 'title': 'CD 167 Extra', 'uploader': 'Cognitive Dissonance Podcast', + 'thumbnail': 're:^https?://.*$', }, }, ] @@ -129,19 +69,33 @@ class PatreonIE(InfoExtractor): mobj = re.match(self._VALID_URL, url) video_id = mobj.group(1) - info_page = self._download_webpage(url, video_id) + webpage = self._download_webpage(url, video_id) + title = self._og_search_title(webpage).strip() - ret = {'id': video_id} - try: - ret['uploader'] = re.search( - r'(.+) is creating', info_page - ).group(1) - except AttributeError: - pass + attach_fn = self._html_search_regex( + r'
    ', + webpage, 'attachment URL', default=None) + if attach_fn is not None: + video_url = 'http://www.patreon.com' + attach_fn + thumbnail = self._og_search_thumbnail(webpage) + uploader = self._html_search_regex( + r'(.*?) is creating', webpage, 'uploader') + else: + playlist_js = self._search_regex( + r'(?s)new\s+jPlayerPlaylist\(\s*\{\s*[^}]*},\s*(\[.*?,?\s*\])', + webpage, 'playlist JSON') + playlist_json = js_to_json(playlist_js) + playlist = json.loads(playlist_json) + data = playlist[0] + video_url = self._proto_relative_url(data['mp3']) + thumbnail = self._proto_relative_url(data.get('cover')) + uploader = data.get('artist') - parser = PatreonHTMLParser() - parser.get_creation_info(info_page) - if not parser.creation_info.get('url'): - raise ExtractorError('Unable to retrieve creation URL') - ret.update(parser.creation_info) - return ret + return { + 'id': video_id, + 'url': video_url, + 'ext': 'mp3', + 'title': title, + 'uploader': uploader, + 'thumbnail': thumbnail, + } diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index f8ec5389f..42ad520f9 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -1474,6 +1474,34 @@ def strip_jsonp(code): return re.sub(r'(?s)^[a-zA-Z0-9_]+\s*\(\s*(.*)\);?\s*?\s*$', r'\1', code) +def js_to_json(code): + def fix_kv(m): + key = m.group(2) + if key.startswith("'"): + assert key.endswith("'") + assert '"' not in key + key = '"%s"' % key[1:-1] + elif not key.startswith('"'): + key = '"%s"' % key + + value = m.group(4) + if value.startswith("'"): + assert value.endswith("'") + assert '"' not in value + value = '"%s"' % value[1:-1] + + return m.group(1) + key + m.group(3) + value + + res = re.sub(r'''(?x) + ([{,]\s*) + ("[^"]*"|\'[^\']*\'|[a-z0-9A-Z]+) + (:\s*) + ([0-9.]+|true|false|"[^"]*"|\'[^\']*\'|\[|\{) + ''', fix_kv, code) + res = re.sub(r',(\s*\])', lambda m: m.group(1), res) + return res + + def qualities(quality_ids): """ Get a numeric quality value out of a list of possible values """ def q(qid): From deda8ac376efba365aa29bc31d4e37db03d0babd Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 02:34:22 +0200 Subject: [PATCH 0567/1761] Credit @terminalmage for patreon (#3390) --- youtube_dl/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 5d2137fe5..f156ba3a0 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -70,6 +70,7 @@ __authors__ = ( 'David Fabijan', 'Sebastian Haas', 'Alexander Kirk', + 'Erik Johnson', ) __license__ = 'Public Domain' From ad06434bd3cd0d132cabf7a359ff8f2f67aa2f5d Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 02:57:08 +0200 Subject: [PATCH 0568/1761] release 2014.08.22 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 15b9d6c61..b7656ce88 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.08.21.3' +__version__ = '2014.08.22' From 388ac0b18a263a3745eba3c6be2a1b8252db36b1 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 03:02:49 +0200 Subject: [PATCH 0569/1761] release 2014.08.22.1 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index b7656ce88..ce5d96fdf 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.08.22' +__version__ = '2014.08.22.1' From 756b046f3ea3444112a73daf3e34b56493ede086 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 03:16:08 +0200 Subject: [PATCH 0570/1761] [pbs] recognize class=partnerPlayer as well (Fixes #3564) --- youtube_dl/extractor/pbs.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/pbs.py b/youtube_dl/extractor/pbs.py index dee4af6f1..2adfde909 100644 --- a/youtube_dl/extractor/pbs.py +++ b/youtube_dl/extractor/pbs.py @@ -54,6 +54,18 @@ class PBSIE(InfoExtractor): 'duration': 801, }, }, + { + 'url': 'http://www.pbs.org/wnet/gperf/dudamel-conducts-verdi-requiem-hollywood-bowl-full-episode/3374/', + 'md5': 'c62859342be2a0358d6c9eb306595978', + 'info_dict': { + 'id': '2365297708', + 'ext': 'mp4', + 'description': 'md5:68d87ef760660eb564455eb30ca464fe', + 'title': 'Dudamel Conducts Verdi Requiem at the Hollywood Bowl - Full', + 'duration': 6559, + 'thumbnail': 're:^https?://.*\.jpg$', + } + } ] def _extract_ids(self, url): @@ -75,7 +87,7 @@ class PBSIE(InfoExtractor): return media_id, presumptive_id url = self._search_regex( - r'', + r'', webpage, 'player URL') mobj = re.match(self._VALID_URL, url) From 50b294aab8966c02c0946c0fbaad995d51ac5d55 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 03:16:16 +0200 Subject: [PATCH 0571/1761] release 2014.08.22.2 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index ce5d96fdf..4e79af131 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.08.22.1' +__version__ = '2014.08.22.2' From a053c3493a0a92c25a4d4fc03619bf27356c3811 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 03:44:30 +0200 Subject: [PATCH 0572/1761] [test_YoutubeDL] Reorder formats (#3542) --- test/test_YoutubeDL.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_YoutubeDL.py b/test/test_YoutubeDL.py index e794cc97f..ab61e1976 100644 --- a/test/test_YoutubeDL.py +++ b/test/test_YoutubeDL.py @@ -221,7 +221,7 @@ class TestFormatSelection(unittest.TestCase): '138', '137', '248', '136', '247', '135', '246', '245', '244', '134', '243', '133', '242', '160', # Dash audio - '141', '172', '140', '139', '171', + '141', '172', '140', '171', '139', ] for f1id, f2id in zip(order, order[1:]): From 218f754940b170ecb9affecfbe3dfe1c23430dc9 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 11:30:39 +0200 Subject: [PATCH 0573/1761] [README] Add thumbnail to _TEST example While it's not mandatory, extractors are highly encouraged to provide a thumbnail field. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ba350b905..72449cad7 100644 --- a/README.md +++ b/README.md @@ -429,6 +429,7 @@ If you want to add support for a new site, you can follow this quick list (assum 'id': '42', 'ext': 'mp4', 'title': 'Video title goes here', + 'thumbnail': 're:^https?://.*\.jpg$', # TODO more properties, either as: # * A value # * MD5 checksum; start the string with md5: From 394df6d7d0f4a5b90e45a519ba1c803484c0e087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Fri, 22 Aug 2014 21:41:51 +0700 Subject: [PATCH 0574/1761] [nuvid] Adapt to latest layout changes --- youtube_dl/extractor/nuvid.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/youtube_dl/extractor/nuvid.py b/youtube_dl/extractor/nuvid.py index 280328b78..58ec81f91 100644 --- a/youtube_dl/extractor/nuvid.py +++ b/youtube_dl/extractor/nuvid.py @@ -38,7 +38,7 @@ class NuvidIE(InfoExtractor): webpage = self._download_webpage( request, video_id, 'Downloading %s page' % format_id) video_url = self._html_search_regex( - r'Continue to watch video', webpage, '%s video URL' % format_id, fatal=False) + r'', webpage, '%s video URL' % format_id, fatal=False) if not video_url: continue formats.append({ @@ -49,19 +49,24 @@ class NuvidIE(InfoExtractor): webpage = self._download_webpage( 'http://m.nuvid.com/video/%s' % video_id, video_id, 'Downloading video page') title = self._html_search_regex( - r'
    \s+]*>([^<]+)', webpage, 'title').strip() - thumbnail = self._html_search_regex( - r'href="(/thumbs/[^"]+)"[^>]*data-link_type="thumbs"', - webpage, 'thumbnail URL', fatal=False) + [r'', + r'
    \s*]*>([^<]+)'], webpage, 'title').strip() + thumbnails = [ + { + 'url': thumb_url, + } for thumb_url in re.findall(r'', webpage) + ] + thumbnail = thumbnails[0]['url'] if thumbnails else None duration = parse_duration(self._html_search_regex( - r'Length:\s*(\d{2}:\d{2})',webpage, 'duration', fatal=False)) + r'\s*(\d{2}:\d{2})', webpage, 'duration', fatal=False)) upload_date = unified_strdate(self._html_search_regex( - r'Added:\s*(\d{4}-\d{2}-\d{2})', webpage, 'upload date', fatal=False)) + r'\s*(\d{4}-\d{2}-\d{2})', webpage, 'upload date', fatal=False)) return { 'id': video_id, 'title': title, - 'thumbnail': 'http://m.nuvid.com%s' % thumbnail, + 'thumbnails': thumbnails, + 'thumbnail': thumbnail, 'duration': duration, 'upload_date': upload_date, 'age_limit': 18, From e330d59abb18a6fcd74ec36d89f8d6ce49f8ad37 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 17:34:50 +0200 Subject: [PATCH 0575/1761] [playfm] Add extractor (Fixes #3538) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/playfm.py | 82 ++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 youtube_dl/extractor/playfm.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 9be1d2e0f..da9606f24 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -243,6 +243,7 @@ from .parliamentliveuk import ParliamentLiveUKIE from .patreon import PatreonIE from .pbs import PBSIE from .photobucket import PhotobucketIE +from .playfm import PlayFMIE from .playvid import PlayvidIE from .podomatic import PodomaticIE from .pornhd import PornHdIE diff --git a/youtube_dl/extractor/playfm.py b/youtube_dl/extractor/playfm.py new file mode 100644 index 000000000..72df4d842 --- /dev/null +++ b/youtube_dl/extractor/playfm.py @@ -0,0 +1,82 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ( + compat_urllib_parse, + compat_urllib_request, + ExtractorError, + float_or_none, + int_or_none, +) + + +class PlayFMIE(InfoExtractor): + IE_NAME = 'play.fm' + _VALID_URL = r'https?://(?:www\.)?play\.fm/[^?#]*(?P[0-9]{8})(?P[0-9]{6})(?:$|[?#])' + + _TEST = { + 'url': 'http://www.play.fm/recording/leipzigelectronicmusicbatofarparis_fr20140712137220', + 'md5': 'c505f8307825a245d0c7ad1850001f22', + 'info_dict': { + 'id': '137220', + 'ext': 'mp3', + 'title': 'LEIPZIG ELECTRONIC MUSIC @ Batofar (Paris,FR) - 2014-07-12', + 'uploader': 'Sven Tasnadi', + 'uploader_id': 'sventasnadi', + 'duration': 5627.428, + 'upload_date': '20140712', + 'view_count': int, + 'thumbnail': 're:^https?://.*\.jpg$', + }, + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + upload_date = mobj.group('upload_date') + + rec_data = compat_urllib_parse.urlencode({'rec_id': video_id}) + req = compat_urllib_request.Request( + 'http://www.play.fm/flexRead/recording', data=rec_data) + req.add_header('Content-Type', 'application/x-www-form-urlencoded') + rec_doc = self._download_xml(req, video_id) + + error_node = rec_doc.find('./error') + if error_node is not None: + raise ExtractorError('An error occured: %s (code %s)' % ( + error_node.text, rec_doc.find('./status').text)) + + recording = rec_doc.find('./recording') + title = recording.find('./title').text + view_count = int_or_none(recording.find('./stats/playcount').text) + duration = float_or_none(recording.find('./duration').text, scale=1000) + thumbnail = recording.find('./image').text + + artist = recording.find('./artists/artist') + uploader = artist.find('./name').text + uploader_id = artist.find('./slug').text + + video_url = '%s//%s/%s/%s/offset/0/sh/%s/rec/%s/jingle/%s/loc/%s' % ( + 'http:', recording.find('./url').text, + recording.find('./_class').text, recording.find('./file_id').text, + rec_doc.find('./uuid').text, video_id, + rec_doc.find('./jingle/file_id').text, + 'http%3A%2F%2Fwww.play.fm%2Fplayer', + ) + + return { + 'id': video_id, + 'url': video_url, + 'ext': 'mp3', + 'filesize': int_or_none(recording.find('./size').text), + 'title': title, + 'upload_date': upload_date, + 'view_count': view_count, + 'duration': duration, + 'thumbnail': thumbnail, + 'uploader': uploader, + 'uploader_id': uploader_id, + } From be843678b134a76b3509b0ced99dd9fff3867a25 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 17:46:57 +0200 Subject: [PATCH 0576/1761] [YouTubeDL] Correct handling of age_limit = None in result --- youtube_dl/YoutubeDL.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index e7194f3e3..a671d6450 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -480,7 +480,10 @@ class YoutubeDL(object): return 'Skipping %s, because it has exceeded the maximum view count (%d/%d)' % (video_title, view_count, max_views) age_limit = self.params.get('age_limit') if age_limit is not None: - if age_limit < info_dict.get('age_limit', 0): + actual_age_limit = info_dict.get('age_limit') + if actual_age_limit is None: + actual_age_limit = 0 + if age_limit < actual_age_limit: return 'Skipping "' + title + '" because it is age restricted' if self.in_download_archive(info_dict): return '%s has already been recorded in archive' % video_title From ed2d6a19607e965602d66ea90ac716118b739a16 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 18:19:56 +0200 Subject: [PATCH 0577/1761] [generic] Simplify playlist support (#2948) --- youtube_dl/extractor/generic.py | 65 +++++++++++---------------------- 1 file changed, 22 insertions(+), 43 deletions(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 7246ea7fc..2ff691b45 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -16,6 +16,7 @@ from ..utils import ( ExtractorError, HEADRequest, + orderedSet, parse_xml, smuggle_url, unescapeHTML, @@ -292,15 +293,17 @@ class GenericIE(InfoExtractor): # YouTube embed via { 'url': 'https://play.google.com/store/apps/details?id=com.gameloft.android.ANMP.GloftA8HM', - 'md5': 'c267b1ab6d736057d64babaa37e07a66', 'info_dict': { - 'id': 'Ybd-qmqYYpA', + 'id': 'jpSGZsgga_I', 'ext': 'mp4', - 'title': 'Asphalt 8: Airborne - Chinese Great Wall - Android Game Trailer', - 'uploader': 'gameloftandroid', - 'uploader_id': 'gameloftandroid', - 'upload_date': '20140321', - 'description': 'md5:9c6dca5dd75b7131ce482ccf080749d6' + 'title': 'Asphalt 8: Airborne - Launch Trailer', + 'uploader': 'Gameloft', + 'uploader_id': 'gameloft', + 'upload_date': '20130821', + 'description': 'md5:87bd95f13d8be3e7da87a5f2c443106a', + }, + 'params': { + 'skip_download': True, } } ] @@ -493,6 +496,12 @@ class GenericIE(InfoExtractor): video_uploader = self._search_regex( r'^(?:https?://)?([^/]*)/.*', url, 'video uploader') + # Helper method + def _playlist_from_matches(matches, getter, ie=None): + urlrs = orderedSet(self.url_result(getter(m), ie) for m in matches) + return self.playlist_result( + urlrs, playlist_id=video_id, playlist_title=video_title) + # Look for BrightCove: bc_urls = BrightcoveIE._extract_brightcove_urls(webpage) if bc_urls: @@ -537,35 +546,15 @@ class GenericIE(InfoExtractor): (?:embed|v)/.+?) \1''', webpage) if matches: - urlrs = [self.url_result(unescapeHTML(tuppl[1]), 'Youtube') - for tuppl in matches] - # First, ensure we have a duplicate free list of entries - seen = set() - new_list = [] - theurl = tuple(url.items()) - if theurl not in seen: - seen.add(theurl) - new_list.append(url) - urlrs = new_list - return self.playlist_result( - urlrs, playlist_id=video_id, playlist_title=video_title) + return _playlist_from_matches( + matches, lambda m: unescapeHTML(m[1]), ie='Youtube') # Look for embedded Dailymotion player matches = re.findall( r']+?src=(["\'])(?P(?:https?:)?//(?:www\.)?dailymotion\.com/embed/video/.+?)\1', webpage) if matches: - urlrs = [self.url_result(unescapeHTML(tuppl[1])) - for tuppl in matches] - # First, ensure we have a duplicate free list of entries - seen = set() - new_list = [] - theurl = tuple(url.items()) - if theurl not in seen: - seen.add(theurl) - new_list.append(url) - urlrs = new_list - return self.playlist_result( - urlrs, playlist_id=video_id, playlist_title=video_title) + return _playlist_from_matches( + matches, lambda m: unescapeHTML(m[1])) # Look for embedded Wistia player match = re.search( @@ -679,18 +668,8 @@ class GenericIE(InfoExtractor): # Look for funnyordie embed matches = re.findall(r']+?src="(https?://(?:www\.)?funnyordie\.com/embed/[^"]+)"', webpage) if matches: - urlrs = [self.url_result(unescapeHTML(eurl), 'FunnyOrDie') - for eurl in matches] - # First, ensure we have a duplicate free list of entries - seen = set() - new_list = [] - theurl = tuple(url.items()) - if theurl not in seen: - seen.add(theurl) - new_list.append(url) - urlrs = new_list - return self.playlist_result( - urlrs, playlist_id=video_id, playlist_title=video_title) + return _playlist_from_matches( + matches, getter=unescapeHTML, ie='FunnyOrDie') # Look for embedded RUTV player rutv_url = RUTVIE._extract_url(webpage) From 2b9faf55427b73cb978ddd661c32a5cb313f9331 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 18:40:26 +0200 Subject: [PATCH 0578/1761] [rtve] Add support for live stream At the moment, only RTVE-1 seems to work flawlessly. -2 seems geoblocked right now. -TDP doesn't seem to be available outside of Spain. --- youtube_dl/extractor/__init__.py | 2 +- youtube_dl/extractor/rtve.py | 152 +++++++++++++++++++++---------- youtube_dl/utils.py | 6 ++ 3 files changed, 113 insertions(+), 47 deletions(-) diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index da9606f24..3753fa291 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -264,7 +264,7 @@ from .rtbf import RTBFIE from .rtlnl import RtlXlIE from .rtlnow import RTLnowIE from .rts import RTSIE -from .rtve import RTVEALaCartaIE +from .rtve import RTVEALaCartaIE, RTVELiveIE from .ruhd import RUHDIE from .rutube import ( RutubeIE, diff --git a/youtube_dl/extractor/rtve.py b/youtube_dl/extractor/rtve.py index c2228b2f0..8cf753902 100644 --- a/youtube_dl/extractor/rtve.py +++ b/youtube_dl/extractor/rtve.py @@ -1,21 +1,66 @@ # encoding: utf-8 from __future__ import unicode_literals -import re import base64 +import re +import time from .common import InfoExtractor from ..utils import ( struct_unpack, + remove_end, ) +def _decrypt_url(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 + + + class RTVEALaCartaIE(InfoExtractor): IE_NAME = 'rtve.es:alacarta' IE_DESC = 'RTVE a la carta' _VALID_URL = r'http://www\.rtve\.es/alacarta/videos/[^/]+/[^/]+/(?P\d+)' - _TEST = { + _TESTS = [{ 'url': 'http://www.rtve.es/alacarta/videos/balonmano/o-swiss-cup-masculina-final-espana-suecia/2491869/', 'md5': '1d49b7e1ca7a7502c56a4bf1b60f1b43', 'info_dict': { @@ -23,48 +68,15 @@ class RTVEALaCartaIE(InfoExtractor): '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 + }, { + 'note': 'Live stream', + 'url': 'http://www.rtve.es/alacarta/videos/television/24h-live/1694255/', + 'info_dict': { + 'id': '1694255', + 'ext': 'flv', + 'title': 'TODO', + } + }] def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) @@ -74,11 +86,59 @@ class RTVEALaCartaIE(InfoExtractor): 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) + video_url = _decrypt_url(png) return { 'id': video_id, 'title': info['title'], 'url': video_url, - 'thumbnail': info['image'], + 'thumbnail': info.get('image'), + 'page_url': url, + } + + +class RTVELiveIE(InfoExtractor): + IE_NAME = 'rtve.es:live' + IE_DESC = 'RTVE.es live streams' + _VALID_URL = r'http://www\.rtve\.es/(?:deportes/directo|noticias(?=/directo-la-1)|television)/(?P[a-zA-Z0-9-]+)' + + _TESTS = [{ + 'url': 'http://www.rtve.es/noticias/directo-la-1/', + 'info_dict': { + 'id': 'directo-la-1', + 'ext': 'flv', + 'title': 're:^La 1 de TVE [0-9]{4}-[0-9]{2}-[0-9]{2}Z[0-9]{6}$', + }, + 'params': { + 'skip_download': 'live stream', + } + }] + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + start_time = time.gmtime() + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + player_url = self._search_regex( + r'', webpage, 'player URL') + title = remove_end(self._og_search_title(webpage), ' en directo') + title += ' ' + time.strftime('%Y-%m-%dZ%H%M%S', start_time) + + vidplayer_id = self._search_regex( + r' id="vidplayer([0-9]+)"', webpage, 'internal video ID') + png_url = 'http://www.rtve.es/ztnr/movil/thumbnail/default/videos/%s.png' % vidplayer_id + png = self._download_webpage(png_url, video_id, 'Downloading url information') + video_url = _decrypt_url(png) + + print(video_url) + + return { + 'id': video_id, + 'ext': 'flv', + 'title': title, + 'url': video_url, + 'app': 'rtve-live-live?ovpfv=2.1.2', + 'player_url': player_url, + 'rtmp_live': True, } diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 42ad520f9..ac8a78adf 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -1285,6 +1285,12 @@ def remove_start(s, start): return s +def remove_end(s, end): + if s.endswith(end): + return s[:-len(end)] + return s + + def url_basename(url): path = compat_urlparse.urlparse(url).path return path.strip(u'/').split(u'/')[-1] From 492641d10a1d9748cfb675f68c9804530f8eca16 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 18:41:43 +0200 Subject: [PATCH 0579/1761] release 2014.08.22.3 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 4e79af131..b2484e508 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.08.22.2' +__version__ = '2014.08.22.3' From 9d048a17d818764e7f0d24519a09a36442d455ea Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 22 Aug 2014 18:47:49 +0200 Subject: [PATCH 0580/1761] [rtve.es:live] Start supporting the 24h channel --- youtube_dl/extractor/rtve.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/youtube_dl/extractor/rtve.py b/youtube_dl/extractor/rtve.py index 8cf753902..4dd35a47b 100644 --- a/youtube_dl/extractor/rtve.py +++ b/youtube_dl/extractor/rtve.py @@ -100,7 +100,7 @@ class RTVEALaCartaIE(InfoExtractor): class RTVELiveIE(InfoExtractor): IE_NAME = 'rtve.es:live' IE_DESC = 'RTVE.es live streams' - _VALID_URL = r'http://www\.rtve\.es/(?:deportes/directo|noticias(?=/directo-la-1)|television)/(?P[a-zA-Z0-9-]+)' + _VALID_URL = r'http://www\.rtve\.es/(?:deportes/directo|noticias|television)/(?P[a-zA-Z0-9-]+)' _TESTS = [{ 'url': 'http://www.rtve.es/noticias/directo-la-1/', @@ -131,8 +131,6 @@ class RTVELiveIE(InfoExtractor): png = self._download_webpage(png_url, video_id, 'Downloading url information') video_url = _decrypt_url(png) - print(video_url) - return { 'id': video_id, 'ext': 'flv', From 68909f0c4ec1722016b6d090c5a851d1f6013de8 Mon Sep 17 00:00:00 2001 From: MikeCol Date: Fri, 22 Aug 2014 22:17:07 +0200 Subject: [PATCH 0581/1761] changed _VALID_URL to allow for country specific prefixes --- youtube_dl/extractor/xhamster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/xhamster.py b/youtube_dl/extractor/xhamster.py index 5374495f9..00b6d1eba 100644 --- a/youtube_dl/extractor/xhamster.py +++ b/youtube_dl/extractor/xhamster.py @@ -14,7 +14,7 @@ from ..utils import ( class XHamsterIE(InfoExtractor): """Information Extractor for xHamster""" - _VALID_URL = r'http://(?:www\.)?xhamster\.com/movies/(?P[0-9]+)/(?P.+?)\.html(?:\?.*)?' + _VALID_URL = r'http://(?:.+?\.)?xhamster\.com/movies/(?P[0-9]+)/(?P.+?)\.html(?:\?.*)?' _TESTS = [ { 'url': 'http://xhamster.com/movies/1509445/femaleagent_shy_beauty_takes_the_bait.html', From bc0bb6fd30ba9b2e2fbdd6d43c307d54015aca6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sat, 23 Aug 2014 17:44:56 +0700 Subject: [PATCH 0582/1761] [movieclips] Add extractor (Closes #3554) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/movieclips.py | 78 ++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 youtube_dl/extractor/movieclips.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 3753fa291..5fe3d39b1 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -194,6 +194,7 @@ from .mooshare import MooshareIE from .morningstar import MorningstarIE from .motherless import MotherlessIE from .motorsport import MotorsportIE +from .movieclips import MovieClipsIE from .moviezine import MoviezineIE from .movshare import MovShareIE from .mtv import ( diff --git a/youtube_dl/extractor/movieclips.py b/youtube_dl/extractor/movieclips.py new file mode 100644 index 000000000..456807dd1 --- /dev/null +++ b/youtube_dl/extractor/movieclips.py @@ -0,0 +1,78 @@ +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ( + ExtractorError, + compat_str, + clean_html, +) + + +class MovieClipsIE(InfoExtractor): + _VALID_URL = r'https?://movieclips\.com/(?P[\da-zA-Z]+)(?:-(?P[\da-z-]+))?' + _TEST = { + 'url': 'http://movieclips.com/Wy7ZU-my-week-with-marilyn-movie-do-you-love-me/', + 'info_dict': { + 'id': 'Wy7ZU', + 'display_id': 'my-week-with-marilyn-movie-do-you-love-me', + 'ext': 'mp4', + 'title': 'My Week with Marilyn - Do You Love Me?', + 'description': 'md5:e86795bd332fe3cff461e7c8dc542acb', + 'thumbnail': 're:^https?://.*\.jpg$', + }, + 'params': { + # rtmp download + 'skip_download': True, + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + display_id = mobj.group('display_id') + show_id = display_id or video_id + + config = self._download_xml( + 'http://config.movieclips.com/player/config/%s' % video_id, + show_id, 'Downloading player config') + + if config.find('./country-region').text == 'false': + raise ExtractorError( + '%s said: %s' % (self.IE_NAME, config.find('./region_alert').text), expected=True) + + properties = config.find('./video/properties') + smil_file = properties.attrib['smil_file'] + + smil = self._download_xml(smil_file, show_id, 'Downloading SMIL') + base_url = smil.find('./head/meta').attrib['base'] + + formats = [] + for video in smil.findall('./body/switch/video'): + vbr = int(video.attrib['system-bitrate']) / 1000 + src = video.attrib['src'] + formats.append({ + 'url': base_url, + 'play_path': src, + 'ext': src.split(':')[0], + 'vbr': vbr, + 'format_id': '%dk' % vbr, + }) + + self._sort_formats(formats) + + title = '%s - %s' % (properties.attrib['clip_movie_title'], properties.attrib['clip_title']) + description = clean_html(compat_str(properties.attrib['clip_description'])) + thumbnail = properties.attrib['image'] + categories = properties.attrib['clip_categories'].split(',') + + return { + 'id': video_id, + 'display_id': display_id, + 'title': title, + 'description': description, + 'thumbnail': thumbnail, + 'categories': categories, + 'formats': formats, + } From b7b04c92348d25346f2a09f3f193b7a174969cbb Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 23 Aug 2014 14:39:45 +0200 Subject: [PATCH 0583/1761] [vodlocker] Allow title to end with a
    --- youtube_dl/extractor/vodlocker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/vodlocker.py b/youtube_dl/extractor/vodlocker.py index 6d3b78749..affef6507 100644 --- a/youtube_dl/extractor/vodlocker.py +++ b/youtube_dl/extractor/vodlocker.py @@ -44,7 +44,7 @@ class VodlockerIE(InfoExtractor): req, video_id, 'Downloading video page') title = self._search_regex( - r'id="file_title".*?>\s*(.*?)\s*\s*(.*?)\s*<(?:br|span)', webpage, 'title') thumbnail = self._search_regex( r'image:\s*"(http[^\"]+)",', webpage, 'thumbnail') url = self._search_regex( From af1fd929c6bb7ec077b9a2c34957834cfb560b6e Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 23 Aug 2014 15:04:11 +0200 Subject: [PATCH 0584/1761] [patreon] Remove unused import --- youtube_dl/extractor/patreon.py | 1 - 1 file changed, 1 deletion(-) diff --git a/youtube_dl/extractor/patreon.py b/youtube_dl/extractor/patreon.py index 707a54e3a..5429592a7 100644 --- a/youtube_dl/extractor/patreon.py +++ b/youtube_dl/extractor/patreon.py @@ -6,7 +6,6 @@ import re from .common import InfoExtractor from ..utils import ( - compat_urlparse, js_to_json, ) From 38fc045253095b61f1e1a2af1559e199a9b66eaa Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 23 Aug 2014 15:05:21 +0200 Subject: [PATCH 0585/1761] [rtlnl] Remove unused code --- youtube_dl/extractor/rtlnl.py | 1 - 1 file changed, 1 deletion(-) diff --git a/youtube_dl/extractor/rtlnl.py b/youtube_dl/extractor/rtlnl.py index 14928cd62..190c8f226 100644 --- a/youtube_dl/extractor/rtlnl.py +++ b/youtube_dl/extractor/rtlnl.py @@ -35,7 +35,6 @@ class RtlXlIE(InfoExtractor): info = self._download_json( 'http://www.rtl.nl/system/s4m/vfd/version=2/uuid=%s/fmt=flash/' % uuid, uuid) - meta = info['meta'] material = info['material'][0] episode_info = info['episodes'][0] From 2ef6fcb5d812278db13768fb461239cbfafbbe6f Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 23 Aug 2014 15:20:49 +0200 Subject: [PATCH 0586/1761] [sbs] Add new extractor (Fixes #3566) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/generic.py | 7 ++++ youtube_dl/extractor/sbs.py | 56 ++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 youtube_dl/extractor/sbs.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 5fe3d39b1..ddcf2e414 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -276,6 +276,7 @@ from .rutube import ( from .rutv import RUTVIE from .sapo import SapoIE from .savefrom import SaveFromIE +from .sbs import SBSIE from .scivee import SciVeeIE from .screencast import ScreencastIE from .servingsys import ServingSysIE diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 2ff691b45..62b1da25e 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -731,6 +731,13 @@ class GenericIE(InfoExtractor): if mobj is not None: return self.url_result(mobj.group('url'), 'Yahoo') + # Look for embedded sbs.com.au player + mobj = re.search( + r']+?src=(["\'])(?Phttps?://(?:www\.)sbs\.com\.au/ondemand/video/single/.+?)\1', + webpage) + if mobj is not None: + return self.url_result(mobj.group('url'), 'SBS') + # Start with something easy: JW Player in SWFObject found = re.findall(r'flashvars: [\'"](?:.*&)?file=(http[^\'"&]*)', webpage) if not found: diff --git a/youtube_dl/extractor/sbs.py b/youtube_dl/extractor/sbs.py new file mode 100644 index 000000000..34058fd4b --- /dev/null +++ b/youtube_dl/extractor/sbs.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import json +import re +from .common import InfoExtractor +from ..utils import ( + js_to_json, + remove_end, +) + + +class SBSIE(InfoExtractor): + IE_DESC = 'sbs.com.au' + _VALID_URL = r'https?://(?:www\.)?sbs\.com\.au/ondemand/video/single/(?P[0-9]+)/' + + _TESTS = [{ + # Original URL is handled by the generic IE which finds the iframe: + # http://www.sbs.com.au/thefeed/blog/2014/08/21/dingo-conservation + 'url': 'http://www.sbs.com.au/ondemand/video/single/320403011771/?source=drupal&vertical=thefeed', + 'md5': '3150cf278965eeabb5b4cea1c963fe0a', + 'info_dict': { + 'id': '320403011771', + 'ext': 'flv', + 'title': 'Dingo Conservation', + 'description': 'Dingoes are on the brink of extinction; most of the animals we think are dingoes are in fact crossbred with wild dogs. This family run a dingo conservation park to prevent their extinction', + 'thumbnail': 're:http://.*\.jpg', + }, + 'add_ies': ['generic'], + }] + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + webpage = self._download_webpage(url, video_id) + + release_urls_json = js_to_json(self._search_regex( + r'(?s)playerParams\.releaseUrls\s*=\s*(\{.*?\n\});\n', + webpage, '')) + release_urls = json.loads(release_urls_json) + theplatform_url = ( + release_urls.get('progressive') or release_urls.get('standard')) + + title = remove_end(self._og_search_title(webpage), ' (The Feed)') + description = self._html_search_meta('description', webpage) + thumbnail = self._og_search_thumbnail(webpage) + + return { + '_type': 'url_transparent', + 'id': video_id, + 'url': theplatform_url, + + 'title': title, + 'description': description, + 'thumbnail': thumbnail, + } From 49f3c16543891425bb40bc5a5a13b626770c437d Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sat, 23 Aug 2014 15:24:31 +0200 Subject: [PATCH 0587/1761] release 2014.08.23 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index b2484e508..0ba9b5086 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.08.22.3' +__version__ = '2014.08.23' From a54bda3ae2d659c9020668a638dccc3545a1ecb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 24 Aug 2014 02:22:10 +0700 Subject: [PATCH 0588/1761] [wat] Add support for SD and HD videos (Closes #3558) --- youtube_dl/extractor/wat.py | 67 ++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/youtube_dl/extractor/wat.py b/youtube_dl/extractor/wat.py index a584e0896..1f330378a 100644 --- a/youtube_dl/extractor/wat.py +++ b/youtube_dl/extractor/wat.py @@ -2,27 +2,30 @@ from __future__ import unicode_literals import re +import time +import hashlib from .common import InfoExtractor from ..utils import ( + ExtractorError, unified_strdate, ) class WatIE(InfoExtractor): - _VALID_URL = r'http://www\.wat\.tv/.*-(?P.*?)_.*?\.html' + _VALID_URL = r'http://www\.wat\.tv/video/(?P.*)-(?P.*?)_.*?\.html' IE_NAME = 'wat.tv' _TEST = { - 'url': 'http://www.wat.tv/video/world-war-philadelphia-vost-6bv55_2fjr7_.html', + 'url': 'http://www.wat.tv/video/soupe-figues-l-orange-aux-epices-6z1uz_2hvf7_.html', + 'md5': 'ce70e9223945ed26a8056d413ca55dc9', 'info_dict': { - 'id': '10631273', + 'id': '11713067', + 'display_id': 'soupe-figues-l-orange-aux-epices', 'ext': 'mp4', - 'title': 'World War Z - Philadelphia VOST', - 'description': 'La menace est partout. Que se passe-t-il à Philadelphia ?\r\nWORLD WAR Z, avec Brad Pitt, au cinéma le 3 juillet.\r\nhttp://www.worldwarz.fr', - }, - 'params': { - # Sometimes wat serves the whole file with the --test option - 'skip_download': True, + 'title': 'Soupe de figues à l\'orange et aux épices', + 'description': 'Retrouvez l\'émission "Petits plats en équilibre", diffusée le 18 août 2014.', + 'upload_date': '20140819', + 'duration': 120, }, } @@ -36,13 +39,20 @@ class WatIE(InfoExtractor): def real_id_for_chapter(chapter): return chapter['tc_start'].split('-')[0] mobj = re.match(self._VALID_URL, url) - short_id = mobj.group('shortID') - webpage = self._download_webpage(url, short_id) + short_id = mobj.group('short_id') + display_id = mobj.group('display_id') + webpage = self._download_webpage(url, display_id or short_id) real_id = self._search_regex(r'xtpage = ".*-(.*?)";', webpage, 'real id') video_info = self.download_video_info(real_id) + + if video_info.get('geolock'): + raise ExtractorError('This content is not available in your area', expected=True) + chapters = video_info['chapters'] first_chapter = chapters[0] + files = video_info['files'] + first_file = files[0] if real_id_for_chapter(first_chapter) != real_id: self.to_screen('Multipart video detected') @@ -61,12 +71,45 @@ class WatIE(InfoExtractor): upload_date = unified_strdate(first_chapter['date_diffusion']) # Otherwise we can continue and extract just one part, we have to use # the short id for getting the video url + + formats = [{ + 'url': 'http://wat.tv/get/android5/%s.mp4' % real_id, + 'format_id': 'Mobile', + }] + + fmts = [('SD', 'web')] + if first_file.get('hasHD'): + fmts.append(('HD', 'webhd')) + + def compute_token(param): + timestamp = '%08x' % int(time.time()) + magic = '9b673b13fa4682ed14c3cfa5af5310274b514c4133e9b3a81e6e3aba009l2564' + return '%s/%s' % (hashlib.md5((magic + param + timestamp).encode('ascii')).hexdigest(), timestamp) + + for fmt in fmts: + webid = '/%s/%s' % (fmt[1], real_id) + video_url = self._download_webpage( + 'http://www.wat.tv/get%s?token=%s&getURL=1' % (webid, compute_token(webid)), + real_id, + 'Downloding %s video URL' % fmt[0], + 'Failed to download %s video URL' % fmt[0], + False) + if not video_url: + continue + formats.append({ + 'url': video_url, + 'ext': 'mp4', + 'format_id': fmt[0], + }) + return { 'id': real_id, - 'url': 'http://wat.tv/get/android5/%s.mp4' % real_id, + 'display_id': display_id, 'title': first_chapter['title'], 'thumbnail': first_chapter['preview'], 'description': first_chapter['description'], 'view_count': video_info['views'], 'upload_date': upload_date, + 'duration': first_file['duration'], + 'formats': formats, } From d769be6c96ebca432a076670a0ed4e72aec101c1 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 01:31:35 +0200 Subject: [PATCH 0589/1761] [grooveshark,http] Make HTTP POST downloads work --- youtube_dl/downloader/http.py | 12 +++++- youtube_dl/extractor/common.py | 6 +++ youtube_dl/extractor/grooveshark.py | 65 ++++++++++++----------------- 3 files changed, 42 insertions(+), 41 deletions(-) diff --git a/youtube_dl/downloader/http.py b/youtube_dl/downloader/http.py index f79e6a995..d01d1897e 100644 --- a/youtube_dl/downloader/http.py +++ b/youtube_dl/downloader/http.py @@ -27,8 +27,16 @@ class HttpFD(FileDownloader): headers['Youtubedl-user-agent'] = info_dict['user_agent'] if 'http_referer' in info_dict: headers['Referer'] = info_dict['http_referer'] - basic_request = compat_urllib_request.Request(url, None, headers) - request = compat_urllib_request.Request(url, None, headers) + add_headers = info_dict.get('http_headers') + if add_headers: + headers.update(add_headers) + data = info_dict.get('http_post_data') + http_method = info_dict.get('http_method') + basic_request = compat_urllib_request.Request(url, data, headers) + request = compat_urllib_request.Request(url, data, headers) + if http_method is not None: + basic_request.get_method = lambda: http_method + request.get_method = lambda: http_method is_test = self.params.get('test', False) diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 2e6eeac08..9d85a538c 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -84,6 +84,12 @@ class InfoExtractor(object): format, irrespective of the file format. -1 for default (order by other properties), -2 or smaller for less than default. + * http_referer HTTP Referer header value to set. + * http_method HTTP method to use for the download. + * http_headers A dictionary of additional HTTP headers + to add to the request. + * http_post_data Additional data to send with a POST + request. url: Final video URL. ext: Video filename extension. format: The video format, defaults to ext (used for --get-format) diff --git a/youtube_dl/extractor/grooveshark.py b/youtube_dl/extractor/grooveshark.py index 77c5a9172..1f2c65afe 100644 --- a/youtube_dl/extractor/grooveshark.py +++ b/youtube_dl/extractor/grooveshark.py @@ -12,7 +12,7 @@ from .common import InfoExtractor from ..utils import ExtractorError, compat_urllib_request, compat_html_parser from ..utils import compat_urlparse -urlparse = compat_urlparse.urlparse + urlunparse = compat_urlparse.urlunparse urldefrag = compat_urlparse.urldefrag @@ -52,7 +52,7 @@ class GroovesharkIE(InfoExtractor): 'id': '6SS1DW', 'title': 'Jolene (Tenth Key Remix ft. Will Sessions)', 'ext': 'mp3', - 'duration': 227 + 'duration': 227, } } @@ -60,7 +60,7 @@ class GroovesharkIE(InfoExtractor): do_bootstrap_request = True def _parse_target(self, target): - uri = urlparse(target) + uri = compat_urlparse.urlparse(target) hash = uri.fragment[1:].split('?')[0] token = basename(hash.rstrip('/')) return (uri, hash, token) @@ -123,22 +123,36 @@ class GroovesharkIE(InfoExtractor): def _get_playerpage(self, target): (_, _, token) = self._parse_target(target) - res = self._download_webpage( + + webpage = self._download_webpage( target, token, note='Downloading player page', errnote='Unable to download player page', fatal=False) - if res is not None: - o = GroovesharkHtmlParser.extract_object_tags(res) - return (res, [x for x in o if x['attrs']['id'] == 'jsPlayerEmbed']) + if webpage is not None: + # Search (for example German) error message + error_msg = self._html_search_regex( + r'
    \s*

    (.*?)

    ', webpage, + 'error message', default=None) + if error_msg is not None: + error_msg = error_msg.replace('\n', ' ') + raise ExtractorError('Grooveshark said: %s' % error_msg) - return (res, None) + if webpage is not None: + o = GroovesharkHtmlParser.extract_object_tags(webpage) + return (webpage, [x for x in o if x['attrs']['id'] == 'jsPlayerEmbed']) + + return (webpage, None) + + def _real_initialize(self): + self.ts = int(time.time() * 1000) # timestamp in millis def _real_extract(self, url): (target_uri, _, token) = self._parse_target(url) # 1. Fill cookiejar by making a request to the player page + swf_referer = None if self.do_playerpage_request: (_, player_objs) = self._get_playerpage(url) if player_objs is not None: @@ -162,11 +176,10 @@ class GroovesharkIE(InfoExtractor): 'Content-Length': len(post_data), 'Content-Type': 'application/x-www-form-urlencoded' } - - if 'swf_referer' in locals(): + if swf_referer is not None: headers['Referer'] = swf_referer - info_dict = { + return { 'id': token, 'title': meta['song']['Name'], 'http_method': 'POST', @@ -174,32 +187,6 @@ class GroovesharkIE(InfoExtractor): 'ext': 'mp3', 'format': 'mp3 audio', 'duration': duration, - - # various ways of supporting the download request. - # remove keys unnecessary to the eventual post implementation - 'post_data': post_data, - 'post_dict': post_dict, - 'headers': headers + 'http_post_data': post_data, + 'http_headers': headers, } - - if 'swf_referer' in locals(): - info_dict['http_referer'] = swf_referer - - return info_dict - - def _real_initialize(self): - self.ts = int(time.time() * 1000) # timestamp in millis - - def _download_json(self, url_or_request, video_id, - note=u'Downloading JSON metadata', - errnote=u'Unable to download JSON metadata', - fatal=True, - transform_source=None): - try: - out = super(GroovesharkIE, self)._download_json( - url_or_request, video_id, note, errnote, transform_source) - return out - except ExtractorError as ee: - if fatal: - raise ee - return None From eb9da9b732c63309e8592729d3e048953086a308 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 01:32:12 +0200 Subject: [PATCH 0590/1761] [grooveshark] Fix test md5sum --- youtube_dl/extractor/grooveshark.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/youtube_dl/extractor/grooveshark.py b/youtube_dl/extractor/grooveshark.py index 1f2c65afe..7939bc094 100644 --- a/youtube_dl/extractor/grooveshark.py +++ b/youtube_dl/extractor/grooveshark.py @@ -47,7 +47,7 @@ class GroovesharkIE(InfoExtractor): _VALID_URL = r'https?://(www\.)?grooveshark\.com/#!/s/([^/]+)/([^/]+)' _TEST = { 'url': 'http://grooveshark.com/#!/s/Jolene+Tenth+Key+Remix+Ft+Will+Sessions/6SS1DW?src=5', - 'md5': 'bbccc50b19daca23b8f961152c1dc95b', + 'md5': '7ecf8aefa59d6b2098517e1baa530023', 'info_dict': { 'id': '6SS1DW', 'title': 'Jolene (Tenth Key Remix ft. Will Sessions)', @@ -123,7 +123,6 @@ class GroovesharkIE(InfoExtractor): def _get_playerpage(self, target): (_, _, token) = self._parse_target(target) - webpage = self._download_webpage( target, token, note='Downloading player page', From c8e9a235d95ee395ce381a37cbf1cbe25fad44ce Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 02:02:17 +0200 Subject: [PATCH 0591/1761] [generic] Add support for camtasia videos (Fixes #3574) --- youtube_dl/extractor/generic.py | 67 +++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 62b1da25e..2ba86878b 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -15,6 +15,7 @@ from ..utils import ( compat_xml_parse_error, ExtractorError, + float_or_none, HEADRequest, orderedSet, parse_xml, @@ -305,6 +306,30 @@ class GenericIE(InfoExtractor): 'params': { 'skip_download': True, } + }, + # Camtasia studio + { + 'url': 'http://www.ll.mit.edu/workshops/education/videocourses/antennas/lecture1/video/', + 'playlist': [{ + 'md5': '0c5e352edabf715d762b0ad4e6d9ee67', + 'info_dict': { + 'id': 'Fenn-AA_PA_Radar_Course_Lecture_1c_Final', + 'title': 'Fenn-AA_PA_Radar_Course_Lecture_1c_Final - video1', + 'ext': 'flv', + 'duration': 2235.90, + } + }, { + 'md5': '10e4bb3aaca9fd630e273ff92d9f3c63', + 'info_dict': { + 'id': 'Fenn-AA_PA_Radar_Course_Lecture_1c_Final_PIP', + 'title': 'Fenn-AA_PA_Radar_Course_Lecture_1c_Final - pip', + 'ext': 'flv', + 'duration': 2235.93, + } + }], + 'info_dict': { + 'title': 'Fenn-AA_PA_Radar_Course_Lecture_1c_Final', + } } ] @@ -389,6 +414,43 @@ class GenericIE(InfoExtractor): 'entries': entries, } + def _extract_camtasia(self, url, video_id, webpage): + """ Returns None if no camtasia video can be found. """ + + camtasia_cfg = self._search_regex( + r'fo\.addVariable\(\s*"csConfigFile",\s*"([^"]+)"\s*\);', + webpage, 'camtasia configuration file', default=None) + if camtasia_cfg is None: + return None + + title = self._html_search_meta('DC.title', webpage, fatal=True) + + camtasia_url = compat_urlparse.urljoin(url, camtasia_cfg) + camtasia_cfg = self._download_xml( + camtasia_url, video_id, + note='Downloading camtasia configuration', + errnote='Failed to download camtasia configuration') + fileset_node = camtasia_cfg.find('./playlist/array/fileset') + + entries = [] + for n in fileset_node.getchildren(): + url_n = n.find('./uri') + if url_n is None: + continue + + entries.append({ + 'id': os.path.splitext(url_n.text.rpartition('/')[2])[0], + 'title': '%s - %s' % (title, n.tag), + 'url': compat_urlparse.urljoin(url, url_n.text), + 'duration': float_or_none(n.find('./duration').text), + }) + + return { + '_type': 'playlist', + 'entries': entries, + 'title': title, + } + def _real_extract(self, url): if url.startswith('//'): return { @@ -477,6 +539,11 @@ class GenericIE(InfoExtractor): except compat_xml_parse_error: pass + # Is it a Camtasia project? + camtasia_res = self._extract_camtasia(url, video_id, webpage) + if camtasia_res is not None: + return camtasia_res + # Sometimes embedded video player is hidden behind percent encoding # (e.g. https://github.com/rg3/youtube-dl/issues/2448) # Unescaping the whole page allows to handle those cases in a generic way From a3db22ebdf608ad4a84adf7eaf4b19d09b758196 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 02:06:59 +0200 Subject: [PATCH 0592/1761] [grooveshark] Use proper imports --- youtube_dl/extractor/grooveshark.py | 31 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/youtube_dl/extractor/grooveshark.py b/youtube_dl/extractor/grooveshark.py index 7939bc094..726adff77 100644 --- a/youtube_dl/extractor/grooveshark.py +++ b/youtube_dl/extractor/grooveshark.py @@ -3,18 +3,17 @@ from __future__ import unicode_literals import time import math +import os.path import re -from urllib import quote, urlencode -from os.path import basename from .common import InfoExtractor from ..utils import ExtractorError, compat_urllib_request, compat_html_parser -from ..utils import compat_urlparse - -urlunparse = compat_urlparse.urlunparse -urldefrag = compat_urlparse.urldefrag +from ..utils import ( + compat_urllib_parse, + compat_urlparse, +) class GroovesharkHtmlParser(compat_html_parser.HTMLParser): @@ -62,25 +61,25 @@ class GroovesharkIE(InfoExtractor): def _parse_target(self, target): uri = compat_urlparse.urlparse(target) hash = uri.fragment[1:].split('?')[0] - token = basename(hash.rstrip('/')) + token = os.path.basename(hash.rstrip('/')) return (uri, hash, token) def _build_bootstrap_url(self, target): (uri, hash, token) = self._parse_target(target) - query = 'getCommunicationToken=1&hash=%s&%d' % (quote(hash, safe=''), self.ts) - return (urlunparse((uri.scheme, uri.netloc, '/preload.php', None, query, None)), token) + query = 'getCommunicationToken=1&hash=%s&%d' % (compat_urllib_parse.quote(hash, safe=''), self.ts) + return (compat_urlparse.urlunparse((uri.scheme, uri.netloc, '/preload.php', None, query, None)), token) def _build_meta_url(self, target): (uri, hash, token) = self._parse_target(target) - query = 'hash=%s&%d' % (quote(hash, safe=''), self.ts) - return (urlunparse((uri.scheme, uri.netloc, '/preload.php', None, query, None)), token) + query = 'hash=%s&%d' % (compat_urllib_parse.quote(hash, safe=''), self.ts) + return (compat_urlparse.urlunparse((uri.scheme, uri.netloc, '/preload.php', None, query, None)), token) def _build_stream_url(self, meta): - return urlunparse(('http', meta['streamKey']['ip'], '/stream.php', None, None, None)) + return compat_urlparse.urlunparse(('http', meta['streamKey']['ip'], '/stream.php', None, None, None)) def _build_swf_referer(self, target, obj): (uri, _, _) = self._parse_target(target) - return urlunparse((uri.scheme, uri.netloc, obj['attrs']['data'], None, None, None)) + return compat_urlparse.urlunparse((uri.scheme, uri.netloc, obj['attrs']['data'], None, None, None)) def _transform_bootstrap(self, js): return re.split('(?m)^\s*try\s*{', js)[0] \ @@ -93,7 +92,7 @@ class GroovesharkIE(InfoExtractor): (meta_url, token) = self._build_meta_url(target) self.to_screen('Metadata URL: %s' % meta_url) - headers = {'Referer': urldefrag(target)[0]} + headers = {'Referer': compat_urlparse.urldefrag(target)[0]} req = compat_urllib_request.Request(meta_url, headers=headers) res = self._download_json(req, token, transform_source=self._transform_meta) @@ -112,7 +111,7 @@ class GroovesharkIE(InfoExtractor): def _get_bootstrap(self, target): (bootstrap_url, token) = self._build_bootstrap_url(target) - headers = {'Referer': urldefrag(target)[0]} + headers = {'Referer': compat_urlparse.urldefrag(target)[0]} req = compat_urllib_request.Request(bootstrap_url, headers=headers) res = self._download_json(req, token, fatal=False, note='Downloading player bootstrap data', @@ -170,7 +169,7 @@ class GroovesharkIE(InfoExtractor): stream_url = self._build_stream_url(meta) duration = int(math.ceil(float(meta['streamKey']['uSecs']) / 1000000)) post_dict = {'streamKey': meta['streamKey']['streamKey']} - post_data = urlencode(post_dict).encode('utf-8') + post_data = compat_urllib_parse.urlencode(post_dict).encode('utf-8') headers = { 'Content-Length': len(post_data), 'Content-Type': 'application/x-www-form-urlencoded' From 685759005919d004dd82acfc4ed88ea60de6111a Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 02:11:26 +0200 Subject: [PATCH 0593/1761] [brightcove] Add a truncated URL warning message (#3571) --- youtube_dl/extractor/brightcove.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/brightcove.py b/youtube_dl/extractor/brightcove.py index 419951b62..eb102244a 100644 --- a/youtube_dl/extractor/brightcove.py +++ b/youtube_dl/extractor/brightcove.py @@ -188,9 +188,13 @@ class BrightcoveIE(InfoExtractor): referer = smuggled_data.get('Referer', url) return self._get_video_info( videoPlayer[0], query_str, query, referer=referer) - else: + elif 'playerKey' in query: player_key = query['playerKey'] return self._get_playlist_info(player_key[0]) + else: + raise ExtractorError( + 'Cannot find playerKey= variable. Did you forget quotes in a shell invocation?', + expected=True) def _get_video_info(self, video_id, query_str, query, referer=None): request_url = self._FEDERATED_URL_TEMPLATE % query_str From fa8deaf38b0d576d693a6565dcdb3b29877a4c94 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 02:24:47 +0200 Subject: [PATCH 0594/1761] [generic] Prevent from downloading a .swf as a video We're seeing quite a number of people who do not put a video file in the og:video field, but the player URL. Try to detect some of these and filter them out. --- youtube_dl/extractor/generic.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 2ba86878b..5bd315051 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -831,7 +831,12 @@ class GenericIE(InfoExtractor): m_video_type = re.findall(r'.*? Date: Sun, 24 Aug 2014 02:29:02 +0200 Subject: [PATCH 0595/1761] [generic] Require og:video URLs to contain a dot --- youtube_dl/extractor/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 5bd315051..f05ac4d38 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -833,7 +833,7 @@ class GenericIE(InfoExtractor): if m_video_type is not None: def check_video(vurl): vpath = compat_urlparse.urlparse(vurl).path - return not vpath.endswith('.swf') + return '.' in vpath and not vpath.endswith('.swf') found = list(filter( check_video, re.findall(r' Date: Sun, 24 Aug 2014 02:40:26 +0200 Subject: [PATCH 0596/1761] [brightcove] Detect geoblocking --- youtube_dl/extractor/brightcove.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/youtube_dl/extractor/brightcove.py b/youtube_dl/extractor/brightcove.py index eb102244a..7aa8a7654 100644 --- a/youtube_dl/extractor/brightcove.py +++ b/youtube_dl/extractor/brightcove.py @@ -206,6 +206,13 @@ class BrightcoveIE(InfoExtractor): req.add_header('Referer', referer) webpage = self._download_webpage(req, video_id) + error_msg = self._html_search_regex( + r"

    We're sorry.

    \s*

    (.*?)

    ", webpage, + 'error message', default=None) + if error_msg is not None: + raise ExtractorError( + 'brightcove said: %s' % error_msg, expected=True) + self.report_extraction(video_id) info = self._search_regex(r'var experienceJSON = ({.*});', webpage, 'json') info = json.loads(info)['data'] From e1ab5000b2429e2421e2d38489b197d525eebf0f Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 02:41:21 +0200 Subject: [PATCH 0597/1761] [brightcove] Add support for videoId= in og:video meta (Fixes #3571) --- youtube_dl/extractor/brightcove.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/brightcove.py b/youtube_dl/extractor/brightcove.py index 7aa8a7654..294670386 100644 --- a/youtube_dl/extractor/brightcove.py +++ b/youtube_dl/extractor/brightcove.py @@ -154,12 +154,14 @@ class BrightcoveIE(InfoExtractor): def _extract_brightcove_urls(cls, webpage): """Return a list of all Brightcove URLs from the webpage """ - url_m = re.search(r' Date: Sun, 24 Aug 2014 02:44:36 +0200 Subject: [PATCH 0598/1761] release 2014.08.24 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 0ba9b5086..6184331d1 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.08.23' +__version__ = '2014.08.24' From 01d906ffe9a9f3a8d9e01b1ee39b3cfcc8f2dfc2 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 02:57:31 +0200 Subject: [PATCH 0599/1761] [arte:creative] Support more URLs (fixes #3572) --- youtube_dl/extractor/arte.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/youtube_dl/extractor/arte.py b/youtube_dl/extractor/arte.py index d86dbba8e..b5e464a30 100644 --- a/youtube_dl/extractor/arte.py +++ b/youtube_dl/extractor/arte.py @@ -177,16 +177,24 @@ class ArteTVPlus7IE(InfoExtractor): # It also uses the arte_vp_url url from the webpage to extract the information class ArteTVCreativeIE(ArteTVPlus7IE): IE_NAME = 'arte.tv:creative' - _VALID_URL = r'https?://creative\.arte\.tv/(?Pfr|de)/magazine?/(?P.+)' + _VALID_URL = r'https?://creative\.arte\.tv/(?Pfr|de)/(?:magazine?/)?(?P[^?#]+)' - _TEST = { + _TESTS = [{ 'url': 'http://creative.arte.tv/de/magazin/agentur-amateur-corporate-design', 'info_dict': { - 'id': '050489-002', + 'id': '72176', 'ext': 'mp4', - 'title': 'Agentur Amateur / Agence Amateur #2 : Corporate Design', + 'title': 'Folge 2 - Corporate Design', + 'upload_date': '20131004', }, - } + }, { + 'url': 'http://creative.arte.tv/fr/Monty-Python-Reunion', + 'info_dict': { + 'id': '160676', + 'ext': 'mp4', + 'title': 'Monty Python live (mostly)', + } + }] class ArteTVFutureIE(ArteTVPlus7IE): From b5f4775b3821ed22e90cecd895977fbefbc97def Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 03:11:00 +0200 Subject: [PATCH 0600/1761] [arte.tv:creative] Fix test case --- youtube_dl/extractor/arte.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/youtube_dl/extractor/arte.py b/youtube_dl/extractor/arte.py index b5e464a30..1c72b2ff6 100644 --- a/youtube_dl/extractor/arte.py +++ b/youtube_dl/extractor/arte.py @@ -193,6 +193,8 @@ class ArteTVCreativeIE(ArteTVPlus7IE): 'id': '160676', 'ext': 'mp4', 'title': 'Monty Python live (mostly)', + 'description': 'Événement ! Quarante-cinq ans après leurs premiers succès, les légendaires Monty Python remontent sur scène.\n', + 'upload_date': '20140805', } }] From 8f9b683eeb01eb60c6cf8373f0429a7f560faa1c Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 03:13:49 +0200 Subject: [PATCH 0601/1761] [blip.tv] Add legacy test case This was broken in the mean time, so add a test case to make sure it doesn't break silently again. --- youtube_dl/extractor/bliptv.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/bliptv.py b/youtube_dl/extractor/bliptv.py index acfc4ad73..4e80d8293 100644 --- a/youtube_dl/extractor/bliptv.py +++ b/youtube_dl/extractor/bliptv.py @@ -49,6 +49,21 @@ class BlipTVIE(SubtitlesInfoExtractor): 'uploader_id': '792887', 'duration': 279, } + }, + { + # https://bugzilla.redhat.com/show_bug.cgi?id=967465 + 'url': 'http://a.blip.tv/api.swf#h6Uag5KbVwI', + 'md5': '314e87b1ebe7a48fcbfdd51b791ce5a6', + 'info_dict': { + 'id': '6573122', + 'ext': 'mov', + 'upload_date': '20130520', + 'description': 'Two hapless space marines argue over what to do when they realize they have an astronomically huge problem on their hands.', + 'title': 'Red vs. Blue Season 11 Trailer', + 'timestamp': 1369029609, + 'uploader': 'redvsblue', + 'uploader_id': '792887', + } } ] @@ -150,7 +165,7 @@ class BlipTVIE(SubtitlesInfoExtractor): class BlipTVUserIE(InfoExtractor): - _VALID_URL = r'(?:(?:(?:https?://)?(?:\w+\.)?blip\.tv/)|bliptvuser:)([^/]+)/*$' + _VALID_URL = r'(?:(?:(?:https?://)?(?:\w+\.)?blip\.tv/)|bliptvuser:)(?!api\.swf)([^/]+)/*$' _PAGE_SIZE = 12 IE_NAME = 'blip.tv:user' From 1f8b6af77341433603601473d33766005177dacd Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 03:20:31 +0200 Subject: [PATCH 0602/1761] [bip.tv] Allow underscore in lookup ids (Fixes #3573) --- youtube_dl/extractor/bliptv.py | 2 +- youtube_dl/extractor/generic.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/bliptv.py b/youtube_dl/extractor/bliptv.py index 4e80d8293..261ead98f 100644 --- a/youtube_dl/extractor/bliptv.py +++ b/youtube_dl/extractor/bliptv.py @@ -15,7 +15,7 @@ from ..utils import ( class BlipTVIE(SubtitlesInfoExtractor): - _VALID_URL = r'https?://(?:\w+\.)?blip\.tv/(?:(?:.+-|rss/flash/)(?P\d+)|((?:play/|api\.swf#)(?P[\da-zA-Z+]+)))' + _VALID_URL = r'https?://(?:\w+\.)?blip\.tv/(?:(?:.+-|rss/flash/)(?P\d+)|((?:play/|api\.swf#)(?P[\da-zA-Z+_TESTS]+)))' _TESTS = [ { diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index f05ac4d38..8b2d1d033 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -640,7 +640,7 @@ class GenericIE(InfoExtractor): mobj = re.search(r']*https?://api\.blip\.tv/\w+/redirect/\w+/(\d+)', webpage) if mobj: return self.url_result('http://blip.tv/a/a-'+mobj.group(1), 'BlipTV') - mobj = re.search(r'<(?:iframe|embed|object)\s[^>]*(https?://(?:\w+\.)?blip\.tv/(?:play/|api\.swf#)[a-zA-Z0-9]+)', webpage) + mobj = re.search(r'<(?:iframe|embed|object)\s[^>]*(https?://(?:\w+\.)?blip\.tv/(?:play/|api\.swf#)[a-zA-Z0-9_]+)', webpage) if mobj: return self.url_result(mobj.group(1), 'BlipTV') From 8c2ccefae657c0347968b27c8713a6e262d59f7e Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 03:20:40 +0200 Subject: [PATCH 0603/1761] release 2014.08.24.1 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 6184331d1..db4be5fb5 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.08.24' +__version__ = '2014.08.24.1' From cf0c5fa3a1a6a03b56bbcdfc17dd50637a77724c Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 03:31:38 +0200 Subject: [PATCH 0604/1761] [ebaumsworld] Modernize --- youtube_dl/extractor/ebaumsworld.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/youtube_dl/extractor/ebaumsworld.py b/youtube_dl/extractor/ebaumsworld.py index 877113d63..046976743 100644 --- a/youtube_dl/extractor/ebaumsworld.py +++ b/youtube_dl/extractor/ebaumsworld.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import re from .common import InfoExtractor @@ -8,12 +10,13 @@ class EbaumsWorldIE(InfoExtractor): _VALID_URL = r'https?://www\.ebaumsworld\.com/video/watch/(?P\d+)' _TEST = { - u'url': u'http://www.ebaumsworld.com/video/watch/83367677/', - u'file': u'83367677.mp4', - u'info_dict': { - u'title': u'A Giant Python Opens The Door', - u'description': u'This is how nightmares start...', - u'uploader': u'jihadpizza', + 'url': 'http://www.ebaumsworld.com/video/watch/83367677/', + 'info_dict': { + 'id': '83367677', + 'ext': 'mp4', + 'title': 'A Giant Python Opens The Door', + 'description': 'This is how nightmares start...', + 'uploader': 'jihadpizza', }, } From f56f8399c7a222dd07cbf09b02c212509f2ad805 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 03:37:19 +0200 Subject: [PATCH 0605/1761] [ebaumsworld] Remove spurious determine_ext --- youtube_dl/extractor/ebaumsworld.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/youtube_dl/extractor/ebaumsworld.py b/youtube_dl/extractor/ebaumsworld.py index 046976743..63c2549d3 100644 --- a/youtube_dl/extractor/ebaumsworld.py +++ b/youtube_dl/extractor/ebaumsworld.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import re from .common import InfoExtractor -from ..utils import determine_ext class EbaumsWorldIE(InfoExtractor): @@ -31,7 +30,6 @@ class EbaumsWorldIE(InfoExtractor): 'id': video_id, 'title': config.find('title').text, 'url': video_url, - 'ext': determine_ext(video_url), 'description': config.find('description').text, 'thumbnail': config.find('image').text, 'uploader': config.find('username').text, From e5402ac1203c8fd0c438ad515bbd80eb288b3907 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 03:44:54 +0200 Subject: [PATCH 0606/1761] [wayofthemaster] Add extractor (Fixes #3575) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/wayofthemaster.py | 53 ++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 youtube_dl/extractor/wayofthemaster.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 0d7824023..52354e6e0 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -390,6 +390,7 @@ from .vuclip import VuClipIE from .vulture import VultureIE from .washingtonpost import WashingtonPostIE from .wat import WatIE +from .wayofthemaster import WayOfTheMasterIE from .wdr import ( WDRIE, WDRMobileIE, diff --git a/youtube_dl/extractor/wayofthemaster.py b/youtube_dl/extractor/wayofthemaster.py new file mode 100644 index 000000000..c0723b8eb --- /dev/null +++ b/youtube_dl/extractor/wayofthemaster.py @@ -0,0 +1,53 @@ +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import determine_ext + + +class WayOfTheMasterIE(InfoExtractor): + _VALID_URL = r'https?://www\.wayofthemaster\.com/([^/?#]*/)*(?P[^/?#]+)\.s?html(?:$|[?#])' + + _TEST = { + 'url': 'http://www.wayofthemaster.com/hbks.shtml', + 'md5': '5316b57487ada8480606a93cb3d18d24', + 'info_dict': { + 'id': 'hbks', + 'ext': 'mp4', + 'title': 'Intelligent Design vs. Evolution', + }, + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + + title = self._search_regex( + r'(.*?)', webpage, 'page title') + + url_base = self._search_regex( + r' Date: Sun, 24 Aug 2014 04:18:09 +0200 Subject: [PATCH 0607/1761] [wayofthemaster] Remove unused import --- youtube_dl/extractor/wayofthemaster.py | 1 - 1 file changed, 1 deletion(-) diff --git a/youtube_dl/extractor/wayofthemaster.py b/youtube_dl/extractor/wayofthemaster.py index c0723b8eb..af7bb8b49 100644 --- a/youtube_dl/extractor/wayofthemaster.py +++ b/youtube_dl/extractor/wayofthemaster.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import re from .common import InfoExtractor -from ..utils import determine_ext class WayOfTheMasterIE(InfoExtractor): From 4d54ef20a291eabc523119ca60ff05f0962771a4 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 24 Aug 2014 04:47:18 +0200 Subject: [PATCH 0608/1761] [ministrygrid] Add extractor (Fixes #2900) --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/generic.py | 13 ++++++- youtube_dl/extractor/ministrygrid.py | 57 ++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 youtube_dl/extractor/ministrygrid.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 52354e6e0..9dccbb8ed 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -184,6 +184,7 @@ from .malemotion import MalemotionIE from .mdr import MDRIE from .metacafe import MetacafeIE from .metacritic import MetacriticIE +from .ministrygrid import MinistryGridIE from .mit import TechTVMITIE, MITIE, OCWMITIE from .mitele import MiTeleIE from .mixcloud import MixcloudIE diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index 8b2d1d033..7fce564c6 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -22,6 +22,7 @@ from ..utils import ( smuggle_url, unescapeHTML, unified_strdate, + unsmuggle_url, url_basename, ) from .brightcove import BrightcoveIE @@ -487,7 +488,14 @@ class GenericIE(InfoExtractor): else: assert ':' in default_search return self.url_result(default_search + url) - video_id = os.path.splitext(url.rstrip('/').split('/')[-1])[0] + + url, smuggled_data = unsmuggle_url(url) + force_videoid = None + if smuggled_data and 'force_videoid' in smuggled_data: + force_videoid = smuggled_data['force_videoid'] + video_id = force_videoid + else: + video_id = os.path.splitext(url.rstrip('/').split('/')[-1])[0] self.to_screen('%s: Requesting header' % video_id) @@ -498,6 +506,9 @@ class GenericIE(InfoExtractor): new_url = response.geturl() if url != new_url: self.report_following_redirect(new_url) + if force_videoid: + new_url = smuggle_url( + new_url, {'force_videoid': force_videoid}) return self.url_result(new_url) # Check for direct link to a video diff --git a/youtube_dl/extractor/ministrygrid.py b/youtube_dl/extractor/ministrygrid.py new file mode 100644 index 000000000..949ad11db --- /dev/null +++ b/youtube_dl/extractor/ministrygrid.py @@ -0,0 +1,57 @@ +from __future__ import unicode_literals + +import json +import re + +from .common import InfoExtractor +from ..utils import ( + ExtractorError, + smuggle_url, +) + + +class MinistryGridIE(InfoExtractor): + _VALID_URL = r'https?://www\.ministrygrid.com/([^/?#]*/)*(?P[^/#?]+)/?(?:$|[?#])' + + _TEST = { + 'url': 'http://www.ministrygrid.com/training-viewer/-/training/t4g-2014-conference/the-gospel-by-numbers-4/the-gospel-by-numbers', + 'md5': '844be0d2a1340422759c2a9101bab017', + 'info_dict': { + 'id': '3453494717001', + 'ext': 'mp4', + 'title': 'The Gospel by Numbers', + 'description': 'Coming soon from T4G 2014!', + 'uploader': 'LifeWay Christian Resources (MG)', + }, + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + portlets_json = self._search_regex( + r'Liferay\.Portlet\.list=(\[.+?\])', webpage, 'portlet list') + portlets = json.loads(portlets_json) + pl_id = self._search_regex( + r' %s\n%s\n\n' % (i, start, end, text) return output + def _convert_subtitles_to_ass(self, subtitles): + output = '' + + def ass_bool(strvalue): + assvalue = '0' + if strvalue == '1': + assvalue = '-1' + return assvalue + + sub_root = xml.etree.ElementTree.fromstring(subtitles) + if not sub_root: + return output + + output = '[Script Info]\n' + output += 'Title: %s\n' % sub_root.attrib["title"] + output += 'ScriptType: v4.00+\n' + output += 'WrapStyle: %s\n' % sub_root.attrib["wrap_style"] + output += 'PlayResX: %s\n' % sub_root.attrib["play_res_x"] + output += 'PlayResY: %s\n' % sub_root.attrib["play_res_y"] + output += """ScaledBorderAndShadow: yes + +[V4+ Styles] +Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding +""" + for style in sub_root.findall('./styles/style'): + output += 'Style: ' + style.attrib["name"] + output += ',' + style.attrib["font_name"] + output += ',' + style.attrib["font_size"] + output += ',' + style.attrib["primary_colour"] + output += ',' + style.attrib["secondary_colour"] + output += ',' + style.attrib["outline_colour"] + output += ',' + style.attrib["back_colour"] + output += ',' + ass_bool(style.attrib["bold"]) + output += ',' + ass_bool(style.attrib["italic"]) + output += ',' + ass_bool(style.attrib["underline"]) + output += ',' + ass_bool(style.attrib["strikeout"]) + output += ',' + style.attrib["scale_x"] + output += ',' + style.attrib["scale_y"] + output += ',' + style.attrib["spacing"] + output += ',' + style.attrib["angle"] + output += ',' + style.attrib["border_style"] + output += ',' + style.attrib["outline"] + output += ',' + style.attrib["shadow"] + output += ',' + style.attrib["alignment"] + output += ',' + style.attrib["margin_l"] + output += ',' + style.attrib["margin_r"] + output += ',' + style.attrib["margin_v"] + output += ',' + style.attrib["encoding"] + output += '\n' + + output += """ +[Events] +Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text +""" + for event in sub_root.findall('./events/event'): + output += 'Dialogue: 0' + output += ',' + event.attrib["start"] + output += ',' + event.attrib["end"] + output += ',' + event.attrib["style"] + output += ',' + event.attrib["name"] + output += ',' + event.attrib["margin_l"] + output += ',' + event.attrib["margin_r"] + output += ',' + event.attrib["margin_v"] + output += ',' + event.attrib["effect"] + output += ',' + event.attrib["text"] + output += '\n' + + return output + def _real_extract(self,url): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('video_id') @@ -177,6 +249,7 @@ class CrunchyrollIE(InfoExtractor): }) subtitles = {} + sub_format = self._downloader.params.get('subtitlesformat', 'srt') for sub_id, sub_name in re.findall(r'\?ssid=([0-9]+)" title="([^"]+)', webpage): sub_page = self._download_webpage('http://www.crunchyroll.com/xml/?req=RpcApiSubtitle_GetXml&subtitle_script_id='+sub_id,\ video_id, note='Downloading subtitles for '+sub_name) @@ -193,7 +266,10 @@ class CrunchyrollIE(InfoExtractor): lang_code = self._search_regex(r'lang_code=["\']([^"\']+)', subtitle, 'subtitle_lang_code', fatal=False) if not lang_code: continue - subtitles[lang_code] = self._convert_subtitles_to_srt(subtitle) + if sub_format == 'ass': + subtitles[lang_code] = self._convert_subtitles_to_ass(subtitle) + else: + subtitles[lang_code] = self._convert_subtitles_to_srt(subtitle) return { 'id': video_id, From 676e3ecf245f230411c9d534b0a4e918c01f5d86 Mon Sep 17 00:00:00 2001 From: peugeot Date: Sat, 30 Aug 2014 17:17:47 +0200 Subject: [PATCH 0691/1761] Add support for Vporn --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/vporn.py | 44 ++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 youtube_dl/extractor/vporn.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 1479d998a..6d94984de 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -393,6 +393,7 @@ from .vine import ( from .viki import VikiIE from .vk import VKIE from .vodlocker import VodlockerIE +from .vporn import VpornIE from .vube import VubeIE from .vuclip import VuClipIE from .vulture import VultureIE diff --git a/youtube_dl/extractor/vporn.py b/youtube_dl/extractor/vporn.py new file mode 100644 index 000000000..bdbd7543d --- /dev/null +++ b/youtube_dl/extractor/vporn.py @@ -0,0 +1,44 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor + +class VpornIE(InfoExtractor): + _VALID_URL = r'http?://(?:www\.)?vporn\.com/[a-z]+/(?P[a-z-]+)/(?P\d+)/?' + _TEST = { + 'url': 'http://www.vporn.com/masturbation/violet-on-her-th-birthday/497944/', + 'md5': 'facf37c1b86546fa0208058546842c55', + 'info_dict': { + 'id': '497944', + 'ext': 'mp4', + 'title': 'Violet On Her 19th Birthday', + 'description': 'Violet dances in front of the camera which is sure to get you horny.', + 'duration': 393, + 'thumbnail': 're:^https?://.*\.jpg$', + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + title = self._html_search_regex(r'(.*?) - Vporn Video', webpage, 'title') + video_url = self._html_search_regex(r'flashvars.videoUrlMedium = "(.*?)"', webpage, 'video_url') + description = self._html_search_regex(r'
    (.*?)
    ', webpage, 'description') + thumbnail = 'http://www.vporn.com' + self._html_search_regex(r'flashvars.imageUrl = "(.*?)"', webpage, 'description') + + mobj = re.search( + r'duration (?P\d+) min (?P\d+) sec ', webpage) + duration = int(mobj.group('minutes')) * 60 + int(mobj.group('seconds')) if mobj else None + + return { + 'id': video_id, + 'url': video_url, + 'thumbnail': thumbnail, + 'title': title, + 'description': description, + 'duration': duration, + } From 72c65d39ff4cfadba5eb5021c8dfd99e69c3e3a4 Mon Sep 17 00:00:00 2001 From: peugeot Date: Sat, 30 Aug 2014 18:37:45 +0200 Subject: [PATCH 0692/1761] Add support for AnySex --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/anysex.py | 42 ++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 youtube_dl/extractor/anysex.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 1479d998a..84f601cef 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -4,6 +4,7 @@ from .addanime import AddAnimeIE from .adultswim import AdultSwimIE from .aftonbladet import AftonbladetIE from .anitube import AnitubeIE +from .anysex import AnySexIE from .aol import AolIE from .allocine import AllocineIE from .aparat import AparatIE diff --git a/youtube_dl/extractor/anysex.py b/youtube_dl/extractor/anysex.py new file mode 100644 index 000000000..ef74805dd --- /dev/null +++ b/youtube_dl/extractor/anysex.py @@ -0,0 +1,42 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor + +class AnySexIE(InfoExtractor): + _VALID_URL = r'http?://(?:www\.)?anysex\.com/(?P\d+)/?' + _TEST = { + 'url': 'http://anysex.com/156592/', + 'md5': '023e9fbb7f7987f5529a394c34ad3d3d', + 'info_dict': { + 'id': '156592', + 'ext': 'mp4', + 'title': 'Busty and sexy blondie in her bikini strips for you', + 'duration': 270 + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + title = self._html_search_regex(r'(.*?)', webpage, 'title') + video_url = self._html_search_regex(r'video_url: \'(.*?)\',', webpage, 'video_url') + thumbnail = self._html_search_regex(r'preview_url: \'(.*?)\',', webpage, 'thumbnail') + + mobj = re.search(r'Duration: (?P\d+):(?P\d+)<', webpage) + duration = int(mobj.group('minutes')) * 60 + int(mobj.group('seconds')) if mobj else None + + view_count = self._html_search_regex(r'Views: (\d+)', webpage, 'view count', fatal=False) + + return { + 'id': video_id, + 'ext': 'mp4', + 'url': video_url, + 'title': title, + 'duration': duration, + 'view_count': view_count + } From bbc9dc56f663ba8a61ce2d5c8aa3fdde7992fb78 Mon Sep 17 00:00:00 2001 From: peugeot Date: Sat, 30 Aug 2014 20:43:03 +0200 Subject: [PATCH 0693/1761] Add support for HornBunny --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/hornbunny.py | 44 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 youtube_dl/extractor/hornbunny.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 1479d998a..17891fb80 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -134,6 +134,7 @@ from .grooveshark import GroovesharkIE from .hark import HarkIE from .helsinki import HelsinkiIE from .hentaistigma import HentaiStigmaIE +from .hornbunny import HornBunnyIE from .hotnewhiphop import HotNewHipHopIE from .howcast import HowcastIE from .howstuffworks import HowStuffWorksIE diff --git a/youtube_dl/extractor/hornbunny.py b/youtube_dl/extractor/hornbunny.py new file mode 100644 index 000000000..a42fba0cb --- /dev/null +++ b/youtube_dl/extractor/hornbunny.py @@ -0,0 +1,44 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import int_or_none + +class HornBunnyIE(InfoExtractor): + _VALID_URL = r'http?://(?:www\.)?hornbunny\.com/videos/(?P[a-z-]+)-(?P\d+)\.html' + _TEST = { + 'url': 'http://hornbunny.com/videos/panty-slut-jerk-off-instruction-5227.html', + 'md5': '95e40865aedd08eff60272b704852ad7', + 'info_dict': { + 'id': '5227', + 'ext': 'flv', + 'title': 'panty slut jerk off instruction', + 'duration': 550 + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + title = self._html_search_regex(r'class="title">(.*?)', webpage, 'title') + redirect_url = self._html_search_regex(r'pg&settings=(.*?)\|0"\);', webpage, 'title') + webpage2 = self._download_webpage(redirect_url, video_id) + video_url = self._html_search_regex(r'flvMask:(.*?);', webpage2, 'video_url') + + mobj = re.search(r'Runtime: (?P\d+):(?P\d+)
    ', webpage) + duration = int(mobj.group('minutes')) * 60 + int(mobj.group('seconds')) if mobj else None + + view_count = self._html_search_regex(r'Views: (\d+)
    ', webpage, 'view count', fatal=False) + + return { + 'id': video_id, + 'url': video_url, + 'title': title, + 'ext': 'flv', + 'duration': duration, + 'view_count': int_or_none(view_count), + } From 0bafcf6f468985df5dfd3d402815a73e69193e2d Mon Sep 17 00:00:00 2001 From: peugeot Date: Sat, 30 Aug 2014 20:46:25 +0200 Subject: [PATCH 0694/1761] forgot to test view count --- youtube_dl/extractor/anysex.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/anysex.py b/youtube_dl/extractor/anysex.py index ef74805dd..bfc7eb3c5 100644 --- a/youtube_dl/extractor/anysex.py +++ b/youtube_dl/extractor/anysex.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import re from .common import InfoExtractor +from ..utils import int_or_none class AnySexIE(InfoExtractor): _VALID_URL = r'http?://(?:www\.)?anysex\.com/(?P\d+)/?' @@ -14,7 +15,8 @@ class AnySexIE(InfoExtractor): 'id': '156592', 'ext': 'mp4', 'title': 'Busty and sexy blondie in her bikini strips for you', - 'duration': 270 + 'duration': 270, + 'view_count': 3652 } } @@ -38,5 +40,5 @@ class AnySexIE(InfoExtractor): 'url': video_url, 'title': title, 'duration': duration, - 'view_count': view_count + 'view_count': int_or_none(view_count), } From 12c82cf9cb59e97186b96fea76a15b52a0a9bb37 Mon Sep 17 00:00:00 2001 From: peugeot Date: Sat, 30 Aug 2014 20:54:38 +0200 Subject: [PATCH 0695/1761] add support for view count --- youtube_dl/extractor/vporn.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/youtube_dl/extractor/vporn.py b/youtube_dl/extractor/vporn.py index bdbd7543d..0d182b650 100644 --- a/youtube_dl/extractor/vporn.py +++ b/youtube_dl/extractor/vporn.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import re from .common import InfoExtractor +from ..utils import int_or_none class VpornIE(InfoExtractor): _VALID_URL = r'http?://(?:www\.)?vporn\.com/[a-z]+/(?P[a-z-]+)/(?P\d+)/?' @@ -30,15 +31,18 @@ class VpornIE(InfoExtractor): description = self._html_search_regex(r'
    (.*?)
    ', webpage, 'description') thumbnail = 'http://www.vporn.com' + self._html_search_regex(r'flashvars.imageUrl = "(.*?)"', webpage, 'description') - mobj = re.search( - r'duration (?P\d+) min (?P\d+) sec ', webpage) + mobj = re.search(r'duration (?P\d+) min (?P\d+) sec ', webpage) duration = int(mobj.group('minutes')) * 60 + int(mobj.group('seconds')) if mobj else None + mobj = re.search(r'((?P\d+),)?(?P\d+) VIEWS', webpage) + view_count = int(mobj.group('thousands')) * 1000 + int(mobj.group('units')) if mobj else None + return { 'id': video_id, 'url': video_url, 'thumbnail': thumbnail, 'title': title, 'description': description, - 'duration': duration, + 'duration': int_or_none(duration), + 'view_count': int_or_none(view_count), } From 17b0b8a1661e0f51e17d1ed74307d79eaab1ccfd Mon Sep 17 00:00:00 2001 From: peugeot Date: Sat, 30 Aug 2014 20:55:42 +0200 Subject: [PATCH 0696/1761] testing view count is stupid --- youtube_dl/extractor/anysex.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/youtube_dl/extractor/anysex.py b/youtube_dl/extractor/anysex.py index bfc7eb3c5..d578a1712 100644 --- a/youtube_dl/extractor/anysex.py +++ b/youtube_dl/extractor/anysex.py @@ -16,7 +16,6 @@ class AnySexIE(InfoExtractor): 'ext': 'mp4', 'title': 'Busty and sexy blondie in her bikini strips for you', 'duration': 270, - 'view_count': 3652 } } @@ -39,6 +38,6 @@ class AnySexIE(InfoExtractor): 'ext': 'mp4', 'url': video_url, 'title': title, - 'duration': duration, + 'duration': int_or_none(duration), 'view_count': int_or_none(view_count), } From 1d57b2520c66908a4e21640b5105e16fd4d4e374 Mon Sep 17 00:00:00 2001 From: peugeot Date: Sat, 30 Aug 2014 22:28:53 +0200 Subject: [PATCH 0697/1761] Add support for Eporner --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/eporner.py | 45 ++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 youtube_dl/extractor/eporner.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 1479d998a..94e469389 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -85,6 +85,7 @@ from .ellentv import ( from .elpais import ElPaisIE from .empflix import EmpflixIE from .engadget import EngadgetIE +from .eporner import EpornerIE from .escapist import EscapistIE from .everyonesmixtape import EveryonesMixtapeIE from .exfm import ExfmIE diff --git a/youtube_dl/extractor/eporner.py b/youtube_dl/extractor/eporner.py new file mode 100644 index 000000000..3071da6db --- /dev/null +++ b/youtube_dl/extractor/eporner.py @@ -0,0 +1,45 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import int_or_none + +class EpornerIE(InfoExtractor): + _VALID_URL = r'http?://(?:www\.)?eporner\.com/hd-porn/(?P\d+)/(?P[\w-]+)/?' + _TEST = { + 'url': 'http://www.eporner.com/hd-porn/95008/Infamous-Tiffany-Teen-Strip-Tease-Video/', + 'md5': '3b427ae4b9d60619106de3185c2987cd', + 'info_dict': { + 'id': '95008', + 'ext': 'flv', + 'title': 'Infamous Tiffany Teen Strip Tease Video', + 'duration': 194 + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + webpage = self._download_webpage(url, video_id) + title = self._html_search_regex(r'(.*?) - EPORNER', webpage, 'title') + + redirect_code = self._html_search_regex(r'<script type="text/javascript" src="/config5/'+str(video_id)+'/([a-f\d]+)/">', webpage, 'redirect_code') + redirect_url = 'http://www.eporner.com/config5/' + str(video_id) +'/'+ redirect_code + webpage2 = self._download_webpage(redirect_url, video_id) + video_url = self._html_search_regex(r'file: "(.*?)",', webpage2, 'video_url') + + mobj = re.search(r'class="mbtim">(?P<minutes>\d+):(?P<seconds>\d+)</div>', webpage) + duration = int(mobj.group('minutes')) * 60 + int(mobj.group('seconds')) if mobj else None + + mobj = re.search(r'id="cinemaviews">((?P<thousands>\d+),)?(?P<units>\d+)<small>views', webpage) + view_count = int(mobj.group('thousands')) * 1000 + int(mobj.group('units')) if mobj else None + + return { + 'id': video_id, + 'url': video_url, + 'title': title, + 'duration': int_or_none(duration), + 'view_count': int_or_none(view_count), + } From 8a6c59865d2ab6e69792488567f993096f8f7695 Mon Sep 17 00:00:00 2001 From: peugeot <peugeot@psa.fr> Date: Sat, 30 Aug 2014 23:03:37 +0200 Subject: [PATCH 0698/1761] Fix exception with n_views<1000 --- youtube_dl/extractor/eporner.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/eporner.py b/youtube_dl/extractor/eporner.py index 3071da6db..72c3850b7 100644 --- a/youtube_dl/extractor/eporner.py +++ b/youtube_dl/extractor/eporner.py @@ -34,7 +34,11 @@ class EpornerIE(InfoExtractor): duration = int(mobj.group('minutes')) * 60 + int(mobj.group('seconds')) if mobj else None mobj = re.search(r'id="cinemaviews">((?P<thousands>\d+),)?(?P<units>\d+)<small>views', webpage) - view_count = int(mobj.group('thousands')) * 1000 + int(mobj.group('units')) if mobj else None + try: + view_count = int(mobj.group('units')) + view_count += int(mobj.group('thousands')) * 1000 + except: + pass return { 'id': video_id, From 9c4c233b846bd9be4c48b788d6d2347af764f15d Mon Sep 17 00:00:00 2001 From: peugeot <peugeot@psa.fr> Date: Sat, 30 Aug 2014 23:05:33 +0200 Subject: [PATCH 0699/1761] Fix exception with n_views<1000 --- youtube_dl/extractor/vporn.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/vporn.py b/youtube_dl/extractor/vporn.py index 0d182b650..645e935ec 100644 --- a/youtube_dl/extractor/vporn.py +++ b/youtube_dl/extractor/vporn.py @@ -35,7 +35,11 @@ class VpornIE(InfoExtractor): duration = int(mobj.group('minutes')) * 60 + int(mobj.group('seconds')) if mobj else None mobj = re.search(r'<span>((?P<thousands>\d+),)?(?P<units>\d+) VIEWS</span>', webpage) - view_count = int(mobj.group('thousands')) * 1000 + int(mobj.group('units')) if mobj else None + try: + view_count = int(mobj.group('units')) + view_count += int(mobj.group('thousands')) * 1000 + except: + pass return { 'id': video_id, From ca7b3246b69215c890193acaf4eab746bc19504e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Sun, 31 Aug 2014 06:41:30 +0700 Subject: [PATCH 0700/1761] [utils] Improve parse_duration --- test/test_utils.py | 3 +++ youtube_dl/utils.py | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/test/test_utils.py b/test/test_utils.py index 3d14f61fb..8d8997977 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -211,6 +211,9 @@ class TestUtil(unittest.TestCase): self.assertEqual(parse_duration('00:01:01'), 61) self.assertEqual(parse_duration('x:y'), None) self.assertEqual(parse_duration('3h11m53s'), 11513) + self.assertEqual(parse_duration('3h 11m 53s'), 11513) + self.assertEqual(parse_duration('3 hours 11 minutes 53 seconds'), 11513) + self.assertEqual(parse_duration('3 hours 11 mins 53 secs'), 11513) self.assertEqual(parse_duration('62m45s'), 3765) self.assertEqual(parse_duration('6m59s'), 419) self.assertEqual(parse_duration('49s'), 49) diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 4f0210872..e07750434 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -1332,8 +1332,10 @@ def parse_duration(s): if s is None: return None + s = s.strip() + m = re.match( - r'(?:(?:(?P<hours>[0-9]+)[:h])?(?P<mins>[0-9]+)[:m])?(?P<secs>[0-9]+)s?(?::[0-9]+)?(?P<ms>\.[0-9]+)?$', s) + r'(?:(?:(?P<hours>[0-9]+)\s*(?:[:h]|hours?)\s*)?(?P<mins>[0-9]+)\s*(?:[:m]|mins?|minutes?)\s*)?(?P<secs>[0-9]+)(?P<ms>\.[0-9]+)?\s*(?:s|secs?|seconds?)?$', s) if not m: return None res = int(m.group('secs')) From 7b53af7f70da81eae41da645cc5af2c777c5c8e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= <dstftw@gmail.com> Date: Sun, 31 Aug 2014 06:43:36 +0700 Subject: [PATCH 0701/1761] [vporn] Fix issues, extract all formats and metadata --- youtube_dl/extractor/vporn.py | 91 ++++++++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 22 deletions(-) diff --git a/youtube_dl/extractor/vporn.py b/youtube_dl/extractor/vporn.py index 645e935ec..426369c51 100644 --- a/youtube_dl/extractor/vporn.py +++ b/youtube_dl/extractor/vporn.py @@ -1,52 +1,99 @@ -# coding: utf-8 from __future__ import unicode_literals import re from .common import InfoExtractor -from ..utils import int_or_none +from ..utils import ( + parse_duration, + str_to_int, +) + class VpornIE(InfoExtractor): - _VALID_URL = r'http?://(?:www\.)?vporn\.com/[a-z]+/(?P<title_dash>[a-z-]+)/(?P<id>\d+)/?' + _VALID_URL = r'https?://(?:www\.)?vporn\.com/[^/]+/(?P<display_id>[^/]+)/(?P<id>\d+)' _TEST = { 'url': 'http://www.vporn.com/masturbation/violet-on-her-th-birthday/497944/', 'md5': 'facf37c1b86546fa0208058546842c55', 'info_dict': { 'id': '497944', + 'display_id': 'violet-on-her-th-birthday', 'ext': 'mp4', - 'title': 'Violet On Her 19th Birthday', + 'title': 'Violet on her 19th birthday', 'description': 'Violet dances in front of the camera which is sure to get you horny.', - 'duration': 393, 'thumbnail': 're:^https?://.*\.jpg$', + 'uploader': 'kileyGrope', + 'categories': ['Masturbation', 'Teen'], + 'duration': 393, + 'age_limit': 18, } } def _real_extract(self, url): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('id') + display_id = mobj.group('display_id') - webpage = self._download_webpage(url, video_id) - title = self._html_search_regex(r'<title>(.*?) - Vporn Video', webpage, 'title') - video_url = self._html_search_regex(r'flashvars.videoUrlMedium = "(.*?)"', webpage, 'video_url') - description = self._html_search_regex(r'
    (.*?)
    ', webpage, 'description') - thumbnail = 'http://www.vporn.com' + self._html_search_regex(r'flashvars.imageUrl = "(.*?)"', webpage, 'description') + webpage = self._download_webpage(url, display_id) - mobj = re.search(r'duration (?P\d+) min (?P\d+) sec ', webpage) - duration = int(mobj.group('minutes')) * 60 + int(mobj.group('seconds')) if mobj else None + title = self._html_search_regex( + r'videoname\s*=\s*\'([^\']+)\'', webpage, 'title').strip() + description = self._html_search_regex( + r'
    (.*?)
    ', webpage, 'description', fatal=False) + thumbnail = self._html_search_regex( + r'flashvars\.imageUrl\s*=\s*"([^"]+)"', webpage, 'description', fatal=False, default=None) + if thumbnail: + thumbnail = 'http://www.vporn.com' + thumbnail - mobj = re.search(r'((?P\d+),)?(?P\d+) VIEWS', webpage) - try: - view_count = int(mobj.group('units')) - view_count += int(mobj.group('thousands')) * 1000 - except: - pass + uploader = self._html_search_regex( + r'(?s)UPLOADED BY.*?
    ([^<]+)', + webpage, 'uploader', fatal=False) + + categories = re.findall(r'([^<]+)', webpage) + + duration = parse_duration(self._search_regex( + r'duration (\d+ min \d+ sec)', webpage, 'duration', fatal=False)) + + view_count = str_to_int(self._html_search_regex( + r'([\d,\.]+) VIEWS', webpage, 'view count', fatal=False)) + like_count = str_to_int(self._html_search_regex( + r'([\d,\.]+)', webpage, 'like count', fatal=False)) + dislike_count = str_to_int(self._html_search_regex( + r'([\d,\.]+)', webpage, 'dislike count', fatal=False)) + comment_count = str_to_int(self._html_search_regex( + r'

    Comments \(([\d,\.]+)\)

    ', webpage, 'comment count', fatal=False)) + + formats = [] + + for video in re.findall(r'flashvars\.videoUrl([^=]+?)\s*=\s*"([^"]+)"', webpage): + video_url = video[1] + fmt = { + 'url': video_url, + 'format_id': video[0], + } + m = re.search(r'_(?P\d+)x(?P\d+)_(?P\d+)k\.mp4$', video_url) + if m: + fmt.update({ + 'width': int(m.group('width')), + 'height': int(m.group('height')), + 'vbr': int(m.group('vbr')), + }) + formats.append(fmt) + + self._sort_formats(formats) return { 'id': video_id, - 'url': video_url, - 'thumbnail': thumbnail, + 'display_id': display_id, 'title': title, 'description': description, - 'duration': int_or_none(duration), - 'view_count': int_or_none(view_count), + 'thumbnail': thumbnail, + 'uploader': uploader, + 'categories': categories, + 'duration': duration, + 'view_count': view_count, + 'like_count': like_count, + 'dislike_count': dislike_count, + 'comment_count': comment_count, + 'age_limit': 18, + 'formats': formats, } From 35241d05d11f713849678577b4d6ccdd25baedb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Sun, 31 Aug 2014 07:05:53 +0700 Subject: [PATCH 0702/1761] [anysex] Simplify and extract more metadata --- youtube_dl/extractor/anysex.py | 39 ++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/youtube_dl/extractor/anysex.py b/youtube_dl/extractor/anysex.py index d578a1712..adeacba01 100644 --- a/youtube_dl/extractor/anysex.py +++ b/youtube_dl/extractor/anysex.py @@ -1,13 +1,16 @@ -# coding: utf-8 from __future__ import unicode_literals import re from .common import InfoExtractor -from ..utils import int_or_none +from ..utils import ( + parse_duration, + int_or_none, +) + class AnySexIE(InfoExtractor): - _VALID_URL = r'http?://(?:www\.)?anysex\.com/(?P\d+)/?' + _VALID_URL = r'https?://(?:www\.)?anysex\.com/(?P\d+)' _TEST = { 'url': 'http://anysex.com/156592/', 'md5': '023e9fbb7f7987f5529a394c34ad3d3d', @@ -15,6 +18,8 @@ class AnySexIE(InfoExtractor): 'id': '156592', 'ext': 'mp4', 'title': 'Busty and sexy blondie in her bikini strips for you', + 'description': 'md5:de9e418178e2931c10b62966474e1383', + 'categories': ['Erotic'], 'duration': 270, } } @@ -24,20 +29,32 @@ class AnySexIE(InfoExtractor): video_id = mobj.group('id') webpage = self._download_webpage(url, video_id) + + video_url = self._html_search_regex(r"video_url\s*:\s*'([^']+)'", webpage, 'video URL') + title = self._html_search_regex(r'(.*?)', webpage, 'title') - video_url = self._html_search_regex(r'video_url: \'(.*?)\',', webpage, 'video_url') - thumbnail = self._html_search_regex(r'preview_url: \'(.*?)\',', webpage, 'thumbnail') + description = self._html_search_regex( + r'
    ([^<]+)
    ', webpage, 'description', fatal=False) + thumbnail = self._html_search_regex( + r'preview_url\s*:\s*\'(.*?)\'', webpage, 'thumbnail', fatal=False) - mobj = re.search(r'Duration: (?P\d+):(?P\d+)<', webpage) - duration = int(mobj.group('minutes')) * 60 + int(mobj.group('seconds')) if mobj else None + categories = re.findall( + r'([^<]+)', webpage) - view_count = self._html_search_regex(r'Views: (\d+)', webpage, 'view count', fatal=False) + duration = parse_duration(self._search_regex( + r'Duration: (\d+:\d+)', webpage, 'duration', fatal=False)) + + view_count = int_or_none(self._html_search_regex( + r'Views: (\d+)', webpage, 'view count', fatal=False)) return { 'id': video_id, - 'ext': 'mp4', 'url': video_url, + 'ext': 'mp4', 'title': title, - 'duration': int_or_none(duration), - 'view_count': int_or_none(view_count), + 'description': description, + 'thumbnail': thumbnail, + 'categories': categories, + 'duration': duration, + 'view_count': view_count, } From 2aebbccefceec3eb2cad147204123cb28b9d81d1 Mon Sep 17 00:00:00 2001 From: peugeot Date: Sun, 31 Aug 2014 11:57:10 +0200 Subject: [PATCH 0703/1761] Add support for beeg.com --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/beeg.py | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 youtube_dl/extractor/beeg.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 1479d998a..01b5f19dd 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -23,6 +23,7 @@ from .auengine import AUEngineIE from .bambuser import BambuserIE, BambuserChannelIE from .bandcamp import BandcampIE, BandcampAlbumIE from .bbccouk import BBCCoUkIE +from .beeg import BeegIE from .bilibili import BiliBiliIE from .blinkx import BlinkxIE from .bliptv import BlipTVIE, BlipTVUserIE diff --git a/youtube_dl/extractor/beeg.py b/youtube_dl/extractor/beeg.py new file mode 100644 index 000000000..775f6be6b --- /dev/null +++ b/youtube_dl/extractor/beeg.py @@ -0,0 +1,48 @@ +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor + + +class BeegIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?beeg\.com/(?P\d+)' + _TEST = { + 'url': 'http://beeg.com/5416503', + 'md5': '634526ae978711f6b748fe0dd6c11f57', + 'info_dict': { + 'id': '5416503', + 'ext': 'mp4', + 'title': 'Sultry Striptease', + 'description': 'md5:6db3c6177972822aaba18652ff59c773', + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + + video_url = self._html_search_regex(r"'480p'\s*:\s*'([^']+)'", webpage, 'video URL') + + title = self._html_search_regex(r'([^<]+)\s*-\s*beeg\.?', webpage, 'title') + + description = self._html_search_regex( + r' Date: Sun, 31 Aug 2014 12:38:00 +0200 Subject: [PATCH 0704/1761] [youtube] Fix extraction of like and dislike count (fixes #3633) --- youtube_dl/extractor/youtube.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index 75044d71a..13676c49f 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -813,15 +813,15 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): else: video_description = u'' - def _extract_count(klass): + def _extract_count(count_name): count = self._search_regex( - r'class="%s">([\d,]+)' % re.escape(klass), - video_webpage, klass, default=None) + r'id="watch-%s"[^>]*>.*?([\d,]+)\s*' % re.escape(count_name), + video_webpage, count_name, default=None) if count is not None: return int(count.replace(',', '')) return None - like_count = _extract_count(u'likes-count') - dislike_count = _extract_count(u'dislikes-count') + like_count = _extract_count(u'like') + dislike_count = _extract_count(u'dislike') # subtitles video_subtitles = self.extract_subtitles(video_id, video_webpage) From 7eb21356f98315b15fc05d9e616951511253076f Mon Sep 17 00:00:00 2001 From: peugeot Date: Sun, 31 Aug 2014 12:48:34 +0200 Subject: [PATCH 0705/1761] Add support for sunporno.com --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/sunporno.py | 57 ++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 youtube_dl/extractor/sunporno.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 1479d998a..72b01505d 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -322,6 +322,7 @@ from .stanfordoc import StanfordOpenClassroomIE from .steam import SteamIE from .streamcloud import StreamcloudIE from .streamcz import StreamCZIE +from .sunporno import SunPornoIE from .swrmediathek import SWRMediathekIE from .syfy import SyfyIE from .sztvhu import SztvHuIE diff --git a/youtube_dl/extractor/sunporno.py b/youtube_dl/extractor/sunporno.py new file mode 100644 index 000000000..2a193dee3 --- /dev/null +++ b/youtube_dl/extractor/sunporno.py @@ -0,0 +1,57 @@ +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ( + parse_duration, + int_or_none, +) + + +class SunPornoIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?sunporno\.com/videos/(?P\d+)' + _TEST = { + 'url': 'http://www.sunporno.com/videos/807778/', + 'md5': '6457d3c165fd6de062b99ef6c2ff4c86', + 'info_dict': { + 'id': '807778', + 'ext': 'flv', + 'title': 'md5:0a400058e8105d39e35c35e7c5184164', + 'description': 'md5:a31241990e1bd3a64e72ae99afb325fb', + 'duration': 302, + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + + video_url = self._html_search_regex( + r'videoSource\s*=\s*\'([^<]*)', webpage, 'title') + + description = self._html_search_regex( + r'Duration: (\d+:\d+)', webpage, 'duration', fatal=False)) + + view_count = int_or_none(self._html_search_regex( + r'(\d+)', webpage, 'view count', fatal=False)) + + return { + 'id': video_id, + 'url': video_url, + 'title': title, + 'description': description, + 'thumbnail': thumbnail, + 'duration': duration, + 'view_count': view_count, + } From 3e7c12240c7b23913a8a9df2ded21dfae7624d84 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 31 Aug 2014 18:10:05 +0200 Subject: [PATCH 0706/1761] [youtube] Test for like_count and dislike_count (#3633) --- youtube_dl/extractor/youtube.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index 13676c49f..bdabcaa27 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -316,6 +316,8 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): u"upload_date": u"20121002", u"description": u"test chars: \"'/\\ä↭𝕐\ntest URL: https://github.com/rg3/youtube-dl/issues/1892\n\nThis is a test video for youtube-dl.\n\nFor more information, contact phihag@phihag.de .", u"categories": [u'Science & Technology'], + 'like_count': int, + 'dislike_count': int, } }, { From ae7246e7d57654381fb629be46662f8e4ded615f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Mon, 1 Sep 2014 01:08:19 +0700 Subject: [PATCH 0707/1761] [sunporno] Extract all formats and metadata --- youtube_dl/extractor/sunporno.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/youtube_dl/extractor/sunporno.py b/youtube_dl/extractor/sunporno.py index 2a193dee3..c7a46eb71 100644 --- a/youtube_dl/extractor/sunporno.py +++ b/youtube_dl/extractor/sunporno.py @@ -6,6 +6,8 @@ from .common import InfoExtractor from ..utils import ( parse_duration, int_or_none, + qualities, + determine_ext, ) @@ -19,6 +21,7 @@ class SunPornoIE(InfoExtractor): 'ext': 'flv', 'title': 'md5:0a400058e8105d39e35c35e7c5184164', 'description': 'md5:a31241990e1bd3a64e72ae99afb325fb', + 'thumbnail': 're:^https?://.*\.jpg$', 'duration': 302, } } @@ -29,29 +32,37 @@ class SunPornoIE(InfoExtractor): webpage = self._download_webpage(url, video_id) - video_url = self._html_search_regex( - r'videoSource\s*=\s*\'([^<]*)', webpage, 'title') - - description = self._html_search_regex( - r'([^<]+)', webpage, 'title') + description = self._html_search_meta('description', webpage, 'description') thumbnail = self._html_search_regex( - r'poster="([^"]*)"', webpage, 'thumbnail', fatal=False) + r'poster="([^"]+)"', webpage, 'thumbnail', fatal=False) duration = parse_duration(self._search_regex( r'Duration: (\d+:\d+)', webpage, 'duration', fatal=False)) view_count = int_or_none(self._html_search_regex( r'(\d+)', webpage, 'view count', fatal=False)) + comment_count = int_or_none(self._html_search_regex( + r'(\d+) Comments?', webpage, 'comment count', fatal=False)) + + formats = [] + quality = qualities(['mp4', 'flv']) + for video_url in re.findall(r' Date: Sun, 31 Aug 2014 23:11:52 +0300 Subject: [PATCH 0708/1761] [tudou] Fix #3643 - filter non-number qualities --- youtube_dl/extractor/tudou.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/tudou.py b/youtube_dl/extractor/tudou.py index 7a3891b89..96e0732bd 100644 --- a/youtube_dl/extractor/tudou.py +++ b/youtube_dl/extractor/tudou.py @@ -57,7 +57,8 @@ class TudouIE(InfoExtractor): segments = json.loads(segs_json) # It looks like the keys are the arguments that have to be passed as # the hd field in the request url, we pick the higher - quality = sorted(segments.keys())[-1] + # Also, filter non-number qualities (see issue #3643). + quality = sorted(filter(lambda k: k.isdigit(), segments.keys()))[-1] parts = segments[quality] result = [] len_parts = len(parts) From f931e2595936776380de5df9288a11c04337d780 Mon Sep 17 00:00:00 2001 From: Naglis Jonaitis Date: Sun, 31 Aug 2014 23:14:35 +0300 Subject: [PATCH 0709/1761] [tudou] Sort qualities by numeric value --- youtube_dl/extractor/tudou.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/tudou.py b/youtube_dl/extractor/tudou.py index 96e0732bd..23816599c 100644 --- a/youtube_dl/extractor/tudou.py +++ b/youtube_dl/extractor/tudou.py @@ -58,7 +58,8 @@ class TudouIE(InfoExtractor): # It looks like the keys are the arguments that have to be passed as # the hd field in the request url, we pick the higher # Also, filter non-number qualities (see issue #3643). - quality = sorted(filter(lambda k: k.isdigit(), segments.keys()))[-1] + quality = sorted(filter(lambda k: k.isdigit(), segments.keys()), + key=lambda k: int(k))[-1] parts = segments[quality] result = [] len_parts = len(parts) From 55f7bd2dccb9b0ff24074ba8e8dbe6d67ed49c0a Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 31 Aug 2014 23:26:19 +0200 Subject: [PATCH 0710/1761] [youtube] Fix category extraction --- youtube_dl/extractor/youtube.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index bdabcaa27..3417c1275 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -786,7 +786,9 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor): upload_date = ' '.join(re.sub(r'[/,-]', r' ', mobj.group(1)).split()) upload_date = unified_strdate(upload_date) - m_cat_container = get_element_by_id("eow-category", video_webpage) + m_cat_container = self._search_regex( + r'(?s)]*>\s*Category\s*\s*]*>(.*?)', + video_webpage, 'categories', fatal=False) if m_cat_container: category = self._html_search_regex( r'(?s)(.*?)', m_cat_container, 'category', From 1ed5b5c9c8d4a99fbe63d7d43912ef5c931086fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sun, 31 Aug 2014 23:44:43 +0200 Subject: [PATCH 0711/1761] [youtube:subscriptions] Fix extraction (fixes #2975) --- youtube_dl/extractor/youtube.py | 43 ++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index 13676c49f..a8d7bc343 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -1430,12 +1430,6 @@ class YoutubeFeedsInfoExtractor(YoutubeBaseInfoExtractor): paging = mobj.group('paging') return self.playlist_result(feed_entries, playlist_title=self._PLAYLIST_TITLE) -class YoutubeSubscriptionsIE(YoutubeFeedsInfoExtractor): - IE_DESC = u'YouTube.com subscriptions feed, "ytsubs" keyword (requires authentication)' - _VALID_URL = r'https?://www\.youtube\.com/feed/subscriptions|:ytsubs(?:criptions)?' - _FEED_NAME = 'subscriptions' - _PLAYLIST_TITLE = u'Youtube Subscriptions' - class YoutubeRecommendedIE(YoutubeFeedsInfoExtractor): IE_DESC = u'YouTube.com recommended videos, "ytrec" keyword (requires authentication)' _VALID_URL = r'https?://www\.youtube\.com/feed/recommended|:ytrec(?:ommended)?' @@ -1468,6 +1462,43 @@ class YoutubeFavouritesIE(YoutubeBaseInfoExtractor): return self.url_result(playlist_id, 'YoutubePlaylist') +class YoutubeSubscriptionsIE(YoutubePlaylistIE): + IE_NAME = u'youtube:subscriptions' + IE_DESC = u'YouTube.com subscriptions feed, "ytsubs" keyword (requires authentication)' + _VALID_URL = r'https?://www\.youtube\.com/feed/subscriptions|:ytsubs(?:criptions)?' + + def _real_extract(self, url): + title = u'Youtube Subscriptions' + page = self._download_webpage('https://www.youtube.com/feed/subscriptions', title) + + # The extraction process is the same as for playlists, but the regex + # for the video ids doesn't contain an index + ids = [] + more_widget_html = content_html = page + + for page_num in itertools.count(1): + matches = re.findall(r'href="\s*/watch\?v=([0-9A-Za-z_-]{11})', content_html) + new_ids = orderedSet(matches) + ids.extend(new_ids) + + mobj = re.search(r'data-uix-load-more-href="/?(?P[^"]+)"', more_widget_html) + if not mobj: + break + + more = self._download_json( + 'https://youtube.com/%s' % mobj.group('more'), title, + 'Downloading page #%s' % page_num, + transform_source=uppercase_escape) + content_html = more['content_html'] + more_widget_html = more['load_more_widget_html'] + + return { + '_type': 'playlist', + 'title': title, + 'entries': self._ids_to_results(ids), + } + + class YoutubeTruncatedURLIE(InfoExtractor): IE_NAME = 'youtube:truncated_url' IE_DESC = False # Do not list From 48d4681efcb02455722e15b0183bd42ab50dc748 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 31 Aug 2014 23:51:36 +0200 Subject: [PATCH 0712/1761] [eporner] Simplify and correct (#3629) --- youtube_dl/extractor/eporner.py | 42 +++++++++++++++++++-------------- youtube_dl/utils.py | 1 + 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/youtube_dl/extractor/eporner.py b/youtube_dl/extractor/eporner.py index 72c3850b7..4c2c074cb 100644 --- a/youtube_dl/extractor/eporner.py +++ b/youtube_dl/extractor/eporner.py @@ -4,10 +4,14 @@ from __future__ import unicode_literals import re from .common import InfoExtractor -from ..utils import int_or_none +from ..utils import ( + parse_duration, + str_to_int, +) + class EpornerIE(InfoExtractor): - _VALID_URL = r'http?://(?:www\.)?eporner\.com/hd-porn/(?P\d+)/(?P[\w-]+)/?' + _VALID_URL = r'https?://(?:www\.)?eporner\.com/hd-porn/(?P\d+)/(?P[\w-]+)/?' _TEST = { 'url': 'http://www.eporner.com/hd-porn/95008/Infamous-Tiffany-Teen-Strip-Tease-Video/', 'md5': '3b427ae4b9d60619106de3185c2987cd', @@ -15,7 +19,8 @@ class EpornerIE(InfoExtractor): 'id': '95008', 'ext': 'flv', 'title': 'Infamous Tiffany Teen Strip Tease Video', - 'duration': 194 + 'duration': 194, + 'view_count': int, } } @@ -23,27 +28,28 @@ class EpornerIE(InfoExtractor): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('id') webpage = self._download_webpage(url, video_id) - title = self._html_search_regex(r'(.*?) - EPORNER', webpage, 'title') + title = self._html_search_regex( + r'<title>(.*?) - EPORNER', webpage, 'title') - redirect_code = self._html_search_regex(r'<script type="text/javascript" src="/config5/'+str(video_id)+'/([a-f\d]+)/">', webpage, 'redirect_code') - redirect_url = 'http://www.eporner.com/config5/' + str(video_id) +'/'+ redirect_code + redirect_code = self._html_search_regex( + r'<script type="text/javascript" src="/config5/%s/([a-f\d]+)/">' % video_id, + webpage, 'redirect_code') + redirect_url = 'http://www.eporner.com/config5/%s/%s' % (video_id, redirect_code) webpage2 = self._download_webpage(redirect_url, video_id) - video_url = self._html_search_regex(r'file: "(.*?)",', webpage2, 'video_url') + video_url = self._html_search_regex( + r'file: "(.*?)",', webpage2, 'video_url') - mobj = re.search(r'class="mbtim">(?P<minutes>\d+):(?P<seconds>\d+)</div>', webpage) - duration = int(mobj.group('minutes')) * 60 + int(mobj.group('seconds')) if mobj else None - - mobj = re.search(r'id="cinemaviews">((?P<thousands>\d+),)?(?P<units>\d+)<small>views', webpage) - try: - view_count = int(mobj.group('units')) - view_count += int(mobj.group('thousands')) * 1000 - except: - pass + duration = parse_duration(self._search_regex( + r'class="mbtim">([0-9:]+)</div>', webpage, 'duration', + fatal=False)) + view_count = str_to_int(self._search_regex( + r'id="cinemaviews">\s*([0-9,]+)\s*<small>views', + webpage, 'view count', fatal=False)) return { 'id': video_id, 'url': video_url, 'title': title, - 'duration': int_or_none(duration), - 'view_count': int_or_none(view_count), + 'duration': duration, + 'view_count': view_count, } diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index e07750434..8a36e619a 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -1318,6 +1318,7 @@ def str_or_none(v, default=None): def str_to_int(int_str): + """ A more relaxed version of int_or_none """ if int_str is None: return None int_str = re.sub(r'[,\.]', u'', int_str) From d169e36f5c4dc50a6c19c2155ea7ea7a89dd5c31 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister <phihag@phihag.de> Date: Mon, 1 Sep 2014 00:00:01 +0200 Subject: [PATCH 0713/1761] [beeg] PEP8 and additional tests --- youtube_dl/extractor/beeg.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/youtube_dl/extractor/beeg.py b/youtube_dl/extractor/beeg.py index 775f6be6b..c2692cfdc 100644 --- a/youtube_dl/extractor/beeg.py +++ b/youtube_dl/extractor/beeg.py @@ -15,6 +15,8 @@ class BeegIE(InfoExtractor): 'ext': 'mp4', 'title': 'Sultry Striptease', 'description': 'md5:6db3c6177972822aaba18652ff59c773', + 'categories': list, # NSFW + 'thumbnail': 're:https?://.*\.jpg$', } } @@ -24,15 +26,18 @@ class BeegIE(InfoExtractor): webpage = self._download_webpage(url, video_id) - video_url = self._html_search_regex(r"'480p'\s*:\s*'([^']+)'", webpage, 'video URL') + video_url = self._html_search_regex( + r"'480p'\s*:\s*'([^']+)'", webpage, 'video URL') - title = self._html_search_regex(r'<title>([^<]+)\s*-\s*beeg\.?', webpage, 'title') + title = self._html_search_regex( + r'([^<]+)\s*-\s*beeg\.?', webpage, 'title') description = self._html_search_regex( - r' Date: Mon, 1 Sep 2014 00:02:47 +0200 Subject: [PATCH 0714/1761] release 2014.09.01 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 7afdc2efd..09854b962 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.08.29' +__version__ = '2014.09.01' From 8bdfddf641b56731c8dcc864f8684e69e6b3fe3c Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 1 Sep 2014 00:16:26 +0200 Subject: [PATCH 0715/1761] [tudou] Modernize --- youtube_dl/extractor/tudou.py | 48 ++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/youtube_dl/extractor/tudou.py b/youtube_dl/extractor/tudou.py index 7a3891b89..3da9978b8 100644 --- a/youtube_dl/extractor/tudou.py +++ b/youtube_dl/extractor/tudou.py @@ -1,5 +1,7 @@ # coding: utf-8 +from __future__ import unicode_literals + import re import json @@ -9,22 +11,21 @@ from .common import InfoExtractor class TudouIE(InfoExtractor): _VALID_URL = r'(?:http://)?(?:www\.)?tudou\.com/(?:listplay|programs|albumplay)/(?:view|(.+?))/(?:([^/]+)|([^/]+))(?:\.html)?' _TESTS = [{ - u'url': u'http://www.tudou.com/listplay/zzdE77v6Mmo/2xN2duXMxmw.html', - u'file': u'159448201.f4v', - u'md5': u'140a49ed444bd22f93330985d8475fcb', - u'info_dict': { - u"title": u"卡马乔国足开大脚长传冲吊集锦" + 'url': 'http://www.tudou.com/listplay/zzdE77v6Mmo/2xN2duXMxmw.html', + 'md5': '140a49ed444bd22f93330985d8475fcb', + 'info_dict': { + 'id': '159448201', + 'ext': 'f4v', + 'title': '卡马乔国足开大脚长传冲吊集锦', + 'thumbnail': 're:^https?://.*\.jpg$', } - }, - { - u'url': u'http://www.tudou.com/albumplay/TenTw_JgiPM/PzsAs5usU9A.html', - u'file': u'todo.mp4', - u'md5': u'todo.mp4', - u'info_dict': { - u'title': u'todo.mp4', + }, { + 'url': 'http://www.tudou.com/albumplay/TenTw_JgiPM/PzsAs5usU9A.html', + 'info_dict': { + 'title': 'todo.mp4', }, - u'add_ie': [u'Youku'], - u'skip': u'Only works from China' + 'add_ie': ['Youku'], + 'skip': 'Only works from China' }] def _url_for_id(self, id, quality = None): @@ -44,14 +45,14 @@ class TudouIE(InfoExtractor): if m and m.group(1): return { '_type': 'url', - 'url': u'youku:' + m.group(1), + 'url': 'youku:' + m.group(1), 'ie_key': 'Youku' } title = self._search_regex( - r",kw:\s*['\"](.+?)[\"']", webpage, u'title') + r",kw:\s*['\"](.+?)[\"']", webpage, 'title') thumbnail_url = self._search_regex( - r",pic:\s*[\"'](.+?)[\"']", webpage, u'thumbnail URL', fatal=False) + r",pic:\s*[\"'](.+?)[\"']", webpage, 'thumbnail URL', fatal=False) segs_json = self._search_regex(r'segs: \'(.*)\'', webpage, 'segments') segments = json.loads(segs_json) @@ -67,12 +68,13 @@ class TudouIE(InfoExtractor): part_id = part['k'] final_url = self._url_for_id(part_id, quality) ext = (final_url.split('?')[0]).split('.')[-1] - part_info = {'id': part_id, - 'url': final_url, - 'ext': ext, - 'title': title, - 'thumbnail': thumbnail_url, - } + part_info = { + 'id': '%s' % part_id, + 'url': final_url, + 'ext': ext, + 'title': title, + 'thumbnail': thumbnail_url, + } result.append(part_info) return result From a8be56ce3d3c816c2f4a1cd1d43d963ebe3a29a7 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 1 Sep 2014 00:20:12 +0200 Subject: [PATCH 0716/1761] [tudou] Add test case for #3643 --- youtube_dl/extractor/tudou.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/youtube_dl/extractor/tudou.py b/youtube_dl/extractor/tudou.py index a85065121..dcd823d08 100644 --- a/youtube_dl/extractor/tudou.py +++ b/youtube_dl/extractor/tudou.py @@ -19,6 +19,14 @@ class TudouIE(InfoExtractor): 'title': '卡马乔国足开大脚长传冲吊集锦', 'thumbnail': 're:^https?://.*\.jpg$', } + }, { + 'url': 'http://www.tudou.com/programs/view/ajX3gyhL0pc/', + 'info_dict': { + 'id': '117049447', + 'ext': 'f4v', + 'title': 'La Sylphide-Bolshoi-Ekaterina Krysanova & Vyacheslav Lopatin 2012', + 'thumbnail': 're:^https?://.*\.jpg$', + } }, { 'url': 'http://www.tudou.com/albumplay/TenTw_JgiPM/PzsAs5usU9A.html', 'info_dict': { From 61edcfb0a2dd9a870657ae71fe5856da3bab2ac4 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 1 Sep 2014 00:20:18 +0200 Subject: [PATCH 0717/1761] release 2014.09.01.1 --- youtube_dl/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/version.py b/youtube_dl/version.py index 09854b962..59f6b4736 100644 --- a/youtube_dl/version.py +++ b/youtube_dl/version.py @@ -1,2 +1,2 @@ -__version__ = '2014.09.01' +__version__ = '2014.09.01.1' From c9cc0bf57b908eabc3765893289449a2c31d402a Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 1 Sep 2014 01:00:40 +0200 Subject: [PATCH 0718/1761] [youtube:playlist] PEP8 --- youtube_dl/extractor/youtube.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index 78f3b7e7b..08a04737c 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -1055,21 +1055,26 @@ class YoutubePlaylistIE(YoutubeBaseInfoExtractor): self._login() def _ids_to_results(self, ids): - return [self.url_result(vid_id, 'Youtube', video_id=vid_id) - for vid_id in ids] + return [ + self.url_result(vid_id, 'Youtube', video_id=vid_id) + for vid_id in ids] def _extract_mix(self, playlist_id): # The mixes are generated from a a single video # the id of the playlist is just 'RD' + video_id url = 'https://youtube.com/watch?v=%s&list=%s' % (playlist_id[-11:], playlist_id) - webpage = self._download_webpage(url, playlist_id, u'Downloading Youtube mix') + webpage = self._download_webpage( + url, playlist_id, u'Downloading Youtube mix') search_title = lambda class_name: get_element_by_attribute('class', class_name, webpage) - title_span = (search_title('playlist-title') or - search_title('title long-title') or search_title('title')) + title_span = ( + search_title('playlist-title') or + search_title('title long-title') or + search_title('title')) title = clean_html(title_span) - video_re = r'''(?x)data-video-username=".*?".*? - href="/watch\?v=([0-9A-Za-z_-]{11})&[^"]*?list=%s''' % re.escape(playlist_id) - ids = orderedSet(re.findall(video_re, webpage, flags=re.DOTALL)) + ids = orderedSet(re.findall( + r'''(?xs)data-video-username=".*?".*? + href="/watch\?v=([0-9A-Za-z_-]{11})&[^"]*?list=%s''' % re.escape(playlist_id), + webpage)) url_results = self._ids_to_results(ids) return self.playlist_result(url_results, playlist_id, title) @@ -1162,6 +1167,7 @@ class YoutubeTopListIE(YoutubePlaylistIE): msg = u'Downloading Youtube mix' if i > 0: msg += ', retry #%d' % i + webpage = self._download_webpage(url, title, msg) ids = orderedSet(re.findall(video_re, webpage)) if ids: From 2582bebe06cf06cd2bdce9ada7764fccc3730ef4 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 1 Sep 2014 01:41:25 +0200 Subject: [PATCH 0719/1761] [utils] Use flock instead of lockf (Fixes #3621) --- youtube_dl/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 8a36e619a..6fe057234 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -1141,10 +1141,10 @@ else: import fcntl def _lock_file(f, exclusive): - fcntl.lockf(f, fcntl.LOCK_EX if exclusive else fcntl.LOCK_SH) + fcntl.flock(f, fcntl.LOCK_EX if exclusive else fcntl.LOCK_SH) def _unlock_file(f): - fcntl.lockf(f, fcntl.LOCK_UN) + fcntl.flock(f, fcntl.LOCK_UN) class locked_file(object): From 9ebf22b7d9a696b34566046366d11a9c5f8445c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Mon, 1 Sep 2014 20:13:04 +0700 Subject: [PATCH 0720/1761] [common] Improve codecs extraction from m3u8 --- youtube_dl/extractor/common.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 8453321c5..929dd1e97 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -677,9 +677,12 @@ class InfoExtractor(object): } codecs = last_info.get('CODECS') if codecs: - video, audio = codecs.split(',') - f['vcodec'] = video.partition('.')[0] - f['acodec'] = audio.partition('.')[0] + # TODO: looks like video codec is not always necessarily goes first + va_codecs = codecs.split(',') + if va_codecs[0]: + f['vcodec'] = va_codecs[0].partition('.')[0] + if len(va_codecs) > 1 and va_codecs[1]: + f['acodec'] = va_codecs[1].partition('.')[0] resolution = last_info.get('RESOLUTION') if resolution: width_str, height_str = resolution.split('x') From c9ea760e3113151ee7bfe97c34717fe01e239b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Mon, 1 Sep 2014 20:13:32 +0700 Subject: [PATCH 0721/1761] [npo] Extract all formats --- youtube_dl/extractor/npo.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/youtube_dl/extractor/npo.py b/youtube_dl/extractor/npo.py index 12e85a716..902d62944 100644 --- a/youtube_dl/extractor/npo.py +++ b/youtube_dl/extractor/npo.py @@ -5,6 +5,7 @@ import re from .common import InfoExtractor from ..utils import ( unified_strdate, + qualities, ) @@ -17,7 +18,7 @@ class NPOIE(InfoExtractor): 'md5': '4b3f9c429157ec4775f2c9cb7b911016', 'info_dict': { 'id': 'VPWON_1220719', - 'ext': 'mp4', + 'ext': 'm4v', 'title': 'Nieuwsuur', 'description': 'Dagelijks tussen tien en elf: nieuws, sport en achtergronden.', 'upload_date': '20140622', @@ -39,24 +40,32 @@ class NPOIE(InfoExtractor): video_id, note='Downloading token' ) - token = self._search_regex(r'npoplayer.token = "(.+?)"', token_page, 'token') - streams_info = self._download_json( - 'http://ida.omroep.nl/odi/?prid=%s&puboptions=h264_std&adaptive=yes&token=%s' % (video_id, token), - video_id - ) + token = self._search_regex(r'npoplayer\.token = "(.+?)"', token_page, 'token') - stream_info = self._download_json( - streams_info['streams'][0] + '&type=json', - video_id, - 'Downloading stream info' - ) + formats = [] + quality = qualities(['adaptive', 'h264_sb', 'h264_bb', 'h264_std']) + for format_id in metadata['pubopties']: + streams_info = self._download_json( + 'http://ida.omroep.nl/odi/?prid=%s&puboptions=%s&adaptive=yes&token=%s' % (video_id, format_id, token), + video_id, 'Downloading %s streams info' % format_id) + stream_info = self._download_json( + streams_info['streams'][0] + '&type=json', + video_id, 'Downloading %s stream info' % format_id) + if format_id == 'adaptive': + formats.extend(self._extract_m3u8_formats(stream_info['url'], video_id)) + else: + formats.append({ + 'url': stream_info['url'], + 'format_id': format_id, + 'quality': quality(format_id), + }) + self._sort_formats(formats) return { 'id': video_id, 'title': metadata['titel'], - 'ext': 'mp4', - 'url': stream_info['url'], 'description': metadata['info'], 'thumbnail': metadata['images'][-1]['url'], 'upload_date': unified_strdate(metadata['gidsdatum']), + 'formats': formats, } From 35b1e44567710f65297472ed6fcd251c452d63e8 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 1 Sep 2014 17:11:28 +0200 Subject: [PATCH 0722/1761] Fix --rm-cache-dir error message --- youtube_dl/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index b15695053..bf616e3b6 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -876,7 +876,7 @@ def _real_main(argv=None): ydl.to_screen(u'No cache dir specified (Did you combine --no-cache-dir and --rm-cache-dir?)') else: if ('.cache' not in opts.cachedir) or ('youtube-dl' not in opts.cachedir): - ydl.to_screen(u'Not removing directory %s - this does not look like a cache dir') + ydl.to_screen(u'Not removing directory %s - this does not look like a cache dir' % opts.cachedir) retcode = 141 else: ydl.to_screen( From 7260ea07051edc5166de5374bcbcd87cf283288b Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 1 Sep 2014 17:57:45 +0200 Subject: [PATCH 0723/1761] [comedycentral] Move tests to the extractor itself --- test/test_all_urls.py | 26 ------------------------- youtube_dl/extractor/comedycentral.py | 28 +++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/test/test_all_urls.py b/test/test_all_urls.py index 5f1092939..84b05da39 100644 --- a/test/test_all_urls.py +++ b/test/test_all_urls.py @@ -143,32 +143,6 @@ class TestAllURLsMatching(unittest.TestCase): self.assertMatch('http://video.pbs.org/viralplayer/2365173446/', ['PBS']) self.assertMatch('http://video.pbs.org/widget/partnerplayer/980042464/', ['PBS']) - def test_ComedyCentralShows(self): - self.assertMatch( - 'http://thedailyshow.cc.com/extended-interviews/xm3fnq/andrew-napolitano-extended-interview', - ['ComedyCentralShows']) - self.assertMatch( - 'http://thecolbertreport.cc.com/videos/29w6fx/-realhumanpraise-for-fox-news', - ['ComedyCentralShows']) - self.assertMatch( - 'http://thecolbertreport.cc.com/videos/gh6urb/neil-degrasse-tyson-pt--1?xrs=eml_col_031114', - ['ComedyCentralShows']) - self.assertMatch( - 'http://thedailyshow.cc.com/guests/michael-lewis/3efna8/exclusive---michael-lewis-extended-interview-pt--3', - ['ComedyCentralShows']) - self.assertMatch( - 'http://thedailyshow.cc.com/episodes/sy7yv0/april-8--2014---denis-leary', - ['ComedyCentralShows']) - self.assertMatch( - 'http://thecolbertreport.cc.com/episodes/8ase07/april-8--2014---jane-goodall', - ['ComedyCentralShows']) - self.assertMatch( - 'http://thedailyshow.cc.com/video-playlists/npde3s/the-daily-show-19088-highlights', - ['ComedyCentralShows']) - self.assertMatch( - 'http://thedailyshow.cc.com/special-editions/2l8fdb/special-edition---a-look-back-at-food', - ['ComedyCentralShows']) - def test_yahoo_https(self): # https://github.com/rg3/youtube-dl/issues/2701 self.assertMatch( diff --git a/youtube_dl/extractor/comedycentral.py b/youtube_dl/extractor/comedycentral.py index c81ce5a96..b4e2a8feb 100644 --- a/youtube_dl/extractor/comedycentral.py +++ b/youtube_dl/extractor/comedycentral.py @@ -50,7 +50,7 @@ class ComedyCentralShowsIE(InfoExtractor): (?P extended-interviews/(?P[0-9a-z]+)/(?:playlist_tds_extended_)?(?P.*?)(/.*?)?))) (?:[?#].*|$)''' - _TEST = { + _TESTS = [{ 'url': 'http://thedailyshow.cc.com/watch/thu-december-13-2012/kristen-stewart', 'md5': '4e2f5cb088a83cd8cdb7756132f9739d', 'info_dict': { @@ -61,7 +61,31 @@ class ComedyCentralShowsIE(InfoExtractor): 'uploader': 'thedailyshow', 'title': 'thedailyshow kristen-stewart part 1', } - } + }, { + 'url': 'http://thedailyshow.cc.com/extended-interviews/xm3fnq/andrew-napolitano-extended-interview', + 'only_matching': True, + }, { + 'url': 'http://thecolbertreport.cc.com/videos/29w6fx/-realhumanpraise-for-fox-news', + 'only_matching': True, + }, { + 'url': 'http://thecolbertreport.cc.com/videos/gh6urb/neil-degrasse-tyson-pt--1?xrs=eml_col_031114', + 'only_matching': True, + }, { + 'url': 'http://thedailyshow.cc.com/guests/michael-lewis/3efna8/exclusive---michael-lewis-extended-interview-pt--3', + 'only_matching': True, + }, { + 'url': 'http://thedailyshow.cc.com/episodes/sy7yv0/april-8--2014---denis-leary', + 'only_matching': True, + }, { + 'url': 'http://thecolbertreport.cc.com/episodes/8ase07/april-8--2014---jane-goodall', + 'only_matching': True, + }, { + 'url': 'http://thedailyshow.cc.com/video-playlists/npde3s/the-daily-show-19088-highlights', + 'only_matching': True, + }, { + 'url': 'http://thedailyshow.cc.com/special-editions/2l8fdb/special-edition---a-look-back-at-food', + 'only_matching': True, + }] _available_formats = ['3500', '2200', '1700', '1200', '750', '400'] From 4c59dc4c34cfd1f3f1d325e7739d146471bab3c3 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 1 Sep 2014 18:37:10 +0200 Subject: [PATCH 0724/1761] [comedycentral] Support news-team URLs (Fixes #3649) --- youtube_dl/extractor/comedycentral.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/comedycentral.py b/youtube_dl/extractor/comedycentral.py index b4e2a8feb..ebabf535c 100644 --- a/youtube_dl/extractor/comedycentral.py +++ b/youtube_dl/extractor/comedycentral.py @@ -43,7 +43,7 @@ class ComedyCentralShowsIE(InfoExtractor): (?Pthedailyshow|thecolbertreport)\.(?:cc\.)?com/ ((?:full-)?episodes/(?:[0-9a-z]{6}/)?(?P.*)| (?P - (?:(?:guests/[^/]+|videos|video-playlists|special-editions)/[^/]+/(?P[^/?#]+)) + (?:(?:guests/[^/]+|videos|video-playlists|special-editions|news-team/[^/]+)/[^/]+/(?P[^/?#]+)) |(the-colbert-report-(videos|collections)/(?P[0-9]+)/[^/]*/(?P.*?)) |(watch/(?P[^/]*)/(?P.*)) )| @@ -85,6 +85,9 @@ class ComedyCentralShowsIE(InfoExtractor): }, { 'url': 'http://thedailyshow.cc.com/special-editions/2l8fdb/special-edition---a-look-back-at-food', 'only_matching': True, + }, { + 'url': 'http://thedailyshow.cc.com/news-team/michael-che/7wnfel/we-need-to-talk-about-israel', + 'only_matching': True, }] _available_formats = ['3500', '2200', '1700', '1200', '750', '400'] From 07e7dc4bdcdf7a9393594ab88a42cb2dfed0208d Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 1 Sep 2014 18:37:21 +0200 Subject: [PATCH 0725/1761] [comedycentral] Prefer RTMP for now --- youtube_dl/extractor/comedycentral.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/youtube_dl/extractor/comedycentral.py b/youtube_dl/extractor/comedycentral.py index ebabf535c..035046120 100644 --- a/youtube_dl/extractor/comedycentral.py +++ b/youtube_dl/extractor/comedycentral.py @@ -212,6 +212,9 @@ class ComedyCentralShowsIE(InfoExtractor): 'ext': self._video_extensions.get(format, 'mp4'), 'height': h, 'width': w, + + 'format_note': 'HTTP 400 at the moment (patches welcome!)', + 'preference': -100, }) formats.append({ 'format_id': 'rtmp-%s' % format, From d740f7e16f936262fec6b23bb8729374f1cf847d Mon Sep 17 00:00:00 2001 From: peugeot Date: Mon, 1 Sep 2014 20:12:51 +0200 Subject: [PATCH 0726/1761] Add support for drtuber.com --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/drtuber.py | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 youtube_dl/extractor/drtuber.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 9f43bb8f4..00c9e7042 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -70,6 +70,7 @@ from .daum import DaumIE from .dfb import DFBIE from .dotsub import DotsubIE from .dreisat import DreiSatIE +from .drtuber import DrTuberIE from .drtv import DRTVIE from .dump import DumpIE from .defense import DefenseGouvFrIE diff --git a/youtube_dl/extractor/drtuber.py b/youtube_dl/extractor/drtuber.py new file mode 100644 index 000000000..7b4b19509 --- /dev/null +++ b/youtube_dl/extractor/drtuber.py @@ -0,0 +1,48 @@ +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor + + +class DrTuberIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?drtuber\.com/video/(?P\d+)/(?P[\w-]+)' + _TEST = { + 'url': 'http://www.drtuber.com/video/1740434/hot-perky-blonde-naked-golf', + 'md5': '93e680cf2536ad0dfb7e74d94a89facd', + 'info_dict': { + 'id': '1740434', + 'ext': 'mp4', + 'title': 'Hot Perky Blonde Naked Golf', + 'categories': list, # NSFW + 'thumbnail': 're:https?://.*\.jpg$', + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + webpage = self._download_webpage(url, video_id) + + video_url = self._html_search_regex( + r'([^<]+)\s*-\s*Free', webpage, 'title') + + thumbnail = self._html_search_regex( + r'poster="([^"]+)"', + webpage, 'thumbnail', fatal=False) + + categories_str = self._html_search_regex( + r' Date: Mon, 1 Sep 2014 22:38:40 +0200 Subject: [PATCH 0727/1761] Add age limit to anysex, beeg, eporner, hornbuny and sunporno --- youtube_dl/extractor/anysex.py | 2 ++ youtube_dl/extractor/beeg.py | 2 ++ youtube_dl/extractor/eporner.py | 2 ++ youtube_dl/extractor/hornbunny.py | 4 +++- youtube_dl/extractor/sunporno.py | 2 ++ 5 files changed, 11 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/anysex.py b/youtube_dl/extractor/anysex.py index adeacba01..95f23adf1 100644 --- a/youtube_dl/extractor/anysex.py +++ b/youtube_dl/extractor/anysex.py @@ -21,6 +21,7 @@ class AnySexIE(InfoExtractor): 'description': 'md5:de9e418178e2931c10b62966474e1383', 'categories': ['Erotic'], 'duration': 270, + 'age_limit': 18, } } @@ -57,4 +58,5 @@ class AnySexIE(InfoExtractor): 'categories': categories, 'duration': duration, 'view_count': view_count, + 'age_limit': 18, } diff --git a/youtube_dl/extractor/beeg.py b/youtube_dl/extractor/beeg.py index c2692cfdc..6f9f4433d 100644 --- a/youtube_dl/extractor/beeg.py +++ b/youtube_dl/extractor/beeg.py @@ -17,6 +17,7 @@ class BeegIE(InfoExtractor): 'description': 'md5:6db3c6177972822aaba18652ff59c773', 'categories': list, # NSFW 'thumbnail': 're:https?://.*\.jpg$', + 'age_limit': 18, } } @@ -50,4 +51,5 @@ class BeegIE(InfoExtractor): 'description': description, 'thumbnail': thumbnail, 'categories': categories, + 'age_limit': 18, } diff --git a/youtube_dl/extractor/eporner.py b/youtube_dl/extractor/eporner.py index 4c2c074cb..33f9ab7a9 100644 --- a/youtube_dl/extractor/eporner.py +++ b/youtube_dl/extractor/eporner.py @@ -21,6 +21,7 @@ class EpornerIE(InfoExtractor): 'title': 'Infamous Tiffany Teen Strip Tease Video', 'duration': 194, 'view_count': int, + 'age_limit': 18, } } @@ -52,4 +53,5 @@ class EpornerIE(InfoExtractor): 'title': title, 'duration': duration, 'view_count': view_count, + 'age_limit': 18, } diff --git a/youtube_dl/extractor/hornbunny.py b/youtube_dl/extractor/hornbunny.py index a42fba0cb..d07105d66 100644 --- a/youtube_dl/extractor/hornbunny.py +++ b/youtube_dl/extractor/hornbunny.py @@ -15,7 +15,8 @@ class HornBunnyIE(InfoExtractor): 'id': '5227', 'ext': 'flv', 'title': 'panty slut jerk off instruction', - 'duration': 550 + 'duration': 550, + 'age_limit': 18, } } @@ -41,4 +42,5 @@ class HornBunnyIE(InfoExtractor): 'ext': 'flv', 'duration': duration, 'view_count': int_or_none(view_count), + 'age_limit': 18, } diff --git a/youtube_dl/extractor/sunporno.py b/youtube_dl/extractor/sunporno.py index c7a46eb71..7de3c9dd5 100644 --- a/youtube_dl/extractor/sunporno.py +++ b/youtube_dl/extractor/sunporno.py @@ -23,6 +23,7 @@ class SunPornoIE(InfoExtractor): 'description': 'md5:a31241990e1bd3a64e72ae99afb325fb', 'thumbnail': 're:^https?://.*\.jpg$', 'duration': 302, + 'age_limit': 18, } } @@ -65,4 +66,5 @@ class SunPornoIE(InfoExtractor): 'view_count': view_count, 'comment_count': comment_count, 'formats': formats, + 'age_limit': 18, } From 49fa38adf2ff1114fc51e89d796a9cbf91622068 Mon Sep 17 00:00:00 2001 From: Naglis Jonaitis Date: Mon, 1 Sep 2014 23:47:14 +0300 Subject: [PATCH 0728/1761] [nosvideo] Add new extractor --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/nosvideo.py | 68 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 youtube_dl/extractor/nosvideo.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 9f43bb8f4..dede0cde5 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -234,6 +234,7 @@ from .niconico import NiconicoIE from .ninegag import NineGagIE from .noco import NocoIE from .normalboots import NormalbootsIE +from .nosvideo import NosVideoIE from .novamov import NovaMovIE from .nowness import NownessIE from .nowvideo import NowVideoIE diff --git a/youtube_dl/extractor/nosvideo.py b/youtube_dl/extractor/nosvideo.py new file mode 100644 index 000000000..dbb03613b --- /dev/null +++ b/youtube_dl/extractor/nosvideo.py @@ -0,0 +1,68 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ( + compat_urllib_parse, + compat_urllib_request, + determine_ext, + xpath_with_ns, +) + +_x = lambda p: xpath_with_ns(p, {'xspf': 'http://xspf.org/ns/0/'}) +_find = lambda el, p: el.find(_x(p)).text.strip() + + +class NosVideoIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?nosvideo\.com/' + \ + '(?:embed/|\?v=)(?P[A-Za-z0-9]{12})/?' + _PLAYLIST_URL = 'http://nosvideo.com/xml/{xml_id:s}.xml' + _TEST = { + 'url': 'http://nosvideo.com/?v=drlp6s40kg54', + 'md5': '4b4ac54c6ad5d70ab88f2c2c6ccec71c', + 'info_dict': { + 'id': 'drlp6s40kg54', + 'ext': 'mp4', + 'title': 'big_buck_bunny_480p_surround-fix.avi.mp4', + 'thumbnail': 're:^https?://.*\.jpg$', + } + } + + def _real_extract(self, url): + mobj = re.match(self._VALID_URL, url) + video_id = mobj.group('id') + + fields = { + 'id': video_id, + 'op': 'download1', + 'method_free': 'Continue to Video', + } + post = compat_urllib_parse.urlencode(fields) + req = compat_urllib_request.Request(url, post) + req.add_header('Content-type', 'application/x-www-form-urlencoded') + webpage = self._download_webpage(req, video_id, + 'Downloading download page') + xml_id = self._search_regex(r'php\|([^\|]+)\|', webpage, 'XML ID') + playlist_url = self._PLAYLIST_URL.format(xml_id=xml_id) + playlist = self._download_xml(playlist_url, video_id) + + track = playlist.find(_x('.//xspf:track')) + title = _find(track, './xspf:title') + url = _find(track, './xspf:file') + thumbnail = _find(track, './xspf:image') + ext = determine_ext(title) + + formats = [{ + 'format_id': 'sd', + 'url': url, + 'ext': ext, + }] + + return { + 'id': video_id, + 'title': title, + 'thumbnail': thumbnail, + 'formats': formats, + } From 11342b54d6a77fb62998f8331d36855829ba391f Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 1 Sep 2014 22:58:59 +0200 Subject: [PATCH 0729/1761] [anysex] Implement age_limit --- youtube_dl/extractor/anysex.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/youtube_dl/extractor/anysex.py b/youtube_dl/extractor/anysex.py index adeacba01..bc64423a3 100644 --- a/youtube_dl/extractor/anysex.py +++ b/youtube_dl/extractor/anysex.py @@ -21,6 +21,7 @@ class AnySexIE(InfoExtractor): 'description': 'md5:de9e418178e2931c10b62966474e1383', 'categories': ['Erotic'], 'duration': 270, + 'age_limit': 18, } } @@ -43,7 +44,6 @@ class AnySexIE(InfoExtractor): duration = parse_duration(self._search_regex( r'Duration: (\d+:\d+)', webpage, 'duration', fatal=False)) - view_count = int_or_none(self._html_search_regex( r'Views: (\d+)', webpage, 'view count', fatal=False)) @@ -57,4 +57,5 @@ class AnySexIE(InfoExtractor): 'categories': categories, 'duration': duration, 'view_count': view_count, + 'age_limit': 18, } From e4039057be0fc38828e0a39f83b2f5d469414f8e Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 1 Sep 2014 23:04:36 +0200 Subject: [PATCH 0730/1761] [hornbunny] Simplify and add age_limit --- youtube_dl/extractor/hornbunny.py | 34 +++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/youtube_dl/extractor/hornbunny.py b/youtube_dl/extractor/hornbunny.py index a42fba0cb..7e7714438 100644 --- a/youtube_dl/extractor/hornbunny.py +++ b/youtube_dl/extractor/hornbunny.py @@ -4,7 +4,11 @@ from __future__ import unicode_literals import re from .common import InfoExtractor -from ..utils import int_or_none +from ..utils import ( + int_or_none, + parse_duration, +) + class HornBunnyIE(InfoExtractor): _VALID_URL = r'http?://(?:www\.)?hornbunny\.com/videos/(?P[a-z-]+)-(?P\d+)\.html' @@ -15,7 +19,8 @@ class HornBunnyIE(InfoExtractor): 'id': '5227', 'ext': 'flv', 'title': 'panty slut jerk off instruction', - 'duration': 550 + 'duration': 550, + 'age_limit': 18, } } @@ -23,16 +28,22 @@ class HornBunnyIE(InfoExtractor): mobj = re.match(self._VALID_URL, url) video_id = mobj.group('id') - webpage = self._download_webpage(url, video_id) - title = self._html_search_regex(r'class="title">(.*?)', webpage, 'title') - redirect_url = self._html_search_regex(r'pg&settings=(.*?)\|0"\);', webpage, 'title') + webpage = self._download_webpage( + url, video_id, note='Downloading initial webpage') + title = self._html_search_regex( + r'class="title">(.*?)', webpage, 'title') + redirect_url = self._html_search_regex( + r'pg&settings=(.*?)\|0"\);', webpage, 'title') webpage2 = self._download_webpage(redirect_url, video_id) - video_url = self._html_search_regex(r'flvMask:(.*?);', webpage2, 'video_url') + video_url = self._html_search_regex( + r'flvMask:(.*?);', webpage2, 'video_url') - mobj = re.search(r'Runtime: (?P\d+):(?P\d+)
    ', webpage) - duration = int(mobj.group('minutes')) * 60 + int(mobj.group('seconds')) if mobj else None - - view_count = self._html_search_regex(r'Views: (\d+)
    ', webpage, 'view count', fatal=False) + duration = parse_duration(self._search_regex( + r'Runtime:\s*([0-9:]+)