2013-10-16 16:57:40 +02:00
# encoding: utf-8
2014-01-28 00:56:09 +01:00
from __future__ import unicode_literals
2013-10-16 16:57:40 +02:00
import re
2014-01-28 00:56:09 +01:00
import itertools
2013-10-16 16:57:40 +02:00
from . common import InfoExtractor
2014-12-13 12:24:42 +01:00
from . . compat import (
2013-10-16 16:57:40 +02:00
compat_str ,
2014-12-13 12:24:42 +01:00
)
from . . utils import (
2015-11-21 13:02:52 +01:00
determine_ext ,
2014-12-13 12:24:42 +01:00
unified_strdate ,
2013-10-16 16:57:40 +02:00
)
class RutubeIE ( InfoExtractor ) :
2014-01-28 00:56:09 +01:00
IE_NAME = ' rutube '
2014-01-28 03:32:07 +01:00
IE_DESC = ' Rutube videos '
2015-12-15 23:44:17 +01:00
_VALID_URL = r ' https?://rutube \ .ru/(?:video|play/embed)/(?P<id>[ \ da-z] {32} ) '
2013-10-16 16:57:40 +02:00
2015-12-15 23:44:17 +01:00
_TESTS = [ {
2014-01-28 00:56:09 +01:00
' url ' : ' http://rutube.ru/video/3eac3b4561676c17df9132a9a1e62e3e/ ' ,
' info_dict ' : {
2014-03-30 10:35:07 +02:00
' id ' : ' 3eac3b4561676c17df9132a9a1e62e3e ' ,
' ext ' : ' mp4 ' ,
2014-01-28 00:56:09 +01:00
' title ' : ' Раненный кенгуру забежал в аптеку ' ,
2014-01-28 03:31:14 +01:00
' description ' : ' http://www.ntdtv.ru ' ,
' duration ' : 80 ,
2014-01-28 00:56:09 +01:00
' uploader ' : ' NTDRussian ' ,
' uploader_id ' : ' 29790 ' ,
2014-01-28 03:31:14 +01:00
' upload_date ' : ' 20131016 ' ,
2015-08-08 18:11:06 +02:00
' age_limit ' : 0 ,
2013-10-16 16:57:40 +02:00
} ,
2014-01-28 00:56:09 +01:00
' params ' : {
2013-10-16 16:57:40 +02:00
# It requires ffmpeg (m3u8 download)
2014-01-28 00:56:09 +01:00
' skip_download ' : True ,
2013-10-16 16:57:40 +02:00
} ,
2015-12-15 23:44:17 +01:00
} , {
' url ' : ' http://rutube.ru/play/embed/a10e53b86e8f349080f718582ce4c661 ' ,
' only_matching ' : True ,
} ]
2013-10-16 16:57:40 +02:00
def _real_extract ( self , url ) :
2014-12-13 12:24:42 +01:00
video_id = self . _match_id ( url )
2014-03-30 11:26:35 +02:00
video = self . _download_json (
2014-03-30 10:35:07 +02:00
' http://rutube.ru/api/video/ %s /?format=json ' % video_id ,
video_id , ' Downloading video JSON ' )
2014-03-30 11:26:35 +02:00
2013-10-16 16:57:40 +02:00
# Some videos don't have the author field
2014-04-19 10:59:12 +02:00
author = video . get ( ' author ' ) or { }
options = self . _download_json (
2014-04-21 14:04:11 +02:00
' http://rutube.ru/api/play/options/ %s /?format=json ' % video_id ,
2014-04-19 10:59:12 +02:00
video_id , ' Downloading options JSON ' )
2015-11-21 13:02:52 +01:00
formats = [ ]
for format_id , format_url in options [ ' video_balancer ' ] . items ( ) :
ext = determine_ext ( format_url )
if ext == ' m3u8 ' :
m3u8_formats = self . _extract_m3u8_formats (
format_url , video_id , ' mp4 ' , m3u8_id = format_id , fatal = False )
if m3u8_formats :
formats . extend ( m3u8_formats )
elif ext == ' f4m ' :
f4m_formats = self . _extract_f4m_formats (
format_url , video_id , f4m_id = format_id , fatal = False )
if f4m_formats :
formats . extend ( f4m_formats )
else :
formats . append ( {
' url ' : format_url ,
' format_id ' : format_id ,
} )
self . _sort_formats ( formats )
2013-10-16 16:57:40 +02:00
return {
2014-01-28 02:19:45 +01:00
' id ' : video [ ' id ' ] ,
' title ' : video [ ' title ' ] ,
' description ' : video [ ' description ' ] ,
' duration ' : video [ ' duration ' ] ,
' view_count ' : video [ ' hits ' ] ,
2014-12-01 18:20:36 +01:00
' formats ' : formats ,
2014-01-28 02:19:45 +01:00
' thumbnail ' : video [ ' thumbnail_url ' ] ,
2013-10-16 16:57:40 +02:00
' uploader ' : author . get ( ' name ' ) ,
' uploader_id ' : compat_str ( author [ ' id ' ] ) if author else None ,
2014-01-28 02:19:45 +01:00
' upload_date ' : unified_strdate ( video [ ' created_ts ' ] ) ,
' age_limit ' : 18 if video [ ' is_adult ' ] else 0 ,
2013-10-16 16:57:40 +02:00
}
2014-01-28 00:56:09 +01:00
2015-01-04 03:15:27 +01:00
class RutubeEmbedIE ( InfoExtractor ) :
IE_NAME = ' rutube:embed '
IE_DESC = ' Rutube embedded videos '
2015-11-21 12:39:24 +01:00
_VALID_URL = ' https?://rutube \ .ru/(?:video|play)/embed/(?P<id>[0-9]+) '
2015-01-04 03:15:27 +01:00
2015-11-21 12:39:24 +01:00
_TESTS = [ {
2015-01-04 03:15:27 +01:00
' url ' : ' http://rutube.ru/video/embed/6722881?vk_puid37=&vk_puid38= ' ,
' info_dict ' : {
' id ' : ' a10e53b86e8f349080f718582ce4c661 ' ,
' ext ' : ' mp4 ' ,
' upload_date ' : ' 20131223 ' ,
' uploader_id ' : ' 297833 ' ,
' description ' : ' Видео группы ★http://vk.com/foxkidsreset★ музей Fox Kids и Jetix<br/><br/> восстановлено и сделано в шикоформате subziro89 http://vk.com/subziro89 ' ,
' uploader ' : ' subziro89 ILya ' ,
' title ' : ' Мистический городок Эйри в Индиан 5 серия озвучка subziro89 ' ,
} ,
' params ' : {
' skip_download ' : ' Requires ffmpeg ' ,
} ,
2015-11-21 12:39:24 +01:00
} , {
' url ' : ' http://rutube.ru/play/embed/8083783 ' ,
' only_matching ' : True ,
} ]
2015-01-04 03:15:27 +01:00
def _real_extract ( self , url ) :
embed_id = self . _match_id ( url )
webpage = self . _download_webpage ( url , embed_id )
canonical_url = self . _html_search_regex (
r ' <link \ s+rel= " canonical " \ s+href= " ([^ " ]+?) " ' , webpage ,
' Canonical URL ' )
return self . url_result ( canonical_url , ' Rutube ' )
2014-01-28 00:56:09 +01:00
class RutubeChannelIE ( InfoExtractor ) :
IE_NAME = ' rutube:channel '
2014-01-28 03:32:07 +01:00
IE_DESC = ' Rutube channels '
2014-01-28 00:56:09 +01:00
_VALID_URL = r ' http://rutube \ .ru/tags/video/(?P<id> \ d+) '
2014-08-28 00:58:24 +02:00
_TESTS = [ {
' url ' : ' http://rutube.ru/tags/video/1800/ ' ,
' info_dict ' : {
' id ' : ' 1800 ' ,
} ,
' playlist_mincount ' : 68 ,
} ]
2014-01-28 00:56:09 +01:00
_PAGE_TEMPLATE = ' http://rutube.ru/api/tags/video/ %s /?page= %s &format=json '
def _extract_videos ( self , channel_id , channel_title = None ) :
entries = [ ]
for pagenum in itertools . count ( 1 ) :
2014-03-30 11:26:35 +02:00
page = self . _download_json (
2014-01-28 03:32:07 +01:00
self . _PAGE_TEMPLATE % ( channel_id , pagenum ) ,
channel_id , ' Downloading page %s ' % pagenum )
2014-01-28 00:56:09 +01:00
results = page [ ' results ' ]
2014-01-28 03:32:07 +01:00
if not results :
break
2014-01-28 02:19:45 +01:00
entries . extend ( self . url_result ( result [ ' video_url ' ] , ' Rutube ' ) for result in results )
2014-01-28 03:32:07 +01:00
if not page [ ' has_next ' ] :
break
2014-01-28 00:56:09 +01:00
return self . playlist_result ( entries , channel_id , channel_title )
def _real_extract ( self , url ) :
mobj = re . match ( self . _VALID_URL , url )
channel_id = mobj . group ( ' id ' )
return self . _extract_videos ( channel_id )
class RutubeMovieIE ( RutubeChannelIE ) :
IE_NAME = ' rutube:movie '
2014-01-28 03:32:07 +01:00
IE_DESC = ' Rutube movies '
2014-01-28 00:56:09 +01:00
_VALID_URL = r ' http://rutube \ .ru/metainfo/tv/(?P<id> \ d+) '
2014-08-28 00:58:24 +02:00
_TESTS = [ ]
2014-01-28 00:56:09 +01:00
_MOVIE_TEMPLATE = ' http://rutube.ru/api/metainfo/tv/ %s /?format=json '
_PAGE_TEMPLATE = ' http://rutube.ru/api/metainfo/tv/ %s /video?page= %s &format=json '
def _real_extract ( self , url ) :
2014-12-13 12:24:42 +01:00
movie_id = self . _match_id ( url )
2014-03-30 11:26:35 +02:00
movie = self . _download_json (
2014-01-28 03:32:07 +01:00
self . _MOVIE_TEMPLATE % movie_id , movie_id ,
' Downloading movie JSON ' )
2014-01-28 00:56:09 +01:00
movie_name = movie [ ' name ' ]
2014-01-28 02:47:17 +01:00
return self . _extract_videos ( movie_id , movie_name )
class RutubePersonIE ( RutubeChannelIE ) :
IE_NAME = ' rutube:person '
IE_DESC = ' Rutube person videos '
_VALID_URL = r ' http://rutube \ .ru/video/person/(?P<id> \ d+) '
2014-08-28 00:58:24 +02:00
_TESTS = [ {
' url ' : ' http://rutube.ru/video/person/313878/ ' ,
' info_dict ' : {
' id ' : ' 313878 ' ,
} ,
' playlist_mincount ' : 37 ,
} ]
2014-01-28 02:47:17 +01:00
2014-01-28 03:32:07 +01:00
_PAGE_TEMPLATE = ' http://rutube.ru/api/video/person/ %s /?page= %s &format=json '