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

Code before:
        ]
    }]

    def _real_extract(self, url):
        playlist_id = self._match_id(url)

        webpage = self._download_webpage(url, playlist_id)
        playlist = get_element_by_class('playlist', webpage)

        # handle cases which match _VALID_URL, but no element is found
        if playlist is None:
            try:
                iframe = get_element_text_and_html_by_tag('iframe', webpage)
            except ValueError:
                iframe = None

            # handle iframes instead of playlist
            if iframe is not None:
                attr = extract_attributes(iframe[1])
                iframesrc = attr['src']
                # handle spotify explicitly
                if iframesrc is not None and re.match(r'https?://(?:www\.|open\.)?spotify\.com', iframesrc):
                    raise ExtractorError('no playlist found, but iframe with spotify', expected=True)
                raise ExtractorError('no playlist element found, but a unhandled iframe')

            raise ExtractorError('no playlist element found - likely not a album', expected=True)

        entries = []
        for track_number, track in enumerate(re.findall(r'(<li[^>]+data-audiopath[^>]+>)', playlist), 1):
            entry = traverse_obj(extract_attributes(track), {
                'url': ('data-audiopath', {url_or_none}),
                'ext': ('data-audiopath', {determine_ext}),
                'id': 'data-trackid',
                'title': 'data-tracktitle',
                'track': 'data-tracktitle',
                'album': 'data-albumtitle',
                'duration': ('data-tracktime', {parse_duration}),
                'release_date': ('data-releasedate', {lambda x: re.match(r'\d{8}', x.replace('.', ''))}, 0),
                'thumbnail': ('data-albumart', {url_or_none}),
            })
            entry['track_number'] = track_number
            entry['artist'] = 'Nekohacker'
            entry['vcodec'] = 'none'
            entry['acodec'] = 'mp3' if entry['ext'] == 'mp3' else None
            entries.append(entry)

        return self.playlist_result(entries, playlist_id, traverse_obj(entries, (0, 'album')))


Review comment (refactor):
 - `utils.try_call` makes it easy when you're setting a var and need a simple try/except

 - I think we don't want to expect the first ExtractorError in my suggestion, since if neither a playlist or iframe is found in the page, that means the website's overall format could have changed and we'd want that to be reported.

 - If the iframe embed is not Spotify, we could try returning the webpage URL as a `url_result` to the generic extractor and seeing if it can detect any embeds that yt-dlp supports (if not it will raise UnsupportedError)
```suggestion
        if not playlist:
            iframe = try_call(lambda: get_element_text_and_html_by_tag('iframe', webpage)[1]) or ''
            iframe_src = url_or_none(extract_attributes(iframe).get('src'))
            if not iframe_src:
                raise ExtractorError('No playlist or embed found in webpage')
            elif re.match(r'https?://(?:\w+\.)?spotify\.com/', iframe_src):
                raise ExtractorError('Spotify embeds are not supported', expected=True)
            return self.url_result(url, 'Generic')
```

Code after:
            }
        ]
    }]

    def _real_extract(self, url):
        playlist_id = self._match_id(url)

        webpage = self._download_webpage(url, playlist_id)
        playlist = get_element_by_class('playlist', webpage)

        if not playlist:
            iframe = try_call(lambda: get_element_text_and_html_by_tag('iframe', webpage)[1]) or ''
            iframe_src = url_or_none(extract_attributes(iframe).get('src'))
            if not iframe_src:
                raise ExtractorError('No playlist or embed found in webpage')
            elif re.match(r'https?://(?:\w+\.)?spotify\.com/', iframe_src):
                raise ExtractorError('Spotify embeds are not supported', expected=True)
            return self.url_result(url, 'Generic')

        entries = []
        for track_number, track in enumerate(re.findall(r'(<li[^>]+data-audiopath[^>]+>)', playlist), 1):
            entry = traverse_obj(extract_attributes(track), {
                'url': ('data-audiopath', {url_or_none}),
                'ext': ('data-audiopath', {determine_ext}),
                'id': 'data-trackid',
                'title': 'data-tracktitle',
                'track': 'data-tracktitle',
                'album': 'data-albumtitle',
                'duration': ('data-tracktime', {parse_duration}),
                'release_date': ('data-releasedate', {lambda x: re.match(r'\d{8}', x.replace('.', ''))}, 0),
                'thumbnail': ('data-albumart', {url_or_none}),
            })
            entries.append({
                **entry,
                'track_number': track_number,
                'artist': 'Neko Hacker',
                'vcodec': 'none',
                'acodec': 'mp3' if entry['ext'] == 'mp3' else None,
            })

        return self.playlist_result(entries, playlist_id, traverse_obj(entries, (0, 'album')))