]>
Raphaƫl G. Git Repositories - youtubedl/blob - youtube_dl/extractor/tvnow.py
2 from __future__
import unicode_literals
6 from .common
import InfoExtractor
7 from ..compat
import compat_str
18 class TVNowBaseIE(InfoExtractor
):
20 'id', 'title', 'free', 'geoblocked', 'articleLong', 'articleShort',
21 'broadcastStartDate', 'isDrm', 'duration', 'season', 'episode',
22 'manifest.dashclear', 'format.title', 'format.defaultImage169Format',
23 'format.defaultImage169Logo')
25 def _call_api(self
, path
, video_id
, query
):
26 return self
._download
_json
(
27 'https://api.tvnow.de/v3/' + path
,
28 video_id
, query
=query
)
30 def _extract_video(self
, info
, display_id
):
31 video_id
= compat_str(info
['id'])
34 mpd_url
= info
['manifest']['dashclear']
38 'Video %s is DRM protected' % video_id
, expected
=True)
39 if info
.get('geoblocked'):
41 'Video %s is not available from your location due to geo restriction' % video_id
,
43 if not info
.get('free', True):
45 'Video %s is not available for free' % video_id
, expected
=True)
47 mpd_url
= update_url_query(mpd_url
, {'filter': ''})
48 formats
= self
._extract
_mpd
_formats
(mpd_url
, video_id
, mpd_id
='dash', fatal
=False)
49 formats
.extend(self
._extract
_ism
_formats
(
50 mpd_url
.replace('dash.', 'hss.').replace('/.mpd', '/Manifest'),
51 video_id
, ism_id
='mss', fatal
=False))
52 formats
.extend(self
._extract
_m
3u8_formats
(
53 mpd_url
.replace('dash.', 'hls.').replace('/.mpd', '/.m3u8'),
54 video_id
, 'mp4', 'm3u8_native', m3u8_id
='hls', fatal
=False))
55 self
._sort
_formats
(formats
)
57 description
= info
.get('articleLong') or info
.get('articleShort')
58 timestamp
= parse_iso8601(info
.get('broadcastStartDate'), ' ')
59 duration
= parse_duration(info
.get('duration'))
61 f
= info
.get('format', {})
64 'url': 'https://aistvnow-a.akamaihd.net/tvnow/movie/%s' % video_id
,
66 thumbnail
= f
.get('defaultImage169Format') or f
.get('defaultImage169Logo')
74 'display_id': display_id
,
76 'description': description
,
77 'thumbnails': thumbnails
,
78 'timestamp': timestamp
,
80 'series': f
.get('title'),
81 'season_number': int_or_none(info
.get('season')),
82 'episode_number': int_or_none(info
.get('episode')),
88 class TVNowIE(TVNowBaseIE
):
91 (?:www\.)?tvnow\.(?:de|at|ch)/[^/]+/
93 (?!(?:list|jahr)(?:/|$))(?P<id>[^/?\#&]+)
97 'url': 'https://www.tvnow.de/rtl2/grip-das-motormagazin/der-neue-porsche-911-gt-3/player',
100 'display_id': 'grip-das-motormagazin/der-neue-porsche-911-gt-3',
102 'title': 'Der neue Porsche 911 GT 3',
103 'description': 'md5:6143220c661f9b0aae73b245e5d898bb',
104 'thumbnail': r
're:^https?://.*\.jpg$',
105 'timestamp': 1495994400,
106 'upload_date': '20170528',
108 'series': 'GRIP - Das Motormagazin',
110 'episode_number': 405,
111 'episode': 'Der neue Porsche 911 GT 3',
115 'url': 'https://www.tvnow.de/rtl2/armes-deutschland/episode-0008/player',
116 'only_matching': True,
119 'url': 'https://www.tvnow.de/nitro/alarm-fuer-cobra-11-die-autobahnpolizei/auf-eigene-faust-pilot/player',
120 'only_matching': True,
123 'url': 'https://www.tvnow.de/superrtl/die-lustigsten-schlamassel-der-welt/u-a-ketchup-effekt/player',
124 'only_matching': True,
127 'url': 'https://www.tvnow.de/ntv/startup-news/goetter-in-weiss/player',
128 'only_matching': True,
131 'url': 'https://www.tvnow.de/vox/auto-mobil/neues-vom-automobilmarkt-2017-11-19-17-00-00/player',
132 'only_matching': True,
135 'url': 'https://www.tvnow.de/rtlplus/op-ruft-dr-bruckner/die-vernaehte-frau/player',
136 'only_matching': True,
138 'url': 'https://www.tvnow.de/rtl2/grip-das-motormagazin/der-neue-porsche-911-gt-3',
139 'only_matching': True,
142 def _real_extract(self
, url
):
143 display_id
= '%s/%s' % re
.match(self
._VALID
_URL
, url
).groups()
145 info
= self
._call
_api
(
146 'movies/' + display_id
, display_id
, query
={
147 'fields': ','.join(self
._VIDEO
_FIELDS
),
150 return self
._extract
_video
(info
, display_id
)
153 class TVNowListBaseIE(TVNowBaseIE
):
154 _SHOW_VALID_URL
= r
'''(?x)
157 (?:www\.)?tvnow\.(?:de|at|ch)/[^/]+/
162 def _extract_list_info(self
, display_id
, show_id
):
163 fields
= list(self
._SHOW
_FIELDS
)
164 fields
.extend('formatTabs.%s' % field
for field
in self
._SEASON
_FIELDS
)
166 'formatTabs.formatTabPages.container.movies.%s' % field
167 for field
in self
._VIDEO
_FIELDS
)
168 return self
._call
_api
(
169 'formats/seo', display_id
, query
={
170 'fields': ','.join(fields
),
171 'name': show_id
+ '.php'
175 class TVNowListIE(TVNowListBaseIE
):
176 _VALID_URL
= r
'%s/(?:list|jahr)/(?P<id>[^?\#&]+)' % TVNowListBaseIE
._SHOW
_VALID
_URL
178 _SHOW_FIELDS
= ('title', )
179 _SEASON_FIELDS
= ('id', 'headline', 'seoheadline', )
180 _VIDEO_FIELDS
= ('id', 'headline', 'seoUrl', )
183 'url': 'https://www.tvnow.de/rtl/30-minuten-deutschland/list/aktuell',
186 'title': '30 Minuten Deutschland - Aktuell',
188 'playlist_mincount': 1,
190 'url': 'https://www.tvnow.de/vox/ab-ins-beet/list/staffel-14',
191 'only_matching': True,
193 'url': 'https://www.tvnow.de/rtl2/grip-das-motormagazin/jahr/2018/3',
194 'only_matching': True,
198 def suitable(cls
, url
):
199 return (False if TVNowIE
.suitable(url
)
200 else super(TVNowListIE
, cls
).suitable(url
))
202 def _real_extract(self
, url
):
203 base_url
, show_id
, season_id
= re
.match(self
._VALID
_URL
, url
).groups()
205 list_info
= self
._extract
_list
_info
(season_id
, show_id
)
208 season
for season
in list_info
['formatTabs']['items']
209 if season
.get('seoheadline') == season_id
)
211 title
= list_info
.get('title')
212 headline
= season
.get('headline')
213 if title
and headline
:
214 title
= '%s - %s' % (title
, headline
)
216 title
= headline
or title
219 for container
in season
['formatTabPages']['items']:
221 container
, lambda x
: x
['container']['movies']['items'],
224 seo_url
= info
.get('seoUrl')
227 video_id
= info
.get('id')
228 entries
.append(self
.url_result(
229 '%s/%s/player' % (base_url
, seo_url
), TVNowIE
.ie_key(),
230 compat_str(video_id
) if video_id
else None))
232 return self
.playlist_result(
233 entries
, compat_str(season
.get('id') or season_id
), title
)
236 class TVNowShowIE(TVNowListBaseIE
):
237 _VALID_URL
= TVNowListBaseIE
._SHOW
_VALID
_URL
239 _SHOW_FIELDS
= ('id', 'title', )
240 _SEASON_FIELDS
= ('id', 'headline', 'seoheadline', )
244 'url': 'https://www.tvnow.at/vox/ab-ins-beet',
247 'title': 'Ab ins Beet!',
249 'playlist_mincount': 7,
251 'url': 'https://www.tvnow.at/vox/ab-ins-beet/list',
252 'only_matching': True,
254 'url': 'https://www.tvnow.de/rtl2/grip-das-motormagazin/jahr/',
255 'only_matching': True,
259 def suitable(cls
, url
):
260 return (False if TVNowIE
.suitable(url
) or TVNowListIE
.suitable(url
)
261 else super(TVNowShowIE
, cls
).suitable(url
))
263 def _real_extract(self
, url
):
264 base_url
, show_id
= re
.match(self
._VALID
_URL
, url
).groups()
266 list_info
= self
._extract
_list
_info
(show_id
, show_id
)
269 for season_info
in list_info
['formatTabs']['items']:
270 season_url
= season_info
.get('seoheadline')
273 season_id
= season_info
.get('id')
274 entries
.append(self
.url_result(
275 '%s/list/%s' % (base_url
, season_url
), TVNowListIE
.ie_key(),
276 compat_str(season_id
) if season_id
else None,
277 season_info
.get('headline')))
279 return self
.playlist_result(entries
, show_id
, list_info
.get('title'))