mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-11-04 08:35:12 +00:00 
			
		
		
		
	[extractor/nhk] Fix API extraction (#7180)
Closes #6992 Authored by: sjthespian, menschel Co-authored-by: Patrick Menschel <menschel.p@posteo.de>
This commit is contained in:
		@@ -67,7 +67,7 @@ class NhkBaseIE(InfoExtractor):
 | 
				
			|||||||
            info.update({
 | 
					            info.update({
 | 
				
			||||||
                '_type': 'url_transparent',
 | 
					                '_type': 'url_transparent',
 | 
				
			||||||
                'ie_key': 'Piksel',
 | 
					                'ie_key': 'Piksel',
 | 
				
			||||||
                'url': 'https://player.piksel.com/v/refid/nhkworld/prefid/' + vod_id,
 | 
					                'url': 'https://movie-s.nhk.or.jp/v/refid/nhkworld/prefid/' + vod_id,
 | 
				
			||||||
                'id': vod_id,
 | 
					                'id': vod_id,
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
@@ -94,6 +94,19 @@ class NhkVodIE(NhkBaseIE):
 | 
				
			|||||||
    # Content available only for a limited period of time. Visit
 | 
					    # Content available only for a limited period of time. Visit
 | 
				
			||||||
    # https://www3.nhk.or.jp/nhkworld/en/ondemand/ for working samples.
 | 
					    # https://www3.nhk.or.jp/nhkworld/en/ondemand/ for working samples.
 | 
				
			||||||
    _TESTS = [{
 | 
					    _TESTS = [{
 | 
				
			||||||
 | 
					        'url': 'https://www3.nhk.or.jp/nhkworld/en/ondemand/video/2061601/',
 | 
				
			||||||
 | 
					        'info_dict': {
 | 
				
			||||||
 | 
					            'id': 'yd8322ch',
 | 
				
			||||||
 | 
					            'ext': 'mp4',
 | 
				
			||||||
 | 
					            'description': 'md5:109c8b05d67a62d0592f2b445d2cd898',
 | 
				
			||||||
 | 
					            'title': 'GRAND SUMO Highlights - [Recap] May Tournament Day 1 (Opening Day)',
 | 
				
			||||||
 | 
					            'upload_date': '20230514',
 | 
				
			||||||
 | 
					            'timestamp': 1684083791,
 | 
				
			||||||
 | 
					            'series': 'GRAND SUMO Highlights',
 | 
				
			||||||
 | 
					            'episode': '[Recap] May Tournament Day 1 (Opening Day)',
 | 
				
			||||||
 | 
					            'thumbnail': 'https://mz-edge.stream.co.jp/thumbs/aid/t1684084443/4028649.jpg?w=1920&h=1080',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    }, {
 | 
				
			||||||
        # video clip
 | 
					        # video clip
 | 
				
			||||||
        'url': 'https://www3.nhk.or.jp/nhkworld/en/ondemand/video/9999011/',
 | 
					        'url': 'https://www3.nhk.or.jp/nhkworld/en/ondemand/video/9999011/',
 | 
				
			||||||
        'md5': '7a90abcfe610ec22a6bfe15bd46b30ca',
 | 
					        'md5': '7a90abcfe610ec22a6bfe15bd46b30ca',
 | 
				
			||||||
@@ -104,6 +117,9 @@ class NhkVodIE(NhkBaseIE):
 | 
				
			|||||||
            'description': 'md5:5aee4a9f9d81c26281862382103b0ea5',
 | 
					            'description': 'md5:5aee4a9f9d81c26281862382103b0ea5',
 | 
				
			||||||
            'timestamp': 1565965194,
 | 
					            'timestamp': 1565965194,
 | 
				
			||||||
            'upload_date': '20190816',
 | 
					            'upload_date': '20190816',
 | 
				
			||||||
 | 
					            'thumbnail': 'https://mz-edge.stream.co.jp/thumbs/aid/t1567086278/3715195.jpg?w=1920&h=1080',
 | 
				
			||||||
 | 
					            'series': 'Dining with the Chef',
 | 
				
			||||||
 | 
					            'episode': 'Chef Saito\'s Family recipe: MENCHI-KATSU',
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    }, {
 | 
					    }, {
 | 
				
			||||||
        # audio clip
 | 
					        # audio clip
 | 
				
			||||||
@@ -114,10 +130,7 @@ class NhkVodIE(NhkBaseIE):
 | 
				
			|||||||
            'title': "Japan's Top Inventions - Miniature Video Cameras",
 | 
					            'title': "Japan's Top Inventions - Miniature Video Cameras",
 | 
				
			||||||
            'description': 'md5:07ea722bdbbb4936fdd360b6a480c25b',
 | 
					            'description': 'md5:07ea722bdbbb4936fdd360b6a480c25b',
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        'params': {
 | 
					        'skip': '404 Not Found',
 | 
				
			||||||
            # m3u8 download
 | 
					 | 
				
			||||||
            'skip_download': True,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    }, {
 | 
					    }, {
 | 
				
			||||||
        'url': 'https://www3.nhk.or.jp/nhkworld/en/ondemand/video/2015173/',
 | 
					        'url': 'https://www3.nhk.or.jp/nhkworld/en/ondemand/video/2015173/',
 | 
				
			||||||
        'only_matching': True,
 | 
					        'only_matching': True,
 | 
				
			||||||
@@ -133,7 +146,6 @@ class NhkVodIE(NhkBaseIE):
 | 
				
			|||||||
    }, {
 | 
					    }, {
 | 
				
			||||||
        # video, alphabetic character in ID #29670
 | 
					        # video, alphabetic character in ID #29670
 | 
				
			||||||
        'url': 'https://www3.nhk.or.jp/nhkworld/en/ondemand/video/9999a34/',
 | 
					        'url': 'https://www3.nhk.or.jp/nhkworld/en/ondemand/video/9999a34/',
 | 
				
			||||||
        'only_matching': True,
 | 
					 | 
				
			||||||
        'info_dict': {
 | 
					        'info_dict': {
 | 
				
			||||||
            'id': 'qfjay6cg',
 | 
					            'id': 'qfjay6cg',
 | 
				
			||||||
            'ext': 'mp4',
 | 
					            'ext': 'mp4',
 | 
				
			||||||
@@ -142,7 +154,8 @@ class NhkVodIE(NhkBaseIE):
 | 
				
			|||||||
            'thumbnail': r're:^https?:/(/[a-z0-9.-]+)+\.jpg\?w=1920&h=1080$',
 | 
					            'thumbnail': r're:^https?:/(/[a-z0-9.-]+)+\.jpg\?w=1920&h=1080$',
 | 
				
			||||||
            'upload_date': '20210615',
 | 
					            'upload_date': '20210615',
 | 
				
			||||||
            'timestamp': 1623722008,
 | 
					            'timestamp': 1623722008,
 | 
				
			||||||
        }
 | 
					        },
 | 
				
			||||||
 | 
					        'skip': '404 Not Found',
 | 
				
			||||||
    }]
 | 
					    }]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _real_extract(self, url):
 | 
					    def _real_extract(self, url):
 | 
				
			||||||
@@ -153,12 +166,19 @@ class NhkVodProgramIE(NhkBaseIE):
 | 
				
			|||||||
    _VALID_URL = r'%s/program%s(?P<id>[0-9a-z]+)(?:.+?\btype=(?P<episode_type>clip|(?:radio|tv)Episode))?' % (NhkBaseIE._BASE_URL_REGEX, NhkBaseIE._TYPE_REGEX)
 | 
					    _VALID_URL = r'%s/program%s(?P<id>[0-9a-z]+)(?:.+?\btype=(?P<episode_type>clip|(?:radio|tv)Episode))?' % (NhkBaseIE._BASE_URL_REGEX, NhkBaseIE._TYPE_REGEX)
 | 
				
			||||||
    _TESTS = [{
 | 
					    _TESTS = [{
 | 
				
			||||||
        # video program episodes
 | 
					        # video program episodes
 | 
				
			||||||
 | 
					        'url': 'https://www3.nhk.or.jp/nhkworld/en/ondemand/program/video/sumo',
 | 
				
			||||||
 | 
					        'info_dict': {
 | 
				
			||||||
 | 
					            'id': 'sumo',
 | 
				
			||||||
 | 
					            'title': 'GRAND SUMO Highlights',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        'playlist_mincount': 12,
 | 
				
			||||||
 | 
					    }, {
 | 
				
			||||||
        'url': 'https://www3.nhk.or.jp/nhkworld/en/ondemand/program/video/japanrailway',
 | 
					        'url': 'https://www3.nhk.or.jp/nhkworld/en/ondemand/program/video/japanrailway',
 | 
				
			||||||
        'info_dict': {
 | 
					        'info_dict': {
 | 
				
			||||||
            'id': 'japanrailway',
 | 
					            'id': 'japanrailway',
 | 
				
			||||||
            'title': 'Japan Railway Journal',
 | 
					            'title': 'Japan Railway Journal',
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        'playlist_mincount': 1,
 | 
					        'playlist_mincount': 12,
 | 
				
			||||||
    }, {
 | 
					    }, {
 | 
				
			||||||
        # video program clips
 | 
					        # video program clips
 | 
				
			||||||
        'url': 'https://www3.nhk.or.jp/nhkworld/en/ondemand/program/video/japanrailway/?type=clip',
 | 
					        'url': 'https://www3.nhk.or.jp/nhkworld/en/ondemand/program/video/japanrailway/?type=clip',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,8 +7,10 @@ from ..utils import (
 | 
				
			|||||||
    int_or_none,
 | 
					    int_or_none,
 | 
				
			||||||
    join_nonempty,
 | 
					    join_nonempty,
 | 
				
			||||||
    parse_iso8601,
 | 
					    parse_iso8601,
 | 
				
			||||||
 | 
					    traverse_obj,
 | 
				
			||||||
    try_get,
 | 
					    try_get,
 | 
				
			||||||
    unescapeHTML,
 | 
					    unescapeHTML,
 | 
				
			||||||
 | 
					    urljoin,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -63,11 +65,11 @@ class PikselIE(InfoExtractor):
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _call_api(self, app_token, resource, display_id, query, fatal=True):
 | 
					    def _call_api(self, app_token, resource, display_id, query, host='https://player.piksel.com', fatal=True):
 | 
				
			||||||
        response = (self._download_json(
 | 
					        url = urljoin(host, f'/ws/ws_{resource}/api/{app_token}/mode/json/apiv/5')
 | 
				
			||||||
            'http://player.piksel.com/ws/ws_%s/api/%s/mode/json/apiv/5' % (resource, app_token),
 | 
					        response = traverse_obj(
 | 
				
			||||||
            display_id, query=query, fatal=fatal) or {}).get('response')
 | 
					            self._download_json(url, display_id, query=query, fatal=fatal), ('response', {dict})) or {}
 | 
				
			||||||
        failure = try_get(response, lambda x: x['failure']['reason'])
 | 
					        failure = traverse_obj(response, ('failure', 'reason')) if response else 'Empty response from API'
 | 
				
			||||||
        if failure:
 | 
					        if failure:
 | 
				
			||||||
            if fatal:
 | 
					            if fatal:
 | 
				
			||||||
                raise ExtractorError(failure, expected=True)
 | 
					                raise ExtractorError(failure, expected=True)
 | 
				
			||||||
@@ -83,7 +85,7 @@ class PikselIE(InfoExtractor):
 | 
				
			|||||||
        ], webpage, 'app token')
 | 
					        ], webpage, 'app token')
 | 
				
			||||||
        query = {'refid': ref_id, 'prefid': display_id} if ref_id else {'v': display_id}
 | 
					        query = {'refid': ref_id, 'prefid': display_id} if ref_id else {'v': display_id}
 | 
				
			||||||
        program = self._call_api(
 | 
					        program = self._call_api(
 | 
				
			||||||
            app_token, 'program', display_id, query)['WsProgramResponse']['program']
 | 
					            app_token, 'program', display_id, query, url)['WsProgramResponse']['program']
 | 
				
			||||||
        video_id = program['uuid']
 | 
					        video_id = program['uuid']
 | 
				
			||||||
        video_data = program['asset']
 | 
					        video_data = program['asset']
 | 
				
			||||||
        title = video_data['title']
 | 
					        title = video_data['title']
 | 
				
			||||||
@@ -129,7 +131,7 @@ class PikselIE(InfoExtractor):
 | 
				
			|||||||
                process_asset_files(try_get(self._call_api(
 | 
					                process_asset_files(try_get(self._call_api(
 | 
				
			||||||
                    app_token, 'asset_file', display_id, {
 | 
					                    app_token, 'asset_file', display_id, {
 | 
				
			||||||
                        'assetid': asset_id,
 | 
					                        'assetid': asset_id,
 | 
				
			||||||
                    }, False), lambda x: x['WsAssetFileResponse']['AssetFiles']))
 | 
					                    }, url, False), lambda x: x['WsAssetFileResponse']['AssetFiles']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        m3u8_url = dict_get(video_data, [
 | 
					        m3u8_url = dict_get(video_data, [
 | 
				
			||||||
            'm3u8iPadURL',
 | 
					            'm3u8iPadURL',
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user