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

Code before:
    }, {
        'url': 'https://www.bilibili.com/medialist/play/ml1103407912',
        'info_dict': {
            'id': '3_1103407912',
        },
        'playlist_mincount': 22,
        'skip': 'redirect url',
    }, {
        'url': 'https://www.bilibili.com/list/watchlater',
        'info_dict': {'id': 'watchlater'},
        'playlist_mincount': 0,
        'skip': 'login required',
    }, {
        'url': 'https://www.bilibili.com/medialist/play/watchlater',
        'info_dict': {'id': 'watchlater'},
        'playlist_mincount': 0,
        'skip': 'login required',
    }]

    def _extract_medialist(self, query, list_id):
        for page_num in itertools.count(1):
            page_data = self._download_json(
                'https://api.bilibili.com/x/v2/medialist/resource/list',
                list_id, query=query, note=f'getting playlist {query["biz_id"]} page {page_num}'
            )['data']
            yield from self._get_entries(page_data, ('media_list', ..., 'bv_id'))
            query['oid'] = traverse_obj(page_data, ('media_list', -1, 'id'))
            if not page_data.get('has_more', False):
                break

    def _real_extract(self, url):
        list_id = self._match_id(url)
        webpage = self._download_webpage(url, list_id)
        initial_state = self._search_json(r'window\.__INITIAL_STATE__\s*=', webpage, 'initial state', list_id)
        if traverse_obj(initial_state, ('error', 'code', {int_or_none})) != 200:
            error_code = traverse_obj(initial_state, ('error', 'trueCode', {int_or_none}))
            error_message = traverse_obj(initial_state, ('error', 'message', {str_or_none}))
            if error_code == -400 and list_id == 'watchlater':
                self.raise_login_required('You need to login to access your watchlater playlist')
            elif error_code == -403:
                self.raise_login_required('This is a private playlist. You need to login as its owner')
            elif error_code == 11010:
                raise ExtractorError('Playlist is no longer available', expected=True)
            raise ExtractorError(f'Could not access playlist: {error_code} {error_message}')

        query = {
            'ps': 20,
            'with_current': False,
            **traverse_obj(initial_state, {
                'type': ('playlist', 'type', {int_or_none}),
                'biz_id': ('playlist', 'id', {int_or_none}),

Review comment (suggestion):
To go along with the suggestion for `BilibiliSpaceListBaseIE._get_entries()`:
```suggestion
            yield from self._get_entries(page_data, 'media_list')
```

Code after:
    }]

    def _real_extract(self, url):
        list_id = getattr(self._get_cookies(url).get('DedeUserID'), 'value', 'watchlater')
        watchlater_info = self._download_json(
            'https://api.bilibili.com/x/v2/history/toview/web?jsonp=jsonp', list_id)
        if watchlater_info['code'] == -101:
            self.raise_login_required(msg='You need to login to access your watchlater list')
        entries = self._get_entries(watchlater_info, ('data', 'list'))
        return self.playlist_result(entries, id=list_id, title='稍后再看')


class BilibiliPlaylistIE(BilibiliSpaceListBaseIE):
    _VALID_URL = r'https?://(?:www\.)?bilibili\.com/(?:medialist/play|list)/(?P<id>\w+)'
    _TESTS = [{
        'url': 'https://www.bilibili.com/list/1958703906?sid=547718',
        'info_dict': {
            'id': '5_547718',
            'title': '直播回放',
            'uploader': '靡烟miya',
            'uploader_id': '1958703906',
            'timestamp': 1637985853,
            'upload_date': '20211127',
        },
        'playlist_mincount': 513,
    }, {
        'url': 'https://www.bilibili.com/medialist/play/1958703906?business=space_series&business_id=547718&desc=1',
        'info_dict': {
            'id': '5_547718',
        },
        'playlist_mincount': 513,
        'skip': 'redirect url',
    }, {
        'url': 'https://www.bilibili.com/list/ml1103407912',
        'info_dict': {
            'id': '3_1103407912',
            'title': '【V2】（旧）',
            'uploader': '晓月春日',
            'uploader_id': '84912',
            'timestamp': 1604905176,
            'upload_date': '20201109',
            'thumbnail': r"re:http://i\d\.hdslb\.com/bfs/archive/14b83c62aa8871b79083df1e9ab4fbc699ad16fe\.jpg",
        },
        'playlist_mincount': 22,
    }, {
        'url': 'https://www.bilibili.com/medialist/play/ml1103407912',
        'info_dict': {
            'id': '3_1103407912',
        },
        'playlist_mincount': 22,
        'skip': 'redirect url',