@@ -17,113 +17,105 @@ def __init__(self, channel_id: str, request_params: str):
1717 self .continuation = None
1818
1919 def prepare_request (self ):
20- if not searchKey :
21- raise Exception ('(searchKey) is not set.' )
22- self .url = 'https://www.youtube.com/youtubei/v1/browse?' + urlencode ({
20+ self .url = 'https://www.youtube.com/youtubei/v1/browse' + "?" + urlencode ({
2321 'key' : searchKey ,
24- ' prettyPrint' : ' false'
22+ " prettyPrint" : " false"
2523 })
2624 self .data = copy .deepcopy (requestPayload )
27- context = self .data .setdefault ('context' , {})
28- client = context .setdefault ('client' , {})
29- client .setdefault ('hl' , client .get ('hl' ))
30- client .setdefault ('gl' , client .get ('gl' ))
3125 if not self .continuation :
32- self .data [' params' ] = self .params
33- self .data [' browseId' ] = self .browseId
26+ self .data [" params" ] = self .params
27+ self .data [" browseId" ] = self .browseId
3428 else :
35- self .data [' continuation' ] = self .continuation
29+ self .data [" continuation" ] = self .continuation
3630
3731 def playlist_parse (self , i ) -> dict :
3832 return {
39- 'id' : getValue (i , [' playlistId' ]),
40- ' thumbnails' : getValue (i , [' thumbnail' , ' thumbnails' ]),
41- ' title' : getValue (i , [' title' , ' runs' , 0 , ' text' ]),
42- ' videoCount' : getValue (i , [' videoCountShortText' , ' simpleText' ]),
43- ' lastEdited' : getValue (i , [' publishedTimeText' , ' simpleText' ]),
33+ "id" : getValue (i , [" playlistId" ]),
34+ " thumbnails" : getValue (i , [" thumbnail" , " thumbnails" ]),
35+ " title" : getValue (i , [" title" , " runs" , 0 , " text" ]),
36+ " videoCount" : getValue (i , [" videoCountShortText" , " simpleText" ]),
37+ " lastEdited" : getValue (i , [" publishedTimeText" , " simpleText" ]),
4438 }
4539
46- def _safe_extend_thumbnails (self , resp , path ):
47- val = getValue (resp , path )
48- if val :
49- try :
50- return list (val )
51- except Exception :
52- return []
53- return []
54-
5540 def parse_response (self ):
56- try :
57- resp = self .data .json ()
58- except Exception :
59- resp = json .loads (self .data .text ) if hasattr (self .data , 'text' ) else {}
41+ response = self .data .json ()
6042
6143 thumbnails = []
62- thumbnails .extend (self ._safe_extend_thumbnails (resp , ['header' , 'c4TabbedHeaderRenderer' , 'avatar' , 'thumbnails' ]))
63- thumbnails .extend (self ._safe_extend_thumbnails (resp , ['metadata' , 'channelMetadataRenderer' , 'avatar' , 'thumbnails' ]))
64- thumbnails .extend (self ._safe_extend_thumbnails (resp , ['microformat' , 'microformatDataRenderer' , 'thumbnail' , 'thumbnails' ]))
65-
66- tabData = {}
67- playlists = []
68-
69- tabs = getValue (resp , ['contents' , 'twoColumnBrowseResultsRenderer' , 'tabs' ]) or []
70- for tab in tabs :
71- title = getValue (tab , ['tabRenderer' , 'title' ])
72- if title == 'Playlists' :
73- playlist = getValue (tab , ['tabRenderer' , 'content' , 'sectionListRenderer' , 'contents' , 0 , 'itemSectionRenderer' , 'contents' , 0 , 'gridRenderer' , 'items' ])
74- if playlist and getValue (playlist , [0 , 'gridPlaylistRenderer' ]):
44+ try :
45+ thumbnails .extend (getValue (response , ["header" , "c4TabbedHeaderRenderer" , "avatar" , "thumbnails" ]))
46+ except (KeyError , AttributeError , TypeError ):
47+ pass
48+ try :
49+ thumbnails .extend (getValue (response , ["metadata" , "channelMetadataRenderer" , "avatar" , "thumbnails" ]))
50+ except (KeyError , AttributeError , TypeError ):
51+ pass
52+ try :
53+ thumbnails .extend (getValue (response , ["microformat" , "microformatDataRenderer" , "thumbnail" , "thumbnails" ]))
54+ except (KeyError , AttributeError , TypeError ):
55+ pass
56+
57+ tabData : dict = {}
58+ playlists : list = []
59+
60+ for tab in getValue (response , ["contents" , "twoColumnBrowseResultsRenderer" , "tabs" ]):
61+ tab : dict
62+ title = getValue (tab , ["tabRenderer" , "title" ])
63+ if title == "Playlists" :
64+ playlist = getValue (tab ,
65+ ["tabRenderer" , "content" , "sectionListRenderer" , "contents" , 0 , "itemSectionRenderer" ,
66+ "contents" , 0 , "gridRenderer" , "items" ])
67+ if playlist is not None and getValue (playlist , [0 , "gridPlaylistRenderer" ]):
7568 for i in playlist :
76- if getValue (i , ['continuationItemRenderer' ]):
77- self .continuation = getValue (i , ['continuationItemRenderer' , 'continuationEndpoint' , 'continuationCommand' , 'token' ])
69+ if getValue (i , ["continuationItemRenderer" ]):
70+ self .continuation = getValue (i , ["continuationItemRenderer" , "continuationEndpoint" ,
71+ "continuationCommand" , "token" ])
7872 break
79- grid = getValue (i , ['gridPlaylistRenderer' ])
80- if grid :
81- playlists .append (self .playlist_parse (grid ))
82- elif title == 'About' :
83- tabData = getValue (tab , ['tabRenderer' ]) or {}
73+ i : dict = i ["gridPlaylistRenderer" ]
74+ playlists .append (self .playlist_parse (i ))
75+ elif title == "About" :
76+ tabData = tab ["tabRenderer" ]
8477
85- metadata = getValue (
86- tabData ,
87- ['content' , 'sectionListRenderer' , 'contents' , 0 , 'itemSectionRenderer' , 'contents' , 0 , 'channelAboutFullMetadataRenderer' ]
88- ) or {}
78+ metadata = getValue (tabData ,
79+ ["content" , "sectionListRenderer" , "contents" , 0 , "itemSectionRenderer" , "contents" , 0 ,
80+ "channelAboutFullMetadataRenderer" ])
8981
9082 self .result = {
91- 'id' : getValue (resp , ['metadata' , 'channelMetadataRenderer' , 'externalId' ]),
92- 'url' : getValue (resp , ['metadata' , 'channelMetadataRenderer' , 'channelUrl' ]),
93- 'description' : getValue (resp , ['metadata' , 'channelMetadataRenderer' , 'description' ]),
94- 'title' : getValue (resp , ['metadata' , 'channelMetadataRenderer' , 'title' ]),
95- 'banners' : getValue (resp , ['header' , 'c4TabbedHeaderRenderer' , 'banner' , 'thumbnails' ]),
96- 'subscribers' : {
97- 'simpleText' : getValue (resp , ['header' , 'c4TabbedHeaderRenderer' , 'subscriberCountText' , 'simpleText' ]),
98- 'label' : getValue (resp , ['header' , 'c4TabbedHeaderRenderer' , 'subscriberCountText' , 'accessibility' , 'accessibilityData' , 'label' ])
83+ "id" : getValue (response , ["metadata" , "channelMetadataRenderer" , "externalId" ]),
84+ "url" : getValue (response , ["metadata" , "channelMetadataRenderer" , "channelUrl" ]),
85+ "description" : getValue (response , ["metadata" , "channelMetadataRenderer" , "description" ]),
86+ "title" : getValue (response , ["metadata" , "channelMetadataRenderer" , "title" ]),
87+ "banners" : getValue (response , ["header" , "c4TabbedHeaderRenderer" , "banner" , "thumbnails" ]),
88+ "subscribers" : {
89+ "simpleText" : getValue (response ,
90+ ["header" , "c4TabbedHeaderRenderer" , "subscriberCountText" , "simpleText" ]),
91+ "label" : getValue (response , ["header" , "c4TabbedHeaderRenderer" , "subscriberCountText" , "accessibility" ,
92+ "accessibilityData" , "label" ])
9993 },
100- 'thumbnails' : thumbnails ,
101- 'availableCountryCodes' : getValue (resp , ['metadata' , 'channelMetadataRenderer' , 'availableCountryCodes' ]),
102- 'isFamilySafe' : getValue (resp , ['metadata' , 'channelMetadataRenderer' , 'isFamilySafe' ]),
103- 'keywords' : getValue (resp , ['metadata' , 'channelMetadataRenderer' , 'keywords' ]),
104- 'tags' : getValue (resp , ['microformat' , 'microformatDataRenderer' , 'tags' ]),
105- 'views' : getValue (metadata , ['viewCountText' , 'simpleText' ]) if metadata else None ,
106- 'joinedDate' : getValue (metadata , ['joinedDateText' , 'runs' , - 1 , 'text' ]) if metadata else None ,
107- 'country' : getValue (metadata , ['country' , 'simpleText' ]) if metadata else None ,
108- 'playlists' : playlists ,
94+ "thumbnails" : thumbnails ,
95+ "availableCountryCodes" : getValue (response ,
96+ ["metadata" , "channelMetadataRenderer" , "availableCountryCodes" ]),
97+ "isFamilySafe" : getValue (response , ["metadata" , "channelMetadataRenderer" , "isFamilySafe" ]),
98+ "keywords" : getValue (response , ["metadata" , "channelMetadataRenderer" , "keywords" ]),
99+ "tags" : getValue (response , ["microformat" , "microformatDataRenderer" , "tags" ]),
100+ "views" : getValue (metadata , ["viewCountText" , "simpleText" ]) if metadata else None ,
101+ "joinedDate" : getValue (metadata , ["joinedDateText" , "runs" , - 1 , "text" ]) if metadata else None ,
102+ "country" : getValue (metadata , ["country" , "simpleText" ]) if metadata else None ,
103+ "playlists" : playlists ,
109104 }
110105
111106 def parse_next_response (self ):
112- try :
113- resp = self .data .json ()
114- except Exception :
115- resp = json .loads (self .data .text ) if hasattr (self .data , 'text' ) else {}
107+ response = self .data .json ()
116108
117109 self .continuation = None
118- items = getValue (resp , ['onResponseReceivedActions' , 0 , 'appendContinuationItemsAction' , 'continuationItems' ]) or []
119110
120- for i in items :
121- if getValue (i , ['continuationItemRenderer' ]):
122- self .continuation = getValue (i , ['continuationItemRenderer' , 'continuationEndpoint' , 'continuationCommand' , 'token' ])
111+ response = getValue (response , ["onResponseReceivedActions" , 0 , "appendContinuationItemsAction" , "continuationItems" ])
112+ for i in response :
113+ if getValue (i , ["continuationItemRenderer" ]):
114+ self .continuation = getValue (i , ["continuationItemRenderer" , "continuationEndpoint" , "continuationCommand" , "token" ])
123115 break
124- grid = getValue (i , ['gridPlaylistRenderer' ]) or getValue ( i , [ 'gridShowRenderer' ])
125- if grid :
126- self . result . setdefault ( 'playlists' , []). append ( self . playlist_parse ( grid ))
116+ elif getValue (i , ['gridPlaylistRenderer' ]):
117+ self . result [ "playlists" ]. append ( self . playlist_parse ( getValue ( i , [ 'gridPlaylistRenderer' ])))
118+ # TODO: Handle other types like gridShowRenderer
127119
128120 async def async_next (self ):
129121 if not self .continuation :
@@ -146,7 +138,6 @@ async def async_create(self):
146138 self .prepare_request ()
147139 self .data = await self .asyncPostRequest ()
148140 self .parse_response ()
149-
150141 def sync_create (self ):
151142 self .prepare_request ()
152143 self .data = self .syncPostRequest ()
0 commit comments