[mediaset] Fix issues and extract all formats (closes #16568)
[youtube-dl] / youtube_dl / extractor / mediaset.py
1 # coding: utf-8
2 from __future__ import unicode_literals
3
4 import re
5
6 from .common import InfoExtractor
7 from ..compat import compat_str
8 from ..utils import (
9     determine_ext,
10     parse_duration,
11     try_get,
12     unified_strdate,
13 )
14
15
16 class MediasetIE(InfoExtractor):
17     _VALID_URL = r'''(?x)
18                     (?:
19                         mediaset:|
20                         https?://
21                             (?:www\.)?video\.mediaset\.it/
22                             (?:
23                                 (?:video|on-demand)/(?:[^/]+/)+[^/]+_|
24                                 player/playerIFrame(?:Twitter)?\.shtml\?.*?\bid=
25                             )
26                     )(?P<id>[0-9]+)
27                     '''
28     _TESTS = [{
29         # full episode
30         'url': 'http://www.video.mediaset.it/video/hello_goodbye/full/quarta-puntata_661824.html',
31         'md5': '9b75534d42c44ecef7bf1ffeacb7f85d',
32         'info_dict': {
33             'id': '661824',
34             'ext': 'mp4',
35             'title': 'Quarta puntata',
36             'description': 'md5:7183696d6df570e3412a5ef74b27c5e2',
37             'thumbnail': r're:^https?://.*\.jpg$',
38             'duration': 1414,
39             'creator': 'mediaset',
40             'upload_date': '20161107',
41             'series': 'Hello Goodbye',
42             'categories': ['reality'],
43         },
44         'expected_warnings': ['is not a supported codec'],
45     }, {
46         'url': 'http://www.video.mediaset.it/video/matrix/full_chiambretti/puntata-del-25-maggio_846685.html',
47         'md5': '1276f966ac423d16ba255ce867de073e',
48         'info_dict': {
49             'id': '846685',
50             'ext': 'mp4',
51             'title': 'Puntata del 25 maggio',
52             'description': 'md5:ee2e456e3eb1dba5e814596655bb5296',
53             'thumbnail': r're:^https?://.*\.jpg$',
54             'duration': 6565,
55             'creator': 'mediaset',
56             'upload_date': '20180525',
57             'series': 'Matrix',
58             'categories': ['infotainment'],
59         },
60         'expected_warnings': ['HTTP Error 403: Forbidden'],
61     }, {
62         # clip
63         'url': 'http://www.video.mediaset.it/video/gogglebox/clip/un-grande-classico-della-commedia-sexy_661680.html',
64         'only_matching': True,
65     }, {
66         # iframe simple
67         'url': 'http://www.video.mediaset.it/player/playerIFrame.shtml?id=665924&autoplay=true',
68         'only_matching': True,
69     }, {
70         # iframe twitter (from http://www.wittytv.it/se-prima-mi-fidavo-zero/)
71         'url': 'https://www.video.mediaset.it/player/playerIFrameTwitter.shtml?id=665104&playrelated=false&autoplay=false&related=true&hidesocial=true',
72         'only_matching': True,
73     }, {
74         'url': 'mediaset:661824',
75         'only_matching': True,
76     }]
77
78     @staticmethod
79     def _extract_urls(webpage):
80         return [
81             mobj.group('url')
82             for mobj in re.finditer(
83                 r'<iframe\b[^>]+\bsrc=(["\'])(?P<url>https?://(?:www\.)?video\.mediaset\.it/player/playerIFrame(?:Twitter)?\.shtml\?.*?\bid=\d+.*?)\1',
84                 webpage)]
85
86     def _real_extract(self, url):
87         video_id = self._match_id(url)
88
89         video = self._download_json(
90             'https://www.video.mediaset.it/html/metainfo.sjson',
91             video_id, 'Downloading media info', query={
92                 'id': video_id
93             })['video']
94
95         title = video['title']
96         media_id = video.get('guid') or video_id
97
98         video_list = self._download_json(
99             'http://cdnsel01.mediaset.net/GetCdn2018.aspx',
100             video_id, 'Downloading video CDN JSON', query={
101                 'streamid': media_id,
102                 'format': 'json',
103             })['videoList']
104
105         formats = []
106         for format_url in video_list:
107             ext = determine_ext(format_url)
108             if ext == 'm3u8':
109                 formats.extend(self._extract_m3u8_formats(
110                     format_url, video_id, 'mp4', entry_protocol='m3u8_native',
111                     m3u8_id='hls', fatal=False))
112             elif ext == 'mpd':
113                 formats.extend(self._extract_mpd_formats(
114                     format_url, video_id, mpd_id='dash', fatal=False))
115             elif ext == 'ism' or '.ism' in format_url:
116                 formats.extend(self._extract_ism_formats(
117                     format_url, video_id, ism_id='mss', fatal=False))
118             else:
119                 formats.append({
120                     'url': format_url,
121                     'format_id': determine_ext(format_url),
122                 })
123         self._sort_formats(formats)
124
125         creator = try_get(
126             video, lambda x: x['brand-info']['publisher'], compat_str)
127         category = try_get(
128             video, lambda x: x['brand-info']['category'], compat_str)
129         categories = [category] if category else None
130
131         return {
132             'id': video_id,
133             'title': title,
134             'description': video.get('short-description'),
135             'thumbnail': video.get('thumbnail'),
136             'duration': parse_duration(video.get('duration')),
137             'creator': creator,
138             'upload_date': unified_strdate(video.get('production-date')),
139             'webpage_url': video.get('url'),
140             'series': video.get('brand-value'),
141             'season': video.get('season'),
142             'categories': categories,
143             'formats': formats,
144         }