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

Code before:
            'upload_date': '20190102',
            'title': 'Overnight Oats',
            'creator': 'Genevieve Ko',
            'thumbnail': r're:https?://\w+\.nyt.com/images/.*\.jpg',
        }
    }]

    def _real_extract(self, url):
        page_id = self._match_id(url)
        webpage = self._download_webpage(url, page_id)

        json_obj = traverse_obj(
            self._search_nextjs_data(webpage, page_id), ('props', 'pageProps'), default={})

        info = traverse_obj(json_obj, {
            'id': ('recipe', 'id', {str_or_none}),
            'title': ('recipe', 'title'),
            'description': ('recipe', 'topnote', {clean_html}),
            'timestamp': ('recipe', 'publishedAt'),
            'creator': ('recipe', 'contentAttribution', 'cardByline'),
            'upload_date': ('meta', 'jsonLD', 'video', 'uploadDate', {unified_strdate}),
            'formats': ('recipe', 'videoSrc', {url_or_none}),
        })

        formats, subtitles = self._extract_m3u8_formats_and_subtitles(
            info.get('formats'), info.get('id'), 'mp4', entry_protocol='m3u8_native', m3u8_id='hls')

        thumbnails = []
        for image in traverse_obj(json_obj, ('recipe', 'image', 'crops', 'recipe', ...)):
            if not url_or_none(image):
                continue
            thumbnails.append({
                'url': image,
            })

        return {
            'id': info.get('id'),
            'title': info.get('title'),
            'description': info.get('description'),
            'timestamp': info.get('timestamp'),
            'upload_date': info.get(' upload_date'),
            'creator': info.get('creator'),
            'formats': formats,
            'subtitles': subtitles,
            'thumbnails': thumbnails,
        }


class NYTimesCookingGuidesIE(NYTimesBaseIE):
    _VALID_URL = r'https?://cooking\.nytimes\.com/guides/(?P<id>[\w-]+)'
    _TESTS = [{

Review comment (refactor):
`entry_protocol='m3u8_native'` is the default

just use `page_id` matched from the url for the video id -- it looks like it's the same as what's found in the next js data

and again, the `_extract_m3u8_formats` call here is fatal so it's fine to risk a KeyError too
```suggestion
            next_data['recipe']['videoSrc'], page_id, 'mp4', m3u8_id='hls')
```

Code after:
    _VALID_URL = r'https?://cooking\.nytimes\.com/guides/(?P<id>[\w-]+)'
    _TESTS = [{
        'url': 'https://cooking.nytimes.com/guides/13-how-to-cook-a-turkey',
        'info_dict': {
            'id': '13-how-to-cook-a-turkey',
            'title': 'How to Cook a Turkey',
            'description': 'md5:726cfd3f9b161bdf5c279879e8050ca0',
        },
        'playlist_count': 2,
    }, {
        # single video example
        'url': 'https://cooking.nytimes.com/guides/50-how-to-make-mac-and-cheese',
        'md5': '64415805fe0b8640fce6b0b9def5989a',
        'info_dict': {
            'id': '100000005835845',
            'ext': 'mp4',
            'title': 'How to Make Mac and Cheese',
            'description': 'md5:b8f2f33ec1fb7523b21367147c9594f1',
            'duration': 9.51,
            'creator': 'Alison Roman',
            'thumbnail': r're:https?://\w+\.nyt.com/images/.*\.jpg',
        },
    }, {
        'url': 'https://cooking.nytimes.com/guides/20-how-to-frost-a-cake',
        'md5': '64415805fe0b8640fce6b0b9def5989a',
        'info_dict': {
            'id': '20-how-to-frost-a-cake',
            'title': 'How to Frost a Cake',
            'description': 'md5:a31fe3b98a8ce7b98aae097730c269cd',
        },
        'playlist_count': 8,
    }]

    def _real_extract(self, url):
        page_id = self._match_id(url)
        webpage = self._download_webpage(url, page_id)
        title = self._html_search_meta(['og:title', 'twitter:title'], webpage)
        description = self._html_search_meta(['og:description', 'twitter:description'], webpage)

        lead_video_id = self._search_regex(
            r'data-video-player-id="(\d+)"></div>', webpage, 'lead video')
        media_ids = traverse_obj(
            get_elements_html_by_class('video-item', webpage), (..., {extract_attributes}, 'data-video-id'))

        if media_ids:
            media_ids.append(lead_video_id)
            return self.playlist_result(
                [self._extract_video(media_id) for media_id in media_ids], page_id, title, description)

        return {
            **self._extract_video(lead_video_id),