2014-08-27 12:52:55 -05:00
from __future__ import unicode_literals
2013-10-10 08:25:11 -05:00
import re
import json
2014-12-07 04:26:07 -06:00
import os
2013-10-10 08:25:11 -05:00
from . common import InfoExtractor
2014-11-26 06:06:02 -06:00
from . . compat import (
2013-10-10 08:25:11 -05:00
compat_urlparse ,
compat_urllib_parse ,
2014-12-02 16:23:18 -06:00
compat_urllib_parse_urlparse
2014-11-26 06:06:02 -06:00
)
from . . utils import (
2013-10-10 08:25:11 -05:00
unified_strdate ,
)
2013-10-11 07:33:26 -05:00
class NHLBaseInfoExtractor ( InfoExtractor ) :
@staticmethod
def _fix_json ( json_string ) :
return json_string . replace ( ' \\ \' ' , ' \' ' )
2015-01-30 11:12:27 -06:00
def _real_extract_video ( self , video_id ) :
2015-05-07 13:12:28 -05:00
vid_parts = video_id . split ( ' , ' )
if len ( vid_parts ) == 3 :
video_id = ' %s 0 %s %s -X-h ' % ( vid_parts [ 0 ] [ : 4 ] , vid_parts [ 1 ] , vid_parts [ 2 ] . rjust ( 4 , ' 0 ' ) )
2015-01-30 11:12:27 -06:00
json_url = ' http://video.nhl.com/videocenter/servlets/playlist?ids= %s &format=json ' % video_id
data = self . _download_json (
json_url , video_id , transform_source = self . _fix_json )
return self . _extract_video ( data [ 0 ] )
2013-10-11 07:33:26 -05:00
def _extract_video ( self , info ) :
video_id = info [ ' id ' ]
self . report_extraction ( video_id )
initial_video_url = info [ ' publishPoint ' ]
2014-10-25 01:56:21 -05:00
if info [ ' formats ' ] == ' 1 ' :
2014-12-02 16:23:18 -06:00
parsed_url = compat_urllib_parse_urlparse ( initial_video_url )
2014-12-07 04:26:07 -06:00
filename , ext = os . path . splitext ( parsed_url . path )
path = ' %s _sd %s ' % ( filename , ext )
2014-10-25 01:56:21 -05:00
data = compat_urllib_parse . urlencode ( {
' type ' : ' fvod ' ,
2014-12-02 16:23:18 -06:00
' path ' : compat_urlparse . urlunparse ( parsed_url [ : 2 ] + ( path , ) + parsed_url [ 3 : ] )
2014-10-25 01:56:21 -05:00
} )
path_url = ' http://video.nhl.com/videocenter/servlets/encryptvideopath? ' + data
path_doc = self . _download_xml (
path_url , video_id , ' Downloading final video url ' )
video_url = path_doc . find ( ' path ' ) . text
else :
2014-11-23 13:41:03 -06:00
video_url = initial_video_url
2013-10-11 07:33:26 -05:00
join = compat_urlparse . urljoin
2015-05-07 14:09:19 -05:00
ret = {
2013-10-11 07:33:26 -05:00
' id ' : video_id ,
' title ' : info [ ' name ' ] ,
' url ' : video_url ,
' description ' : info [ ' description ' ] ,
' duration ' : int ( info [ ' duration ' ] ) ,
' thumbnail ' : join ( join ( video_url , ' /u/ ' ) , info [ ' bigImage ' ] ) ,
' upload_date ' : unified_strdate ( info [ ' releaseDate ' ] . split ( ' . ' ) [ 0 ] ) ,
}
2015-05-07 14:09:19 -05:00
if video_url . startswith ( ' rtmp: ' ) :
mobj = re . match ( r ' (?P<tc_url>rtmp://[^/]+/(?P<app>[a-z0-9/]+))/(?P<play_path>mp4:.*) ' , video_url )
ret . update ( {
' tc_url ' : mobj . group ( ' tc_url ' ) ,
' play_path ' : mobj . group ( ' play_path ' ) ,
' app ' : mobj . group ( ' app ' ) ,
' no_resume ' : True ,
} )
return ret
2013-10-11 07:33:26 -05:00
class NHLIE ( NHLBaseInfoExtractor ) :
2014-08-27 12:52:55 -05:00
IE_NAME = ' nhl.com '
2015-09-24 12:48:23 -05:00
_VALID_URL = r ' https?://video(?P<team> \ .[^.]*)? \ .nhl \ .com/videocenter/(?:console|embed)?(?: \ ?(?:.*?[?&])?)(?:id|hlg|playlist)=(?P<id>[-0-9a-zA-Z,]+) '
2013-10-10 08:25:11 -05:00
2014-09-16 03:08:34 -05:00
_TESTS = [ {
2014-08-27 12:52:55 -05:00
' url ' : ' http://video.canucks.nhl.com/videocenter/console?catid=6?id=453614 ' ,
2014-10-25 01:56:21 -05:00
' md5 ' : ' db704a4ea09e8d3988c85e36cc892d09 ' ,
2014-08-27 12:52:55 -05:00
' info_dict ' : {
' id ' : ' 453614 ' ,
' ext ' : ' mp4 ' ,
' title ' : ' Quick clip: Weise 4-3 goal vs Flames ' ,
' description ' : ' Dale Weise scores his first of the season to put the Canucks up 4-3. ' ,
' duration ' : 18 ,
' upload_date ' : ' 20131006 ' ,
2013-10-10 08:25:11 -05:00
} ,
2014-10-25 01:56:21 -05:00
} , {
' url ' : ' http://video.nhl.com/videocenter/console?id=2014020024-628-h ' ,
' md5 ' : ' d22e82bc592f52d37d24b03531ee9696 ' ,
' info_dict ' : {
' id ' : ' 2014020024-628-h ' ,
' ext ' : ' mp4 ' ,
' title ' : ' Alex Galchenyuk Goal on Ray Emery (14:40/3rd) ' ,
' description ' : ' Home broadcast - Montreal Canadiens at Philadelphia Flyers - October 11, 2014 ' ,
' duration ' : 0 ,
' upload_date ' : ' 20141011 ' ,
} ,
2014-12-02 16:23:18 -06:00
} , {
' url ' : ' http://video.mapleleafs.nhl.com/videocenter/console?id=58665&catid=802 ' ,
' md5 ' : ' c78fc64ea01777e426cfc202b746c825 ' ,
' info_dict ' : {
' id ' : ' 58665 ' ,
' ext ' : ' flv ' ,
' title ' : ' Classic Game In Six - April 22, 1979 ' ,
' description ' : ' It was the last playoff game for the Leafs in the decade, and the last time the Leafs and Habs played in the playoffs. Great game, not a great ending. ' ,
' duration ' : 400 ,
' upload_date ' : ' 20100129 '
} ,
2014-09-16 03:08:34 -05:00
} , {
' url ' : ' http://video.flames.nhl.com/videocenter/console?id=630616 ' ,
' only_matching ' : True ,
2015-01-30 10:46:53 -06:00
} , {
' url ' : ' http://video.nhl.com/videocenter/?id=736722 ' ,
' only_matching ' : True ,
2015-05-07 13:12:28 -05:00
} , {
' url ' : ' http://video.nhl.com/videocenter/console?hlg=20142015,2,299&lang=en ' ,
' md5 ' : ' 076fcb88c255154aacbf0a7accc3f340 ' ,
' info_dict ' : {
' id ' : ' 2014020299-X-h ' ,
' ext ' : ' mp4 ' ,
' title ' : ' Penguins at Islanders / Game Highlights ' ,
' description ' : ' Home broadcast - Pittsburgh Penguins at New York Islanders - November 22, 2014 ' ,
' duration ' : 268 ,
' upload_date ' : ' 20141122 ' ,
}
2015-05-07 14:09:19 -05:00
} , {
' url ' : ' http://video.oilers.nhl.com/videocenter/console?id=691469&catid=4 ' ,
' info_dict ' : {
' id ' : ' 691469 ' ,
' ext ' : ' mp4 ' ,
' title ' : ' RAW | Craig MacTavish Full Press Conference ' ,
' description ' : ' Oilers GM Craig MacTavish addresses the media at Rexall Place on Friday. ' ,
' upload_date ' : ' 20141205 ' ,
} ,
' params ' : {
' skip_download ' : True , # Requires rtmpdump
}
2015-09-24 12:48:23 -05:00
} , {
' url ' : ' http://video.nhl.com/videocenter/embed?playlist=836127 ' ,
' only_matching ' : True ,
2014-09-16 03:08:34 -05:00
} ]
2013-10-10 08:25:11 -05:00
def _real_extract ( self , url ) :
2015-01-30 11:12:27 -06:00
video_id = self . _match_id ( url )
return self . _real_extract_video ( video_id )
class NHLNewsIE ( NHLBaseInfoExtractor ) :
IE_NAME = ' nhl.com:news '
IE_DESC = ' NHL news '
2015-09-24 12:54:16 -05:00
_VALID_URL = r ' https?://(?:.+? \ .)?nhl \ .com/(?:ice|club)/news \ .html?(?: \ ?(?:.*?[?&])?)id=(?P<id>[-0-9a-zA-Z]+) '
2015-01-30 11:12:27 -06:00
2015-09-24 12:54:16 -05:00
_TESTS = [ {
2015-01-30 11:12:27 -06:00
' url ' : ' http://www.nhl.com/ice/news.htm?id=750727 ' ,
' md5 ' : ' 4b3d1262e177687a3009937bd9ec0be8 ' ,
' info_dict ' : {
' id ' : ' 736722 ' ,
' ext ' : ' mp4 ' ,
' title ' : ' Cal Clutterbuck has been fined $2,000 ' ,
' description ' : ' md5:45fe547d30edab88b23e0dd0ab1ed9e6 ' ,
' duration ' : 37 ,
' upload_date ' : ' 20150128 ' ,
} ,
2015-09-24 12:54:16 -05:00
} , {
# iframe embed
' url ' : ' http://sabres.nhl.com/club/news.htm?id=780189 ' ,
' md5 ' : ' 9f663d1c006c90ac9fb82777d4294e12 ' ,
' info_dict ' : {
' id ' : ' 836127 ' ,
' ext ' : ' mp4 ' ,
' title ' : ' Morning Skate: OTT vs. BUF (9/23/15) ' ,
' description ' : " Brian Duff chats with Tyler Ennis prior to Buffalo ' s first preseason home game. " ,
' duration ' : 93 ,
' upload_date ' : ' 20150923 ' ,
} ,
} ]
2015-01-30 11:12:27 -06:00
def _real_extract ( self , url ) :
news_id = self . _match_id ( url )
webpage = self . _download_webpage ( url , news_id )
video_id = self . _search_regex (
2015-09-24 12:54:16 -05:00
[ r ' pVid( \ d+) ' , r " nlid \ s*: \ s* ' ( \ d+) ' " ,
r ' <iframe[^>]+src=[ " \' ]https?://video.*? \ .nhl \ .com/videocenter/embed \ ?.* \ bplaylist=( \ d+) ' ] ,
2015-01-30 11:12:27 -06:00
webpage , ' video id ' )
return self . _real_extract_video ( video_id )
2013-10-11 07:33:26 -05:00
class NHLVideocenterIE ( NHLBaseInfoExtractor ) :
2014-08-27 12:52:55 -05:00
IE_NAME = ' nhl.com:videocenter '
IE_DESC = ' NHL videocenter category '
2014-12-02 16:56:30 -06:00
_VALID_URL = r ' https?://video \ .(?P<team>[^.]*) \ .nhl \ .com/videocenter/(console \ ?[^(id=)]*catid=(?P<catid>[0-9]+)(?![&?]id=).*?)?$ '
2014-08-27 12:52:55 -05:00
_TEST = {
' url ' : ' http://video.canucks.nhl.com/videocenter/console?catid=999 ' ,
' info_dict ' : {
' id ' : ' 999 ' ,
' title ' : ' Highlights ' ,
} ,
' playlist_count ' : 12 ,
}
2013-10-11 07:33:26 -05:00
def _real_extract ( self , url ) :
mobj = re . match ( self . _VALID_URL , url )
team = mobj . group ( ' team ' )
webpage = self . _download_webpage ( url , team )
cat_id = self . _search_regex (
[ r ' var defaultCatId = " (.+?) " ; ' ,
r ' { statusIndex:0,index:0,.*?id:(.*?), ' ] ,
2014-08-27 12:52:55 -05:00
webpage , ' category id ' )
2013-10-11 07:33:26 -05:00
playlist_title = self . _html_search_regex (
2013-10-22 14:01:16 -05:00
r ' tab0 " [^>]*?>(.*?)</td> ' ,
2014-08-27 12:52:55 -05:00
webpage , ' playlist title ' , flags = re . DOTALL ) . lower ( ) . capitalize ( )
2013-10-10 08:25:11 -05:00
data = compat_urllib_parse . urlencode ( {
2013-10-11 07:33:26 -05:00
' cid ' : cat_id ,
# This is the default value
' count ' : 12 ,
' ptrs ' : 3 ,
' format ' : ' json ' ,
2013-10-10 08:25:11 -05:00
} )
2013-10-11 07:33:26 -05:00
path = ' /videocenter/servlets/browse? ' + data
request_url = compat_urlparse . urljoin ( url , path )
response = self . _download_webpage ( request_url , playlist_title )
response = self . _fix_json ( response )
if not response . strip ( ) :
2016-01-10 09:17:47 -06:00
self . _downloader . report_warning ( ' Got an empty response, trying '
2014-08-27 12:52:55 -05:00
' adding the " newvideos " parameter ' )
2013-10-11 07:33:26 -05:00
response = self . _download_webpage ( request_url + ' &newvideos=true ' ,
2014-11-23 14:39:15 -06:00
playlist_title )
2013-10-11 07:33:26 -05:00
response = self . _fix_json ( response )
videos = json . loads ( response )
2013-10-10 08:25:11 -05:00
return {
2013-10-11 07:33:26 -05:00
' _type ' : ' playlist ' ,
' title ' : playlist_title ,
' id ' : cat_id ,
2014-08-27 12:52:55 -05:00
' entries ' : [ self . _extract_video ( v ) for v in videos ] ,
2013-10-10 08:25:11 -05:00
}