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