]> jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/tv24ua.py
723049e781ae5098ce80a72a12c6308b0880357a
[yt-dlp.git] / yt_dlp / extractor / tv24ua.py
1 import base64
2 import re
3 import urllib.parse
4
5 from .common import InfoExtractor
6 from ..utils import (
7 determine_ext,
8 extract_attributes,
9 get_elements_html_by_class,
10 js_to_json,
11 mimetype2ext,
12 smuggle_url,
13 traverse_obj,
14 )
15
16
17 class TV24UAVideoIE(InfoExtractor):
18 _VALID_URL = r'https?://24tv\.ua/news/showPlayer\.do.*?(?:\?|&)objectId=(?P<id>\d+)'
19 _EMBED_REGEX = [rf'<iframe[^>]+?src=["\']?(?P<url>{_VALID_URL})["\']?']
20 IE_NAME = '24tv.ua'
21 _TESTS = [{
22 'url': 'https://24tv.ua/news/showPlayer.do?objectId=2074790&videoUrl=2022/07/2074790&w=640&h=360',
23 'info_dict': {
24 'id': '2074790',
25 'ext': 'mp4',
26 'title': 'У Харкові ворожа ракета прилетіла в будинок, де слухали пісні про "офіцерів-росіян"',
27 'thumbnail': r're:^https?://.*\.jpe?g',
28 }
29 }, {
30 'url': 'https://24tv.ua/news/showPlayer.do?videoUrl=2022/07/2074790&objectId=2074790&w=640&h=360',
31 'only_matching': True,
32 }]
33
34 _WEBPAGE_TESTS = [
35 {
36 # iframe embed created from share menu.
37 'url': 'data:text/html,%3Ciframe%20src=%22https://24tv.ua/news/showPlayer.do?objectId=1886193&videoUrl'
38 '=2022/03/1886193&w=640&h=360%22%20width=%22640%22%20height=%22360%22%20frameborder=%220%22'
39 '%20scrolling=%22no%22%3E%3C/iframe%3E',
40 'info_dict': {
41 'id': '1886193',
42 'ext': 'mp4',
43 'title': 'Росіяни руйнують Бородянку на Київщині та стріляють з літаків по мешканцях: шокуючі фото',
44 'thumbnail': r're:^https?://.*\.jpe?g',
45 }
46 },
47 {
48 'url': 'https://24tv.ua/vipalyuyut-nashi-mista-sela-dsns-pokazali-motoroshni-naslidki_n1883966',
49 'info_dict': {
50 'id': '1883966',
51 'ext': 'mp4',
52 'title': 'Випалюють наші міста та села, – моторошні наслідки обстрілів на Чернігівщині',
53 'thumbnail': r're:^https?://.*\.jpe?g',
54 },
55 'params': {'allowed_extractors': ['Generic', '24tv.ua']},
56 }
57 ]
58
59 def _real_extract(self, url):
60 video_id = self._match_id(url)
61 webpage = self._download_webpage(url, video_id)
62
63 formats = []
64 subtitles = {}
65 for j in re.findall(r'vPlayConfig\.sources\s*=\s*(?P<json>\[{\s*(?s:.+?)\s*}])', webpage):
66 sources = self._parse_json(j, video_id, fatal=False, ignore_extra=True, transform_source=js_to_json, errnote='') or []
67 for source in sources:
68 if mimetype2ext(traverse_obj(source, 'type')) == 'm3u8':
69 f, s = self._extract_m3u8_formats_and_subtitles(source['src'], video_id)
70 formats.extend(f)
71 self._merge_subtitles(subtitles, s)
72 else:
73 formats.append({
74 'url': source['src'],
75 'ext': determine_ext(source['src']),
76 })
77 thumbnail = traverse_obj(
78 self._search_json(
79 r'var\s*vPlayConfig\s*=\s*', webpage, 'thumbnail',
80 video_id, default=None, transform_source=js_to_json), 'poster')
81 self._sort_formats(formats)
82 return {
83 'id': video_id,
84 'formats': formats,
85 'subtitles': subtitles,
86 'thumbnail': thumbnail or self._og_search_thumbnail(webpage),
87 'title': self._html_extract_title(webpage) or self._og_search_title(webpage),
88 'description': self._og_search_description(webpage, default=None),
89 }
90
91
92 class TV24UAGenericPassthroughIE(InfoExtractor):
93 _VALID_URL = r'https?://(?:[a-zA-Z0-9]+?\.)?24tv\.ua/(?P<id>[^/]+?_n\d+)'
94
95 _TESTS = [{
96 # Generic iframe, not within media_embed
97 'url': 'https://24tv.ua/vipalyuyut-nashi-mista-sela-dsns-pokazali-motoroshni-naslidki_n1883966',
98 'info_dict': {
99 'id': '1883966',
100 'ext': 'mp4',
101 'title': 'Випалюють наші міста та села, – моторошні наслідки обстрілів на Чернігівщині',
102 'thumbnail': r're:^https?://.*\.jpe?g',
103 }
104 }, {
105 # Generic iframe embed of TV24UAPlayerIE, within media_embed
106 'url': 'https://24tv.ua/harkivyani-zgaduyut-misto-do-viyni-shhemlive-video_n1887584',
107 'info_dict': {
108 'id': 'harkivyani-zgaduyut-misto-do-viyni-shhemlive-video_n1887584',
109 'title': 'Харків\'яни згадують місто до війни: щемливе відео'
110 },
111 'playlist': [{
112 'info_dict': {
113 'id': '1887584',
114 'ext': 'mp4',
115 'title': 'Харків\'яни згадують місто до війни: щемливе відео',
116 'thumbnail': r're:^https?://.*\.jpe?g',
117 },
118 }]
119 }, {
120 # 2 media_embeds with YouTube iframes
121 'url': 'https://24tv.ua/bronetransporteri-ozbroyenni-zsu-shho-vidomo-pro-bronovik-wolfhound_n2167966',
122 'info_dict': {
123 'id': 'bronetransporteri-ozbroyenni-zsu-shho-vidomo-pro-bronovik-wolfhound_n2167966',
124 'title': 'Броньовик Wolfhound: гігант, який допомагає ЗСУ знищувати окупантів на фронті',
125 },
126 'playlist_count': 2
127 }, {
128 'url': 'https://men.24tv.ua/fitnes-bloger-sprobuvav-vikonati-trenuvannya-naysilnishoyi-lyudini_n2164538',
129 'only_matching': True,
130 }]
131
132 def _real_extract(self, url):
133 display_id = self._match_id(url)
134 webpage = self._download_webpage(url, display_id)
135 data_urls = []
136 # The site contains escaped iframe embeds within an attribute.
137 # Once escaped, generic can handle them, so we use a data url to pass the escaped html back.
138 for html in get_elements_html_by_class('media_embed', webpage):
139 data = urllib.parse.unquote(extract_attributes(html).get('data-html'))
140 data_urls.append(f'data:text/html;base64,{base64.b64encode(data.encode("utf-8")).decode("utf-8")}')
141
142 if not data_urls:
143 return self.url_result(url, 'Generic')
144 return self.playlist_from_matches(
145 [smuggle_url(url, {'to_generic': True}) for url in data_urls], display_id, ie='Generic',
146 playlist_title=self._og_search_title(webpage) or self._html_extract_title(webpage))