nhl.py (5004B)
1 from __future__ import unicode_literals 2 3 import re 4 5 from .common import InfoExtractor 6 from ..compat import compat_str 7 from ..utils import ( 8 determine_ext, 9 int_or_none, 10 parse_iso8601, 11 parse_duration, 12 ) 13 14 15 class NHLBaseIE(InfoExtractor): 16 def _real_extract(self, url): 17 site, tmp_id = re.match(self._VALID_URL, url).groups() 18 video_data = self._download_json( 19 'https://%s/%s/%sid/v1/%s/details/web-v1.json' 20 % (self._CONTENT_DOMAIN, site[:3], 'item/' if site == 'mlb' else '', tmp_id), tmp_id) 21 if video_data.get('type') != 'video': 22 video_data = video_data['media'] 23 video = video_data.get('video') 24 if video: 25 video_data = video 26 else: 27 videos = video_data.get('videos') 28 if videos: 29 video_data = videos[0] 30 31 video_id = compat_str(video_data['id']) 32 title = video_data['title'] 33 34 formats = [] 35 for playback in video_data.get('playbacks', []): 36 playback_url = playback.get('url') 37 if not playback_url: 38 continue 39 ext = determine_ext(playback_url) 40 if ext == 'm3u8': 41 m3u8_formats = self._extract_m3u8_formats( 42 playback_url, video_id, 'mp4', 'm3u8_native', 43 m3u8_id=playback.get('name', 'hls'), fatal=False) 44 self._check_formats(m3u8_formats, video_id) 45 formats.extend(m3u8_formats) 46 else: 47 height = int_or_none(playback.get('height')) 48 formats.append({ 49 'format_id': playback.get('name', 'http' + ('-%dp' % height if height else '')), 50 'url': playback_url, 51 'width': int_or_none(playback.get('width')), 52 'height': height, 53 'tbr': int_or_none(self._search_regex(r'_(\d+)[kK]', playback_url, 'bitrate', default=None)), 54 }) 55 self._sort_formats(formats) 56 57 thumbnails = [] 58 cuts = video_data.get('image', {}).get('cuts') or [] 59 if isinstance(cuts, dict): 60 cuts = cuts.values() 61 for thumbnail_data in cuts: 62 thumbnail_url = thumbnail_data.get('src') 63 if not thumbnail_url: 64 continue 65 thumbnails.append({ 66 'url': thumbnail_url, 67 'width': int_or_none(thumbnail_data.get('width')), 68 'height': int_or_none(thumbnail_data.get('height')), 69 }) 70 71 return { 72 'id': video_id, 73 'title': title, 74 'description': video_data.get('description'), 75 'timestamp': parse_iso8601(video_data.get('date')), 76 'duration': parse_duration(video_data.get('duration')), 77 'thumbnails': thumbnails, 78 'formats': formats, 79 } 80 81 82 class NHLIE(NHLBaseIE): 83 IE_NAME = 'nhl.com' 84 _VALID_URL = r'https?://(?:www\.)?(?P<site>nhl|wch2016)\.com/(?:[^/]+/)*c-(?P<id>\d+)' 85 _CONTENT_DOMAIN = 'nhl.bamcontent.com' 86 _TESTS = [{ 87 # type=video 88 'url': 'https://www.nhl.com/video/anisimov-cleans-up-mess/t-277752844/c-43663503', 89 'md5': '0f7b9a8f986fb4b4eeeece9a56416eaf', 90 'info_dict': { 91 'id': '43663503', 92 'ext': 'mp4', 93 'title': 'Anisimov cleans up mess', 94 'description': 'md5:a02354acdfe900e940ce40706939ca63', 95 'timestamp': 1461288600, 96 'upload_date': '20160422', 97 }, 98 }, { 99 # type=article 100 'url': 'https://www.nhl.com/news/dennis-wideman-suspended/c-278258934', 101 'md5': '1f39f4ea74c1394dea110699a25b366c', 102 'info_dict': { 103 'id': '40784403', 104 'ext': 'mp4', 105 'title': 'Wideman suspended by NHL', 106 'description': 'Flames defenseman Dennis Wideman was banned 20 games for violation of Rule 40 (Physical Abuse of Officials)', 107 'upload_date': '20160204', 108 'timestamp': 1454544904, 109 }, 110 }, { 111 # Some m3u8 URLs are invalid (https://github.com/ytdl-org/youtube-dl/issues/10713) 112 'url': 'https://www.nhl.com/predators/video/poile-laviolette-on-subban-trade/t-277437416/c-44315003', 113 'md5': '50b2bb47f405121484dda3ccbea25459', 114 'info_dict': { 115 'id': '44315003', 116 'ext': 'mp4', 117 'title': 'Poile, Laviolette on Subban trade', 118 'description': 'General manager David Poile and head coach Peter Laviolette share their thoughts on acquiring P.K. Subban from Montreal (06/29/16)', 119 'timestamp': 1467242866, 120 'upload_date': '20160629', 121 }, 122 }, { 123 'url': 'https://www.wch2016.com/video/caneur-best-of-game-2-micd-up/t-281230378/c-44983703', 124 'only_matching': True, 125 }, { 126 'url': 'https://www.wch2016.com/news/3-stars-team-europe-vs-team-canada/c-282195068', 127 'only_matching': True, 128 }]