You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
5.4 KiB

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