From 1c7c76e4fb1f5d5c05cfa22483a46e7dd870ac0f Mon Sep 17 00:00:00 2001 From: Frederic Bournival Date: Wed, 19 Apr 2017 17:43:32 -0400 Subject: [noovo] Add extractor --- youtube_dl/extractor/noovo.py | 52 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 youtube_dl/extractor/noovo.py (limited to 'youtube_dl/extractor/noovo.py') diff --git a/youtube_dl/extractor/noovo.py b/youtube_dl/extractor/noovo.py new file mode 100644 index 000000000..9f441c2fc --- /dev/null +++ b/youtube_dl/extractor/noovo.py @@ -0,0 +1,52 @@ +# coding: utf-8 +from __future__ import unicode_literals +from .common import InfoExtractor + + +class NoovoIE(InfoExtractor): + IE_NAME = 'Noovo' + IE_DESC = 'VTele, Max, MusiquePlus' + _VALID_URL = r'https?://(?:[a-z0-9-]+\.)?noovo\.ca/videos/(?P[a-z0-9-]+/[a-z0-9-]+)' + _TESTS = [{ + 'url': 'http://noovo.ca/videos/rpm-plus/chrysler-imperial', + 'md5': '2fcc04d0a8f4a853fad91233c2fdd121', + 'info_dict': { + 'id': '5386045029001', + 'description': 'Antoine présente des véhicules qu\'il aperçoit sur la rue.', + 'ext': 'mp4', + 'timestamp': 1491399228, + 'title': 'Chrysler Imperial', + 'upload_date': '20170405', + 'uploader_id': '618566855001' + } + }, { + 'url': 'http://noovo.ca/videos/l-amour-est-dans-le-pre/episode-13-8', + 'md5': '1199e96fbb93f2d42717115f72097b6b', + 'info_dict': { + 'id': '5395865725001', + 'description': 'md5:336d5ebc5436534e61d16e63ddfca327', + 'ext': 'mp4', + 'timestamp': 1492019320, + 'title': 'md5:2895fdc124639be0ef64ea0d06f5e493', + 'upload_date': '20170412', + 'uploader_id': '618566855001' + } + }, { + 'url': 'http://interventions.noovo.ca/911/video/intoxication-aux-drogues-dures/?autoplay=1', + 'only_matching': True + }] + API_URL_TEMPLATE = 'http://api.noovo.ca/api/v1/pages/single-episode/%s' + BRIGHTCOVE_URL_TEMPLATE = 'http://players.brightcove.net/618566855001/default_default/index.html?videoId=%s' + + def _real_extract(self, url): + video_id = self._match_id(url) + api_url = self.API_URL_TEMPLATE % video_id + api_content = self._download_json(api_url, video_id) + + brightcove_id = api_content.get('data').get('brightcoveId') + if not brightcove_id: + brightcove_id = api_content.get('data').get('contents')[0].get('brightcoveId') + + return self.url_result( + self.BRIGHTCOVE_URL_TEMPLATE % brightcove_id, 'BrightcoveNew', brightcove_id + ) -- cgit 1.4.1 From b5c39537be8b7c3405af0df30dfaea3c5ed9d649 Mon Sep 17 00:00:00 2001 From: Sergey M․ Date: Sun, 30 Apr 2017 00:23:50 +0700 Subject: [noovo] Improve extraction (closes #12792) --- youtube_dl/extractor/noovo.py | 93 ++++++++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 24 deletions(-) (limited to 'youtube_dl/extractor/noovo.py') diff --git a/youtube_dl/extractor/noovo.py b/youtube_dl/extractor/noovo.py index 9f441c2fc..f7fa098a5 100644 --- a/youtube_dl/extractor/noovo.py +++ b/youtube_dl/extractor/noovo.py @@ -1,52 +1,97 @@ # coding: utf-8 from __future__ import unicode_literals + +from .brightcove import BrightcoveNewIE from .common import InfoExtractor +from ..compat import compat_str +from ..utils import ( + int_or_none, + smuggle_url, + try_get, +) class NoovoIE(InfoExtractor): - IE_NAME = 'Noovo' - IE_DESC = 'VTele, Max, MusiquePlus' - _VALID_URL = r'https?://(?:[a-z0-9-]+\.)?noovo\.ca/videos/(?P[a-z0-9-]+/[a-z0-9-]+)' + _VALID_URL = r'https?://(?:[^/]+\.)?noovo\.ca/videos/(?P[^/]+/[^/?#&]+)' _TESTS = [{ + # clip 'url': 'http://noovo.ca/videos/rpm-plus/chrysler-imperial', - 'md5': '2fcc04d0a8f4a853fad91233c2fdd121', 'info_dict': { 'id': '5386045029001', - 'description': 'Antoine présente des véhicules qu\'il aperçoit sur la rue.', 'ext': 'mp4', - 'timestamp': 1491399228, 'title': 'Chrysler Imperial', + 'description': 'md5:de3c898d1eb810f3e6243e08c8b4a056', + 'timestamp': 1491399228, 'upload_date': '20170405', - 'uploader_id': '618566855001' - } + 'uploader_id': '618566855001', + 'creator': 'vtele', + 'view_count': int, + 'series': 'RPM+', + }, + 'params': { + 'skip_download': True, + }, }, { + # episode 'url': 'http://noovo.ca/videos/l-amour-est-dans-le-pre/episode-13-8', - 'md5': '1199e96fbb93f2d42717115f72097b6b', 'info_dict': { 'id': '5395865725001', + 'title': 'Épisode 13 : Les retrouvailles', 'description': 'md5:336d5ebc5436534e61d16e63ddfca327', 'ext': 'mp4', 'timestamp': 1492019320, - 'title': 'md5:2895fdc124639be0ef64ea0d06f5e493', 'upload_date': '20170412', - 'uploader_id': '618566855001' - } - }, { - 'url': 'http://interventions.noovo.ca/911/video/intoxication-aux-drogues-dures/?autoplay=1', - 'only_matching': True + 'uploader_id': '618566855001', + 'creator': 'vtele', + 'view_count': int, + 'series': "L'amour est dans le pré", + 'season_number': 5, + 'episode': 'Épisode 13', + 'episode_number': 13, + }, + 'params': { + 'skip_download': True, + }, }] - API_URL_TEMPLATE = 'http://api.noovo.ca/api/v1/pages/single-episode/%s' BRIGHTCOVE_URL_TEMPLATE = 'http://players.brightcove.net/618566855001/default_default/index.html?videoId=%s' def _real_extract(self, url): video_id = self._match_id(url) - api_url = self.API_URL_TEMPLATE % video_id - api_content = self._download_json(api_url, video_id) - brightcove_id = api_content.get('data').get('brightcoveId') - if not brightcove_id: - brightcove_id = api_content.get('data').get('contents')[0].get('brightcoveId') + data = self._download_json( + 'http://api.noovo.ca/api/v1/pages/single-episode/%s' % video_id, + video_id)['data'] - return self.url_result( - self.BRIGHTCOVE_URL_TEMPLATE % brightcove_id, 'BrightcoveNew', brightcove_id - ) + content = try_get(data, lambda x: x['contents'][0]) + + brightcove_id = data.get('brightcoveId') or content['brightcoveId'] + + series = try_get( + data, ( + lambda x: x['show']['title'], + lambda x: x['season']['show']['title']), + compat_str) + + episode = None + og = data.get('og') + if isinstance(og, dict) and og.get('type') == 'video.episode': + episode = og.get('title') + + video = content or data + + return { + '_type': 'url_transparent', + 'ie_key': BrightcoveNewIE.ie_key(), + 'url': smuggle_url( + self.BRIGHTCOVE_URL_TEMPLATE % brightcove_id, + {'geo_countries': ['CA']}), + 'id': brightcove_id, + 'title': video.get('title'), + 'creator': video.get('source'), + 'view_count': int_or_none(video.get('viewsCount')), + 'series': series, + 'season_number': int_or_none(try_get( + data, lambda x: x['season']['seasonNumber'])), + 'episode': episode, + 'episode_number': int_or_none(data.get('episodeNumber')), + } -- cgit 1.4.1 From a4245acef85ac2414e77cf2cda4cb39adb617241 Mon Sep 17 00:00:00 2001 From: Sergey M․ Date: Fri, 15 Sep 2017 23:12:19 +0700 Subject: [noovo] Fix extraction (closes #14214) --- youtube_dl/extractor/noovo.py | 61 +++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 29 deletions(-) (limited to 'youtube_dl/extractor/noovo.py') diff --git a/youtube_dl/extractor/noovo.py b/youtube_dl/extractor/noovo.py index f7fa098a5..974de3c3e 100644 --- a/youtube_dl/extractor/noovo.py +++ b/youtube_dl/extractor/noovo.py @@ -6,6 +6,7 @@ from .common import InfoExtractor from ..compat import compat_str from ..utils import ( int_or_none, + js_to_json, smuggle_url, try_get, ) @@ -24,8 +25,6 @@ class NoovoIE(InfoExtractor): 'timestamp': 1491399228, 'upload_date': '20170405', 'uploader_id': '618566855001', - 'creator': 'vtele', - 'view_count': int, 'series': 'RPM+', }, 'params': { @@ -37,13 +36,11 @@ class NoovoIE(InfoExtractor): 'info_dict': { 'id': '5395865725001', 'title': 'Épisode 13 : Les retrouvailles', - 'description': 'md5:336d5ebc5436534e61d16e63ddfca327', + 'description': 'md5:888c3330f0c1b4476c5bc99a1c040473', 'ext': 'mp4', 'timestamp': 1492019320, 'upload_date': '20170412', 'uploader_id': '618566855001', - 'creator': 'vtele', - 'view_count': int, 'series': "L'amour est dans le pré", 'season_number': 5, 'episode': 'Épisode 13', @@ -58,40 +55,46 @@ class NoovoIE(InfoExtractor): def _real_extract(self, url): video_id = self._match_id(url) - data = self._download_json( - 'http://api.noovo.ca/api/v1/pages/single-episode/%s' % video_id, - video_id)['data'] + webpage = self._download_webpage(url, video_id) - content = try_get(data, lambda x: x['contents'][0]) + bc_url = BrightcoveNewIE._extract_url(self, webpage) - brightcove_id = data.get('brightcoveId') or content['brightcoveId'] + data = self._parse_json( + self._search_regex( + r'(?s)dataLayer\.push\(\s*({.+?})\s*\);', webpage, 'data', + default='{}'), + video_id, transform_source=js_to_json, fatal=False) + + title = try_get( + data, lambda x: x['video']['nom'], + compat_str) or self._html_search_meta( + 'dcterms.Title', webpage, 'title', fatal=True) + + description = self._html_search_meta( + ('dcterms.Description', 'description'), webpage, 'description') series = try_get( - data, ( - lambda x: x['show']['title'], - lambda x: x['season']['show']['title']), - compat_str) + data, lambda x: x['emission']['nom']) or self._search_regex( + r']+class="banner-card__subtitle h4"[^>]*>([^<]+)', + webpage, 'series', default=None) - episode = None - og = data.get('og') - if isinstance(og, dict) and og.get('type') == 'video.episode': - episode = og.get('title') + season_el = try_get(data, lambda x: x['emission']['saison'], dict) or {} + season = try_get(season_el, lambda x: x['nom'], compat_str) + season_number = int_or_none(try_get(season_el, lambda x: x['numero'])) - video = content or data + episode_el = try_get(season_el, lambda x: x['episode'], dict) or {} + episode = try_get(episode_el, lambda x: x['nom'], compat_str) + episode_number = int_or_none(try_get(episode_el, lambda x: x['numero'])) return { '_type': 'url_transparent', 'ie_key': BrightcoveNewIE.ie_key(), - 'url': smuggle_url( - self.BRIGHTCOVE_URL_TEMPLATE % brightcove_id, - {'geo_countries': ['CA']}), - 'id': brightcove_id, - 'title': video.get('title'), - 'creator': video.get('source'), - 'view_count': int_or_none(video.get('viewsCount')), + 'url': smuggle_url(bc_url, {'geo_countries': ['CA']}), + 'title': title, + 'description': description, 'series': series, - 'season_number': int_or_none(try_get( - data, lambda x: x['season']['seasonNumber'])), + 'season': season, + 'season_number': season_number, 'episode': episode, - 'episode_number': int_or_none(data.get('episodeNumber')), + 'episode_number': episode_number, } -- cgit 1.4.1