[youtube:search_url] Add playlist/channel support

Closes #1213, #1214
This commit is contained in:
pukkandan 2021-11-24 09:27:59 +05:30
parent a6213a4925
commit a61fd4cf6f
No known key found for this signature in database
GPG key ID: 0F00D95A001F4698

View file

@ -3117,6 +3117,7 @@ def process_language(container, base_url, lang_code, sub_name, query):
return info return info
class YoutubeTabBaseInfoExtractor(YoutubeBaseInfoExtractor): class YoutubeTabBaseInfoExtractor(YoutubeBaseInfoExtractor):
def _extract_channel_id(self, webpage): def _extract_channel_id(self, webpage):
@ -3326,6 +3327,8 @@ def _extract_entries(self, parent_renderer, continuation_list):
'shelfRenderer': lambda x: self._shelf_entries(x), 'shelfRenderer': lambda x: self._shelf_entries(x),
'backstagePostThreadRenderer': self._post_thread_entries, 'backstagePostThreadRenderer': self._post_thread_entries,
'videoRenderer': lambda x: [self._video_entry(x)], 'videoRenderer': lambda x: [self._video_entry(x)],
'playlistRenderer': lambda x: self._grid_entries({'items': [{'playlistRenderer': x}]}),
'channelRenderer': lambda x: self._grid_entries({'items': [{'channelRenderer': x}]}),
} }
for key, renderer in isr_content.items(): for key, renderer in isr_content.items():
if key not in known_renderers: if key not in known_renderers:
@ -3744,50 +3747,19 @@ def _search_results(self, query, params=NO_DEFAULT):
params = self._SEARCH_PARAMS params = self._SEARCH_PARAMS
if params: if params:
data['params'] = params data['params'] = params
continuation = {} continuation_list = [None]
for page_num in itertools.count(1): for page_num in itertools.count(1):
data.update(continuation) data.update(continuation_list[0] or {})
search = self._extract_response( search = self._extract_response(
item_id='query "%s" page %s' % (query, page_num), ep='search', query=data, item_id='query "%s" page %s' % (query, page_num), ep='search', query=data,
check_get_keys=('contents', 'onResponseReceivedCommands') check_get_keys=('contents', 'onResponseReceivedCommands'))
)
if not search:
break
slr_contents = try_get( slr_contents = try_get(
search, search,
(lambda x: x['contents']['twoColumnSearchResultsRenderer']['primaryContents']['sectionListRenderer']['contents'], (lambda x: x['contents']['twoColumnSearchResultsRenderer']['primaryContents']['sectionListRenderer']['contents'],
lambda x: x['onResponseReceivedCommands'][0]['appendContinuationItemsAction']['continuationItems']), lambda x: x['onResponseReceivedCommands'][0]['appendContinuationItemsAction']['continuationItems']),
list) list)
if not slr_contents: yield from self._extract_entries({'contents': slr_contents}, continuation_list)
break if not continuation_list[0]:
# Youtube sometimes adds promoted content to searches,
# changing the index location of videos and token.
# So we search through all entries till we find them.
continuation = None
for slr_content in slr_contents:
if not continuation:
continuation = self._extract_continuation({'contents': [slr_content]})
isr_contents = try_get(
slr_content,
lambda x: x['itemSectionRenderer']['contents'],
list)
if not isr_contents:
continue
for content in isr_contents:
if not isinstance(content, dict):
continue
video = content.get('videoRenderer')
if not isinstance(video, dict):
continue
video_id = video.get('videoId')
if not video_id:
continue
yield self._extract_video(video)
if not continuation:
break break
@ -4569,14 +4541,15 @@ class YoutubeSearchIE(YoutubeTabBaseInfoExtractor, SearchInfoExtractor):
IE_DESC = 'YouTube search' IE_DESC = 'YouTube search'
IE_NAME = 'youtube:search' IE_NAME = 'youtube:search'
_SEARCH_KEY = 'ytsearch' _SEARCH_KEY = 'ytsearch'
_SEARCH_PARAMS = None _SEARCH_PARAMS = 'EgIQAQ%3D%3D' # Videos only
_TESTS = [] _TESTS = []
class YoutubeSearchDateIE(SearchInfoExtractor, YoutubeTabBaseInfoExtractor): class YoutubeSearchDateIE(SearchInfoExtractor, YoutubeTabBaseInfoExtractor):
IE_NAME = YoutubeSearchIE.IE_NAME + ':date' IE_NAME = YoutubeSearchIE.IE_NAME + ':date'
_SEARCH_KEY = 'ytsearchdate' _SEARCH_KEY = 'ytsearchdate'
IE_DESC = 'YouTube search, newest videos first' IE_DESC = 'YouTube search, newest videos first'
_SEARCH_PARAMS = 'CAI%3D' _SEARCH_PARAMS = 'CAISAhAB' # Videos only, sorted by date
class YoutubeSearchURLIE(YoutubeTabBaseInfoExtractor): class YoutubeSearchURLIE(YoutubeTabBaseInfoExtractor):
@ -4590,6 +4563,14 @@ class YoutubeSearchURLIE(YoutubeTabBaseInfoExtractor):
'id': 'youtube-dl test video', 'id': 'youtube-dl test video',
'title': 'youtube-dl test video', 'title': 'youtube-dl test video',
} }
}, {
'url': 'https://www.youtube.com/results?search_query=python&sp=EgIQAg%253D%253D',
'playlist_mincount': 5,
'info_dict': {
'id': 'python',
'title': 'python',
}
}, { }, {
'url': 'https://www.youtube.com/results?q=test&sp=EgQIBBgB', 'url': 'https://www.youtube.com/results?q=test&sp=EgQIBBgB',
'only_matching': True, 'only_matching': True,