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

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

        def fetch_page(page_idx):
            return self._download_json(
                'https://api.bilibili.com/audio/music-service/web/song/upper', playlist_id,
                note=f'Downloading page {page_idx}',
                query={'uid': playlist_id, 'pn': page_idx + 1, 'ps': 30, 'order': 1, 'jsonp': 'jsonp'})['data']

        def get_metadata(page_data):
            return {
                'page_count': page_data['pageCount'],
                'page_size': page_data['pageSize'],
            }

        def get_entries(page_data):
            for entry in page_data.get('data', []):
                yield self.url_result(f'https://www.bilibili.com/audio/au{entry["id"]}', BilibiliAudioIE, entry['id'])

        metadata, paged_list = self._extract_playlist(fetch_page, get_metadata, get_entries)
        return self.playlist_result(paged_list, playlist_id)


class BilibiliSpaceListBaseIE(BilibiliSpaceBaseIE):
    def _get_entries(self, page_data, bvid_path=None):
        for bvid in traverse_obj(page_data, bvid_path) or []:
            yield self.url_result(f'https://www.bilibili.com/video/{bvid}', BiliBiliIE, bvid)

    def _get_uploader(self, uid, playlist_id):
        webpage = self._download_webpage(f'https://space.bilibili.com/{uid}', playlist_id, fatal=False)
        return self._search_regex(r'(?s)<title\b[^>]*>([^<]+)的个人空间-', webpage, 'uploader', fatal=False)

    def _extract_playlist(self, fetch_page, get_metadata, get_entries):
        metadata, page_list = super()._extract_playlist(fetch_page, get_metadata, get_entries)
        metadata.pop('page_count', None)
        metadata.pop('page_size', None)
        return metadata, page_list


class BilibiliCollectionListIE(BilibiliSpaceListBaseIE):
    _VALID_URL = r'https?://space.bilibili\.com/(?P<mid>\d+)/channel/collectiondetail/?\?sid=(?P<sid>\d+)'
    _TESTS = [{
        'url': 'https://space.bilibili.com/2142762/channel/collectiondetail?sid=57445',
        'info_dict': {
            'id': '2142762_57445',
            'title': '【完结】《底特律 变人》全结局流程解说',
            'description': '',
            'uploader': '老戴在此',
            'uploader_id': '2142762',
            'timestamp': int,
            'upload_date': str,

Review comment (suggestion):
I think it would be better to do it like this; reduces code duplication and chances of usage error:
```suggestion
    def _get_entries(self, page_data, bvid_keys):
        for bvid in traverse_obj(page_data, (*variadic(bvid_keys, (str, bytes, dict, set)), ..., 'bvid', {str})):
```

Code after:
                'pn': page_idx + 1,
                'ps': 30,
                'tid': 0,
                'web_location': 1550101,
                'wts': int(time.time()),
            }
            query['w_rid'] = hashlib.md5(f'{urllib.parse.urlencode(query)}{signature}'.encode()).hexdigest()

            try:
                response = self._download_json('https://api.bilibili.com/x/space/wbi/arc/search',
                                               playlist_id, note=f'Downloading page {page_idx}', query=query)
            except ExtractorError as e:
                if isinstance(e.cause, HTTPError) and e.cause.status == 412:
                    raise ExtractorError(
                        'Request is blocked by server (412), please add cookies, wait and try later.', expected=True)
                raise
            if response['code'] == -401:
                raise ExtractorError(
                    'Request is blocked by server (401), please add cookies, wait and try later.', expected=True)
            return response['data']

        def get_metadata(page_data):
            page_size = page_data['page']['ps']
            entry_count = page_data['page']['count']
            return {
                'page_count': math.ceil(entry_count / page_size),
                'page_size': page_size,
            }

        def get_entries(page_data):
            for entry in traverse_obj(page_data, ('list', 'vlist')) or []:
                yield self.url_result(f'https://www.bilibili.com/video/{entry["bvid"]}', BiliBiliIE, entry['bvid'])

        metadata, paged_list = self._extract_playlist(fetch_page, get_metadata, get_entries)
        return self.playlist_result(paged_list, playlist_id)


class BilibiliSpaceAudioIE(BilibiliSpaceBaseIE):
    _VALID_URL = r'https?://space\.bilibili\.com/(?P<id>\d+)/audio'
    _TESTS = [{
        'url': 'https://space.bilibili.com/313580179/audio',
        'info_dict': {
            'id': '313580179',
        },
        'playlist_mincount': 1,
    }]

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

        def fetch_page(page_idx):