[cleanup] Make more playlist entries lazy (#11763)
[yt-dlp.git] / yt_dlp / extractor / rtnews.py
blob558511f1c021f05c04051e75eefe284a1cf2fb50
1 import re
3 from .common import InfoExtractor
4 from ..utils import js_to_json
7 class RTNewsIE(InfoExtractor):
8 _VALID_URL = r'https?://(?:www\.)?rt\.com/[^/]+/(?:[^/]+/)?(?P<id>\d+)'
10 _TESTS = [{
11 'url': 'https://www.rt.com/sport/546301-djokovic-arrives-belgrade-crowds/',
12 'playlist_mincount': 2,
13 'info_dict': {
14 'id': '546301',
15 'title': 'Crowds gather to greet deported Djokovic as he returns to Serbia (VIDEO)',
16 'description': 'md5:1d5bfe1a988d81fd74227cfdf93d314d',
17 'thumbnail': 'https://cdni.rt.com/files/2022.01/article/61e587a085f540102c3386c1.png',
19 }, {
20 'url': 'https://www.rt.com/shows/in-question/535980-plot-to-assassinate-julian-assange/',
21 'playlist_mincount': 1,
22 'info_dict': {
23 'id': '535980',
24 'title': 'The plot to assassinate Julian Assange',
25 'description': 'md5:55279ce5e4441dc1d16e2e4a730152cd',
26 'thumbnail': 'https://cdni.rt.com/files/2021.09/article/615226f42030274e8879b53d.png',
28 'playlist': [{
29 'info_dict': {
30 'id': '6152271d85f5400464496162',
31 'ext': 'mp4',
32 'title': '6152271d85f5400464496162',
34 }],
37 def _entries(self, webpage):
38 video_urls = set(re.findall(r'https://cdnv\.rt\.com/.*[a-f0-9]+\.mp4', webpage))
39 for v_url in video_urls:
40 v_id = re.search(r'([a-f0-9]+)\.mp4', v_url).group(1)
41 if v_id:
42 yield {
43 'id': v_id,
44 'title': v_id,
45 'url': v_url,
48 def _real_extract(self, url):
49 playlist_id = self._match_id(url)
50 webpage = self._download_webpage(url, playlist_id)
52 return {
53 '_type': 'playlist',
54 'id': playlist_id,
55 'entries': self._entries(webpage),
56 'title': self._og_search_title(webpage),
57 'description': self._og_search_description(webpage),
58 'thumbnail': self._og_search_thumbnail(webpage),
62 class RTDocumentryIE(InfoExtractor):
63 _VALID_URL = r'https?://rtd\.rt\.com/(?:(?:series|shows)/[^/]+|films)/(?P<id>[^/?$&#]+)'
65 _TESTS = [{
66 'url': 'https://rtd.rt.com/films/escobars-hitman/',
67 'info_dict': {
68 'id': 'escobars-hitman',
69 'ext': 'mp4',
70 'title': "Escobar's Hitman. Former drug-gang killer, now loved and loathed in Colombia",
71 'description': 'md5:647c76984b7cb9a8b52a567e87448d88',
72 'thumbnail': 'https://cdni.rt.com/rtd-files/films/escobars-hitman/escobars-hitman_11.jpg',
73 'average_rating': 8.53,
74 'duration': 3134.0,
76 'params': {'skip_download': True},
77 }, {
78 'url': 'https://rtd.rt.com/shows/the-kalashnikova-show-military-secrets-anna-knishenko/iskander-tactical-system-natos-headache/',
79 'info_dict': {
80 'id': 'iskander-tactical-system-natos-headache',
81 'ext': 'mp4',
82 'title': "Iskander tactical system. NATO's headache | The Kalashnikova Show. Episode 10",
83 'description': 'md5:da7c24a0aa67bc2bb88c86658508ca87',
84 'thumbnail': 'md5:89de8ce38c710b7c501ff02d47e2aa89',
85 'average_rating': 9.27,
86 'duration': 274.0,
87 'timestamp': 1605726000,
88 'view_count': int,
89 'upload_date': '20201118',
91 'params': {'skip_download': True},
92 }, {
93 'url': 'https://rtd.rt.com/series/i-am-hacked-trailer/introduction-to-safe-digital-life-ep2/',
94 'info_dict': {
95 'id': 'introduction-to-safe-digital-life-ep2',
96 'ext': 'mp4',
97 'title': 'How to Keep your Money away from Hackers | I am Hacked. Episode 2',
98 'description': 'md5:c46fa9a5af86c0008c45a3940a8cce87',
99 'thumbnail': 'md5:a5e81b9bf5aed8f5e23d9c053601b825',
100 'average_rating': 10.0,
101 'duration': 1524.0,
102 'timestamp': 1636977600,
103 'view_count': int,
104 'upload_date': '20211115',
106 'params': {'skip_download': True},
109 def _real_extract(self, url):
110 video_id = self._match_id(url)
111 webpage = self._download_webpage(url, video_id)
112 ld_json = self._search_json_ld(webpage, None, fatal=False)
113 if not ld_json:
114 self.raise_no_formats('No video/audio found at the provided url.', expected=True)
115 media_json = self._parse_json(
116 self._search_regex(r'(?s)\'Med\'\s*:\s*\[\s*({.+})\s*\]\s*};', webpage, 'media info'),
117 video_id, transform_source=js_to_json)
118 if 'title' not in ld_json and 'title' in media_json:
119 ld_json['title'] = media_json['title']
120 formats = [{'url': src['file']} for src in media_json.get('sources') or [] if src.get('file')]
122 return {
123 'id': video_id,
124 'thumbnail': media_json.get('image'),
125 'formats': formats,
126 **ld_json,
130 class RTDocumentryPlaylistIE(InfoExtractor):
131 _VALID_URL = r'https?://rtd\.rt\.com/(?:series|shows)/(?P<id>[^/]+)/$'
133 _TESTS = [{
134 'url': 'https://rtd.rt.com/series/i-am-hacked-trailer/',
135 'playlist_mincount': 6,
136 'info_dict': {
137 'id': 'i-am-hacked-trailer',
139 }, {
140 'url': 'https://rtd.rt.com/shows/the-kalashnikova-show-military-secrets-anna-knishenko/',
141 'playlist_mincount': 34,
142 'info_dict': {
143 'id': 'the-kalashnikova-show-military-secrets-anna-knishenko',
147 def _entries(self, webpage, playlist_id):
148 video_urls = set(re.findall(r'list-2__link\s*"\s*href="([^"]+)"', webpage))
149 for v_url in video_urls:
150 if playlist_id not in v_url:
151 continue
152 yield self.url_result(
153 f'https://rtd.rt.com{v_url}',
154 ie=RTDocumentryIE.ie_key())
156 def _real_extract(self, url):
157 playlist_id = self._match_id(url)
158 webpage = self._download_webpage(url, playlist_id)
160 return {
161 '_type': 'playlist',
162 'id': playlist_id,
163 'entries': self._entries(webpage, playlist_id),
167 class RuptlyIE(InfoExtractor):
168 _VALID_URL = r'https?://(?:www\.)?ruptly\.tv/[a-z]{2}/videos/(?P<id>\d+-\d+)'
170 _TESTS = [{
171 'url': 'https://www.ruptly.tv/en/videos/20220112-020-Japan-Double-trouble-Tokyo-zoo-presents-adorable-panda-twins',
172 'info_dict': {
173 'id': '20220112-020',
174 'ext': 'mp4',
175 'title': 'Japan: Double trouble! Tokyo zoo presents adorable panda twins | Video Ruptly',
176 'description': 'md5:85a8da5fdb31486f0562daf4360ce75a',
177 'thumbnail': 'https://storage.ruptly.tv/thumbnails/20220112-020/i6JQKnTNpYuqaXsR/i6JQKnTNpYuqaXsR.jpg',
179 'params': {'skip_download': True},
182 def _real_extract(self, url):
183 video_id = self._match_id(url)
184 webpage = self._download_webpage(url, video_id)
185 m3u8_url = self._search_regex(r'preview_url"\s?:\s?"(https?://storage\.ruptly\.tv/video_projects/.+\.m3u8)"', webpage, 'm3u8 url', fatal=False)
186 if not m3u8_url:
187 self.raise_no_formats('No video/audio found at the provided url.', expected=True)
188 formats, subs = self._extract_m3u8_formats_and_subtitles(m3u8_url, video_id, ext='mp4')
189 return {
190 'id': video_id,
191 'formats': formats,
192 'subtitles': subs,
193 'title': self._og_search_title(webpage),
194 'description': self._og_search_description(webpage),
195 'thumbnail': self._og_search_thumbnail(webpage),