2016-10-02 04:39:18 -07:00
# coding: utf-8
2014-01-29 21:13:57 -08:00
from __future__ import unicode_literals
2013-09-08 12:55:11 -07:00
import re
from . common import InfoExtractor
2018-02-11 05:03:31 -08:00
from . . compat import (
compat_str ,
compat_urlparse ,
)
2014-12-13 03:24:42 -08:00
from . . utils import (
2014-09-16 09:47:59 -07:00
clean_html ,
2018-02-11 06:58:04 -08:00
determine_ext ,
2014-12-13 03:24:42 -08:00
ExtractorError ,
2014-09-16 09:47:59 -07:00
int_or_none ,
2014-12-13 03:24:42 -08:00
parse_duration ,
2018-02-11 06:58:04 -08:00
try_get ,
2018-07-21 05:08:28 -07:00
url_or_none ,
2013-09-08 12:55:11 -07:00
)
2017-12-06 01:54:20 -08:00
from . dailymotion import DailymotionIE
2013-09-08 12:55:11 -07:00
2013-09-10 06:50:34 -07:00
class FranceTVBaseInfoExtractor ( InfoExtractor ) :
2018-02-11 06:40:38 -08:00
def _make_url_result ( self , video_or_full_id , catalog = None ) :
full_id = ' francetv: %s ' % video_or_full_id
if ' @ ' not in video_or_full_id and catalog :
2018-02-11 06:14:05 -08:00
full_id + = ' @ %s ' % catalog
return self . url_result (
2018-02-11 06:40:38 -08:00
full_id , ie = FranceTVIE . ie_key ( ) ,
video_id = video_or_full_id . split ( ' @ ' ) [ 0 ] )
2018-02-11 06:14:05 -08:00
class FranceTVIE ( InfoExtractor ) :
_VALID_URL = r ''' (?x)
( ? :
https ? : / /
sivideo \. webservices \. francetelevisions \. fr / tools / getInfosOeuvre / v2 / \?
. * ? \bidDiffusion = [ ^ & ] + |
( ? :
https ? : / / videos \. francetv \. fr / video / |
francetv :
)
( ? P < id > [ ^ @ ] + ) ( ? : @ ( ? P < catalog > . + ) ) ?
)
'''
_TESTS = [ {
# without catalog
' url ' : ' https://sivideo.webservices.francetelevisions.fr/tools/getInfosOeuvre/v2/?idDiffusion=162311093&callback=_jsonp_loader_callback_request_0 ' ,
' md5 ' : ' c2248a8de38c4e65ea8fae7b5df2d84f ' ,
' info_dict ' : {
' id ' : ' 162311093 ' ,
' ext ' : ' mp4 ' ,
' title ' : ' 13h15, le dimanche... - Les mystères de Jésus ' ,
' description ' : ' md5:75efe8d4c0a8205e5904498ffe1e1a42 ' ,
' timestamp ' : 1502623500 ,
' upload_date ' : ' 20170813 ' ,
} ,
} , {
# with catalog
' url ' : ' https://sivideo.webservices.francetelevisions.fr/tools/getInfosOeuvre/v2/?idDiffusion=NI_1004933&catalogue=Zouzous&callback=_jsonp_loader_callback_request_4 ' ,
' only_matching ' : True ,
} , {
' url ' : ' http://videos.francetv.fr/video/NI_657393@Regions ' ,
' only_matching ' : True ,
} , {
' url ' : ' francetv:162311093 ' ,
' only_matching ' : True ,
} , {
' url ' : ' francetv:NI_1004933@Zouzous ' ,
' only_matching ' : True ,
} , {
' url ' : ' francetv:NI_983319@Info-web ' ,
' only_matching ' : True ,
} , {
' url ' : ' francetv:NI_983319 ' ,
' only_matching ' : True ,
} , {
' url ' : ' francetv:NI_657393@Regions ' ,
' only_matching ' : True ,
2018-02-11 06:58:04 -08:00
} , {
# france-3 live
' url ' : ' francetv:SIM_France3 ' ,
' only_matching ' : True ,
2018-02-11 06:14:05 -08:00
} ]
2017-05-09 09:07:01 -07:00
def _extract_video ( self , video_id , catalogue = None ) :
2018-02-11 06:14:05 -08:00
# Videos are identified by idDiffusion so catalogue part is optional.
# However when provided, some extra formats may be returned so we pass
# it if available.
2014-09-16 09:47:59 -07:00
info = self . _download_json (
2017-05-09 09:07:01 -07:00
' https://sivideo.webservices.francetelevisions.fr/tools/getInfosOeuvre/v2/ ' ,
video_id , ' Downloading video JSON ' , query = {
' idDiffusion ' : video_id ,
' catalogue ' : catalogue or ' ' ,
} )
2014-09-16 09:47:59 -07:00
if info . get ( ' status ' ) == ' NOK ' :
raise ExtractorError (
2018-02-11 05:03:31 -08:00
' %s returned error: %s ' % ( self . IE_NAME , info [ ' message ' ] ) ,
expected = True )
2014-11-24 10:37:20 -08:00
allowed_countries = info [ ' videos ' ] [ 0 ] . get ( ' geoblocage ' )
if allowed_countries :
georestricted = True
geo_info = self . _download_json (
' http://geo.francetv.fr/ws/edgescape.json ' , video_id ,
' Downloading geo restriction info ' )
country = geo_info [ ' reponse ' ] [ ' geo_info ' ] [ ' country_code ' ]
if country not in allowed_countries :
raise ExtractorError (
' The video is not available from your location ' ,
expected = True )
else :
georestricted = False
2018-02-11 05:03:31 -08:00
def sign ( manifest_url , manifest_id ) :
for host in ( ' hdfauthftv-a.akamaihd.net ' , ' hdfauth.francetv.fr ' ) :
2018-07-21 05:08:28 -07:00
signed_url = url_or_none ( self . _download_webpage (
2018-02-11 05:03:31 -08:00
' https:// %s /esi/TA ' % host , video_id ,
' Downloading signed %s manifest URL ' % manifest_id ,
fatal = False , query = {
' url ' : manifest_url ,
2018-07-21 05:08:28 -07:00
} ) )
if signed_url :
2018-02-11 05:03:31 -08:00
return signed_url
return manifest_url
2018-02-11 06:58:04 -08:00
is_live = None
2014-09-16 09:47:59 -07:00
formats = [ ]
for video in info [ ' videos ' ] :
if video [ ' statut ' ] != ' ONLINE ' :
continue
video_url = video [ ' url ' ]
if not video_url :
continue
2018-02-11 06:58:04 -08:00
if is_live is None :
is_live = ( try_get (
video , lambda x : x [ ' plages_ouverture ' ] [ 0 ] [ ' direct ' ] ,
bool ) is True ) or ' /live.francetv.fr/ ' in video_url
2014-09-16 09:47:59 -07:00
format_id = video [ ' format ' ]
2015-04-04 10:02:04 -07:00
ext = determine_ext ( video_url )
if ext == ' f4m ' :
2014-11-24 10:37:20 -08:00
if georestricted :
# See https://github.com/rg3/youtube-dl/issues/3963
# m3u8 urls work fine
continue
2018-02-11 05:03:31 -08:00
formats . extend ( self . _extract_f4m_formats (
sign ( video_url , format_id ) + ' &hdcore=3.7.0&plugin=aasp-3.7.0.39.44 ' ,
video_id , f4m_id = format_id , fatal = False ) )
2015-04-04 10:02:04 -07:00
elif ext == ' m3u8 ' :
2018-02-11 05:03:31 -08:00
formats . extend ( self . _extract_m3u8_formats (
sign ( video_url , format_id ) , video_id , ' mp4 ' ,
entry_protocol = ' m3u8_native ' , m3u8_id = format_id ,
fatal = False ) )
2014-09-16 09:47:59 -07:00
elif video_url . startswith ( ' rtmp ' ) :
formats . append ( {
' url ' : video_url ,
' format_id ' : ' rtmp- %s ' % format_id ,
' ext ' : ' flv ' ,
} )
else :
2016-03-20 00:00:46 -07:00
if self . _is_valid_url ( video_url , video_id , format_id ) :
formats . append ( {
' url ' : video_url ,
' format_id ' : format_id ,
} )
2014-09-16 09:47:59 -07:00
self . _sort_formats ( formats )
2013-09-10 06:50:34 -07:00
2015-09-01 09:37:42 -07:00
title = info [ ' titre ' ]
subtitle = info . get ( ' sous_titre ' )
if subtitle :
title + = ' - %s ' % subtitle
2016-03-19 23:44:04 -07:00
title = title . strip ( )
2015-09-01 09:37:42 -07:00
2015-10-26 07:11:09 -07:00
subtitles = { }
2015-10-26 07:35:28 -07:00
subtitles_list = [ {
2015-10-28 00:22:04 -07:00
' url ' : subformat [ ' url ' ] ,
' ext ' : subformat . get ( ' format ' ) ,
} for subformat in info . get ( ' subtitles ' , [ ] ) if subformat . get ( ' url ' ) ]
2015-10-26 07:35:28 -07:00
if subtitles_list :
subtitles [ ' fr ' ] = subtitles_list
2015-10-26 07:11:09 -07:00
2014-07-28 05:37:13 -07:00
return {
' id ' : video_id ,
2018-02-11 06:58:04 -08:00
' title ' : self . _live_title ( title ) if is_live else title ,
2014-09-16 09:47:59 -07:00
' description ' : clean_html ( info [ ' synopsis ' ] ) ,
' thumbnail ' : compat_urlparse . urljoin ( ' http://pluzz.francetv.fr ' , info [ ' image ' ] ) ,
2015-07-18 09:43:42 -07:00
' duration ' : int_or_none ( info . get ( ' real_duration ' ) ) or parse_duration ( info [ ' duree ' ] ) ,
2014-09-16 09:47:59 -07:00
' timestamp ' : int_or_none ( info [ ' diffusion ' ] [ ' timestamp ' ] ) ,
2018-02-11 06:58:04 -08:00
' is_live ' : is_live ,
2014-07-28 05:37:13 -07:00
' formats ' : formats ,
2015-10-26 07:11:09 -07:00
' subtitles ' : subtitles ,
2014-07-28 05:37:13 -07:00
}
2013-09-10 06:50:34 -07:00
2018-02-11 06:14:05 -08:00
def _real_extract ( self , url ) :
mobj = re . match ( self . _VALID_URL , url )
video_id = mobj . group ( ' id ' )
catalog = mobj . group ( ' catalog ' )
if not video_id :
qs = compat_urlparse . parse_qs ( compat_urlparse . urlparse ( url ) . query )
video_id = qs . get ( ' idDiffusion ' , [ None ] ) [ 0 ]
catalog = qs . get ( ' catalogue ' , [ None ] ) [ 0 ]
if not video_id :
raise ExtractorError ( ' Invalid URL ' , expected = True )
return self . _extract_video ( video_id , catalog )
2013-09-10 06:50:34 -07:00
2018-02-11 06:14:05 -08:00
class FranceTVSiteIE ( FranceTVBaseInfoExtractor ) :
2017-05-31 10:15:15 -07:00
_VALID_URL = r ' https?://(?:(?:www \ .)?france \ .tv|mobile \ .france \ .tv)/(?:[^/]+/)*(?P<id>[^/]+) \ .html '
2013-09-08 12:55:11 -07:00
2017-05-09 09:07:01 -07:00
_TESTS = [ {
' url ' : ' https://www.france.tv/france-2/13h15-le-dimanche/140921-les-mysteres-de-jesus.html ' ,
' info_dict ' : {
2018-02-11 06:14:05 -08:00
' id ' : ' 162311093 ' ,
2017-05-09 09:07:01 -07:00
' ext ' : ' mp4 ' ,
' title ' : ' 13h15, le dimanche... - Les mystères de Jésus ' ,
' description ' : ' md5:75efe8d4c0a8205e5904498ffe1e1a42 ' ,
2018-02-11 06:14:05 -08:00
' timestamp ' : 1502623500 ,
' upload_date ' : ' 20170813 ' ,
2017-05-09 09:07:01 -07:00
} ,
' params ' : {
' skip_download ' : True ,
} ,
2018-02-11 06:14:05 -08:00
' add_ie ' : [ FranceTVIE . ie_key ( ) ] ,
2017-05-09 09:07:01 -07:00
} , {
# france3
' url ' : ' https://www.france.tv/france-3/des-chiffres-et-des-lettres/139063-emission-du-mardi-9-mai-2017.html ' ,
' only_matching ' : True ,
} , {
# france4
' url ' : ' https://www.france.tv/france-4/hero-corp/saison-1/134151-apres-le-calme.html ' ,
' only_matching ' : True ,
} , {
# france5
' url ' : ' https://www.france.tv/france-5/c-a-dire/saison-10/137013-c-a-dire.html ' ,
' only_matching ' : True ,
} , {
# franceo
' url ' : ' https://www.france.tv/france-o/archipels/132249-mon-ancetre-l-esclave.html ' ,
' only_matching ' : True ,
} , {
# france2 live
' url ' : ' https://www.france.tv/france-2/direct.html ' ,
' only_matching ' : True ,
} , {
' url ' : ' https://www.france.tv/documentaires/histoire/136517-argentine-les-500-bebes-voles-de-la-dictature.html ' ,
' only_matching ' : True ,
} , {
' url ' : ' https://www.france.tv/jeux-et-divertissements/divertissements/133965-le-web-contre-attaque.html ' ,
' only_matching ' : True ,
2017-05-13 07:57:00 -07:00
} , {
' url ' : ' https://mobile.france.tv/france-5/c-dans-l-air/137347-emission-du-vendredi-12-mai-2017.html ' ,
' only_matching ' : True ,
2017-05-31 10:15:15 -07:00
} , {
' url ' : ' https://www.france.tv/142749-rouge-sang.html ' ,
' only_matching ' : True ,
2018-02-11 09:25:42 -08:00
} , {
# france-3 live
' url ' : ' https://www.france.tv/france-3/direct.html ' ,
' only_matching ' : True ,
2017-05-09 09:07:01 -07:00
} ]
2013-09-08 12:55:11 -07:00
def _real_extract ( self , url ) :
2015-10-27 08:43:29 -07:00
display_id = self . _match_id ( url )
webpage = self . _download_webpage ( url , display_id )
2017-05-09 09:07:01 -07:00
catalogue = None
video_id = self . _search_regex (
r ' data-main-video=([ " \' ])(?P<id>(?:(?! \ 1).)+) \ 1 ' ,
webpage , ' video id ' , default = None , group = ' id ' )
2015-10-27 08:43:29 -07:00
if not video_id :
2017-05-09 09:07:01 -07:00
video_id , catalogue = self . _html_search_regex (
r ' (?:href=|player \ .setVideo \ ( \ s*) " http://videos? \ .francetv \ .fr/video/([^@]+@[^ " ]+) " ' ,
webpage , ' video ID ' ) . split ( ' @ ' )
2018-02-11 06:14:05 -08:00
return self . _make_url_result ( video_id , catalogue )
2017-05-09 09:07:01 -07:00
class FranceTVEmbedIE ( FranceTVBaseInfoExtractor ) :
_VALID_URL = r ' https?://embed \ .francetv \ .fr/* \ ?.*? \ bue=(?P<id>[^&]+) '
2018-02-11 06:14:05 -08:00
_TESTS = [ {
2017-05-09 09:07:01 -07:00
' url ' : ' http://embed.francetv.fr/?ue=7fd581a2ccf59d2fc5719c5c13cf6961 ' ,
' info_dict ' : {
' id ' : ' NI_983319 ' ,
' ext ' : ' mp4 ' ,
' title ' : ' Le Pen Reims ' ,
' upload_date ' : ' 20170505 ' ,
' timestamp ' : 1493981780 ,
' duration ' : 16 ,
} ,
2018-02-11 06:14:05 -08:00
' params ' : {
' skip_download ' : True ,
} ,
' add_ie ' : [ FranceTVIE . ie_key ( ) ] ,
} ]
2015-10-27 08:43:29 -07:00
2017-05-09 09:07:01 -07:00
def _real_extract ( self , url ) :
video_id = self . _match_id ( url )
video = self . _download_json (
' http://api-embed.webservices.francetelevisions.fr/key/ %s ' % video_id ,
video_id )
2013-09-08 12:55:11 -07:00
2018-02-11 06:14:05 -08:00
return self . _make_url_result ( video [ ' video_id ' ] , video . get ( ' catalog ' ) )
2013-09-08 12:55:11 -07:00
2017-05-09 09:07:01 -07:00
class FranceTVInfoIE ( FranceTVBaseInfoExtractor ) :
2014-01-29 21:13:57 -08:00
IE_NAME = ' francetvinfo.fr '
2018-02-11 06:14:05 -08:00
_VALID_URL = r ' https?://(?:www|mobile|france3-regions) \ .francetvinfo \ .fr/(?:[^/]+/)*(?P<id>[^/?#&.]+) '
2013-09-08 12:55:11 -07:00
2014-05-16 06:51:01 -07:00
_TESTS = [ {
2014-01-29 21:13:57 -08:00
' url ' : ' http://www.francetvinfo.fr/replay-jt/france-3/soir-3/jt-grand-soir-3-lundi-26-aout-2013_393427.html ' ,
' info_dict ' : {
2014-05-16 06:51:01 -07:00
' id ' : ' 84981923 ' ,
2016-03-20 00:00:46 -07:00
' ext ' : ' mp4 ' ,
2014-01-29 21:13:57 -08:00
' title ' : ' Soir 3 ' ,
2014-09-16 09:47:59 -07:00
' upload_date ' : ' 20130826 ' ,
' timestamp ' : 1377548400 ,
2015-10-26 07:35:45 -07:00
' subtitles ' : {
' fr ' : ' mincount:2 ' ,
} ,
2013-09-10 06:50:34 -07:00
} ,
2016-03-20 00:00:46 -07:00
' params ' : {
' skip_download ' : True ,
} ,
2018-02-11 06:14:05 -08:00
' add_ie ' : [ FranceTVIE . ie_key ( ) ] ,
2014-05-16 06:51:01 -07:00
} , {
' url ' : ' http://www.francetvinfo.fr/elections/europeennes/direct-europeennes-regardez-le-debat-entre-les-candidats-a-la-presidence-de-la-commission_600639.html ' ,
2018-02-11 06:14:05 -08:00
' only_matching ' : True ,
2015-06-21 06:31:33 -07:00
} , {
' url ' : ' http://www.francetvinfo.fr/economie/entreprises/les-entreprises-familiales-le-secret-de-la-reussite_933271.html ' ,
2018-02-11 06:14:05 -08:00
' only_matching ' : True ,
2016-03-19 23:44:04 -07:00
} , {
' url ' : ' http://france3-regions.francetvinfo.fr/bretagne/cotes-d-armor/thalassa-echappee-breizh-ce-venredi-dans-les-cotes-d-armor-954961.html ' ,
2018-02-11 06:14:05 -08:00
' only_matching ' : True ,
2016-07-06 08:37:54 -07:00
} , {
# Dailymotion embed
' url ' : ' http://www.francetvinfo.fr/politique/notre-dame-des-landes/video-sur-france-inter-cecile-duflot-denonce-le-regard-meprisant-de-patrick-cohen_1520091.html ' ,
' md5 ' : ' ee7f1828f25a648addc90cb2687b1f12 ' ,
' info_dict ' : {
' id ' : ' x4iiko0 ' ,
' ext ' : ' mp4 ' ,
' title ' : ' NDDL, référendum, Brexit : Cécile Duflot répond à Patrick Cohen ' ,
' description ' : ' Au lendemain de la victoire du " oui " au référendum sur l \' aéroport de Notre-Dame-des-Landes, l \' ancienne ministre écologiste est l \' invitée de Patrick Cohen. Plus d \' info : https://www.franceinter.fr/emissions/le-7-9/le-7-9-27-juin-2016 ' ,
' timestamp ' : 1467011958 ,
' upload_date ' : ' 20160627 ' ,
' uploader ' : ' France Inter ' ,
' uploader_id ' : ' x2q2ez ' ,
} ,
' add_ie ' : [ ' Dailymotion ' ] ,
2016-08-11 07:42:55 -07:00
} , {
' url ' : ' http://france3-regions.francetvinfo.fr/limousin/emissions/jt-1213-limousin ' ,
' only_matching ' : True ,
2014-05-16 06:51:01 -07:00
} ]
2013-09-10 06:50:34 -07:00
def _real_extract ( self , url ) :
2018-02-11 06:14:05 -08:00
display_id = self . _match_id ( url )
webpage = self . _download_webpage ( url , display_id )
2015-06-21 06:31:33 -07:00
2016-07-06 08:37:54 -07:00
dailymotion_urls = DailymotionIE . _extract_urls ( webpage )
if dailymotion_urls :
return self . playlist_result ( [
self . url_result ( dailymotion_url , DailymotionIE . ie_key ( ) )
for dailymotion_url in dailymotion_urls ] )
2015-06-21 06:31:33 -07:00
2014-09-16 09:47:59 -07:00
video_id , catalogue = self . _search_regex (
2016-03-19 23:44:04 -07:00
( r ' id-video=([^@]+@[^ " ]+) ' ,
r ' <a[^>]+href= " (?:https?:)?//videos \ .francetv \ .fr/video/([^@]+@[^ " ]+) " ' ) ,
webpage , ' video id ' ) . split ( ' @ ' )
2018-02-11 06:14:05 -08:00
return self . _make_url_result ( video_id , catalogue )
2013-09-23 12:28:33 -07:00
2018-05-31 03:40:37 -07:00
class FranceTVInfoSportIE ( FranceTVBaseInfoExtractor ) :
IE_NAME = ' sport.francetvinfo.fr '
_VALID_URL = r ' https?://sport \ .francetvinfo \ .fr/(?:[^/]+/)*(?P<id>[^/?#&]+) '
_TESTS = [ {
' url ' : ' https://sport.francetvinfo.fr/les-jeux-olympiques/retour-sur-les-meilleurs-moments-de-pyeongchang-2018 ' ,
' info_dict ' : {
' id ' : ' 6e49080e-3f45-11e8-b459-000d3a2439ea ' ,
' ext ' : ' mp4 ' ,
' title ' : ' Retour sur les meilleurs moments de Pyeongchang 2018 ' ,
' timestamp ' : 1523639962 ,
' upload_date ' : ' 20180413 ' ,
} ,
' params ' : {
' skip_download ' : True ,
} ,
' add_ie ' : [ FranceTVIE . ie_key ( ) ] ,
} ]
def _real_extract ( self , url ) :
display_id = self . _match_id ( url )
webpage = self . _download_webpage ( url , display_id )
video_id = self . _search_regex ( r ' data-video= " ([^ " ]+) " ' , webpage , ' video_id ' )
return self . _make_url_result ( video_id , ' Sport-web ' )
2017-11-25 06:49:49 -08:00
class GenerationWhatIE ( InfoExtractor ) :
IE_NAME = ' france2.fr:generation-what '
2018-02-11 06:14:05 -08:00
_VALID_URL = r ' https?://generation-what \ .francetv \ .fr/[^/]+/video/(?P<id>[^/?#&]+) '
2013-09-23 12:41:54 -07:00
2017-11-25 06:49:49 -08:00
_TESTS = [ {
' url ' : ' http://generation-what.francetv.fr/portrait/video/present-arms ' ,
2014-01-29 21:13:57 -08:00
' info_dict ' : {
2017-11-25 06:49:49 -08:00
' id ' : ' wtvKYUG45iw ' ,
2015-02-01 06:06:55 -08:00
' ext ' : ' mp4 ' ,
2017-11-25 06:49:49 -08:00
' title ' : ' Generation What - Garde à vous - FRA ' ,
' uploader ' : ' Generation What ' ,
' uploader_id ' : ' UCHH9p1eetWCgt4kXBYCb3_w ' ,
' upload_date ' : ' 20160411 ' ,
2013-09-23 12:41:54 -07:00
} ,
2018-02-11 06:14:05 -08:00
' params ' : {
' skip_download ' : True ,
} ,
' add_ie ' : [ ' Youtube ' ] ,
2017-11-25 06:49:49 -08:00
} , {
' url ' : ' http://generation-what.francetv.fr/europe/video/present-arms ' ,
' only_matching ' : True ,
} ]
2013-09-23 12:41:54 -07:00
def _real_extract ( self , url ) :
2015-02-01 06:06:55 -08:00
display_id = self . _match_id ( url )
2018-02-11 06:14:05 -08:00
2017-11-25 06:49:49 -08:00
webpage = self . _download_webpage ( url , display_id )
2018-02-11 06:14:05 -08:00
2017-11-25 06:49:49 -08:00
youtube_id = self . _search_regex (
r " window \ .videoURL \ s*= \ s* ' ([0-9A-Za-z_-] {11} ) ' ; " ,
webpage , ' youtube id ' )
2018-02-11 06:14:05 -08:00
return self . url_result ( youtube_id , ie = ' Youtube ' , video_id = youtube_id )
2014-01-08 07:16:34 -08:00
class CultureboxIE ( FranceTVBaseInfoExtractor ) :
2018-02-11 06:14:05 -08:00
_VALID_URL = r ' https?://(?:m \ .)?culturebox \ .francetvinfo \ .fr/(?:[^/]+/)*(?P<id>[^/?#&]+) '
2014-01-08 07:16:34 -08:00
2018-02-11 06:14:05 -08:00
_TESTS = [ {
' url ' : ' https://culturebox.francetvinfo.fr/opera-classique/musique-classique/c-est-baroque/concerts/cantates-bwv-4-106-et-131-de-bach-par-raphael-pichon-57-268689 ' ,
2014-01-29 21:13:57 -08:00
' info_dict ' : {
2018-02-11 06:14:05 -08:00
' id ' : ' EV_134885 ' ,
' ext ' : ' mp4 ' ,
' title ' : ' Cantates BWV 4, 106 et 131 de Bach par Raphaël Pichon 5/7 ' ,
' description ' : ' md5:19c44af004b88219f4daa50fa9a351d4 ' ,
' upload_date ' : ' 20180206 ' ,
' timestamp ' : 1517945220 ,
' duration ' : 5981 ,
2015-04-04 09:50:13 -07:00
} ,
2018-02-11 06:14:05 -08:00
' params ' : {
' skip_download ' : True ,
} ,
' add_ie ' : [ FranceTVIE . ie_key ( ) ] ,
} ]
2014-01-08 07:16:34 -08:00
def _real_extract ( self , url ) :
2018-02-11 06:14:05 -08:00
display_id = self . _match_id ( url )
2015-04-04 09:43:34 -07:00
2018-02-11 06:14:05 -08:00
webpage = self . _download_webpage ( url , display_id )
2015-04-04 09:43:34 -07:00
if " >Ce live n ' est plus disponible en replay< " in webpage :
2018-02-11 06:14:05 -08:00
raise ExtractorError (
' Video %s is not available ' % display_id , expected = True )
2015-04-04 09:43:34 -07:00
2014-09-16 09:47:59 -07:00
video_id , catalogue = self . _search_regex (
2017-12-10 07:46:21 -08:00
r ' [ " \' >]https?://videos \ .francetv \ .fr/video/([^@]+@.+?)[ " \' <] ' ,
webpage , ' video id ' ) . split ( ' @ ' )
2014-09-16 09:47:59 -07:00
2018-02-11 06:14:05 -08:00
return self . _make_url_result ( video_id , catalogue )
2018-02-11 06:40:38 -08:00
class FranceTVJeunesseIE ( FranceTVBaseInfoExtractor ) :
_VALID_URL = r ' (?P<url>https?://(?:www \ .)?(?:zouzous|ludo) \ .fr/heros/(?P<id>[^/?#&]+)) '
_TESTS = [ {
' url ' : ' https://www.zouzous.fr/heros/simon ' ,
' info_dict ' : {
' id ' : ' simon ' ,
} ,
' playlist_count ' : 9 ,
} , {
' url ' : ' https://www.ludo.fr/heros/ninjago ' ,
' info_dict ' : {
' id ' : ' ninjago ' ,
} ,
' playlist_count ' : 10 ,
} , {
' url ' : ' https://www.zouzous.fr/heros/simon?abc ' ,
' only_matching ' : True ,
} ]
def _real_extract ( self , url ) :
mobj = re . match ( self . _VALID_URL , url )
playlist_id = mobj . group ( ' id ' )
playlist = self . _download_json (
' %s / %s ' % ( mobj . group ( ' url ' ) , ' playlist ' ) , playlist_id )
if not playlist . get ( ' count ' ) :
raise ExtractorError (
' %s is not available ' % playlist_id , expected = True )
entries = [ ]
for item in playlist [ ' items ' ] :
identity = item . get ( ' identity ' )
if identity and isinstance ( identity , compat_str ) :
entries . append ( self . _make_url_result ( identity ) )
return self . playlist_result ( entries , playlist_id )