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

Code before:
                        self.report_warning('%s. Retrying...' % str(e.cause or e.msg))
                        continue
                    raise
                break
            yield from post_list.get('aweme_list', [])
            if not post_list.get('has_more'):
                break
            query['max_cursor'] = post_list['max_cursor']

    def _entries_api(self, user_id, videos):
        for video in videos:
            yield {
                **self._parse_aweme_video_app(video),
                'extractor_key': TikTokIE.ie_key(),
                'extractor': 'TikTok',
                'webpage_url': f'https://tiktok.com/@{user_id}/video/{video["aweme_id"]}',
            }

    def _real_extract(self, url):
        user_name = self._match_id(url)
        webpage = self._download_webpage(url, user_name, headers={
            'User-Agent': 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)'
        })
        user_id = self._html_search_regex(r'snssdk\d*://user/profile/(\d+)', webpage, 'user ID', default=None)
        if not user_id:
            user_id = user_name

        videos = LazyList(self._video_entries_api(webpage, user_id, user_name))
        thumbnail = traverse_obj(videos, (0, 'author', 'avatar_larger', 'url_list', 0))

        return self.playlist_result(self._entries_api(user_id, videos), user_id, user_name, thumbnail=thumbnail)


class TikTokBaseListIE(TikTokBaseIE):
    def _entries(self, list_id, display_id):
        query = {
            self._QUERY_NAME: list_id,
            'cursor': 0,
            'count': 20,
            'type': 5,
            'device_id': ''.join(random.choice(string.digits) for i in range(19))
        }

        max_retries = self.get_param('extractor_retries', 3)
        for page in itertools.count(1):
            for retries in itertools.count():
                try:
                    post_list = self._call_api(self._API_ENDPOINT, query, display_id,
                                               note='Downloading video list page %d%s' % (page, f' (attempt {retries})' if retries != 0 else ''),
                                               errnote='Unable to download video list')
                except ExtractorError as e:

Review comment (suggestion):
```suggestion
        user_id = self._html_search_regex(r'snssdk\d*://user/profile/(\d+)', webpage, 'user ID', default=None) or user_name
```

Code after:
                        self.report_warning('%s. Retrying...' % str(e.cause or e.msg))
                        continue
                    raise
                break
            yield from post_list.get('aweme_list', [])
            if not post_list.get('has_more'):
                break
            query['max_cursor'] = post_list['max_cursor']

    def _entries_api(self, user_id, videos):
        for video in videos:
            yield {
                **self._parse_aweme_video_app(video),
                'extractor_key': TikTokIE.ie_key(),
                'extractor': 'TikTok',
                'webpage_url': f'https://tiktok.com/@{user_id}/video/{video["aweme_id"]}',
            }

    def _real_extract(self, url):
        user_name = self._match_id(url)
        webpage = self._download_webpage(url, user_name, headers={
            'User-Agent': 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)'
        })
        user_id = self._html_search_regex(r'snssdk\d*://user/profile/(\d+)', webpage, 'user ID', default=None) or user_name

        videos = LazyList(self._video_entries_api(webpage, user_id, user_name))
        thumbnail = traverse_obj(videos, (0, 'author', 'avatar_larger', 'url_list', 0))

        return self.playlist_result(self._entries_api(user_id, videos), user_id, user_name, thumbnail=thumbnail)


class TikTokBaseListIE(TikTokBaseIE):
    def _entries(self, list_id, display_id):
        query = {
            self._QUERY_NAME: list_id,
            'cursor': 0,
            'count': 20,
            'type': 5,
            'device_id': ''.join(random.choice(string.digits) for i in range(19))
        }

        max_retries = self.get_param('extractor_retries', 3)
        for page in itertools.count(1):
            for retries in itertools.count():
                try:
                    post_list = self._call_api(self._API_ENDPOINT, query, display_id,
                                               note='Downloading video list page %d%s' % (page, f' (attempt {retries})' if retries != 0 else ''),
                                               errnote='Unable to download video list')
                except ExtractorError as e:
                    if isinstance(e.cause, json.JSONDecodeError) and e.cause.pos == 0 and retries != max_retries:
                        self.report_warning('%s. Retrying...' % str(e.cause or e.msg))