craftsy.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import json
  2. from .brightcove import BrightcoveNewIE
  3. from .common import InfoExtractor
  4. from ..utils import (
  5. extract_attributes,
  6. get_element_html_by_class,
  7. get_element_text_and_html_by_tag,
  8. )
  9. from ..utils.traversal import traverse_obj
  10. class CraftsyIE(InfoExtractor):
  11. _VALID_URL = r'https?://www\.craftsy\.com/class/(?P<id>[\w-]+)'
  12. _TESTS = [{
  13. 'url': 'https://www.craftsy.com/class/the-midnight-quilt-show-season-5/',
  14. 'info_dict': {
  15. 'id': 'the-midnight-quilt-show-season-5',
  16. 'title': 'The Midnight Quilt Show Season 5',
  17. 'description': 'md5:113eda818e985d1a566625fb2f833b7a',
  18. },
  19. 'playlist_count': 10,
  20. }, {
  21. 'url': 'https://www.craftsy.com/class/sew-your-own-designer-handbag/',
  22. 'info_dict': {
  23. 'id': 'sew-your-own-designer-handbag',
  24. 'title': 'Sew Your Own Designer Handbag',
  25. 'description': 'md5:8270d0ef5427d3c895a27351aeaac276',
  26. },
  27. 'playlist_mincount': 1,
  28. }, {
  29. 'url': 'https://www.craftsy.com/class/all-access-estes-park-wool-market/',
  30. 'info_dict': {
  31. 'id': 'all-access-estes-park-wool-market',
  32. 'title': 'All Access: Estes Park Wool Market',
  33. 'description': 'md5:aded1bd8d38ae2fae4dae936c0ae01e7',
  34. },
  35. 'playlist_count': 6,
  36. }]
  37. def _real_extract(self, url):
  38. video_id = self._match_id(url)
  39. webpage = self._download_webpage(url, video_id)
  40. video_player = get_element_html_by_class('class-video-player', webpage)
  41. video_data = traverse_obj(video_player, (
  42. {extract_attributes}, 'wire:snapshot', {json.loads}, 'data', {dict})) or {}
  43. video_js = traverse_obj(video_player, (
  44. {lambda x: get_element_text_and_html_by_tag('video-js', x)}, 1, {extract_attributes})) or {}
  45. has_access = video_data.get('userHasAccess')
  46. lessons = traverse_obj(video_data, ('lessons', ..., ..., lambda _, v: v['video_id']))
  47. preview_id = video_js.get('data-video-id')
  48. if preview_id and preview_id not in traverse_obj(lessons, (..., 'video_id')):
  49. if not lessons and not has_access:
  50. self.report_warning(
  51. 'Only extracting preview. For the full class, pass cookies '
  52. f'from an account that has access. {self._login_hint()}')
  53. lessons.append({'video_id': preview_id})
  54. if not lessons and not has_access:
  55. self.raise_login_required('You do not have access to this class')
  56. account_id = video_data.get('accountId') or video_js['data-account']
  57. def entries(lessons):
  58. for lesson in lessons:
  59. yield self.url_result(
  60. f'http://players.brightcove.net/{account_id}/default_default/index.html?videoId={lesson["video_id"]}',
  61. BrightcoveNewIE, lesson['video_id'], lesson.get('title'))
  62. return self.playlist_result(
  63. entries(lessons), video_id, self._html_search_meta(('og:title', 'twitter:title'), webpage),
  64. self._html_search_meta(('og:description', 'description'), webpage, default=None))