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

Code before:
                    }],
                } if capfile else None,
            })

        if len(entries) == 1:
            entry = dict(entries[0])
            entry['id'] = 'c' + video_id if video_type == 'clip' else video_id
            return entry
        else:
            return {
                '_type': 'playlist',
                'entries': entries,
                'title': title,
                'id': 'c' + video_id if video_type == 'clip' else video_id,
            }


class CSpanCongressIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?c-span\.org/congress/'
    _TESTS = [{
        'url': 'https://www.c-span.org/congress/?chamber=house&date=2017-12-13&t=1513208380',
        'info_dict': {
            'id': 'house_2017-12-13',
            'title': 'Congressional Chronicle - Members of Congress, Hearings and More | C-SPAN.org',
            'description': 'md5:54c264b7a8f219937987610243305a84',
            'thumbnail': 'https://ximage.c-spanvideo.org/eyJidWNrZXQiOiJwaWN0dXJlcy5jLXNwYW52aWRlby5vcmciLCJrZXkiOiJGaWxlc1wvODdkXC8yMDE3MTIxMzEwMDAzMjAwMV9oZC5qcGciLCJlZGl0cyI6eyJyZXNpemUiOnsiZml0IjoiY292ZXIiLCJoZWlnaHQiOjU3Niwid2lkdGgiOjEwMjR9fX0=',
            'ext': 'mp4'
        }
    }]

    def _real_extract(self, url):
        parsed_url = urlparse(url)
        if parse_qs(parsed_url.query)['chamber'] is not None:
            display_id = parse_qs(parsed_url.query)['chamber'][0]
            if parse_qs(parsed_url.query)['date'] is not None:
                display_id = display_id + '_' + parse_qs(parsed_url.query)['date'][0]
        else:
            display_id = self._generic_id(url)

        webpage = self._download_webpage(url, display_id)
        jwplayer_data = self._parse_json(
            self._search_regex(r'jwsetup\s*=\s*({(?:.|\n)[^;]+});', webpage, 'player config'),
            display_id, transform_source=js_to_json)
        result = self._parse_jwplayer_data(jwplayer_data, display_id, False)

        for f in result['formats']:
            f.setdefault('http_headers', {})['Referer'] = 'https://www.c-span.org/'

        result['title'] = self._og_search_title(webpage, default=None) or self._html_search_regex(
            r'(?s)<title>(.*?)</title>', webpage, 'video title')
        result['description'] = self._og_search_description(webpage, default=None) or self._html_search_meta(

Review comment (suggestion):
```suggestion
            'thumbnail': r're:https://ximage.c-spanvideo.org/.+',
```

Code after:
                } if capfile else None,
            })

        if len(entries) == 1:
            entry = dict(entries[0])
            entry['id'] = 'c' + video_id if video_type == 'clip' else video_id
            return entry
        else:
            return {
                '_type': 'playlist',
                'entries': entries,
                'title': title,
                'id': 'c' + video_id if video_type == 'clip' else video_id,
            }


class CSpanCongressIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?c-span\.org/congress/'
    _TESTS = [{
        'url': 'https://www.c-span.org/congress/?chamber=house&date=2017-12-13&t=1513208380',
        'info_dict': {
            'id': 'house_2017-12-13',
            'title': 'Congressional Chronicle - Members of Congress, Hearings and More',
            'description': 'md5:54c264b7a8f219937987610243305a84',
            'thumbnail': r're:https://ximage.c-spanvideo.org/.+',
            'ext': 'mp4'
        }
    }]

    def _real_extract(self, url):
        query = parse_qs(url)
        video_date = query.get('date', [None])[0]
        video_id = join_nonempty(query.get('chamber', ['senate'])[0], video_date, delim='_')
        webpage = self._download_webpage(url, video_id)
        if not video_date:
            jwp_date = re.search(r'jwsetup.clipprogdate = \'(?P<date>\d{4}-\d{2}-\d{2})\';', webpage)
            if jwp_date:
                video_id = f'{video_id}_{jwp_date.group("date")}'
        jwplayer_data = self._parse_json(
            self._search_regex(r'jwsetup\s*=\s*({(?:.|\n)[^;]+});', webpage, 'player config'),
            video_id, transform_source=js_to_json)

        title = (self._og_search_title(webpage, default=None)
                 or self._html_search_regex(r'(?s)<title>(.*?)</title>', webpage, 'video title'))
        description = (self._og_search_description(webpage, default=None)
                       or self._html_search_meta('description', webpage, 'description', default=None))

        return {
            **self._parse_jwplayer_data(jwplayer_data, video_id, False),
            'title': re.sub(r'\s+', ' ', title.split('|')[0]).strip(),
            'description': description,