+class FunimationPageIE(InfoExtractor):
+ IE_NAME = 'funimation:page'
+ _VALID_URL = r'(?P<origin>https?://(?:www\.)?funimation(?:\.com|now\.uk))/(?P<lang>[^/]+/)?(?P<path>shows/(?P<id>[^/]+/[^/?#&]+).*$)'
+
+ _TESTS = [{
+ 'url': 'https://www.funimation.com/shows/attack-on-titan-junior-high/broadcast-dub-preview/',
+ 'info_dict': {
+ 'id': '210050',
+ 'ext': 'mp4',
+ 'title': 'Broadcast Dub Preview',
+ # Other metadata is tested in FunimationIE
+ },
+ 'params': {
+ 'skip_download': 'm3u8',
+ },
+ 'add_ie': ['Funimation'],
+ }, {
+ # Not available in US
+ 'url': 'https://www.funimation.com/shows/hacksign/role-play/',
+ 'only_matching': True,
+ }, {
+ # with lang code
+ 'url': 'https://www.funimation.com/en/shows/hacksign/role-play/',
+ 'only_matching': True,
+ }, {
+ 'url': 'https://www.funimationnow.uk/shows/puzzle-dragons-x/drop-impact/simulcast/',
+ 'only_matching': True,
+ }]
+
+ def _real_extract(self, url):
+ mobj = re.match(self._VALID_URL, url)
+ display_id = mobj.group('id').replace('/', '_')
+ if not mobj.group('lang'):
+ url = '%s/en/%s' % (mobj.group('origin'), mobj.group('path'))
+
+ webpage = self._download_webpage(url, display_id)
+ title_data = self._parse_json(self._search_regex(
+ r'TITLE_DATA\s*=\s*({[^}]+})',
+ webpage, 'title data', default=''),
+ display_id, js_to_json, fatal=False) or {}
+
+ video_id = (
+ title_data.get('id')
+ or self._search_regex(
+ (r"KANE_customdimensions.videoID\s*=\s*'(\d+)';", r'<iframe[^>]+src="/player/(\d+)'),
+ webpage, 'video_id', default=None)
+ or self._search_regex(
+ r'/player/(\d+)',
+ self._html_search_meta(['al:web:url', 'og:video:url', 'og:video:secure_url'], webpage, fatal=True),
+ 'video id'))
+ return self.url_result(f'https://www.funimation.com/player/{video_id}', FunimationIE.ie_key(), video_id)
+
+