infoq.py (5072B)
1 # coding: utf-8 2 3 from __future__ import unicode_literals 4 5 from ..compat import ( 6 compat_b64decode, 7 compat_urllib_parse_unquote, 8 compat_urlparse, 9 ) 10 from ..utils import ( 11 determine_ext, 12 update_url_query, 13 ) 14 from .bokecc import BokeCCBaseIE 15 16 17 class InfoQIE(BokeCCBaseIE): 18 _VALID_URL = r'https?://(?:www\.)?infoq\.com/(?:[^/]+/)+(?P<id>[^/]+)' 19 20 _TESTS = [{ 21 'url': 'http://www.infoq.com/presentations/A-Few-of-My-Favorite-Python-Things', 22 'md5': 'b5ca0e0a8c1fed93b0e65e48e462f9a2', 23 'info_dict': { 24 'id': 'A-Few-of-My-Favorite-Python-Things', 25 'ext': 'mp4', 26 'description': 'Mike Pirnat presents some tips and tricks, standard libraries and third party packages that make programming in Python a richer experience.', 27 'title': 'A Few of My Favorite [Python] Things', 28 }, 29 }, { 30 'url': 'http://www.infoq.com/fr/presentations/changez-avis-sur-javascript', 31 'only_matching': True, 32 }, { 33 'url': 'http://www.infoq.com/cn/presentations/openstack-continued-delivery', 34 'md5': '4918d0cca1497f2244572caf626687ef', 35 'info_dict': { 36 'id': 'openstack-continued-delivery', 37 'title': 'OpenStack持续交付之路', 38 'ext': 'flv', 39 'description': 'md5:308d981fb28fa42f49f9568322c683ff', 40 }, 41 }, { 42 'url': 'https://www.infoq.com/presentations/Simple-Made-Easy', 43 'md5': '0e34642d4d9ef44bf86f66f6399672db', 44 'info_dict': { 45 'id': 'Simple-Made-Easy', 46 'title': 'Simple Made Easy', 47 'ext': 'mp3', 48 'description': 'md5:3e0e213a8bbd074796ef89ea35ada25b', 49 }, 50 'params': { 51 'format': 'bestaudio', 52 }, 53 }] 54 55 def _extract_rtmp_video(self, webpage): 56 # The server URL is hardcoded 57 video_url = 'rtmpe://videof.infoq.com/cfx/st/' 58 59 # Extract video URL 60 encoded_id = self._search_regex( 61 r"jsclassref\s*=\s*'([^']*)'", webpage, 'encoded id', default=None) 62 63 real_id = compat_urllib_parse_unquote(compat_b64decode(encoded_id).decode('utf-8')) 64 playpath = 'mp4:' + real_id 65 66 return [{ 67 'format_id': 'rtmp_video', 68 'url': video_url, 69 'ext': determine_ext(playpath), 70 'play_path': playpath, 71 }] 72 73 def _extract_cf_auth(self, webpage): 74 policy = self._search_regex(r'InfoQConstants\.scp\s*=\s*\'([^\']+)\'', webpage, 'policy') 75 signature = self._search_regex(r'InfoQConstants\.scs\s*=\s*\'([^\']+)\'', webpage, 'signature') 76 key_pair_id = self._search_regex(r'InfoQConstants\.sck\s*=\s*\'([^\']+)\'', webpage, 'key-pair-id') 77 return { 78 'Policy': policy, 79 'Signature': signature, 80 'Key-Pair-Id': key_pair_id, 81 } 82 83 def _extract_http_video(self, webpage): 84 http_video_url = self._search_regex(r'P\.s\s*=\s*\'([^\']+)\'', webpage, 'video URL') 85 http_video_url = update_url_query(http_video_url, self._extract_cf_auth(webpage)) 86 return [{ 87 'format_id': 'http_video', 88 'url': http_video_url, 89 'http_headers': {'Referer': 'https://www.infoq.com/'}, 90 }] 91 92 def _extract_http_audio(self, webpage, video_id): 93 fields = self._form_hidden_inputs('mp3Form', webpage) 94 http_audio_url = fields.get('filename') 95 if not http_audio_url: 96 return [] 97 98 # base URL is found in the Location header in the response returned by 99 # GET https://www.infoq.com/mp3download.action?filename=... when logged in. 100 http_audio_url = compat_urlparse.urljoin('http://ress.infoq.com/downloads/mp3downloads/', http_audio_url) 101 http_audio_url = update_url_query(http_audio_url, self._extract_cf_auth(webpage)) 102 103 # audio file seem to be missing some times even if there is a download link 104 # so probe URL to make sure 105 if not self._is_valid_url(http_audio_url, video_id): 106 return [] 107 108 return [{ 109 'format_id': 'http_audio', 110 'url': http_audio_url, 111 'vcodec': 'none', 112 }] 113 114 def _real_extract(self, url): 115 video_id = self._match_id(url) 116 webpage = self._download_webpage(url, video_id) 117 118 video_title = self._html_search_regex(r'<title>(.*?)</title>', webpage, 'title') 119 video_description = self._html_search_meta('description', webpage, 'description') 120 121 if '/cn/' in url: 122 # for China videos, HTTP video URL exists but always fails with 403 123 formats = self._extract_bokecc_formats(webpage, video_id) 124 else: 125 formats = ( 126 self._extract_rtmp_video(webpage) 127 + self._extract_http_video(webpage) 128 + self._extract_http_audio(webpage, video_id)) 129 130 self._sort_formats(formats) 131 132 return { 133 'id': video_id, 134 'title': video_title, 135 'description': video_description, 136 'formats': formats, 137 }