from requests import session
from youtube_util import getinitialdata, fullyexpand, getapikey, getlver
from time import sleep
mysession = session()
#extract latest version automatically
homepage = mysession.get("https://www.youtube.com/").text
API_KEY = getapikey(homepage)
params = (
('key', API_KEY),
)
API_VERSION = getlver(getinitialdata(homepage))
continuationheaders = {"x-youtube-client-name": "1", "x-youtube-client-version": API_VERSION, "Accept-Language": "en-US"}
del homepage
def process_channel(channelid: str):
playlists = set()
shelfres = set()
channellist = set()
# PLAYLISTS
data = {"context":{"client":{"hl":"en","gl":"US","clientName":"WEB","clientVersion":API_VERSION}},"browseId":channelid,"params":"EglwbGF5bGlzdHM%3D"}
while True:
initdata = mysession.post("https://www.youtube.com/youtubei/v1/browse", params=params, json=data)
if initdata.status_code == 200:
initdata = initdata.json()
break
else:
print("Non-200 API status code, waiting 30 seconds before retrying...")
sleep(30)
CHANNELS_ID = 0
PLAYLISTS_ID = 0
current = 0
for tab in initdata["contents"]["twoColumnBrowseResultsRenderer"]["tabs"]:
if "tabRenderer" in tab.keys():
if tab["tabRenderer"]["endpoint"]["commandMetadata"]["webCommandMetadata"]["url"].rsplit("/", 1)[-1] == "playlists":
PLAYLISTS_ID = current
elif tab["tabRenderer"]["endpoint"]["commandMetadata"]["webCommandMetadata"]["url"].rsplit("/", 1)[-1] == "channels":
CHANNELS_ID = current
current += 1
del current
shelflist = initdata["contents"]["twoColumnBrowseResultsRenderer"]["tabs"][PLAYLISTS_ID]["tabRenderer"]["content"]["sectionListRenderer"]["contents"]
for item in shelflist:
itemint = item["itemSectionRenderer"]["contents"][0]
if "shelfRenderer" in itemint.keys():
shelfres.add(itemint["shelfRenderer"]["title"]["runs"][0]["navigationEndpoint"]["commandMetadata"]["webCommandMetadata"]["url"])
elif "gridRenderer" in itemint.keys():
playlistsint = fullyexpand(itemint["gridRenderer"], mysession, continuationheaders)["items"]
for playlist in playlistsint:
playlists.add(playlist["gridPlaylistRenderer"]["playlistId"])
if "shortBylineText" in playlist["gridPlaylistRenderer"].keys():
channellist.add(playlist["gridPlaylistRenderer"]["shortBylineText"]["runs"][0]["navigationEndpoint"]["browseEndpoint"]["browseId"])
for item in shelfres:
while True:
shelfintp = mysession.get("https://www.youtube.com/"+str(item))
if not """
Sorry for the interruption. We have been receiving a large volume of requests from your network.
To continue with your YouTube experience, please fill out the form below.
""" in shelfintp.text and shelfintp.status_code == 200:
break
else:
print("Non-200 status code, waiting 30 seconds before retrying...")
sleep(30)
shelfiteminitdata = getinitialdata(shelfintp.text)
playlistsint = fullyexpand(shelfiteminitdata["contents"]["twoColumnBrowseResultsRenderer"]["tabs"][PLAYLISTS_ID]["tabRenderer"]["content"]["sectionListRenderer"]["contents"][0]["itemSectionRenderer"]["contents"][0]["gridRenderer"], mysession, continuationheaders)["items"]
for playlist in playlistsint:
playlists.add(playlist["gridPlaylistRenderer"]["playlistId"])
if "shortBylineText" in playlist["gridPlaylistRenderer"].keys():
channellist.add(playlist["gridPlaylistRenderer"]["shortBylineText"]["runs"][0]["navigationEndpoint"]["browseEndpoint"]["browseId"])
# CHANNELS
cshelfres = set()
# PLAYLISTS
data = {"context":{"client":{"hl":"en","gl":"US","clientName":"WEB","clientVersion":API_VERSION}},"browseId":channelid,"params":"EghjaGFubmVscw%3D%3D"}
while True:
initdata = mysession.post("https://www.youtube.com/youtubei/v1/browse", params=params, json=data)
if initdata.status_code == 200:
initdata = initdata.json()
break
else:
print("Non-200 API status code, waiting 30 seconds before retrying...")
sleep(30)
shelflist = initdata["contents"]["twoColumnBrowseResultsRenderer"]["tabs"][CHANNELS_ID]["tabRenderer"]["content"]["sectionListRenderer"]["contents"]
for item in shelflist:
itemint = item["itemSectionRenderer"]["contents"][0]
if "shelfRenderer" in itemint.keys():
cshelfres.add(itemint["shelfRenderer"]["title"]["runs"][0]["navigationEndpoint"]["commandMetadata"]["webCommandMetadata"]["url"])
elif "gridRenderer" in itemint.keys():
chanlistint = fullyexpand(itemint["gridRenderer"], mysession, continuationheaders)["items"]
for channel in chanlistint:
channellist.add(channel["gridChannelRenderer"]["channelId"])
for item in cshelfres:
while True:
shelfintc = mysession.get("https://www.youtube.com/"+str(item))
if not """
Sorry for the interruption. We have been receiving a large volume of requests from your network.
To continue with your YouTube experience, please fill out the form below.
""" in shelfintc.text and shelfintc.status_code == 200:
break
else:
print("Non-200 status code, waiting 30 seconds before retrying...")
sleep(30)
shelfiteminitdata = getinitialdata(shelfintc.text)
chanlistint = fullyexpand(shelfiteminitdata["contents"]["twoColumnBrowseResultsRenderer"]["tabs"][CHANNELS_ID]["tabRenderer"]["content"]["sectionListRenderer"]["contents"][0]["itemSectionRenderer"]["contents"][0]["gridRenderer"], mysession, continuationheaders)["items"]
for channel in chanlistint:
channellist.add(channel["gridChannelRenderer"]["channelId"])
return {"playlists": playlists, "channels": channellist}
if __name__ == "__main__":
from sys import argv
chanl = argv
chanl.pop(0)
for channel in chanl:
print(process_channel(channel))
# SAMPLES:
# UCqj7Cz7revf5maW9g5pgNcg lots of playlists
# UCRwczJ_nk1t9IGHyHfHbXRQ Nathaniel Bandy - created playlists only, featured channels only
# UCo8bcnLyZH8tBIH9V1mLgqQ the odd 1 is out - shelf, way too many subscriptions
# UCfXIV2vThxEF8Hq2OE17AeQ no playlists or channels featured
# UCJqV2-l0jqAa7uYN8IGJW7w TONS OF SUBSCRIPTIONS, no featured channels
# UC_1nZUpPS6jFv5Pn3f85CaA TONS OF SUBSCRIPTIONS, some featured channels
# UCJOh5FKisc0hUlEeWFBlD-w no subscriptions, plenty of featured channels
# UC7fjJERoGTs_eOKk-nn7RMw fair number of featured channels