]> jfr.im git - yt-dlp.git/commitdiff
[extractor/drtv] Add series extractors (#5644)
authorFrederik Nordahl Jul Sabroe <redacted>
Fri, 6 Jan 2023 19:07:52 +0000 (20:07 +0100)
committerGitHub <redacted>
Fri, 6 Jan 2023 19:07:52 +0000 (00:37 +0530)
Authored by: FrederikNS
Closes #3567

yt_dlp/extractor/_extractors.py
yt_dlp/extractor/drtv.py

index 7a390a8d25755306cd86c26ad0911dbfd1e4fa1f..df31164e403a2e2ec44b4077e228d5c4e22b804b 100644 (file)
 from .drtv import (
     DRTVIE,
     DRTVLiveIE,
+    DRTVSeasonIE,
+    DRTVSeriesIE,
 )
 from .dtube import DTubeIE
 from .dvtv import DVTVIE
index 128f4391452d27fd614ecfb86966e49d15c54d06..f4df3e2462aadf40224c5f9748026f992ea434bd 100644 (file)
@@ -12,6 +12,7 @@
     float_or_none,
     mimetype2ext,
     str_or_none,
+    traverse_obj,
     try_get,
     unified_timestamp,
     update_url_query,
@@ -19,6 +20,9 @@
 )
 
 
