pandoratv.py (4801B)
1 # coding: utf-8 2 from __future__ import unicode_literals 3 4 import re 5 6 from .common import InfoExtractor 7 from ..compat import ( 8 compat_str, 9 compat_urlparse, 10 ) 11 from ..utils import ( 12 ExtractorError, 13 float_or_none, 14 parse_duration, 15 str_to_int, 16 urlencode_postdata, 17 ) 18 19 20 class PandoraTVIE(InfoExtractor): 21 IE_NAME = 'pandora.tv' 22 IE_DESC = '판도라TV' 23 _VALID_URL = r'''(?x) 24 https?:// 25 (?: 26 (?:www\.)?pandora\.tv/view/(?P<user_id>[^/]+)/(?P<id>\d+)| # new format 27 (?:.+?\.)?channel\.pandora\.tv/channel/video\.ptv\?| # old format 28 m\.pandora\.tv/?\? # mobile 29 ) 30 ''' 31 _TESTS = [{ 32 'url': 'http://jp.channel.pandora.tv/channel/video.ptv?c1=&prgid=53294230&ch_userid=mikakim&ref=main&lot=cate_01_2', 33 'info_dict': { 34 'id': '53294230', 35 'ext': 'flv', 36 'title': '頭を撫でてくれる?', 37 'description': '頭を撫でてくれる?', 38 'thumbnail': r're:^https?://.*\.jpg$', 39 'duration': 39, 40 'upload_date': '20151218', 41 'uploader': 'カワイイ動物まとめ', 42 'uploader_id': 'mikakim', 43 'view_count': int, 44 'like_count': int, 45 } 46 }, { 47 'url': 'http://channel.pandora.tv/channel/video.ptv?ch_userid=gogoucc&prgid=54721744', 48 'info_dict': { 49 'id': '54721744', 50 'ext': 'flv', 51 'title': '[HD] JAPAN COUNTDOWN 170423', 52 'description': '[HD] JAPAN COUNTDOWN 170423', 53 'thumbnail': r're:^https?://.*\.jpg$', 54 'duration': 1704.9, 55 'upload_date': '20170423', 56 'uploader': 'GOGO_UCC', 57 'uploader_id': 'gogoucc', 58 'view_count': int, 59 'like_count': int, 60 }, 61 'params': { 62 # Test metadata only 63 'skip_download': True, 64 }, 65 }, { 66 'url': 'http://www.pandora.tv/view/mikakim/53294230#36797454_new', 67 'only_matching': True, 68 }, { 69 'url': 'http://m.pandora.tv/?c=view&ch_userid=mikakim&prgid=54600346', 70 'only_matching': True, 71 }] 72 73 def _real_extract(self, url): 74 mobj = re.match(self._VALID_URL, url) 75 user_id = mobj.group('user_id') 76 video_id = mobj.group('id') 77 78 if not user_id or not video_id: 79 qs = compat_urlparse.parse_qs(compat_urlparse.urlparse(url).query) 80 video_id = qs.get('prgid', [None])[0] 81 user_id = qs.get('ch_userid', [None])[0] 82 if any(not f for f in (video_id, user_id,)): 83 raise ExtractorError('Invalid URL', expected=True) 84 85 data = self._download_json( 86 'http://m.pandora.tv/?c=view&m=viewJsonApi&ch_userid=%s&prgid=%s' 87 % (user_id, video_id), video_id) 88 89 info = data['data']['rows']['vod_play_info']['result'] 90 91 formats = [] 92 for format_id, format_url in info.items(): 93 if not format_url: 94 continue 95 height = self._search_regex( 96 r'^v(\d+)[Uu]rl$', format_id, 'height', default=None) 97 if not height: 98 continue 99 100 play_url = self._download_json( 101 'http://m.pandora.tv/?c=api&m=play_url', video_id, 102 data=urlencode_postdata({ 103 'prgid': video_id, 104 'runtime': info.get('runtime'), 105 'vod_url': format_url, 106 }), 107 headers={ 108 'Origin': url, 109 'Content-Type': 'application/x-www-form-urlencoded', 110 }) 111 format_url = play_url.get('url') 112 if not format_url: 113 continue 114 115 formats.append({ 116 'format_id': '%sp' % height, 117 'url': format_url, 118 'height': int(height), 119 }) 120 self._sort_formats(formats) 121 122 return { 123 'id': video_id, 124 'title': info['subject'], 125 'description': info.get('body'), 126 'thumbnail': info.get('thumbnail') or info.get('poster'), 127 'duration': float_or_none(info.get('runtime'), 1000) or parse_duration(info.get('time')), 128 'upload_date': info['fid'].split('/')[-1][:8] if isinstance(info.get('fid'), compat_str) else None, 129 'uploader': info.get('nickname'), 130 'uploader_id': info.get('upload_userid'), 131 'view_count': str_to_int(info.get('hit')), 132 'like_count': str_to_int(info.get('likecnt')), 133 'formats': formats, 134 }