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

Code before:

        return formats

    def _extract_performers(self, prog):
        return traverse_obj(prog, (
            'pfm/text()', ..., {lambda x: re.split(r'[/／、　,，]', x)}, ..., {str.strip})) or None


class RadikoIE(RadikoBaseIE):
    _VALID_URL = r'https?://(?:www\.)?radiko\.jp/#!/ts/(?P<station>[A-Z0-9-]+)/(?P<timestring>\d+)'

    _TESTS = [{
        # QRR (文化放送) station provides <desc>
        'url': 'https://radiko.jp/#!/ts/QRR/20210425101300',
        'only_matching': True,
    }, {
        # FMT (TOKYO FM) station does not provide <desc>
        'url': 'https://radiko.jp/#!/ts/FMT/20210810150000',
        'only_matching': True,
    }, {
        'url': 'https://radiko.jp/#!/ts/JOAK-FM/20210509090000',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        station, timestring = self._match_valid_url(url).groups()
        video_id = join_nonempty(station, timestring)
        vid_int = unified_timestamp(timestring, False)
        prog, station_program, ft, radio_begin, radio_end = self._find_program(video_id, station, vid_int)

        auth_token, area_id = self._auth_client()

        return {
            'id': video_id,
            'title': try_call(lambda: prog.find('title').text),
            'cast': self._extract_performers(prog),
            'description': clean_html(try_call(lambda: prog.find('info').text)),
            'uploader': try_call(lambda: station_program.find('.//name').text),
            'uploader_id': station,
            'timestamp': vid_int,
            'duration': try_call(lambda: unified_timestamp(radio_end, False) - unified_timestamp(radio_begin, False)),
            'is_live': True,
            'formats': self._extract_formats(
                video_id=video_id, station=station, is_onair=False,
                ft=ft, cursor=vid_int, auth_token=auth_token, area_id=area_id,
                query={
                    'start_at': radio_begin,
                    'ft': radio_begin,
                    'end_at': radio_end,
                    'to': radio_end,
                    'seek': timestring,

Review comment (suggestion):
```suggestion
        station, timestring = self._match_valid_url(url).group('station', 'timestring')
```

Code after:

        return formats

    def _extract_performers(self, prog):
        return traverse_obj(prog, (
            'pfm/text()', ..., {lambda x: re.split(r'[/／、　,，]', x)}, ..., {str.strip})) or None


class RadikoIE(RadikoBaseIE):
    _VALID_URL = r'https?://(?:www\.)?radiko\.jp/#!/ts/(?P<station>[A-Z0-9-]+)/(?P<timestring>\d+)'

    _TESTS = [{
        # QRR (文化放送) station provides <desc>
        'url': 'https://radiko.jp/#!/ts/QRR/20210425101300',
        'only_matching': True,
    }, {
        # FMT (TOKYO FM) station does not provide <desc>
        'url': 'https://radiko.jp/#!/ts/FMT/20210810150000',
        'only_matching': True,
    }, {
        'url': 'https://radiko.jp/#!/ts/JOAK-FM/20210509090000',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        station, timestring = self._match_valid_url(url).group('station', 'timestring')
        video_id = join_nonempty(station, timestring)
        vid_int = unified_timestamp(timestring, False)
        prog, station_program, ft, radio_begin, radio_end = self._find_program(video_id, station, vid_int)

        auth_token, area_id = self._auth_client()

        return {
            'id': video_id,
            'title': try_call(lambda: prog.find('title').text),
            'cast': self._extract_performers(prog),
            'description': clean_html(try_call(lambda: prog.find('info').text)),
            'uploader': try_call(lambda: station_program.find('.//name').text),
            'uploader_id': station,
            'timestamp': vid_int,
            'duration': try_call(lambda: unified_timestamp(radio_end, False) - unified_timestamp(radio_begin, False)),
            'is_live': True,
            'formats': self._extract_formats(
                video_id=video_id, station=station, is_onair=False,
                ft=ft, cursor=vid_int, auth_token=auth_token, area_id=area_id,
                query={
                    'start_at': radio_begin,
                    'ft': radio_begin,
                    'end_at': radio_end,
                    'to': radio_end,
                    'seek': timestring,