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

Code before:
                self._download_webpage(
                    self._API_URL % (list_id, page_num), list_id,
                    note='Downloading page %d' % page_num),
                list_id)['data']

            max_count = max_count or try_get(data, lambda x: x['page']['count'])

            entries = try_get(data, lambda x: x['list']['vlist'])
            if not entries:
                return
            for entry in entries:
                yield self.url_result(
                    'https://www.bilibili.com/video/%s' % entry['bvid'],
                    BiliBiliIE.ie_key(), entry['bvid'])

            count += len(entries)
            if max_count and count >= max_count:
                return

    def _real_extract(self, url):
        list_id = self._match_id(url)
        return self.playlist_result(self._entries(list_id), list_id)


# https://www.bilibili.com/v/kichiku/mad/#/
class BilibiliCategoryIE(SearchInfoExtractor):
    IE_NAME = 'Bilibili category extractor'
    _MAX_RESULTS = 1000000
    _VALID_URL = r'https?://www\.bilibili\.com/v/[a-zA-Z]+\/[a-zA-Z]+'
    _TESTS = [{
        'url': 'https://www.bilibili.com/v/kichiku/mad',
        'info_dict': {
            'id': 'kichiku: mad',
            'title': 'kichiku: mad'
        },
        'playlist_mincount': 45,
        'params': {
            'playlistend': 45
        }
    }]

    def _fetch_page(self, api_url, num_pages, query, page_num):
        time.sleep(2)

        parsed_json = self._download_json(
            api_url + '&pn=%s' % page_num, 'None', query={'Search_key': query},
            note='Extracting results from page %s of %s' % (page_num, num_pages))

        video_list = try_get(parsed_json, lambda x: x['data']['archives'], list)
        if not video_list:
            raise ExtractorError('failed to retrieve video list for page %d' % page_num)

Review comment (refactor):
Why inherit from `SearchInfoExtractor`? This is behaving like a normal `InfoExtractor`

Code after:
                    self._API_URL % (list_id, page_num), list_id,
                    note='Downloading page %d' % page_num),
                list_id)['data']

            max_count = max_count or try_get(data, lambda x: x['page']['count'])

            entries = try_get(data, lambda x: x['list']['vlist'])
            if not entries:
                return
            for entry in entries:
                yield self.url_result(
                    'https://www.bilibili.com/video/%s' % entry['bvid'],
                    BiliBiliIE.ie_key(), entry['bvid'])

            count += len(entries)
            if max_count and count >= max_count:
                return

    def _real_extract(self, url):
        list_id = self._match_id(url)
        return self.playlist_result(self._entries(list_id), list_id)


class BilibiliCategoryIE(InfoExtractor):
    IE_NAME = 'Bilibili category extractor'
    _MAX_RESULTS = 1000000
    _VALID_URL = r'https?://www\.bilibili\.com/v/[a-zA-Z]+\/[a-zA-Z]+'
    _TESTS = [{
        'url': 'https://www.bilibili.com/v/kichiku/mad',
        'info_dict': {
            'id': 'kichiku: mad',
            'title': 'kichiku: mad'
        },
        'playlist_mincount': 45,
        'params': {
            'playlistend': 45
        }
    }]

    def _fetch_page(self, api_url, num_pages, query, page_num):
        parsed_json = self._download_json(
            api_url, query, query={'Search_key': query, 'pn': page_num},
            note='Extracting results from page %s of %s' % (page_num, num_pages))

        video_list = try_get(parsed_json, lambda x: x['data']['archives'], list)
        if not video_list:
            raise ExtractorError('Failed to retrieve video list for page %d' % page_num)

        for video in video_list:
            yield self.url_result(
                'https://www.bilibili.com/video/%s' % video['bvid'], 'BiliBili', video['bvid'])