Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/bbc.py (Python)

Code before:
                    })

            for resp in traverse_obj(initial_data, ('data', lambda _, v: v.get('name'))):
                name = resp['name']
            for resp in (initial_data.get('data') or {}).values():
                name = resp.get('name')
                if name == 'media-experience':
                    parse_media(try_get(resp, lambda x: x['data']['initialItem']['mediaItem'], dict))
                elif name == 'article':
                    for block in traverse_obj(resp, ('data', (
                            None, ('content', 'model')), 'blocks',
                            lambda _, v: v.get('type') in {'media', 'video'},
                            'model', {dict})):
                        parse_media(block)
            return self.playlist_result(
                entries, playlist_id, playlist_title, playlist_description)

        def extract_all(pattern):
            return list(filter(None, map(
                lambda s: self._parse_json(s, playlist_id, fatal=False),
                re.findall(pattern, webpage))))

        # US accessed article with single embedded video (e.g.
        # https://www.bbc.com/news/uk-68546268)
        next_data = traverse_obj(self._search_nextjs_data(webpage, playlist_id, default={}), (
            'props', 'pageProps', 'page'))
        model = traverse_obj(next_data, (
            ..., 'contents', lambda _, v: v['type'] == 'video',
            'model', 'blocks', lambda _, v: v['type'] == 'media',
            'model', 'blocks', lambda _, v: v['type'] == 'mediaMetadata',
            'model', {dict}, any))
        if model:
            entry = parse_model(model)
            if entry:
                if entry.get('timestamp') is None:
                    entry['timestamp'] = traverse_obj(next_data, (
                        ..., 'contents', lambda _, v: v['type'] == 'timestamp',
                        'model', 'timestamp', {k_int_or_none}, any))
                entries.append(entry)
                return self.playlist_result(
                    entries, playlist_id, playlist_title, playlist_description)

        # Multiple video article (e.g.
        # http://www.bbc.co.uk/blogs/adamcurtis/entries/3662a707-0af9-3149-963f-47bea720b460)
        EMBED_URL = r'https?://(?:www\.)?bbc\.co\.uk/(?:[^/]+/)+%s(?:\b[^"]+)?' % self._ID_REGEX
        entries = []
        for match in extract_all(r'new\s+SMP\(({.+?})\)'):
            embed_url = match.get('playerSettings', {}).get('externalEmbedUrl')
            if embed_url and re.match(EMBED_URL, embed_url):
                entries.append(embed_url)
        entries.extend(re.findall(

Review comment (suggestion):
```suggestion
        next_data = traverse_obj(self._search_nextjs_data(webpage, playlist_id, default={}),
                                 ('props', 'pageProps', 'page'))
```

Code after:
                            is_type('media', 'video'), 'model', {dict})):
                        parse_media(block)
            return self.playlist_result(
                entries, playlist_id, playlist_title, playlist_description)

        # extract from SIMORGH_DATA hydration JSON
        simorgh_data = self._search_json(
            r'window\s*\.\s*SIMORGH_DATA\s*=', webpage,
            'simorgh data', playlist_id, default={})
        if simorgh_data:
            done = False
            for video_data in traverse_obj(simorgh_data, (
                    'pageData', 'content', 'model', 'blocks', is_type('video', 'legacyMedia'))):
                model = traverse_obj(video_data, (
                    'model', 'blocks', is_type('aresMedia'),
                    'model', 'blocks', is_type('aresMediaMetadata'),
                    'model', {dict}, any))
                if video_data['type'] == 'video':
                    entry = parse_model(model)
                else:  # legacyMedia: no duration, subtitles
                    block_id, entry = traverse_obj(model, ('blockId', {str})), None
                    media_data = traverse_obj(simorgh_data, (
                        'pageData', 'promo', 'media',
                        {lambda x: x if x['id'] == block_id else None}))
                    formats = traverse_obj(media_data, ('playlist', lambda _, v: url_or_none(v['url']), {
                        'url': ('url', {url_or_none}),
                        'ext': ('format', {str}),
                        'tbr': ('bitrate', {functools.partial(int_or_none, scale=1000)}),
                    }))
                    if formats:
                        entry = {
                            'id': block_id,
                            'display_id': playlist_id,
                            'formats': formats,
                            'description': traverse_obj(simorgh_data, ('pageData', 'promo', 'summary', {str})),
                            **traverse_obj(model, {
                                'title': ('title', {str}),
                                'thumbnail': ('imageUrl', {lambda u: urljoin(url, u.replace('$recipe', 'raw'))}),
                                'description': ('synopses', ('long', 'medium', 'short'), {str}, any),
                                'timestamp': ('firstPublished', {functools.partial(int_or_none, scale=1000)}),
                            }),
                        }
                        done = True
                if entry:
                    entries.append(entry)
                if done:
                    break
            if entries:
                return self.playlist_result(
                    entries, playlist_id, playlist_title, playlist_description)