]>
Commit | Line | Data |
---|---|---|
d5822b96 | 1 | import re |
75c94812 | 2 | import json |
d5822b96 PH |
3 | |
4 | from .common import InfoExtractor | |
5 | from ..utils import ( | |
75c94812 | 6 | # This is used by the not implemented extractLiveStream method |
d5822b96 | 7 | compat_urllib_parse, |
d5822b96 PH |
8 | |
9 | ExtractorError, | |
10 | unified_strdate, | |
11 | ) | |
12 | ||
13 | class ArteTvIE(InfoExtractor): | |
37b6a661 JMF |
14 | """ |
15 | There are two sources of video in arte.tv: videos.arte.tv and | |
16 | www.arte.tv/guide, the extraction process is different for each one. | |
17 | The videos expire in 7 days, so we can't add tests. | |
18 | """ | |
19 | _EMISSION_URL = r'(?:http://)?www\.arte.tv/guide/(?:fr|de)/(?:(?:sendungen|emissions)/)?(?P<id>.*?)/(?P<name>.*?)(\?.*)?' | |
20 | _VIDEOS_URL = r'(?:http://)?videos.arte.tv/(?:fr|de)/.*-(?P<id>.*?).html' | |
d5822b96 PH |
21 | _LIVE_URL = r'index-[0-9]+\.html$' |
22 | ||
23 | IE_NAME = u'arte.tv' | |
24 | ||
37b6a661 JMF |
25 | @classmethod |
26 | def suitable(cls, url): | |
27 | return any(re.match(regex, url) for regex in (cls._EMISSION_URL, cls._VIDEOS_URL)) | |
28 | ||
9b3a760b PH |
29 | # TODO implement Live Stream |
30 | # def extractLiveStream(self, url): | |
31 | # video_lang = url.split('/')[-4] | |
32 | # info = self.grep_webpage( | |
33 | # url, | |
34 | # r'src="(.*?/videothek_js.*?\.js)', | |
35 | # 0, | |
36 | # [ | |
37 | # (1, 'url', u'Invalid URL: %s' % url) | |
38 | # ] | |
39 | # ) | |
40 | # http_host = url.split('/')[2] | |
41 | # next_url = 'http://%s%s' % (http_host, compat_urllib_parse.unquote(info.get('url'))) | |
42 | # info = self.grep_webpage( | |
43 | # next_url, | |
44 | # r'(s_artestras_scst_geoFRDE_' + video_lang + '.*?)\'.*?' + | |
45 | # '(http://.*?\.swf).*?' + | |
46 | # '(rtmp://.*?)\'', | |
47 | # re.DOTALL, | |
48 | # [ | |
49 | # (1, 'path', u'could not extract video path: %s' % url), | |
50 | # (2, 'player', u'could not extract video player: %s' % url), | |
51 | # (3, 'url', u'could not extract video url: %s' % url) | |
52 | # ] | |
53 | # ) | |
54 | # video_url = u'%s/%s' % (info.get('url'), info.get('path')) | |
d5822b96 | 55 | |
d5822b96 | 56 | def _real_extract(self, url): |
37b6a661 JMF |
57 | mobj = re.match(self._EMISSION_URL, url) |
58 | if mobj is not None: | |
59 | name = mobj.group('name') | |
60 | # This is not a real id, it can be for example AJT for the news | |
61 | # http://www.arte.tv/guide/fr/emissions/AJT/arte-journal | |
62 | video_id = mobj.group('id') | |
63 | return self._extract_emission(url, video_id) | |
64 | ||
65 | mobj = re.match(self._VIDEOS_URL, url) | |
66 | if mobj is not None: | |
67 | id = mobj.group('id') | |
68 | return self._extract_video(url, id) | |
d5822b96 PH |
69 | |
70 | if re.search(self._LIVE_URL, video_id) is not None: | |
9b3a760b PH |
71 | raise ExtractorError(u'Arte live streams are not yet supported, sorry') |
72 | # self.extractLiveStream(url) | |
73 | # return | |
75c94812 | 74 | |
37b6a661 JMF |
75 | def _extract_emission(self, url, video_id): |
76 | """Extract from www.arte.tv/guide""" | |
75c94812 JMF |
77 | webpage = self._download_webpage(url, video_id) |
78 | json_url = self._html_search_regex(r'arte_vp_url="(.*?)"', webpage, 'json url') | |
79 | ||
80 | json_info = self._download_webpage(json_url, video_id, 'Downloading info json') | |
81 | self.report_extraction(video_id) | |
82 | info = json.loads(json_info) | |
83 | player_info = info['videoJsonPlayer'] | |
84 | ||
85 | info_dict = {'id': player_info['VID'], | |
86 | 'title': player_info['VTI'], | |
87 | 'description': player_info['VDE'], | |
88 | 'upload_date': unified_strdate(player_info['VDA'].split(' ')[0]), | |
89 | 'thumbnail': player_info['programImage'], | |
37b6a661 | 90 | 'ext': 'flv', |
75c94812 JMF |
91 | } |
92 | ||
93 | formats = player_info['VSR'].values() | |
94 | # We order the formats by quality | |
95 | formats = sorted(formats, key=lambda f: int(f['height'])) | |
96 | # Pick the best quality | |
97 | format_info = formats[-1] | |
98 | if format_info['mediaType'] == u'rtmp': | |
99 | info_dict['url'] = format_info['streamer'] | |
100 | info_dict['play_path'] = 'mp4:' + format_info['url'] | |
d5822b96 | 101 | else: |
75c94812 | 102 | info_dict['url'] = format_info['url'] |
d5822b96 | 103 | |
75c94812 | 104 | return info_dict |
37b6a661 JMF |
105 | |
106 | def _extract_video(self, url, video_id): | |
107 | """Extract from videos.arte.tv""" | |
108 | config_xml_url = url.replace('/videos/', '/do_delegate/videos/') | |
109 | config_xml_url = config_xml_url.replace('.html', ',view,asPlayerXml.xml') | |
110 | config_xml = self._download_webpage(config_xml_url, video_id) | |
111 | config_xml_url = self._html_search_regex(r'<video lang=".*?" ref="(.*?)"', config_xml, 'config xml url') | |
112 | config_xml = self._download_webpage(config_xml_url, video_id) | |
113 | ||
114 | video_urls = list(re.finditer(r'<url quality="(?P<quality>.*?)">(?P<url>.*?)</url>', config_xml)) | |
115 | def _key(m): | |
116 | quality = m.group('quality') | |
117 | if quality == 'hd': | |
118 | return 2 | |
119 | else: | |
120 | return 1 | |
121 | # We pick the best quality | |
122 | video_urls = sorted(video_urls, key=_key) | |
123 | video_url = list(video_urls)[-1].group('url') | |
124 | ||
125 | title = self._html_search_regex(r'<name>(.*?)</name>', config_xml, 'title') | |
126 | thumbnail = self._html_search_regex(r'<firstThumbnailUrl>(.*?)</firstThumbnailUrl>', | |
127 | config_xml, 'thumbnail') | |
128 | return {'id': video_id, | |
129 | 'title': title, | |
130 | 'thumbnail': thumbnail, | |
131 | 'url': video_url, | |
132 | 'ext': 'flv', | |
133 | } |