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

Code before:
    _TESTS = [{
        'url': 'https://www.bilibili.com/bangumi/media/md24097891',
        'info_dict': {
            'id': '24097891',
        },
        'playlist_mincount': 25,
    }]

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

        initial_state = self._search_json(r'window\.__INITIAL_STATE__\s*=', webpage, 'initial_state', media_id)
        episode_list = traverse_obj(
            self._download_json('https://api.bilibili.com/pgc/web/season/section', media_id,
                                query={'season_id': traverse_obj(initial_state, ('mediaInfo', 'season_id'))},
                                headers={'Referer': url, **self.geo_verification_headers()},
                                note='Downloading season info'),
            ('result', 'main_section', 'episodes'))

        return self.playlist_result((
            self.url_result(entry['share_url'], BiliBiliBangumiEpisodeIE, entry['id'])
            for entry in episode_list), media_id)


class BiliBiliBangumiSeasonIE(InfoExtractor):
    _VALID_URL = r'(?x)https?://www\.bilibili\.com/bangumi/play/ss(?P<id>\d+)$'
    _TESTS = [{
        'url': 'https://www.bilibili.com/bangumi/play/ss26801',
        'info_dict': {
            'id': '26801'
        },
        'playlist_mincount': 26
    }]

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

        episode_list = traverse_obj(
            self._download_json('https://api.bilibili.com/pgc/web/season/section', ss_id,
                                query={'season_id': ss_id},
                                headers={'Referer': url, **self.geo_verification_headers()},
                                note='Downloading season info'),
            ('result', 'main_section', 'episodes'))

        return self.playlist_result((
            self.url_result(entry['share_url'], BiliBiliBangumiEpisodeIE, entry['id'])
            for entry in episode_list), ss_id)


class BilibiliSpaceBaseIE(InfoExtractor):

Review comment (suggestion):
this is almost the same code as the `BiliBiliBangumiMediaIE`, maybe a baseclass would make sense? (and it also needs the same suggested changes applied)

Code after:
            'episode_id': episode_id,
            'episode_number': int_or_none(episode_info.get('title')) or episode_number,
            'season_id': str_or_none(season_id),
            'season_number': season_number,
            'timestamp': int_or_none(episode_info.get('pub_time')),
            'duration': float_or_none(play_info.get('timelength'), scale=1000),
            'subtitles': self.extract_subtitles(video_id, aid, episode_info.get('cid')),
            '__post_extractor': self.extract_comments(aid),
            'http_headers': headers,
        }


class BiliBiliBangumiMediaIE(BilibiliBaseIE):
    _VALID_URL = r'https?://www\.bilibili\.com/bangumi/media/md(?P<id>\d+)'
    _TESTS = [{
        'url': 'https://www.bilibili.com/bangumi/media/md24097891',
        'info_dict': {
            'id': '24097891',
        },
        'playlist_mincount': 25,
    }]

    def _real_extract(self, url):
        media_id = self._match_id(url)
        webpage = self._download_webpage(url, media_id)
        ss_id = self._search_json(
            r'window\.__INITIAL_STATE__\s*=', webpage, 'initial_state', media_id)['mediaInfo']['season_id']

        return self.playlist_result(self._get_episodes_from_season(ss_id, url), media_id)


class BiliBiliBangumiSeasonIE(BilibiliBaseIE):
    _VALID_URL = r'(?x)https?://www\.bilibili\.com/bangumi/play/ss(?P<id>\d+)'
    _TESTS = [{
        'url': 'https://www.bilibili.com/bangumi/play/ss26801',
        'info_dict': {
            'id': '26801'
        },
        'playlist_mincount': 26
    }]

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

        return self.playlist_result(self._get_episodes_from_season(ss_id, url), ss_id)


class BilibiliSpaceBaseIE(InfoExtractor):
    def _extract_playlist(self, fetch_page, get_metadata, get_entries):
        first_page = fetch_page(0)
        metadata = get_metadata(first_page)