]> jfr.im git - yt-dlp.git/blobdiff - yt_dlp/extractor/duboku.py
[ie/matchtv] Fix extractor (#10190)
[yt-dlp.git] / yt_dlp / extractor / duboku.py
index 24403842d32817026eca1f4e0dd5b22daec24d68..68c3f05731f7cad45b8751612f1b70d4131c2702 100644 (file)
@@ -1,11 +1,12 @@
+import base64
 import re
+import urllib.parse
 
 from .common import InfoExtractor
-from ..compat import compat_urlparse
 from ..utils import (
+    ExtractorError,
     clean_html,
     extract_attributes,
-    ExtractorError,
     get_elements_by_class,
     int_or_none,
     js_to_json,
@@ -22,23 +23,23 @@ def _get_elements_by_tag_and_attrib(html, tag=None, attribute=None, value=None,
     if attribute is None:
         attribute = ''
     else:
-        attribute = r'\s+(?P<attribute>%s)' % re.escape(attribute)
+        attribute = rf'\s+(?P<attribute>{re.escape(attribute)})'
     if value is None:
         value = ''
     else:
         value = re.escape(value) if escape_value else value
-        value = '=[\'"]?(?P<value>%s)[\'"]?' % value
+        value = f'=[\'"]?(?P<value>{value})[\'"]?'
 
     retlist = []
-    for m in re.finditer(r'''(?xs)
-        <(?P<tag>%s)
+    for m in re.finditer(rf'''(?xs)
+        <(?P<tag>{tag})
          (?:\s+[a-zA-Z0-9:._-]+(?:=[a-zA-Z0-9:._-]*|="[^"]*"|='[^']*'|))*?
-         %s%s
+         {attribute}{value}
          (?:\s+[a-zA-Z0-9:._-]+(?:=[a-zA-Z0-9:._-]*|="[^"]*"|='[^']*'|))*?
         \s*>
         (?P<content>.*?)
         </\1>
-    ''' % (tag, attribute, value), html):
+    ''', html):
         retlist.append(m)
 
     return retlist
@@ -51,31 +52,39 @@ def _get_element_by_tag_and_attrib(html, tag=None, attribute=None, value=None, e
 
 class DubokuIE(InfoExtractor):
     IE_NAME = 'duboku'
-    IE_DESC = 'www.duboku.co'
+    IE_DESC = 'www.duboku.io'
 
-    _VALID_URL = r'(?:https?://[^/]+\.duboku\.co/vodplay/)(?P<id>[0-9]+-[0-9-]+)\.html.*'
+    _VALID_URL = r'(?:https?://[^/]+\.duboku\.io/vodplay/)(?P<id>[0-9]+-[0-9-]+)\.html.*'
     _TESTS = [{
-        'url': 'https://www.duboku.co/vodplay/1575-1-1.html',
+        'url': 'https://w.duboku.io/vodplay/1575-1-1.html',
         'info_dict': {
             'id': '1575-1-1',
-            'ext': 'ts',
+            'ext': 'mp4',
             'series': '白色月光',
             'title': 'contains:白色月光',
             'season_number': 1,
             'episode_number': 1,
+            'season': 'Season 1',
+            'episode_id': '1',
+            'season_id': '1',
+            'episode': 'Episode 1',
         },
         'params': {
             'skip_download': 'm3u8 download',
         },
     }, {
-        'url': 'https://www.duboku.co/vodplay/1588-1-1.html',
+        'url': 'https://w.duboku.io/vodplay/1588-1-1.html',
         'info_dict': {
             'id': '1588-1-1',
-            'ext': 'ts',
+            'ext': 'mp4',
             'series': '亲爱的自己',
-            'title': 'contains:预告片',
+            'title': 'contains:第1集',
             'season_number': 1,
             'episode_number': 1,
+            'episode': 'Episode 1',
+            'season': 'Season 1',
+            'episode_id': '1',
+            'season_id': '1',
         },
         'params': {
             'skip_download': 'm3u8 download',
@@ -91,7 +100,7 @@ def _real_extract(self, url):
         season_id = temp[1]
         episode_id = temp[2]
 
-        webpage_url = 'https://www.duboku.co/vodplay/%s.html' % video_id
+        webpage_url = f'https://w.duboku.io/vodplay/{video_id}.html'
         webpage_html = self._download_webpage(webpage_url, video_id)
 
         # extract video url
@@ -121,15 +130,20 @@ def _real_extract(self, url):
         data_url = player_data.get('url')
         if not data_url:
             raise ExtractorError('Cannot find url in player_data')
-        data_from = player_data.get('from')
+        player_encrypt = player_data.get('encrypt')
+        if player_encrypt == 1:
+            data_url = urllib.parse.unquote(data_url)
+        elif player_encrypt == 2:
+            data_url = urllib.parse.unquote(base64.b64decode(data_url).decode('ascii'))
 
         # if it is an embedded iframe, maybe it's an external source
-        if data_from == 'iframe':
+        headers = {'Referer': webpage_url}
+        if player_data.get('from') == 'iframe':
             # use _type url_transparent to retain the meaningful details
             # of the video.
             return {
                 '_type': 'url_transparent',
-                'url': smuggle_url(data_url, {'http_headers': {'Referer': webpage_url}}),
+                'url': smuggle_url(data_url, {'referer': webpage_url}),
                 'id': video_id,
                 'title': title,
                 'series': series_title,
@@ -139,7 +153,7 @@ def _real_extract(self, url):
                 'episode_id': episode_id,
             }
 
-        formats = self._extract_m3u8_formats(data_url, video_id, 'mp4')
+        formats = self._extract_m3u8_formats(data_url, video_id, 'mp4', headers=headers)
 
         return {
             'id': video_id,
@@ -150,46 +164,39 @@ def _real_extract(self, url):
             'episode_number': int_or_none(episode_id),
             'episode_id': episode_id,
             'formats': formats,
-            'http_headers': {'Referer': 'https://www.duboku.co/static/player/videojs.html'}
+            'http_headers': headers,
         }
 
 
 class DubokuPlaylistIE(InfoExtractor):
     IE_NAME = 'duboku:list'
-    IE_DESC = 'www.duboku.co entire series'
+    IE_DESC = 'www.duboku.io entire series'
 
-    _VALID_URL = r'(?:https?://[^/]+\.duboku\.co/voddetail/)(?P<id>[0-9]+)\.html.*'
+    _VALID_URL = r'(?:https?://[^/]+\.duboku\.io/voddetail/)(?P<id>[0-9]+)\.html.*'
     _TESTS = [{
-        'url': 'https://www.duboku.co/voddetail/1575.html',
+        'url': 'https://w.duboku.io/voddetail/1575.html',
         'info_dict': {
             'id': 'startswith:1575',
             'title': '白色月光',
         },
         'playlist_count': 12,
     }, {
-        'url': 'https://www.duboku.co/voddetail/1554.html',
+        'url': 'https://w.duboku.io/voddetail/1554.html',
         'info_dict': {
             'id': 'startswith:1554',
             'title': '以家人之名',
         },
         'playlist_mincount': 30,
-    }, {
-        'url': 'https://www.duboku.co/voddetail/1554.html#playlist2',
-        'info_dict': {
-            'id': '1554#playlist2',
-            'title': '以家人之名',
-        },
-        'playlist_mincount': 27,
     }]
 
     def _real_extract(self, url):
         mobj = self._match_valid_url(url)
         if mobj is None:
-            raise ExtractorError('Invalid URL: %s' % url)
+            raise ExtractorError(f'Invalid URL: {url}')
         series_id = mobj.group('id')
-        fragment = compat_urlparse.urlparse(url).fragment
+        fragment = urllib.parse.urlparse(url).fragment
 
-        webpage_url = 'https://www.duboku.co/voddetail/%s.html' % series_id
+        webpage_url = f'https://w.duboku.io/voddetail/{series_id}.html'
         webpage_html = self._download_webpage(webpage_url, series_id)
 
         # extract title
@@ -213,7 +220,7 @@ def _real_extract(self, url):
                     div.group('content'), 'a', 'href', value='[^\'"]+?', escape_value=False):
                 playlist.append({
                     'href': unescapeHTML(a.group('value')),
-                    'title': unescapeHTML(a.group('content'))
+                    'title': unescapeHTML(a.group('content')),
                 })
             playlists[playlist_id] = playlist
 
@@ -229,11 +236,11 @@ def _real_extract(self, url):
                 (playlist_id, playlist) = first
         if not playlist:
             raise ExtractorError(
-                'Cannot find %s' % fragment if fragment else 'Cannot extract playlist')
+                f'Cannot find {fragment}' if fragment else 'Cannot extract playlist')
 
         # return url results
         return self.playlist_result([
             self.url_result(
-                compat_urlparse.urljoin('https://www.duboku.co', x['href']),
+                urllib.parse.urljoin('https://w.duboku.io', x['href']),
                 ie=DubokuIE.ie_key(), video_title=x.get('title'))
             for x in playlist], series_id + '#' + playlist_id, title)