[ie/youtube:tab] Fix pagination (#16948)

* Support `continuationViewModel` continuation tokens

Closes #16692, Closes #16943
Authored by: bashonly
This commit is contained in:
bashonly 2026-06-13 18:06:23 -05:00 committed by GitHub
parent 9055188250
commit b23046bbc8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 85 additions and 79 deletions

View File

@ -1037,8 +1037,10 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
return next_continuation return next_continuation
return traverse_obj(renderer, ( return traverse_obj(renderer, (
('contents', 'items', 'rows', 'subThreads'), ..., 'continuationItemRenderer', ('contents', 'items', 'rows', 'subThreads'), ..., (
('continuationEndpoint', ('button', 'buttonRenderer', 'command')), ('continuationItemRenderer', ('continuationEndpoint', ('button', 'buttonRenderer', 'command'))),
('continuationItemViewModel', 'continuationCommand', 'innertubeCommand'),
),
), get_all=False, expected_type=cls._extract_continuation_ep_data) ), get_all=False, expected_type=cls._extract_continuation_ep_data)
@classmethod @classmethod

View File

@ -1032,14 +1032,14 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
'playlist_mincount': 94, 'playlist_mincount': 94,
'info_dict': { 'info_dict': {
'id': 'UCqj7Cz7revf5maW9g5pgNcg', 'id': 'UCqj7Cz7revf5maW9g5pgNcg',
'title': 'Igor Kleiner - Playlists', 'title': 'Igor DS: ИИ, Наука и Творчество - Playlists',
'description': r're:(?s)Добро пожаловать на мой канал! Здесь вы найдете видео .{504}/a1/50b/10a$', 'description': r're:(?s)Добро пожаловать! Здесь сложные технологии встречаются.+\n$',
'uploader': 'Igor Kleiner ', 'uploader': 'Igor DS: ИИ, Наука и Творчество ',
'uploader_id': '@IgorDataScience', 'uploader_id': '@IgorDataScience',
'uploader_url': 'https://www.youtube.com/@IgorDataScience', 'uploader_url': 'https://www.youtube.com/@IgorDataScience',
'channel': 'Igor Kleiner ', 'channel': 'Igor DS: ИИ, Наука и Творчество ',
'channel_id': 'UCqj7Cz7revf5maW9g5pgNcg', 'channel_id': 'UCqj7Cz7revf5maW9g5pgNcg',
'tags': 'count:23', 'tags': 'count:19',
'channel_url': 'https://www.youtube.com/channel/UCqj7Cz7revf5maW9g5pgNcg', 'channel_url': 'https://www.youtube.com/channel/UCqj7Cz7revf5maW9g5pgNcg',
'channel_follower_count': int, 'channel_follower_count': int,
}, },
@ -1049,14 +1049,13 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
'playlist_mincount': 94, 'playlist_mincount': 94,
'info_dict': { 'info_dict': {
'id': 'UCqj7Cz7revf5maW9g5pgNcg', 'id': 'UCqj7Cz7revf5maW9g5pgNcg',
'title': 'Igor Kleiner - Playlists', 'title': 'Igor DS: ИИ, Наука и Творчество - Playlists',
'description': r're:(?s)Добро пожаловать на мой канал! Здесь вы найдете видео .{504}/a1/50b/10a$', 'description': r're:(?s)Добро пожаловать! Здесь сложные технологии встречаются.+\n$',
'uploader': 'Igor Kleiner ',
'uploader_id': '@IgorDataScience', 'uploader_id': '@IgorDataScience',
'uploader_url': 'https://www.youtube.com/@IgorDataScience', 'uploader_url': 'https://www.youtube.com/@IgorDataScience',
'tags': 'count:23', 'tags': 'count:19',
'channel_id': 'UCqj7Cz7revf5maW9g5pgNcg', 'channel_id': 'UCqj7Cz7revf5maW9g5pgNcg',
'channel': 'Igor Kleiner ', 'channel': 'Igor DS: ИИ, Наука и Творчество ',
'channel_url': 'https://www.youtube.com/channel/UCqj7Cz7revf5maW9g5pgNcg', 'channel_url': 'https://www.youtube.com/channel/UCqj7Cz7revf5maW9g5pgNcg',
'channel_follower_count': int, 'channel_follower_count': int,
}, },
@ -1139,90 +1138,89 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
'playlist_count': 0, 'playlist_count': 0,
}, { }, {
'note': 'Home tab', 'note': 'Home tab',
'url': 'https://www.youtube.com/channel/UCKfVa3S1e4PHvxWcwyMMg8w/featured', 'url': 'https://www.youtube.com/channel/UCTwECeGqMZee77BjdoYtI2Q/featured',
'info_dict': { 'info_dict': {
'id': 'UCKfVa3S1e4PHvxWcwyMMg8w', 'id': 'UCTwECeGqMZee77BjdoYtI2Q',
'title': 'lex will - Home', 'title': 'Creative Commons - Home',
'description': 'md5:2163c5d0ff54ed5f598d6a7e6211e488', 'description': 'md5:7cfc22824277588d26a66054f22d93c8',
'uploader': 'lex will', 'uploader': 'Creative Commons',
'uploader_id': '@lexwill718', 'uploader_id': '@creativecommons',
'channel': 'lex will', 'uploader_url': 'https://www.youtube.com/@creativecommons',
'tags': ['bible', 'history', 'prophesy'], 'channel': 'Creative Commons',
'uploader_url': 'https://www.youtube.com/@lexwill718', 'channel_id': 'UCTwECeGqMZee77BjdoYtI2Q',
'channel_url': 'https://www.youtube.com/channel/UCKfVa3S1e4PHvxWcwyMMg8w', 'channel_url': 'https://www.youtube.com/channel/UCTwECeGqMZee77BjdoYtI2Q',
'channel_id': 'UCKfVa3S1e4PHvxWcwyMMg8w',
'channel_follower_count': int, 'channel_follower_count': int,
'tags': ['creative commons', 'remix', 'culture', 'nonprofit'],
}, },
'playlist_mincount': 2, 'playlist_mincount': 6,
}, { }, {
'note': 'Videos tab', 'note': 'Videos tab',
'url': 'https://www.youtube.com/channel/UCKfVa3S1e4PHvxWcwyMMg8w/videos', 'url': 'https://www.youtube.com/channel/UCTwECeGqMZee77BjdoYtI2Q/videos',
'info_dict': { 'info_dict': {
'id': 'UCKfVa3S1e4PHvxWcwyMMg8w', 'id': 'UCTwECeGqMZee77BjdoYtI2Q',
'title': 'lex will - Videos', 'title': 'Creative Commons - Videos',
'description': 'md5:2163c5d0ff54ed5f598d6a7e6211e488', 'description': 'md5:7cfc22824277588d26a66054f22d93c8',
'uploader': 'lex will', 'uploader': 'Creative Commons',
'uploader_id': '@lexwill718', 'uploader_id': '@creativecommons',
'tags': ['bible', 'history', 'prophesy'], 'uploader_url': 'https://www.youtube.com/@creativecommons',
'channel_url': 'https://www.youtube.com/channel/UCKfVa3S1e4PHvxWcwyMMg8w', 'channel': 'Creative Commons',
'channel_id': 'UCKfVa3S1e4PHvxWcwyMMg8w', 'channel_id': 'UCTwECeGqMZee77BjdoYtI2Q',
'uploader_url': 'https://www.youtube.com/@lexwill718', 'channel_url': 'https://www.youtube.com/channel/UCTwECeGqMZee77BjdoYtI2Q',
'channel': 'lex will',
'channel_follower_count': int, 'channel_follower_count': int,
'tags': ['creative commons', 'remix', 'culture', 'nonprofit'],
}, },
'playlist_mincount': 975, 'playlist_mincount': 239,
}, { }, {
'note': 'Videos tab, sorted by popular', 'note': 'Videos tab, sorted by popular',
'url': 'https://www.youtube.com/channel/UCKfVa3S1e4PHvxWcwyMMg8w/videos?view=0&sort=p&flow=grid', 'url': 'https://www.youtube.com/channel/UCTwECeGqMZee77BjdoYtI2Q/videos?view=0&sort=p&flow=grid',
'info_dict': { 'info_dict': {
'id': 'UCKfVa3S1e4PHvxWcwyMMg8w', 'id': 'UCTwECeGqMZee77BjdoYtI2Q',
'title': 'lex will - Videos', 'title': 'Creative Commons - Videos',
'description': 'md5:2163c5d0ff54ed5f598d6a7e6211e488', 'description': 'md5:7cfc22824277588d26a66054f22d93c8',
'uploader': 'lex will', 'uploader': 'Creative Commons',
'uploader_id': '@lexwill718', 'uploader_id': '@creativecommons',
'channel_id': 'UCKfVa3S1e4PHvxWcwyMMg8w', 'uploader_url': 'https://www.youtube.com/@creativecommons',
'uploader_url': 'https://www.youtube.com/@lexwill718', 'channel': 'Creative Commons',
'channel': 'lex will', 'channel_id': 'UCTwECeGqMZee77BjdoYtI2Q',
'tags': ['bible', 'history', 'prophesy'], 'channel_url': 'https://www.youtube.com/channel/UCTwECeGqMZee77BjdoYtI2Q',
'channel_url': 'https://www.youtube.com/channel/UCKfVa3S1e4PHvxWcwyMMg8w',
'channel_follower_count': int, 'channel_follower_count': int,
'tags': ['creative commons', 'remix', 'culture', 'nonprofit'],
}, },
'playlist_mincount': 199, 'playlist_mincount': 239,
}, { }, {
'note': 'Playlists tab', 'note': 'Playlists tab',
'url': 'https://www.youtube.com/channel/UCKfVa3S1e4PHvxWcwyMMg8w/playlists', 'url': 'https://www.youtube.com/channel/UCTwECeGqMZee77BjdoYtI2Q/playlists',
'info_dict': { 'info_dict': {
'id': 'UCKfVa3S1e4PHvxWcwyMMg8w', 'id': 'UCTwECeGqMZee77BjdoYtI2Q',
'title': 'lex will - Playlists', 'title': 'Creative Commons - Playlists',
'description': 'md5:2163c5d0ff54ed5f598d6a7e6211e488', 'description': 'md5:7cfc22824277588d26a66054f22d93c8',
'uploader': 'lex will', 'uploader': 'Creative Commons',
'uploader_id': '@lexwill718', 'uploader_id': '@creativecommons',
'uploader_url': 'https://www.youtube.com/@lexwill718', 'uploader_url': 'https://www.youtube.com/@creativecommons',
'channel': 'lex will', 'channel': 'Creative Commons',
'channel_url': 'https://www.youtube.com/channel/UCKfVa3S1e4PHvxWcwyMMg8w', 'channel_id': 'UCTwECeGqMZee77BjdoYtI2Q',
'channel_id': 'UCKfVa3S1e4PHvxWcwyMMg8w', 'channel_url': 'https://www.youtube.com/channel/UCTwECeGqMZee77BjdoYtI2Q',
'tags': ['bible', 'history', 'prophesy'],
'channel_follower_count': int, 'channel_follower_count': int,
'tags': ['creative commons', 'remix', 'culture', 'nonprofit'],
}, },
'playlist_mincount': 17, 'playlist_mincount': 20,
}, { }, {
'note': 'Posts tab', 'note': 'Posts tab',
'url': 'https://www.youtube.com/channel/UCKfVa3S1e4PHvxWcwyMMg8w/community', 'url': 'https://www.youtube.com/channel/UCtS3BcCw-tITPFYSvkbP0Bg/posts',
'info_dict': { 'info_dict': {
'id': 'UCKfVa3S1e4PHvxWcwyMMg8w', 'id': 'UCtS3BcCw-tITPFYSvkbP0Bg',
'title': 'lex will - Posts', 'title': 'Office Hours Live with Tim Heidecker - Posts',
'description': 'md5:2163c5d0ff54ed5f598d6a7e6211e488', 'description': 'md5:01ec1460ea6c6e2aa47d3be9c756559c',
'channel': 'lex will', 'uploader': 'Office Hours Live with Tim Heidecker',
'channel_url': 'https://www.youtube.com/channel/UCKfVa3S1e4PHvxWcwyMMg8w', 'uploader_id': '@OfficeHoursLive',
'channel_id': 'UCKfVa3S1e4PHvxWcwyMMg8w', 'uploader_url': 'https://www.youtube.com/@OfficeHoursLive',
'tags': ['bible', 'history', 'prophesy'], 'channel': 'Office Hours Live with Tim Heidecker',
'channel_id': 'UCtS3BcCw-tITPFYSvkbP0Bg',
'channel_url': 'https://www.youtube.com/channel/UCtS3BcCw-tITPFYSvkbP0Bg',
'channel_follower_count': int, 'channel_follower_count': int,
'uploader_url': 'https://www.youtube.com/@lexwill718', 'tags': 'count:17',
'uploader_id': '@lexwill718',
'uploader': 'lex will',
}, },
'playlist_mincount': 18, 'playlist_mincount': 145,
'skip': 'This Community isn\'t available',
}, { }, {
# TODO: fix channel_is_verified extraction # TODO: fix channel_is_verified extraction
'note': 'Search tab', 'note': 'Search tab',
@ -1272,6 +1270,7 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
}, },
'playlist_count': 96, 'playlist_count': 96,
}, { }, {
# TODO: fix availability extraction
'note': 'Large playlist', 'note': 'Large playlist',
'url': 'https://www.youtube.com/playlist?list=UUBABnxM4Ar9ten8Mdjj1j0Q', 'url': 'https://www.youtube.com/playlist?list=UUBABnxM4Ar9ten8Mdjj1j0Q',
'info_dict': { 'info_dict': {
@ -1296,6 +1295,8 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
'url': 'http://www.youtube.com/user/NASAgovVideo/videos', 'url': 'http://www.youtube.com/user/NASAgovVideo/videos',
'only_matching': True, 'only_matching': True,
}, { }, {
# TODO: fix availability extraction
# The 'note' below is outdated: there is no longer a "Load more" button
'note': 'Buggy playlist: the webpage has a "Load more" button but it doesn\'t have more videos', 'note': 'Buggy playlist: the webpage has a "Load more" button but it doesn\'t have more videos',
'url': 'https://www.youtube.com/playlist?list=UUXw-G3eDE9trcvY2sBMM_aA', 'url': 'https://www.youtube.com/playlist?list=UUXw-G3eDE9trcvY2sBMM_aA',
'info_dict': { 'info_dict': {
@ -1313,7 +1314,7 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
'uploader': 'Interstellar Movie', 'uploader': 'Interstellar Movie',
'uploader_url': 'https://www.youtube.com/@InterstellarMovie', 'uploader_url': 'https://www.youtube.com/@InterstellarMovie',
}, },
'playlist_mincount': 21, 'playlist_mincount': 10,
}, { }, {
# TODO: fix availability extraction # TODO: fix availability extraction
'note': 'Playlist with "show unavailable videos" button', 'note': 'Playlist with "show unavailable videos" button',
@ -1336,6 +1337,7 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
'playlist_mincount': 150, 'playlist_mincount': 150,
'expected_warnings': [r'[Uu]navailable videos (are|will be) hidden'], 'expected_warnings': [r'[Uu]navailable videos (are|will be) hidden'],
}, { }, {
# TODO: fix availability extraction
'note': 'Playlist with unavailable videos in page 7', 'note': 'Playlist with unavailable videos in page 7',
'url': 'https://www.youtube.com/playlist?list=UU8l9frL61Yl5KFOl87nIm2w', 'url': 'https://www.youtube.com/playlist?list=UU8l9frL61Yl5KFOl87nIm2w',
'info_dict': { 'info_dict': {
@ -1407,7 +1409,7 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
}, { }, {
'url': 'https://www.youtube.com/channel/UCoMdktPbSTixAyNGwb-UYkQ/live', 'url': 'https://www.youtube.com/channel/UCoMdktPbSTixAyNGwb-UYkQ/live',
'info_dict': { 'info_dict': {
'id': 'VFGoUmo74wE', # This will keep changing 'id': 'ubIX-TwVqZI', # This will keep changing
'ext': 'mp4', 'ext': 'mp4',
'title': str, 'title': str,
'upload_date': r're:\d{8}', 'upload_date': r're:\d{8}',
@ -1586,6 +1588,7 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
'playlist_count': 50, 'playlist_count': 50,
'expected_warnings': ['YouTube Music is not directly supported'], 'expected_warnings': ['YouTube Music is not directly supported'],
}, { }, {
# TODO: investigate test failing on differing channel*/uploader*/view_count
'note': 'unlisted single video playlist', 'note': 'unlisted single video playlist',
'url': 'https://www.youtube.com/playlist?list=PLt5yu3-wZAlQLfIN0MMgp0wVV6MP3bM4_', 'url': 'https://www.youtube.com/playlist?list=PLt5yu3-wZAlQLfIN0MMgp0wVV6MP3bM4_',
'info_dict': { 'info_dict': {
@ -1809,7 +1812,7 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
'title': 'Not Just Bikes - Shorts', 'title': 'Not Just Bikes - Shorts',
'tags': 'count:10', 'tags': 'count:10',
'channel_url': 'https://www.youtube.com/channel/UC0intLFzLaudFG-xAvUEO-A', 'channel_url': 'https://www.youtube.com/channel/UC0intLFzLaudFG-xAvUEO-A',
'description': 'md5:295758591d0d43d8594277be54584da7', 'description': 'md5:2cb3ccdafa58608fa016f1de4930ec54',
'channel_follower_count': int, 'channel_follower_count': int,
'channel_id': 'UC0intLFzLaudFG-xAvUEO-A', 'channel_id': 'UC0intLFzLaudFG-xAvUEO-A',
'channel': 'Not Just Bikes', 'channel': 'Not Just Bikes',
@ -1831,8 +1834,8 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
'channel': '中村悠一', 'channel': '中村悠一',
'channel_follower_count': int, 'channel_follower_count': int,
'description': 'md5:76b312b48a26c3b0e4d90e2dfc1b417d', 'description': 'md5:76b312b48a26c3b0e4d90e2dfc1b417d',
'uploader_url': 'https://www.youtube.com/@Yuichi-Nakamura', 'uploader_url': 'https://www.youtube.com/@中村悠一のあそびば',
'uploader_id': '@Yuichi-Nakamura', 'uploader_id': '@中村悠一のあそびば',
'uploader': '中村悠一', 'uploader': '中村悠一',
}, },
'playlist_mincount': 60, 'playlist_mincount': 60,
@ -2010,7 +2013,7 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
'channel': '99% Invisible', 'channel': '99% Invisible',
'uploader_id': '@99percentinvisiblepodcast', 'uploader_id': '@99percentinvisiblepodcast',
}, },
'playlist_count': 5, 'playlist_mincount': 5,
}, { }, {
# Releases tab, with rich entry playlistRenderers (same as Podcasts tab) # Releases tab, with rich entry playlistRenderers (same as Podcasts tab)
# TODO: fix channel_is_verified extraction # TODO: fix channel_is_verified extraction
@ -2034,6 +2037,7 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
# Playlist with only shorts, shown as reel renderers # Playlist with only shorts, shown as reel renderers
# FIXME: future: YouTube currently doesn't give continuation for this, # FIXME: future: YouTube currently doesn't give continuation for this,
# may do in future. # may do in future.
# TODO: fix availability extraction
'url': 'https://www.youtube.com/playlist?list=UUxqPAgubo4coVn9Lx1FuKcg', 'url': 'https://www.youtube.com/playlist?list=UUxqPAgubo4coVn9Lx1FuKcg',
'info_dict': { 'info_dict': {
'id': 'UUxqPAgubo4coVn9Lx1FuKcg', 'id': 'UUxqPAgubo4coVn9Lx1FuKcg',