From 6abc344f22482f1b8433f577087cf755f566bc83 Mon Sep 17 00:00:00 2001 From: EduTel <15623704+EduTel@users.noreply.github.com> Date: Fri, 21 Jan 2022 18:01:06 -0600 Subject: [PATCH 1/9] fix platzi --- youtube_dl/extractor/platzi.py | 56 +++++++++++++++------------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/youtube_dl/extractor/platzi.py b/youtube_dl/extractor/platzi.py index 23c8256b5..9efa51bdd 100644 --- a/youtube_dl/extractor/platzi.py +++ b/youtube_dl/extractor/platzi.py @@ -104,50 +104,40 @@ class PlatziIE(PlatziBaseIE): lecture_id = self._match_id(url) webpage = self._download_webpage(url, lecture_id) - - data = self._parse_json( - self._search_regex( - # client_data may contain "};" so that we have to try more - # strict regex first - (r'client_data\s*=\s*({.+?})\s*;\s*\n', - r'client_data\s*=\s*({.+?})\s*;'), - webpage, 'client data'), + data_preloaded_state = self._parse_json( + self._search_regex((r'window.__PRELOADED_STATE__ = (.*)\<\/script'), webpage, 'client data'), lecture_id) - material = data['initialState']['material'] - desc = material['description'] - title = desc['title'] - + # desc = data_preloaded_state['videoPlayer']['courseDescription'] + title = data_preloaded_state['videoPlayer']['name'] + duration = data_preloaded_state['videoPlayer']['duration'] + servers = data_preloaded_state['videoPlayer']['video']['servers'] formats = [] - for server_id, server in material['videos'].items(): - if not isinstance(server, dict): - continue + for server in servers.keys(): for format_id in ('hls', 'dash'): - format_url = url_or_none(server.get(format_id)) - if not format_url: - continue - if format_id == 'hls': + server_json = servers[server] + if 'hls' in server_json.keys(): formats.extend(self._extract_m3u8_formats( - format_url, lecture_id, 'mp4', + server_json['hls'], lecture_id, 'mp4', entry_protocol='m3u8_native', m3u8_id=format_id, - note='Downloading %s m3u8 information' % server_id, + note='Downloading %s m3u8 information' % server_json['id'], fatal=False)) - elif format_id == 'dash': + elif 'dash' in server_json.keys(): formats.extend(self._extract_mpd_formats( - format_url, lecture_id, mpd_id=format_id, - note='Downloading %s MPD manifest' % server_id, + server_json['dash'], lecture_id, mpd_id=format_id, + note='Downloading %s MPD manifest' % server_json['id'], fatal=False)) self._sort_formats(formats) - content = str_or_none(desc.get('content')) - description = (clean_html(compat_b64decode(content).decode('utf-8')) - if content else None) - duration = int_or_none(material.get('duration'), invscale=60) + # content = str_or_none(data['videoPlayer']['content']) + # description = (clean_html(compat_b64decode(content).decode('utf-8')) + # if content else None) + duration = int_or_none(duration, invscale=60) return { 'id': lecture_id, 'title': title, - 'description': description, + 'description': '', 'duration': duration, 'formats': formats, } @@ -186,10 +176,12 @@ class PlatziCourseIE(PlatziBaseIE): webpage = self._download_webpage(url, course_name) + initialData = self._search_regex( + (r'window.initialData\s*=\s*({.+?})\s*;\s*\n', r'window.initialData\s*=\s*({.+?})\s*;'), + webpage, 'window.initialData') props = self._parse_json( - self._search_regex(r'data\s*=\s*({.+?})\s*;', webpage, 'data'), - course_name)['initialProps'] - + initialData, + course_name)['initialState'] entries = [] for chapter_num, chapter in enumerate(props['concepts'], 1): if not isinstance(chapter, dict): From 3ee378c0991c1193df5ee5f1d3d24099171f1b48 Mon Sep 17 00:00:00 2001 From: EduTel <15623704+EduTel@users.noreply.github.com> Date: Sun, 23 Jan 2022 14:36:00 -0600 Subject: [PATCH 2/9] refactor and fix --- youtube_dl/extractor/platzi.py | 43 ++++++++++++++-------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/youtube_dl/extractor/platzi.py b/youtube_dl/extractor/platzi.py index 9efa51bdd..7fef4d1b1 100644 --- a/youtube_dl/extractor/platzi.py +++ b/youtube_dl/extractor/platzi.py @@ -3,16 +3,13 @@ from __future__ import unicode_literals from .common import InfoExtractor from ..compat import ( - compat_b64decode, compat_str, ) from ..utils import ( - clean_html, ExtractorError, int_or_none, str_or_none, try_get, - url_or_none, urlencode_postdata, urljoin, ) @@ -105,39 +102,35 @@ class PlatziIE(PlatziBaseIE): webpage = self._download_webpage(url, lecture_id) data_preloaded_state = self._parse_json( - self._search_regex((r'window.__PRELOADED_STATE__ = (.*)\<\/script'), webpage, 'client data'), + self._search_regex( + (r'window\s*.\s*__PRELOADED_STATE__\s*=\s*({.*?});?\s* Date: Fri, 28 Oct 2022 21:55:44 +0000 Subject: [PATCH 3/9] Improve extraction * use User-Agent Mozilla/5.0 * use Referer for manifests and downloads * finalise review comments --- youtube_dl/extractor/platzi.py | 67 +++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/youtube_dl/extractor/platzi.py b/youtube_dl/extractor/platzi.py index 7fef4d1b1..0bf916084 100644 --- a/youtube_dl/extractor/platzi.py +++ b/youtube_dl/extractor/platzi.py @@ -6,9 +6,12 @@ from ..compat import ( compat_str, ) from ..utils import ( + clean_html, ExtractorError, + get_element_by_class, int_or_none, str_or_none, + strip_or_none, try_get, urlencode_postdata, urljoin, @@ -100,38 +103,47 @@ class PlatziIE(PlatziBaseIE): def _real_extract(self, url): lecture_id = self._match_id(url) - webpage = self._download_webpage(url, lecture_id) + headers = {'User-Agent': 'Mozilla/5.0'} + webpage = self._download_webpage(url, lecture_id, headers=headers) data_preloaded_state = self._parse_json( self._search_regex( (r'window\s*.\s*__PRELOADED_STATE__\s*=\s*({.*?});?\s* Date: Fri, 28 Oct 2022 22:43:54 +0000 Subject: [PATCH 4/9] Further improve extraction * detect when login required * extract further metadata --- youtube_dl/extractor/platzi.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/youtube_dl/extractor/platzi.py b/youtube_dl/extractor/platzi.py index 0bf916084..06aff4ae2 100644 --- a/youtube_dl/extractor/platzi.py +++ b/youtube_dl/extractor/platzi.py @@ -7,12 +7,15 @@ from ..compat import ( ) from ..utils import ( clean_html, + dict_get, ExtractorError, get_element_by_class, int_or_none, + parse_iso8601, str_or_none, strip_or_none, try_get, + url_or_none, urlencode_postdata, urljoin, ) @@ -113,6 +116,13 @@ class PlatziIE(PlatziBaseIE): video_player = try_get(data_preloaded_state, lambda x: x['videoPlayer'], dict) title = strip_or_none(video_player.get('name')) or self._og_search_title(webpage) servers = try_get(video_player, lambda x: x['video']['servers'], dict) or {} + if not servers and try_get(video_player, lambda x: x['blockedInfo']['blocked']): + why = video_player['blockedInfo'].get('type') or 'unspecified' + if why == 'unlogged': + self.raise_login_required() + raise ExtractorError( + 'All video formats blocked because ' + why, expected=True) + formats = [] headers['Referer'] = url extractions = { @@ -137,13 +147,22 @@ class PlatziIE(PlatziBaseIE): for f in formats: f.setdefault('http_headers', {})['Referer'] = headers['Referer'] + def categories(): + cat = strip_or_none(video_player.get('courseCategory')) + if cat: + return [cat] + return { 'id': lecture_id, 'title': title, - 'description': self._og_search_description(webpage), - 'thumbnail': self._og_search_thumbnail(webpage), + 'description': clean_html(video_player.get('courseDescription')) or self._og_search_description(webpage), 'duration': int_or_none(video_player.get('duration'), invscale=60), - 'creator': clean_html(get_element_by_class('TeacherDetails-name', webpage)), + 'thumbnail': url_or_none(video_player.get('thumbnail')) or self._og_search_thumbnail(webpage), + 'timestamp': parse_iso8601(dict_get(video_player, ('dataModified', 'dataPublished'))), + 'creator': strip_or_none(video_player.get('teacherName')) or clean_html(get_element_by_class('TeacherDetails-name', webpage)), + 'comment_count': int_or_none(video_player.get('commentsNumber')), + 'categories': categories(), + 'series': strip_or_none(video_player.get('courseTitle')) or None, 'formats': formats, } From dc80f50f7e3dac75bfc1248346c195be0a562ed5 Mon Sep 17 00:00:00 2001 From: dirkf Date: Sat, 29 Oct 2022 01:44:44 +0000 Subject: [PATCH 5/9] Outdent for linter --- youtube_dl/extractor/platzi.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/youtube_dl/extractor/platzi.py b/youtube_dl/extractor/platzi.py index 06aff4ae2..0f79cf555 100644 --- a/youtube_dl/extractor/platzi.py +++ b/youtube_dl/extractor/platzi.py @@ -127,14 +127,14 @@ class PlatziIE(PlatziBaseIE): headers['Referer'] = url extractions = { 'hls': lambda x: formats.extend(self._extract_m3u8_formats( - server_json[x], lecture_id, 'mp4', - entry_protocol='m3u8_native', m3u8_id='hls', - note='Downloading %s m3u8 information' % (server_json.get('id', x), ), - headers=headers, fatal=False)), + server_json[x], lecture_id, 'mp4', + entry_protocol='m3u8_native', m3u8_id='hls', + note='Downloading %s m3u8 information' % (server_json.get('id', x), ), + headers=headers, fatal=False)), 'dash': lambda x: formats.extend(self._extract_mpd_formats( - server_json[x], lecture_id, mpd_id='dash', - note='Downloading %s MPD manifest' % (server_json.get('id', x), ), - headers=headers, fatal=False)), + server_json[x], lecture_id, mpd_id='dash', + note='Downloading %s MPD manifest' % (server_json.get('id', x), ), + headers=headers, fatal=False)), } for server, server_json in servers.items(): if not isinstance(server_json, dict): From 04a7c7a84901692058b23209f30c55ccbe88704f Mon Sep 17 00:00:00 2001 From: dirkf Date: Sat, 29 Oct 2022 07:32:52 +0100 Subject: [PATCH 6/9] Fix test --- youtube_dl/extractor/platzi.py | 56 ++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/youtube_dl/extractor/platzi.py b/youtube_dl/extractor/platzi.py index 0f79cf555..c9597a747 100644 --- a/youtube_dl/extractor/platzi.py +++ b/youtube_dl/extractor/platzi.py @@ -3,7 +3,9 @@ from __future__ import unicode_literals from .common import InfoExtractor from ..compat import ( + compat_kwargs, compat_str, + compat_urllib_parse_urlparse, ) from ..utils import ( clean_html, @@ -78,6 +80,26 @@ class PlatziIE(PlatziBaseIE): ''' _TESTS = [{ + 'url': 'https://platzi.com/clases/1927-intro-selenium/29383-bienvenida-al-curso', + 'md5': '0af120f1ffd18a2246f19099d52b83e2', + 'info_dict': { + 'id': '29383', + 'ext': 'mp4', + 'title': 'Por qué aprender Selenium y qué verás', + 'description': 'md5:bbe91d2760052ca4054a3149a6580436', + 'timestamp': 1627400390, + 'upload_date': '20210727', + 'creator': 'Héctor Vega', + 'series': 'Curso de Introducción a Selenium con Python', + 'duration': 11700, + 'categories': list, + }, + 'params': { + 'format': 'bestvideo', + # 'skip_download': True, + }, + 'expected_warnings': ['HTTP Error 401'] + }, { 'url': 'https://platzi.com/clases/1311-next-js/12074-creando-nuestra-primera-pagina/', 'md5': '8f56448241005b561c10f11a595b37e3', 'info_dict': { @@ -87,7 +109,7 @@ class PlatziIE(PlatziBaseIE): 'description': 'md5:4c866e45034fc76412fbf6e60ae008bc', 'duration': 420, }, - 'skip': 'Requires platzi account credentials', + 'skip': 'Content expired', }, { 'url': 'https://courses.platzi.com/classes/1367-communication-codestream/13430-background/', 'info_dict': { @@ -97,23 +119,39 @@ class PlatziIE(PlatziBaseIE): 'description': 'md5:49c83c09404b15e6e71defaf87f6b305', 'duration': 360, }, - 'skip': 'Requires platzi account credentials', - 'params': { - 'skip_download': True, - }, + 'skip': 'Content expired', }] + def _download_webpage_handle(self, url_or_request, video_id, *args, **kwargs): + # CF likes Connection: keep-alive and so disfavours Py2 + # retry on 403 may get in + kwargs['expected_status'] = 403 + x = super(PlatziIE, self)._download_webpage_handle(url_or_request, video_id, *args, **kwargs) + if x is not False and x[1].getcode() == 403: + kwargs.pop('expected_status', None) + note = kwargs.pop('note', '') + kwargs['note'] = (note or 'Downloading webpage') + ' - retrying' + x = super(PlatziIE, self)._download_webpage_handle(url_or_request, video_id, *args, **kwargs) + return x + def _real_extract(self, url): lecture_id = self._match_id(url) - headers = {'User-Agent': 'Mozilla/5.0'} - webpage = self._download_webpage(url, lecture_id, headers=headers) + # header parameters required fpor Py3 to breach site's CF fence w/o 403 + headers = { + 'User-Agent': 'Mozilla/5.0', # (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36', + } + webpage, urlh = self._download_webpage_handle(url, lecture_id, headers=headers) + if compat_urllib_parse_urlparse(urlh.geturl()).path == '/': + raise ExtractorError( + 'Redirected to home page: content expired?', expected=True) + data_preloaded_state = self._parse_json( self._search_regex( (r'window\s*.\s*__PRELOADED_STATE__\s*=\s*({.*?});?\s* Date: Sat, 29 Oct 2022 07:49:38 +0100 Subject: [PATCH 7/9] Linted --- youtube_dl/extractor/platzi.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/youtube_dl/extractor/platzi.py b/youtube_dl/extractor/platzi.py index c9597a747..ff84d0d77 100644 --- a/youtube_dl/extractor/platzi.py +++ b/youtube_dl/extractor/platzi.py @@ -125,13 +125,13 @@ class PlatziIE(PlatziBaseIE): def _download_webpage_handle(self, url_or_request, video_id, *args, **kwargs): # CF likes Connection: keep-alive and so disfavours Py2 # retry on 403 may get in - kwargs['expected_status'] = 403 + kwargs['expected_status'] = 403 x = super(PlatziIE, self)._download_webpage_handle(url_or_request, video_id, *args, **kwargs) if x is not False and x[1].getcode() == 403: kwargs.pop('expected_status', None) note = kwargs.pop('note', '') - kwargs['note'] = (note or 'Downloading webpage') + ' - retrying' - x = super(PlatziIE, self)._download_webpage_handle(url_or_request, video_id, *args, **kwargs) + kwargs['note'] = (note or 'Downloading webpage') + ' - retrying' + x = super(PlatziIE, self)._download_webpage_handle(url_or_request, video_id, *args, **compat_kwargs(kwargs)) return x def _real_extract(self, url): @@ -139,7 +139,7 @@ class PlatziIE(PlatziBaseIE): # header parameters required fpor Py3 to breach site's CF fence w/o 403 headers = { - 'User-Agent': 'Mozilla/5.0', # (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36', + 'User-Agent': 'Mozilla/5.0', } webpage, urlh = self._download_webpage_handle(url, lecture_id, headers=headers) if compat_urllib_parse_urlparse(urlh.geturl()).path == '/': From eff6cd4c2499a88c2795b3436550068759eb2b8a Mon Sep 17 00:00:00 2001 From: dirkf Date: Sat, 29 Oct 2022 15:57:14 +0000 Subject: [PATCH 8/9] Improve course/category extraction --- youtube_dl/extractor/platzi.py | 130 ++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 28 deletions(-) diff --git a/youtube_dl/extractor/platzi.py b/youtube_dl/extractor/platzi.py index ff84d0d77..2ca53128a 100644 --- a/youtube_dl/extractor/platzi.py +++ b/youtube_dl/extractor/platzi.py @@ -1,6 +1,8 @@ # coding: utf-8 from __future__ import unicode_literals +import re + from .common import InfoExtractor from ..compat import ( compat_kwargs, @@ -27,6 +29,42 @@ class PlatziBaseIE(InfoExtractor): _LOGIN_URL = 'https://platzi.com/login/' _NETRC_MACHINE = 'platzi' + def _raise_extractor_error(self, video_id, reason, expected=True): + raise ExtractorError('[%s] %s: %s' % (self.IE_NAME, video_id, reason), expected=expected) + + def _download_webpage(self, url_or_request, video_id, *args, **kwargs): + # CF likes Connection: keep-alive and so disfavours Py2 + # retry on 403 may get in + kwargs['expected_status'] = 403 + # header parameters required fpor Py3 to breach site's CF fence w/o 403 + headers = kwargs.get('headers') or {} + new_hdrs = {} + if 'User-Agent' not in headers: + headers['User-Agent'] = 'Mozilla/5.0' # (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36' + kwargs['headers'] = new_hdrs = headers + if new_hdrs: + kwargs = compat_kwargs(kwargs) + for _ in range(2): + x = super(PlatziBaseIE, self)._download_webpage_handle(url_or_request, video_id, *args, **kwargs) + if x is False: + return x + if x[1].getcode() != 403: + break + kwargs.pop('expected_status', None) + note = kwargs.pop('note', '') + kwargs['note'] = (note or 'Downloading webpage') + ' - retrying' + kwargs = compat_kwargs(kwargs) + path = compat_urllib_parse_urlparse(x[1].geturl()) + if path == '/': + self._raise_extractor_error(video_id, 'Redirected to home page: content expired?') + elif path =='/login': + self.raise_login_required() + else: + errs = clean_html(get_element_by_class('Errorpage-text', x[0])) + if errs: + self._raise_extractor_error(video_id, errs) + return x[0] + def _real_initialize(self): self._login() @@ -122,29 +160,10 @@ class PlatziIE(PlatziBaseIE): 'skip': 'Content expired', }] - def _download_webpage_handle(self, url_or_request, video_id, *args, **kwargs): - # CF likes Connection: keep-alive and so disfavours Py2 - # retry on 403 may get in - kwargs['expected_status'] = 403 - x = super(PlatziIE, self)._download_webpage_handle(url_or_request, video_id, *args, **kwargs) - if x is not False and x[1].getcode() == 403: - kwargs.pop('expected_status', None) - note = kwargs.pop('note', '') - kwargs['note'] = (note or 'Downloading webpage') + ' - retrying' - x = super(PlatziIE, self)._download_webpage_handle(url_or_request, video_id, *args, **compat_kwargs(kwargs)) - return x - def _real_extract(self, url): lecture_id = self._match_id(url) - # header parameters required fpor Py3 to breach site's CF fence w/o 403 - headers = { - 'User-Agent': 'Mozilla/5.0', - } - webpage, urlh = self._download_webpage_handle(url, lecture_id, headers=headers) - if compat_urllib_parse_urlparse(urlh.geturl()).path == '/': - raise ExtractorError( - 'Redirected to home page: content expired?', expected=True) + webpage = self._download_webpage(url, lecture_id) data_preloaded_state = self._parse_json( self._search_regex( @@ -158,11 +177,10 @@ class PlatziIE(PlatziBaseIE): why = video_player['blockedInfo'].get('type') or 'unspecified' if why == 'unlogged': self.raise_login_required() - raise ExtractorError( - 'All video formats blocked because ' + why, expected=True) + self._raise_extractor_error(video_id, 'All video formats blocked because ' + why) formats = [] - headers['Referer'] = url + headers = {'Referer': url} extractions = { 'hls': lambda x: formats.extend(self._extract_m3u8_formats( server_json[x], lecture_id, 'mp4', @@ -209,17 +227,35 @@ class PlatziCourseIE(PlatziBaseIE): _VALID_URL = r'''(?x) https?:// (?: - platzi\.com/clases| # es version - courses\.platzi\.com/classes # en version + (?P + platzi\.com/clases| # es version + courses\.platzi\.com/classes # en version + )| + platzi\.com(?:/(?Pcursos))? )/(?P[^/?\#&]+) ''' _TESTS = [{ + 'url': 'https://platzi.com/web-angular/', + 'info_dict': { + 'id': 'web-angular', + 'title': 'Frontend con Angular', + }, + 'playlist_count': 9, + }, { + 'url': 'https://platzi.com/cursos/angular/', + 'info_dict': { + 'id': '2478', + 'title': 'Curso de Fundamentos de Angular', + }, + 'playlist_count': 21, + }, { 'url': 'https://platzi.com/clases/next-js/', 'info_dict': { 'id': '1311', 'title': 'Curso de Next.js', }, 'playlist_count': 22, + 'skip': 'Oops (updating page)', }, { 'url': 'https://courses.platzi.com/classes/communication-codestream/', 'info_dict': { @@ -227,16 +263,54 @@ class PlatziCourseIE(PlatziBaseIE): 'title': 'Codestream Course', }, 'playlist_count': 14, + 'skip': 'Content expired', }] + @classmethod + def _match_valid_url(cls, url): + return re.match(cls._VALID_URL, url) + @classmethod def suitable(cls, url): return False if PlatziIE.suitable(url) else super(PlatziCourseIE, cls).suitable(url) - def _real_extract(self, url): - course_name = self._match_id(url) + def __extract_things(self, webpage, thing_id, thing_pattern): + return self.playlist_from_matches( + re.finditer(thing_pattern, webpage), + playlist_id=thing_id, + playlist_title=self._og_search_title(webpage, default=None), + getter=lambda m: urljoin('https://platzi.com', m.group('path'))) - webpage = self._download_webpage(url, course_name) + def _extract_classes(self, webpage, course_id): + display_id = course_id + course_id = self._search_regex( + r'''(["'])courseId\1\s*:\s*(?P\d+)''', + webpage, 'course id', group='id', fatal=False) or course_id + return self.__extract_things( + webpage, course_id, + r''']+\bhref\s*=\s*['"]?(?P/clases/\d+-%s/[^/]+)''' + % (display_id, )) + + def _extract_categories(self, webpage, cat_id): + return self.__extract_things( + webpage, cat_id, + r''']+\bhref\s*=\s*['"]?(?P/cursos/[^/]+)''') + + def _real_extract(self, url): + + m = self._match_valid_url(url) + classes, courses, this_id = m.group('clas', 'curs', 'id') + + webpage = self._download_webpage(url, this_id) + + if courses: + return self._extract_classes(webpage, this_id) + + if not classes: + return self._extract_categories(webpage, this_id) + + # this branch now seems always to give "Oops" pages + course_name = this_id initialData = self._search_regex( (r'window.initialData\s*=\s*({.+?})\s*;\s*\n', r'window.initialData\s*=\s*({.+?})\s*;'), From ea4948068d323a081324f69a805df14ddab13f6f Mon Sep 17 00:00:00 2001 From: dirkf Date: Sat, 29 Oct 2022 16:10:56 +0000 Subject: [PATCH 9/9] Linted --- youtube_dl/extractor/platzi.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/youtube_dl/extractor/platzi.py b/youtube_dl/extractor/platzi.py index 2ca53128a..47328c5fe 100644 --- a/youtube_dl/extractor/platzi.py +++ b/youtube_dl/extractor/platzi.py @@ -57,7 +57,7 @@ class PlatziBaseIE(InfoExtractor): path = compat_urllib_parse_urlparse(x[1].geturl()) if path == '/': self._raise_extractor_error(video_id, 'Redirected to home page: content expired?') - elif path =='/login': + elif path == '/login': self.raise_login_required() else: errs = clean_html(get_element_by_class('Errorpage-text', x[0])) @@ -177,7 +177,7 @@ class PlatziIE(PlatziBaseIE): why = video_player['blockedInfo'].get('type') or 'unspecified' if why == 'unlogged': self.raise_login_required() - self._raise_extractor_error(video_id, 'All video formats blocked because ' + why) + self._raise_extractor_error(lecture_id, 'All video formats blocked because ' + why) formats = [] headers = {'Referer': url} @@ -287,13 +287,13 @@ class PlatziCourseIE(PlatziBaseIE): r'''(["'])courseId\1\s*:\s*(?P\d+)''', webpage, 'course id', group='id', fatal=False) or course_id return self.__extract_things( - webpage, course_id, + webpage, course_id, r''']+\bhref\s*=\s*['"]?(?P/clases/\d+-%s/[^/]+)''' % (display_id, )) def _extract_categories(self, webpage, cat_id): return self.__extract_things( - webpage, cat_id, + webpage, cat_id, r''']+\bhref\s*=\s*['"]?(?P/cursos/[^/]+)''') def _real_extract(self, url):