youtube-dl

Another place where youtube-dl lives on
git clone git://git.oshgnacknak.de/youtube-dl.git
Log | Files | Refs | README | LICENSE

hidive.py (4113B)


      1 # coding: utf-8
      2 from __future__ import unicode_literals
      3 
      4 import re
      5 
      6 from .common import InfoExtractor
      7 from ..compat import compat_str
      8 from ..utils import (
      9     ExtractorError,
     10     int_or_none,
     11     url_or_none,
     12     urlencode_postdata,
     13 )
     14 
     15 
     16 class HiDiveIE(InfoExtractor):
     17     _VALID_URL = r'https?://(?:www\.)?hidive\.com/stream/(?P<title>[^/]+)/(?P<key>[^/?#&]+)'
     18     # Using X-Forwarded-For results in 403 HTTP error for HLS fragments,
     19     # so disabling geo bypass completely
     20     _GEO_BYPASS = False
     21     _NETRC_MACHINE = 'hidive'
     22     _LOGIN_URL = 'https://www.hidive.com/account/login'
     23 
     24     _TESTS = [{
     25         'url': 'https://www.hidive.com/stream/the-comic-artist-and-his-assistants/s01e001',
     26         'info_dict': {
     27             'id': 'the-comic-artist-and-his-assistants/s01e001',
     28             'ext': 'mp4',
     29             'title': 'the-comic-artist-and-his-assistants/s01e001',
     30             'series': 'the-comic-artist-and-his-assistants',
     31             'season_number': 1,
     32             'episode_number': 1,
     33         },
     34         'params': {
     35             'skip_download': True,
     36         },
     37         'skip': 'Requires Authentication',
     38     }]
     39 
     40     def _real_initialize(self):
     41         email, password = self._get_login_info()
     42         if email is None:
     43             return
     44 
     45         webpage = self._download_webpage(self._LOGIN_URL, None)
     46         form = self._search_regex(
     47             r'(?s)<form[^>]+action="/account/login"[^>]*>(.+?)</form>',
     48             webpage, 'login form')
     49         data = self._hidden_inputs(form)
     50         data.update({
     51             'Email': email,
     52             'Password': password,
     53         })
     54         self._download_webpage(
     55             self._LOGIN_URL, None, 'Logging in', data=urlencode_postdata(data))
     56 
     57     def _real_extract(self, url):
     58         mobj = re.match(self._VALID_URL, url)
     59         title, key = mobj.group('title', 'key')
     60         video_id = '%s/%s' % (title, key)
     61 
     62         settings = self._download_json(
     63             'https://www.hidive.com/play/settings', video_id,
     64             data=urlencode_postdata({
     65                 'Title': title,
     66                 'Key': key,
     67                 'PlayerId': 'f4f895ce1ca713ba263b91caeb1daa2d08904783',
     68             }))
     69 
     70         restriction = settings.get('restrictionReason')
     71         if restriction == 'RegionRestricted':
     72             self.raise_geo_restricted()
     73 
     74         if restriction and restriction != 'None':
     75             raise ExtractorError(
     76                 '%s said: %s' % (self.IE_NAME, restriction), expected=True)
     77 
     78         formats = []
     79         subtitles = {}
     80         for rendition_id, rendition in settings['renditions'].items():
     81             bitrates = rendition.get('bitrates')
     82             if not isinstance(bitrates, dict):
     83                 continue
     84             m3u8_url = url_or_none(bitrates.get('hls'))
     85             if not m3u8_url:
     86                 continue
     87             formats.extend(self._extract_m3u8_formats(
     88                 m3u8_url, video_id, 'mp4', entry_protocol='m3u8_native',
     89                 m3u8_id='%s-hls' % rendition_id, fatal=False))
     90             cc_files = rendition.get('ccFiles')
     91             if not isinstance(cc_files, list):
     92                 continue
     93             for cc_file in cc_files:
     94                 if not isinstance(cc_file, list) or len(cc_file) < 3:
     95                     continue
     96                 cc_lang = cc_file[0]
     97                 cc_url = url_or_none(cc_file[2])
     98                 if not isinstance(cc_lang, compat_str) or not cc_url:
     99                     continue
    100                 subtitles.setdefault(cc_lang, []).append({
    101                     'url': cc_url,
    102                 })
    103         self._sort_formats(formats)
    104 
    105         season_number = int_or_none(self._search_regex(
    106             r's(\d+)', key, 'season number', default=None))
    107         episode_number = int_or_none(self._search_regex(
    108             r'e(\d+)', key, 'episode number', default=None))
    109 
    110         return {
    111             'id': video_id,
    112             'title': video_id,
    113             'subtitles': subtitles,
    114             'formats': formats,
    115             'series': title,
    116             'season_number': season_number,
    117             'episode_number': episode_number,
    118         }