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

Code before:
            'ts': time.time(),
        })
        return self._wbi_key_cache['key']

    def _sign_wbi(self, params, video_id):
        params['wts'] = round(time.time())
        params = {
            k: ''.join(filter(lambda char: char not in "!'()*", str(v)))
            for k, v in sorted(params.items())
        }
        query = urllib.parse.urlencode(params)
        params['w_rid'] = hashlib.md5(f'{query}{self._get_wbi_key(video_id)}'.encode()).hexdigest()
        return params

    def _download_playinfo(self, bvid, cid, headers=None, fatal=True, qn=None):
        params = {'bvid': bvid, 'cid': cid, 'fnval': 4048}
        if qn:
            params['qn'] = qn
        play_info_obj = self._download_json(
            'https://api.bilibili.com/x/player/wbi/playurl', bvid,
            query=self._sign_wbi(params, bvid), headers=headers, fatal=fatal,
            note=f'Downloading video formats for cid {cid} {qn or ""}')
        if fatal:
            return play_info_obj['data']
        else:
            return play_info_obj.get('data')

    def json2srt(self, json_data):
        srt_data = ''
        for idx, line in enumerate(json_data.get('body') or []):
            srt_data += (f'{idx + 1}\n'
                         f'{srt_subtitles_timecode(line["from"])} --> {srt_subtitles_timecode(line["to"])}\n'
                         f'{line["content"]}\n\n')
        return srt_data

    def _get_subtitles(self, video_id, cid, aid=None):
        subtitles = {
            'danmaku': [{
                'ext': 'xml',
                'url': f'https://comment.bilibili.com/{cid}.xml',
            }],
        }

        video_info = self._download_json(
            'https://api.bilibili.com/x/player/v2', video_id,
            query={'aid': aid, 'cid': cid} if aid else {'bvid': video_id, 'cid': cid},
            note=f'Extracting subtitle info {cid}', headers=self._HEADERS)
        if traverse_obj(video_info, ('data', 'need_login_subtitle')):
            self.report_warning(
                f'Subtitles are only available when logged in. {self._login_hint()}', only_once=True)
        for s in traverse_obj(video_info, (

Review comment (suggestion):
`.get()` is fatal
```suggestion
        return traverse_obj(play_info, ('data', {dict})) or {}
```

Code after:
            'ts': time.time(),
        })
        return self._wbi_key_cache['key']

    def _sign_wbi(self, params, video_id):
        params['wts'] = round(time.time())
        params = {
            k: ''.join(filter(lambda char: char not in "!'()*", str(v)))
            for k, v in sorted(params.items())
        }
        query = urllib.parse.urlencode(params)
        params['w_rid'] = hashlib.md5(f'{query}{self._get_wbi_key(video_id)}'.encode()).hexdigest()
        return params

    def _download_playinfo(self, bvid, cid, headers=None, qn=None):
        params = {'bvid': bvid, 'cid': cid, 'fnval': 4048}
        if qn:
            params['qn'] = qn
        return self._download_json(
            'https://api.bilibili.com/x/player/wbi/playurl', bvid,
            query=self._sign_wbi(params, bvid), headers=headers,
            note=f'Downloading video formats for cid {cid} {qn or ""}')['data']

    def json2srt(self, json_data):
        srt_data = ''
        for idx, line in enumerate(json_data.get('body') or []):
            srt_data += (f'{idx + 1}\n'
                         f'{srt_subtitles_timecode(line["from"])} --> {srt_subtitles_timecode(line["to"])}\n'
                         f'{line["content"]}\n\n')
        return srt_data

    def _get_subtitles(self, video_id, cid, aid=None):
        subtitles = {
            'danmaku': [{
                'ext': 'xml',
                'url': f'https://comment.bilibili.com/{cid}.xml',
            }],
        }

        video_info = self._download_json(
            'https://api.bilibili.com/x/player/v2', video_id,
            query={'aid': aid, 'cid': cid} if aid else {'bvid': video_id, 'cid': cid},
            note=f'Extracting subtitle info {cid}', headers=self._HEADERS)
        if traverse_obj(video_info, ('data', 'need_login_subtitle')):
            self.report_warning(
                f'Subtitles are only available when logged in. {self._login_hint()}', only_once=True)
        for s in traverse_obj(video_info, (
                'data', 'subtitle', 'subtitles', lambda _, v: v['subtitle_url'] and v['lan'])):
            subtitles.setdefault(s['lan'], []).append({
                'ext': 'srt',
                'data': self.json2srt(self._download_json(s['subtitle_url'], video_id)),