+SERIES_API = 'https://production-cdn.dr-massive.com/api/page?device=web_browser&item_detail_expand=all&lang=da&max_list_prefetch=3&path=%s'
+
+
 class DRTVIE(InfoExtractor):
     _VALID_URL = r'''(?x)
                     https?://
@@ -141,13 +145,13 @@ class DRTVIE(InfoExtractor):
     }]
 
     def _real_extract(self, url):
-        video_id = self._match_id(url)
+        raw_video_id = self._match_id(url)
 
-        webpage = self._download_webpage(url, video_id)
+        webpage = self._download_webpage(url, raw_video_id)
 
         if '>Programmet er ikke længere tilgængeligt' in webpage:
             raise ExtractorError(
-                'Video %s is not available' % video_id, expected=True)
+                'Video %s is not available' % raw_video_id, expected=True)
 
         video_id = self._search_regex(
             (r'data-(?:material-identifier|episode-slug)="([^"]+)"',
@@ -182,6 +186,10 @@ def _real_extract(self, url):
         data = self._download_json(
             programcard_url, video_id, 'Downloading video JSON', query=query)
 
+        supplementary_data = self._download_json(
+            SERIES_API % f'/episode/{raw_video_id}', raw_video_id,
+            default={}) if re.search(r'_\d+$', raw_video_id) else {}
+
         title = str_or_none(data.get('Title')) or re.sub(
             r'\s*\|\s*(?:TV\s*\|\s*DR|DRTV)$', '',
             self._og_search_title(webpage))
@@ -313,8 +321,8 @@ def decrypt_uri(e):
             'season': str_or_none(data.get('SeasonTitle')),
             'season_number': int_or_none(data.get('SeasonNumber')),
             'season_id': str_or_none(data.get('SeasonUrn')),
-            'episode': str_or_none(data.get('EpisodeTitle')),
-            'episode_number': int_or_none(data.get('EpisodeNumber')),
+            'episode': traverse_obj(supplementary_data, ('entries', 0, 'item', 'contextualTitle')) or str_or_none(data.get('EpisodeTitle')),
+            'episode_number': traverse_obj(supplementary_data, ('entries', 0, 'item', 'episodeNumber')) or int_or_none(data.get('EpisodeNumber')),
             'release_year': int_or_none(data.get('ProductionYear')),
         }
 
@@ -372,3 +380,92 @@ def _real_extract(self, url):
             'formats': formats,
             'is_live': True,
         }
+
+
+class DRTVSeasonIE(InfoExtractor):
+    IE_NAME = 'drtv:season'
+    _VALID_URL = r'https?://(?:www\.)?(?:dr\.dk|dr-massive\.com)/drtv/saeson/(?P<display_id>[\w-]+)_(?P<id>\d+)'
+    _GEO_COUNTRIES = ['DK']
+    _TESTS = [{
+        'url': 'https://www.dr.dk/drtv/saeson/frank-and-kastaniegaarden_9008',
+        'info_dict': {
+            'id': '9008',
+            'display_id': 'frank-and-kastaniegaarden',
+            'title': 'Frank & Kastaniegaarden',
+            'series': 'Frank & Kastaniegaarden',
+        },
+        'playlist_mincount': 8
+    }, {
+        'url': 'https://www.dr.dk/drtv/saeson/frank-and-kastaniegaarden_8761',
+        'info_dict': {
+            'id': '8761',
+            'display_id': 'frank-and-kastaniegaarden',
+            'title': 'Frank & Kastaniegaarden',
+            'series': 'Frank & Kastaniegaarden',
+        },
+        'playlist_mincount': 19
+    }]
+
+    def _real_extract(self, url):
+        display_id, season_id = self._match_valid_url(url).group('display_id', 'id')
+        data = self._download_json(SERIES_API % f'/saeson/{display_id}_{season_id}', display_id)
+
+        entries = [{
+            '_type': 'url',
+            'url': f'https://www.dr.dk/drtv{episode["path"]}',
+            'ie_key': DRTVIE.ie_key(),
+            'title': episode.get('title'),
+            'episode': episode.get('episodeName'),
+            'description': episode.get('shortDescription'),
+            'series': traverse_obj(data, ('entries', 0, 'item', 'title')),
+            'season_number': traverse_obj(data, ('entries', 0, 'item', 'seasonNumber')),
+            'episode_number': episode.get('episodeNumber'),
+        } for episode in traverse_obj(data, ('entries', 0, 'item', 'episodes', 'items'))]
+
+        return {
+            '_type': 'playlist',
+            'id': season_id,
+            'display_id': display_id,
+            'title': traverse_obj(data, ('entries', 0, 'item', 'title')),
+            'series': traverse_obj(data, ('entries', 0, 'item', 'title')),
+            'entries': entries,
+            'season_number': traverse_obj(data, ('entries', 0, 'item', 'seasonNumber'))
+        }
+
+
+class DRTVSeriesIE(InfoExtractor):
+    IE_NAME = 'drtv:series'
+    _VALID_URL = r'https?://(?:www\.)?(?:dr\.dk|dr-massive\.com)/drtv/serie/(?P<display_id>[\w-]+)_(?P<id>\d+)'
+    _GEO_COUNTRIES = ['DK']
+    _TESTS = [{
+        'url': 'https://www.dr.dk/drtv/serie/frank-and-kastaniegaarden_6954',
+        'info_dict': {
+            'id': '6954',
+            'display_id': 'frank-and-kastaniegaarden',
+            'title': 'Frank & Kastaniegaarden',
+            'series': 'Frank & Kastaniegaarden',
+        },
+        'playlist_mincount': 15
+    }]
+
+    def _real_extract(self, url):
+        display_id, series_id = self._match_valid_url(url).group('display_id', 'id')
+        data = self._download_json(SERIES_API % f'/serie/{display_id}_{series_id}', display_id)
+
+        entries = [{
+            '_type': 'url',
+            'url': f'https://www.dr.dk/drtv{season.get("path")}',
+            'ie_key': DRTVSeasonIE.ie_key(),
+            'title': season.get('title'),
+            'series': traverse_obj(data, ('entries', 0, 'item', 'title')),
+            'season_number': traverse_obj(data, ('entries', 0, 'item', 'seasonNumber'))
+        } for season in traverse_obj(data, ('entries', 0, 'item', 'show', 'seasons', 'items'))]
+
+        return {
+            '_type': 'playlist',
+            'id': series_id,
+            'display_id': display_id,
+            'title': traverse_obj(data, ('entries', 0, 'item', 'title')),
+            'series': traverse_obj(data, ('entries', 0, 'item', 'title')),
+            'entries': entries
+        }