@ -23,7 +23,7 @@ class VikiIE(InfoExtractor):
# iPad2
# iPad2
_USER_AGENT = ' Mozilla/5.0(iPad; U; CPU OS 4_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8F191 Safari/6533.18.5 '
_USER_AGENT = ' Mozilla/5.0(iPad; U; CPU OS 4_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8F191 Safari/6533.18.5 '
_VALID_URL = r ' ^ https?://(?:www\ .)?viki \ .com/videos/(?P<id>[0-9]+v) '
_VALID_URL = r ' https?://(?:www \ .)?viki \ .com/videos/(?P<id>[0-9]+v) '
_TESTS = [ {
_TESTS = [ {
' url ' : ' http://www.viki.com/videos/1023585v-heirs-episode-14 ' ,
' url ' : ' http://www.viki.com/videos/1023585v-heirs-episode-14 ' ,
' info_dict ' : {
' info_dict ' : {
@ -93,7 +93,7 @@ class VikiIE(InfoExtractor):
' Video %s is blocked from your location. ' % video_id ,
' Video %s is blocked from your location. ' % video_id ,
expected = True )
expected = True )
else :
else :
raise ExtractorError ( ' Viki said: ' + err_msg )
raise ExtractorError ( ' Viki said: %s %s ' % ( err_msg , url ) )
mobj = re . search (
mobj = re . search (
r ' <source[^>]+type= " (?P<mime_type>[^ " ]+) " [^>]+src= " (?P<url>[^ " ]+) " ' , info_webpage )
r ' <source[^>]+type= " (?P<mime_type>[^ " ]+) " [^>]+src= " (?P<url>[^ " ]+) " ' , info_webpage )
if not mobj :
if not mobj :
@ -145,3 +145,57 @@ class VikiIE(InfoExtractor):
' ext ' : ' vtt ' ,
' ext ' : ' vtt ' ,
} ]
} ]
return res
return res
class VikiChannelIE ( InfoExtractor ) :
IE_NAME = ' viki:channel '
_VALID_URL = r ' https?://(?:www \ .)?viki \ .com/tv/(?P<id>[0-9]+c) '
_TESTS = [ {
' url ' : ' http://www.viki.com/tv/50c-boys-over-flowers ' ,
' info_dict ' : {
' id ' : ' 50c ' ,
' title ' : ' Boys Over Flowers ' ,
' description ' : ' md5:ecd3cff47967fe193cff37c0bec52790 ' ,
} ,
' playlist_count ' : 70 ,
} , {
' url ' : ' http://www.viki.com/tv/1354c-poor-nastya-complete ' ,
' info_dict ' : {
' id ' : ' 1354c ' ,
' title ' : ' Poor Nastya [COMPLETE] ' ,
' description ' : ' md5:05bf5471385aa8b21c18ad450e350525 ' ,
} ,
' playlist_count ' : 127 ,
} ]
_API_BASE = ' http://api.viki.io/v4/containers '
_APP = ' 100000a '
_PER_PAGE = 25
def _real_extract ( self , url ) :
channel_id = self . _match_id ( url )
channel = self . _download_json (
' %s / %s .json?app= %s ' % ( self . _API_BASE , channel_id , self . _APP ) ,
channel_id , ' Downloading channel JSON ' )
titles = channel [ ' titles ' ]
title = titles . get ( ' en ' ) or titles [ titles . keys ( ) [ 0 ] ]
descriptions = channel [ ' descriptions ' ]
description = descriptions . get ( ' en ' ) or descriptions [ descriptions . keys ( ) [ 0 ] ]
entries = [ ]
for video_type in ( ' episodes ' , ' clips ' ) :
page_url = ' %s / %s / %s .json?app= %s &per_page= %d &sort=number&direction=asc&with_paging=true&page=1 ' % ( self . _API_BASE , channel_id , video_type , self . _APP , self . _PER_PAGE )
while page_url :
page = self . _download_json (
page_url , channel_id ,
' Downloading %s JSON page # %s '
% ( video_type , re . search ( r ' [?&]page=([0-9]+) ' , page_url ) . group ( 1 ) ) )
for video in page [ ' response ' ] :
video_id = video [ ' id ' ]
entries . append ( self . url_result (
' http://www.viki.com/videos/ %s ' % video_id , ' Viki ' , video_id ) )
page_url = page [ ' pagination ' ] [ ' next ' ]
return self . playlist_result ( entries , channel_id , title , description )