nowness.py (6024B)
1 # coding: utf-8 2 from __future__ import unicode_literals 3 4 from .brightcove import ( 5 BrightcoveLegacyIE, 6 BrightcoveNewIE, 7 ) 8 from .common import InfoExtractor 9 from ..compat import compat_str 10 from ..utils import ( 11 ExtractorError, 12 sanitized_Request, 13 ) 14 15 16 class NownessBaseIE(InfoExtractor): 17 def _extract_url_result(self, post): 18 if post['type'] == 'video': 19 for media in post['media']: 20 if media['type'] == 'video': 21 video_id = media['content'] 22 source = media['source'] 23 if source == 'brightcove': 24 player_code = self._download_webpage( 25 'http://www.nowness.com/iframe?id=%s' % video_id, video_id, 26 note='Downloading player JavaScript', 27 errnote='Unable to download player JavaScript') 28 bc_url = BrightcoveLegacyIE._extract_brightcove_url(player_code) 29 if bc_url: 30 return self.url_result(bc_url, BrightcoveLegacyIE.ie_key()) 31 bc_url = BrightcoveNewIE._extract_url(self, player_code) 32 if bc_url: 33 return self.url_result(bc_url, BrightcoveNewIE.ie_key()) 34 raise ExtractorError('Could not find player definition') 35 elif source == 'vimeo': 36 return self.url_result('http://vimeo.com/%s' % video_id, 'Vimeo') 37 elif source == 'youtube': 38 return self.url_result(video_id, 'Youtube') 39 elif source == 'cinematique': 40 # youtube-dl currently doesn't support cinematique 41 # return self.url_result('http://cinematique.com/embed/%s' % video_id, 'Cinematique') 42 pass 43 44 def _api_request(self, url, request_path): 45 display_id = self._match_id(url) 46 request = sanitized_Request( 47 'http://api.nowness.com/api/' + request_path % display_id, 48 headers={ 49 'X-Nowness-Language': 'zh-cn' if 'cn.nowness.com' in url else 'en-us', 50 }) 51 return display_id, self._download_json(request, display_id) 52 53 54 class NownessIE(NownessBaseIE): 55 IE_NAME = 'nowness' 56 _VALID_URL = r'https?://(?:(?:www|cn)\.)?nowness\.com/(?:story|(?:series|category)/[^/]+)/(?P<id>[^/]+?)(?:$|[?#])' 57 _TESTS = [{ 58 'url': 'https://www.nowness.com/story/candor-the-art-of-gesticulation', 59 'md5': '068bc0202558c2e391924cb8cc470676', 60 'info_dict': { 61 'id': '2520295746001', 62 'ext': 'mp4', 63 'title': 'Candor: The Art of Gesticulation', 64 'description': 'Candor: The Art of Gesticulation', 65 'thumbnail': r're:^https?://.*\.jpg', 66 'timestamp': 1446745676, 67 'upload_date': '20151105', 68 'uploader_id': '2385340575001', 69 }, 70 'add_ie': ['BrightcoveNew'], 71 }, { 72 'url': 'https://cn.nowness.com/story/kasper-bjorke-ft-jaakko-eino-kalevi-tnr', 73 'md5': 'e79cf125e387216f86b2e0a5b5c63aa3', 74 'info_dict': { 75 'id': '3716354522001', 76 'ext': 'mp4', 77 'title': 'Kasper Bjørke ft. Jaakko Eino Kalevi: TNR', 78 'description': 'Kasper Bjørke ft. Jaakko Eino Kalevi: TNR', 79 'thumbnail': r're:^https?://.*\.jpg', 80 'timestamp': 1407315371, 81 'upload_date': '20140806', 82 'uploader_id': '2385340575001', 83 }, 84 'add_ie': ['BrightcoveNew'], 85 }, { 86 # vimeo 87 'url': 'https://www.nowness.com/series/nowness-picks/jean-luc-godard-supercut', 88 'md5': '9a5a6a8edf806407e411296ab6bc2a49', 89 'info_dict': { 90 'id': '130020913', 91 'ext': 'mp4', 92 'title': 'Bleu, Blanc, Rouge - A Godard Supercut', 93 'description': 'md5:f0ea5f1857dffca02dbd37875d742cec', 94 'thumbnail': r're:^https?://.*\.jpg', 95 'upload_date': '20150607', 96 'uploader': 'Cinema Sem Lei', 97 'uploader_id': 'cinemasemlei', 98 }, 99 'add_ie': ['Vimeo'], 100 }] 101 102 def _real_extract(self, url): 103 _, post = self._api_request(url, 'post/getBySlug/%s') 104 return self._extract_url_result(post) 105 106 107 class NownessPlaylistIE(NownessBaseIE): 108 IE_NAME = 'nowness:playlist' 109 _VALID_URL = r'https?://(?:(?:www|cn)\.)?nowness\.com/playlist/(?P<id>\d+)' 110 _TEST = { 111 'url': 'https://www.nowness.com/playlist/3286/i-guess-thats-why-they-call-it-the-blues', 112 'info_dict': { 113 'id': '3286', 114 }, 115 'playlist_mincount': 8, 116 } 117 118 def _real_extract(self, url): 119 playlist_id, playlist = self._api_request(url, 'post?PlaylistId=%s') 120 entries = [self._extract_url_result(item) for item in playlist['items']] 121 return self.playlist_result(entries, playlist_id) 122 123 124 class NownessSeriesIE(NownessBaseIE): 125 IE_NAME = 'nowness:series' 126 _VALID_URL = r'https?://(?:(?:www|cn)\.)?nowness\.com/series/(?P<id>[^/]+?)(?:$|[?#])' 127 _TEST = { 128 'url': 'https://www.nowness.com/series/60-seconds', 129 'info_dict': { 130 'id': '60', 131 'title': '60 Seconds', 132 'description': 'One-minute wisdom in a new NOWNESS series', 133 }, 134 'playlist_mincount': 4, 135 } 136 137 def _real_extract(self, url): 138 display_id, series = self._api_request(url, 'series/getBySlug/%s') 139 entries = [self._extract_url_result(post) for post in series['posts']] 140 series_title = None 141 series_description = None 142 translations = series.get('translations', []) 143 if translations: 144 series_title = translations[0].get('title') or translations[0]['seoTitle'] 145 series_description = translations[0].get('seoDescription') 146 return self.playlist_result( 147 entries, compat_str(series['id']), series_title, series_description)