diff --git a/yt_dlp/extractor/rule34video.py b/yt_dlp/extractor/rule34video.py index 3630f5e40..bfcd7110e 100644 --- a/yt_dlp/extractor/rule34video.py +++ b/yt_dlp/extractor/rule34video.py @@ -9,6 +9,7 @@ get_element_html_by_class, get_elements_by_class, int_or_none, + merge_dicts, parse_count, parse_duration, unescapeHTML, @@ -72,45 +73,58 @@ def _real_extract(self, url): formats = [] - for mobj in re.finditer(r']+href="(?P[^"]+download=true[^"]+)".*>(?P[^\s]+) (?P[^<]+)p', webpage): - url, ext, quality = mobj.groups() + for mobj in re.finditer(r']+href="(?P[^"]+download=true[^"]+)".*>(?P[^\s]+) (?P[^<]+)p', webpage): + url, ext, height = mobj.groups() formats.append({ 'url': url, 'ext': ext.lower(), - 'quality': quality, + 'height': int_or_none(height), }) categories, creators, uploader, uploader_url = [None] * 4 for col in get_elements_by_class('col', webpage): label = clean_html(get_element_by_class('label', col)) - if label == 'Categories:': + if label == 'Categories': categories = list(map(clean_html, get_elements_by_class('item', col))) - elif label == 'Artist:': + elif label == 'Artist': creators = list(map(clean_html, get_elements_by_class('item', col))) - elif label == 'Uploaded By:': - uploader = clean_html(get_element_by_class('name', col)) - uploader_url = extract_attributes(get_element_html_by_class('name', col) or '').get('href') + elif label == 'Uploaded by': + uploader_link = get_element_html_by_class('btn_link', col) + uploader = clean_html(uploader_link) + uploader_url = extract_attributes(uploader_link or '').get('href') - return { - **traverse_obj(self._search_json_ld(webpage, video_id, default={}), ({ - 'title': 'title', - 'view_count': 'view_count', - 'like_count': 'like_count', - 'duration': 'duration', - 'timestamp': 'timestamp', - 'description': 'description', - 'thumbnail': ('thumbnails', 0, 'url'), - })), + view_count, duration = [None] * 2 + for item_info in get_elements_by_class('item_info', webpage): + item_info_text = clean_html(item_info) + if get_element_by_class('custom-eye', item_info) is not None: + precise_view_count = re.search(r'\(([\d,]+)\)', item_info_text) + view_count = parse_count(precise_view_count.group(1) if precise_view_count is not None else item_info_text) + elif get_element_by_class('custom-time', item_info) is not None: + duration = parse_duration(clean_html(item_info)) + + like_count = None + if like_count_text := re.search(r'\(([\d,]+)\)', get_element_by_class('voters count', webpage)): + like_count = parse_count(like_count_text.group(1)) + + json_ld = traverse_obj(self._search_json_ld(webpage, video_id, default={}), ({ + 'title': 'title', + 'view_count': 'view_count', + 'like_count': 'like_count', + 'duration': 'duration', + 'timestamp': 'timestamp', + 'description': 'description', + 'thumbnail': ('thumbnails', 0, 'url'), + })) + + return merge_dicts({ 'id': video_id, 'formats': formats, 'title': self._html_extract_title(webpage), 'thumbnail': self._html_search_regex( r'preview_url:\s+\'([^\']+)\'', webpage, 'thumbnail', default=None), - 'duration': parse_duration(self._html_search_regex( - r'"icon-clock">\s+((?:\d+:?)+)', webpage, 'duration', default=None)), - 'view_count': int_or_none(self._html_search_regex( - r'"icon-eye">\s+([ \d]+)', webpage, 'views', default='').replace(' ', '')), - 'like_count': parse_count(get_element_by_class('voters count', webpage)), + 'duration': duration, + 'view_count': view_count, + 'like_count': like_count, 'comment_count': int_or_none(self._search_regex( r'[^(]+\((\d+)\)', get_element_by_attribute('href', '#tab_comments', webpage), 'comment count', fatal=False)), 'age_limit': 18, @@ -120,4 +134,4 @@ def _real_extract(self, url): 'categories': categories, 'tags': list(map(unescapeHTML, re.findall( r']+\bhref="https://rule34video\.com/tags/\d+/"[^>]*>(?P[^>]*)', webpage))), - } + }, json_ld)