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.

102 lines
3.4 KiB

  1. from __future__ import unicode_literals
  2. import re
  3. from .common import InfoExtractor
  4. from .vimeo import VimeoIE
  5. from ..utils import (
  6. extract_attributes,
  7. ExtractorError,
  8. smuggle_url,
  9. unsmuggle_url,
  10. urljoin,
  11. )
  12. class RayWenderlichIE(InfoExtractor):
  13. _VALID_URL = r'https?://videos\.raywenderlich\.com/courses/(?P<course_id>[^/]+)/lessons/(?P<id>\d+)'
  14. _TESTS = [{
  15. 'url': 'https://videos.raywenderlich.com/courses/105-testing-in-ios/lessons/1',
  16. 'info_dict': {
  17. 'id': '248377018',
  18. 'ext': 'mp4',
  19. 'title': 'Testing In iOS Episode 1: Introduction',
  20. 'duration': 133,
  21. 'uploader': 'Ray Wenderlich',
  22. 'uploader_id': 'user3304672',
  23. },
  24. 'params': {
  25. 'noplaylist': True,
  26. 'skip_download': True,
  27. },
  28. 'add_ie': [VimeoIE.ie_key()],
  29. 'expected_warnings': ['HTTP Error 403: Forbidden'],
  30. }, {
  31. 'url': 'https://videos.raywenderlich.com/courses/105-testing-in-ios/lessons/1',
  32. 'info_dict': {
  33. 'title': 'Testing in iOS',
  34. 'id': '105-testing-in-ios',
  35. },
  36. 'params': {
  37. 'noplaylist': False,
  38. },
  39. 'playlist_count': 29,
  40. }]
  41. def _real_extract(self, url):
  42. url, smuggled_data = unsmuggle_url(url, {})
  43. mobj = re.match(self._VALID_URL, url)
  44. course_id, lesson_id = mobj.group('course_id', 'id')
  45. video_id = '%s/%s' % (course_id, lesson_id)
  46. webpage = self._download_webpage(url, video_id)
  47. no_playlist = self._downloader.params.get('noplaylist')
  48. if no_playlist or smuggled_data.get('force_video', False):
  49. if no_playlist:
  50. self.to_screen(
  51. 'Downloading just video %s because of --no-playlist'
  52. % video_id)
  53. if '>Subscribe to unlock' in webpage:
  54. raise ExtractorError(
  55. 'This content is only available for subscribers',
  56. expected=True)
  57. vimeo_id = self._search_regex(
  58. r'data-vimeo-id=["\'](\d+)', webpage, 'video id')
  59. return self.url_result(
  60. VimeoIE._smuggle_referrer(
  61. 'https://player.vimeo.com/video/%s' % vimeo_id, url),
  62. ie=VimeoIE.ie_key(), video_id=vimeo_id)
  63. self.to_screen(
  64. 'Downloading playlist %s - add --no-playlist to just download video'
  65. % course_id)
  66. lesson_ids = set((lesson_id, ))
  67. for lesson in re.findall(
  68. r'(<a[^>]+\bclass=["\']lesson-link[^>]+>)', webpage):
  69. attrs = extract_attributes(lesson)
  70. if not attrs:
  71. continue
  72. lesson_url = attrs.get('href')
  73. if not lesson_url:
  74. continue
  75. lesson_id = self._search_regex(
  76. r'/lessons/(\d+)', lesson_url, 'lesson id', default=None)
  77. if not lesson_id:
  78. continue
  79. lesson_ids.add(lesson_id)
  80. entries = []
  81. for lesson_id in sorted(lesson_ids):
  82. entries.append(self.url_result(
  83. smuggle_url(urljoin(url, lesson_id), {'force_video': True}),
  84. ie=RayWenderlichIE.ie_key()))
  85. title = self._search_regex(
  86. r'class=["\']course-title[^>]+>([^<]+)', webpage, 'course title',
  87. default=None)
  88. return self.playlist_result(entries, course_id, title)