]>
Raphaƫl G. Git Repositories - youtubedl/blob - youtube_dl/extractor/funimation.py
   2 from __future__ 
import unicode_literals
 
   7 from .common 
import InfoExtractor
 
   8 from ..compat 
import compat_HTTPError
 
  18 class FunimationIE(InfoExtractor
): 
  19     _VALID_URL 
= r
'https?://(?:www\.)?funimation(?:\.com|now\.uk)/shows/[^/]+/(?P<id>[^/?#&]+)' 
  21     _NETRC_MACHINE 
= 'funimation' 
  25         'url': 'https://www.funimation.com/shows/hacksign/role-play/', 
  28             'display_id': 'role-play', 
  30             'title': '.hack//SIGN - Role Play', 
  31             'description': 'md5:b602bdc15eef4c9bbb201bb6e6a4a2dd', 
  32             'thumbnail': r
're:https?://.*\.jpg', 
  36             'skip_download': True, 
  39         'url': 'https://www.funimation.com/shows/attack-on-titan-junior-high/broadcast-dub-preview/', 
  42             'display_id': 'broadcast-dub-preview', 
  44             'title': 'Attack on Titan: Junior High - Broadcast Dub Preview', 
  45             'thumbnail': r
're:https?://.*\.(?:jpg|png)', 
  49             'skip_download': True, 
  52         'url': 'https://www.funimationnow.uk/shows/puzzle-dragons-x/drop-impact/simulcast/', 
  53         'only_matching': True, 
  57         username
, password 
= self
._get
_login
_info
() 
  61             data 
= self
._download
_json
( 
  62                 'https://prod-api-funimationnow.dadcdigital.com/api/auth/login/', 
  63                 None, 'Logging in', data
=urlencode_postdata({ 
  67             self
._TOKEN 
= data
['token'] 
  68         except ExtractorError 
as e
: 
  69             if isinstance(e
.cause
, compat_HTTPError
) and e
.cause
.code 
== 401: 
  70                 error 
= self
._parse
_json
(e
.cause
.read().decode(), None)['error'] 
  71                 raise ExtractorError(error
, expected
=True) 
  74     def _real_initialize(self
): 
  77     def _real_extract(self
, url
): 
  78         display_id 
= self
._match
_id
(url
) 
  79         webpage 
= self
._download
_webpage
(url
, display_id
) 
  81         def _search_kane(name
): 
  82             return self
._search
_regex
( 
  83                 r
"KANE_customdimensions\.%s\s*=\s*'([^']+)';" % name
, 
  84                 webpage
, name
, default
=None) 
  86         title_data 
= self
._parse
_json
(self
._search
_regex
( 
  87             r
'TITLE_DATA\s*=\s*({[^}]+})', 
  88             webpage
, 'title data', default
=''), 
  89             display_id
, js_to_json
, fatal
=False) or {} 
  91         video_id 
= title_data
.get('id') or self
._search
_regex
([ 
  92             r
"KANE_customdimensions.videoID\s*=\s*'(\d+)';", 
  93             r
'<iframe[^>]+src="/player/(\d+)', 
  94         ], webpage
, 'video_id', default
=None) 
  96             player_url 
= self
._html
_search
_meta
([ 
  99                 'og:video:secure_url', 
 100             ], webpage
, fatal
=True) 
 101             video_id 
= self
._search
_regex
(r
'/player/(\d+)', player_url
, 'video id') 
 103         title 
= episode 
= title_data
.get('title') or _search_kane('videoTitle') or self
._og
_search
_title
(webpage
) 
 104         series 
= _search_kane('showName') 
 106             title 
= '%s - %s' % (series
, title
) 
 107         description 
= self
._html
_search
_meta
(['description', 'og:description'], webpage
, fatal
=True) 
 112                 headers
['Authorization'] = 'Token %s' % self
._TOKEN
 
 113             sources 
= self
._download
_json
( 
 114                 'https://www.funimation.com/api/showexperience/%s/' % video_id
, 
 115                 video_id
, headers
=headers
, query
={ 
 116                     'pinst_id': ''.join([random
.choice(string
.digits 
+ string
.ascii_letters
) for _ 
in range(8)]), 
 118         except ExtractorError 
as e
: 
 119             if isinstance(e
.cause
, compat_HTTPError
) and e
.cause
.code 
== 403: 
 120                 error 
= self
._parse
_json
(e
.cause
.read(), video_id
)['errors'][0] 
 121                 raise ExtractorError('%s said: %s' % ( 
 122                     self
.IE_NAME
, error
.get('detail') or error
.get('title')), expected
=True) 
 126         for source 
in sources
: 
 127             source_url 
= source
.get('src') 
 130             source_type 
= source
.get('videoType') or determine_ext(source_url
) 
 131             if source_type 
== 'm3u8': 
 132                 formats
.extend(self
._extract
_m
3u8_formats
( 
 133                     source_url
, video_id
, 'mp4', 
 134                     m3u8_id
='hls', fatal
=False)) 
 137                     'format_id': source_type
, 
 140         self
._sort
_formats
(formats
) 
 144             'display_id': display_id
, 
 146             'description': description
, 
 147             'thumbnail': self
._og
_search
_thumbnail
(webpage
), 
 149             'season_number': int_or_none(title_data
.get('seasonNum') or _search_kane('season')), 
 150             'episode_number': int_or_none(title_data
.get('episodeNum')), 
 152             'season_id': title_data
.get('seriesId'),