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

Code before:
        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, query=None):
        params = {'bvid': bvid, 'cid': cid, 'fnval': 4048, **(query or {})}
        if self.is_logged_in:
            params.pop('try_look', None)
        if qn := params.get('qn'):
            note = f'Downloading video format {qn} for cid {cid}'
        else:
            note = f'Downloading video formats for cid {cid}'

        # TODO: remove this patch once utils.networking.random_user_agent() is updated, see #13735
        # playurl requests carrying old UA will be rejected, patch old ua generated by random_user_agent
        ua = re.sub(r'Chrome/9\d\.0\.\d+\.\d+', f'Chrome/{random.randint(118,138)}.0.0.0',
                    traverse_obj(self._downloader.params, ('http_headers', 'User-Agent'), casesense=False))
        headers = {'User-Agent': ua, **(headers or {})}

        return self._download_json(
            'https://api.bilibili.com/x/player/wbi/playurl', bvid,
            query=self._sign_wbi(params, bvid), headers=headers, note=note)['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/wbi/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)

Review comment (suggestion):
```suggestion
        # playurl requests carrying old UA will be rejected
        headers = {
            'User-Agent': f'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{random.randint(118,138)}.0.0.0 Safari/537.36,
            **(headers or {}),
        }
```

Code after:
        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, query=None):
        params = {'bvid': bvid, 'cid': cid, 'fnval': 4048, **(query or {})}
        if self.is_logged_in:
            params.pop('try_look', None)
        if qn := params.get('qn'):
            note = f'Downloading video format {qn} for cid {cid}'
        else:
            note = f'Downloading video formats for cid {cid}'

        # TODO: remove this patch once utils.networking.random_user_agent() is updated, see #13735
        # playurl requests carrying old UA will be rejected
        headers = {
            'User-Agent': f'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{random.randint(118,138)}.0.0.0 Safari/537.36',
            **(headers or {}),
        }

        return self._download_json(
            'https://api.bilibili.com/x/player/wbi/playurl', bvid,
            query=self._sign_wbi(params, bvid), headers=headers, note=note)['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/wbi/v2', video_id,
            query={'aid': aid, 'cid': cid} if aid else {'bvid': video_id, 'cid': cid},