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

Code before:
            'uploader': 'ManyakisArt',
            'duration': 5,
            'age_limit': 18,
        }
    }

    def _real_extract(self, url):
        video_id = self._match_id(url)

        webpage = self._download_webpage(url, video_id)

        video_url = self._search_regex(
            r'href="(https?://xhamster\.com/(?:movies/{0}/[^"]*\.html|videos/[^/]*-{0})[^"]*)"'.format(video_id),
            webpage, 'xhamster url', default=None)

        if not video_url:
            vars = self._parse_json(
                self._search_regex(r'vars\s*:\s*({.+?})\s*,\s*\n', webpage, 'vars'),
                video_id)
            video_url = dict_get(vars, ('downloadLink', 'homepageLink', 'commentsLink', 'shareUrl'))

        return self.url_result(video_url, 'XHamster')


class XHamsterUserIE(InfoExtractor):
    _VALID_URL = rf'https?://(?:.+?\.)?{XHamsterIE._DOMAINS}/(?:(?P<user>users)|creators)/(?P<id>[^/?#&]+)'
    _TESTS = [{
        # Paginated user profile
        'url': 'https://xhamster.com/users/netvideogirls/videos',
        'info_dict': {
            'id': 'netvideogirls',
        },
        'playlist_mincount': 267,
    }, {
        # Non-paginated user profile
        'url': 'https://xhamster.com/users/firatkaan/videos',
        'info_dict': {
            'id': 'firatkaan',
        },
        'playlist_mincount': 1,
    }, {
        'url': 'https://xhamster.com/creators/squirt-orgasm-69',
        'info_dict': {
            'id': 'squirt-orgasm-69',
        },
        'playlist_mincount': 150,
    }, {
        'url': 'https://xhday.com/users/mobhunter',
        'only_matching': True,
    }, {
        'url': 'https://xhvid.com/users/pelushe21',

Review comment (suggestion):
```suggestion
    _VALID_URL = rf'https?://(?:[^/?#]+\.)?{XHamsterIE._DOMAINS}/(?:(?P<user>users)|creators)/(?P<id>[^/?#&]+)'
```
wouldn't hurt to fix this up in the other `_VALID_URL`s as well, imo

Code after:
            'uploader': 'ManyakisArt',
            'duration': 5,
            'age_limit': 18,
        }
    }

    def _real_extract(self, url):
        video_id = self._match_id(url)

        webpage = self._download_webpage(url, video_id)

        video_url = self._search_regex(
            r'href="(https?://xhamster\.com/(?:movies/{0}/[^"]*\.html|videos/[^/]*-{0})[^"]*)"'.format(video_id),
            webpage, 'xhamster url', default=None)

        if not video_url:
            vars = self._parse_json(
                self._search_regex(r'vars\s*:\s*({.+?})\s*,\s*\n', webpage, 'vars'),
                video_id)
            video_url = dict_get(vars, ('downloadLink', 'homepageLink', 'commentsLink', 'shareUrl'))

        return self.url_result(video_url, 'XHamster')


class XHamsterUserIE(InfoExtractor):
    _VALID_URL = rf'https?://(?:[^/?#]+\.)?{XHamsterIE._DOMAINS}/(?:(?P<user>users)|creators)/(?P<id>[^/?#&]+)'
    _TESTS = [{
        # Paginated user profile
        'url': 'https://xhamster.com/users/netvideogirls/videos',
        'info_dict': {
            'id': 'netvideogirls',
        },
        'playlist_mincount': 267,
    }, {
        # Non-paginated user profile
        'url': 'https://xhamster.com/users/firatkaan/videos',
        'info_dict': {
            'id': 'firatkaan',
        },
        'playlist_mincount': 1,
    }, {
        'url': 'https://xhamster.com/creators/squirt-orgasm-69',
        'info_dict': {
            'id': 'squirt-orgasm-69',
        },
        'playlist_mincount': 150,
    }, {
        'url': 'https://xhday.com/users/mobhunter',
        'only_matching': True,
    }, {
        'url': 'https://xhvid.com/users/pelushe21',