Created
February 19, 2020 21:27
-
-
Save iKlotho/00a3a8b16b1ba7bd72b7fd54a0d379cc to your computer and use it in GitHub Desktop.
Youtube Python Upload
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| Upload a video to youtube | |
| """ | |
| import os | |
| import time | |
| import cookielib | |
| import json | |
| import requests | |
| import mechanize | |
| from BeautifulSoup import BeautifulSoup | |
| class YoutubeUpload: | |
| def __init__( | |
| self, | |
| email, | |
| passwd, | |
| file="", | |
| video_name="default", | |
| description="", | |
| privacy="public", | |
| tags="", | |
| ): | |
| self.rupio_formdata = { | |
| "protocolVersion": "0.8", | |
| "createSessionRequest": { | |
| "fields": [ | |
| { | |
| "external": { | |
| "name": "file", | |
| "filename": "videoname", | |
| "put": {}, | |
| "size": 0, | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "return_address", | |
| "content": "www.youtube.com", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "user_token", | |
| "content": "aBSi_UqNbqLNey9asEQZrl3awgh8MTQ0MzIxMjM3MEAxNDQyNjA3NTcw", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "authuser", | |
| "content": "0", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "uploader_type", | |
| "content": "Web_XHR", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "frontend_id", | |
| "content": "web_upload:b7ef7a96-a27f-48dd-9ff1-8f311b0d11ac:0", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "use_drishti_thumbnailer", | |
| "content": "1", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "use_drishti_thumbnailer_for_high_priority", | |
| "content": "1", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "use_venom_processing", | |
| "content": "true", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "field_privacy", | |
| "content": "private", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "field_myvideo_title", | |
| "content": "videosxlilyseditzxokay issa", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "field_myvideo_descr", | |
| "content": "", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "field_myvideo_keywords", | |
| "content": "", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "field_myvideo_categories", | |
| "content": "23", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "allow_public_stats", | |
| "content": "yes", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "allow_comments", | |
| "content": "yes", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "allow_comments_detail", | |
| "content": "all", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "allow_ratings", | |
| "content": "yes", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "privacy_draft", | |
| "content": "public", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "session_token", | |
| "content": "QUFFLUhqbnVUZW9NckNVbWE0OHJaTVFHVzdaZkwyZW1WZ3xBQ3Jtc0tsZFBGajRVNWhxQnp0VWF1MlZfb3BRSkUzRjVnZU51S3hWWWhuYlAxTGRhMzgyZkpKekJJNXJNekdkSHVaOWt1V3RkNkx3d1pLQkc5blJSMW9TWjdKeEZTc2NxVjhrQmw5Wk1TUVpZRERreTh2djczZHBIbVRfMVZfcmpmSElXWjlndnFveWc0Z1BZbTFibXlBVEtPLUE5cTZLV0E=", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| { | |
| "inlined": { | |
| "name": "experiment_ids", | |
| "content": "9415398,9416475,9417481,9419979,9420289,9422596,9423555,9428398,9428632,9429954,9431012,9431681,9432939,9433221,9433839,9433870,9434046,9434289,9434949,9435354,9435521,9438309,9439451,9439580,9439877,9440054,9441194,9441513,9441929,9442387,9442393,9442426,9442746,9444189,9445634,9445860,9446054,9446062,9446142,9446364,9446877,9447232,9447774,9448302,9449034,9449074,9449243,9449256,9450059,9450402,9450544,9450641,9451164,9451343,9451345,9451494,9451783,9451814,9451827,9451873,9451929,9451937,9452119,9452146,9452448,9452833,9452850,9453098,9453167,9453553,9453682,9454366,9454383,9454394,9454653,9454793,9455031,9455068,9455072,9455655,9455983,9456026,9456133,9456249,9456443,9456445,9456516,9456628,9456631,9456640,9456760,9456930,9457141,9457146,9457169,9457492,9457494,9457591,9457595,9457598,9457623,9457968,9458027,9458029,9458054,9458240,9458265,9458386,9458668,9458670,9458881,9459035,9459067,9459073,9459075,9459187,9459429,9459444,9459605,9459762,9459768,9459793,9459798,9460103,9460349,9460431,9460434,9460599,9460727,9460830,9461013,9461125,9461208,9461327,9461498", | |
| "contentType": "text/plain", | |
| } | |
| }, | |
| ] | |
| }, | |
| } | |
| self.json_data_check = False | |
| self.user = email | |
| self.passwd = passwd | |
| self.rupio_url = "https://upload.youtube.com/upload/rupio" | |
| self.csa_url = "https://www.youtube.com/creator_suggestions_ajax" | |
| self.yummyajax_url = "https://www.youtube.com/yummy_ajax" | |
| self.setvideoparams_url = "https://www.youtube.com/api/tag_suggest" | |
| self.list_payload = {} | |
| self.video_id = None | |
| self.upload_id = None | |
| self.ssn_token = None | |
| self.user_token = None | |
| self.frontend_upload_id = None | |
| self.video_name = video_name | |
| self.description = description | |
| self.privacy = privacy | |
| self.file_name = file | |
| self.tag = tags | |
| self.br = mechanize.Browser() | |
| self.cj = cookielib.LWPCookieJar() | |
| self.br.set_cookiejar(self.cj) | |
| self.br.set_handle_equiv(True) | |
| self.br.set_handle_gzip(False) | |
| self.br.set_handle_redirect(True) | |
| self.br.set_handle_referer(True) | |
| self.br.set_handle_robots(False) | |
| self.br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1) | |
| self.br.addheaders = [ | |
| ( | |
| "User-agent", | |
| "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0", | |
| ) | |
| ] | |
| self.br.addheaders = [("Accept-Language", "en-US;q=0.5,en;q=0.3")] | |
| # call functions | |
| self.access_1() | |
| time.sleep(1) | |
| self.access_2() | |
| time.sleep((1)) | |
| self.getSessionToken() | |
| self.getFrontendUploadIdBase() | |
| self.getUserToken() | |
| self.find_youtube_web_uploads() | |
| self.setRupioData(self.file_name) | |
| self.post_creator_suggestions_ajax() | |
| time.sleep(0.5) | |
| self.post_rupio() | |
| time.sleep(0.5) | |
| self.post_yummyAjax() | |
| time.sleep(0.5) | |
| self.doOptions() | |
| time.sleep(0.5) | |
| self.setVideoParamaters() | |
| def access_1(self): | |
| # pylint: disable=line-too-long | |
| self.br.open( | |
| "https://accounts.google.com/ServiceLogin?passive=true&continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Faction_handle_signin%3Dtrue%26app%3Ddesktop%26feature%3Dsign_in_button%26hl%3Dtr%26next%3D%252F&uilel=3&hl=tr&service=youtube#identifier" | |
| ) | |
| self.br.select_form(nr=0) | |
| self.br.form.set_all_readonly(False) | |
| self.br.form["Email"] = self.user | |
| self.br.submit() | |
| def access_2(self): | |
| self.br.select_form(nr=0) | |
| self.br.form.set_all_readonly(False) | |
| self.br.form["Passwd"] = self.passwd | |
| self.br.submit() | |
| self.session = requests.Session() | |
| self.session.cookies = self.cj | |
| self.session.headers[ | |
| "User-Agent" | |
| ] = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0" | |
| self.session.headers["Accept-Language"] = "en-US;q=0.5,en;q=0.3" | |
| def getSessionToken(self): | |
| token_req = self.session.get("https://www.youtube.com/upload") | |
| self.soup = BeautifulSoup(token_req.content) | |
| script = self.soup.findAll("script") | |
| # TODO find with regex | |
| script_id = self.find_word_fr_script(script, "session_token") | |
| loc = script[script_id].text.find("var session_token") | |
| if loc: | |
| self.ssn_token = script[script_id].text[loc + 21 : loc + 313] | |
| def find_word_fr_script(self, scripts, word): | |
| count = 0 | |
| for j in scripts: | |
| if j.text.find(word) > 0: | |
| break | |
| count += 1 | |
| return count | |
| def getUserToken(self): | |
| script = self.soup.findAll("script") | |
| script_id = self.find_word_fr_script(script, "userToken") | |
| loc = script[script_id].text.find("userToken") | |
| if loc: | |
| self.user_token = script[script_id].text[loc + 12 : loc + 68] | |
| def getFrontendUploadIdBase(self): | |
| script = self.soup.findAll("script") | |
| script_id = self.find_word_fr_script(script, "frontend_upload_idBase") | |
| loc = script[script_id].text.find("frontend_upload_idBase") | |
| if loc: | |
| self.frontend_upload_id = script[script_id].text[loc + 23 : loc + 59] | |
| def get_userId(self): | |
| get_user_id_req = self.session.get("https://www.youtube.com/account_advanced") | |
| soup = BeautifulSoup(get_user_id_req.content) | |
| div = soup.findAll("div", "account-subsection") | |
| return div[0].findAll("p")[2].text[25 + 2 :] | |
| def get_videoId(self): | |
| self.list_payload = { | |
| "client": { | |
| "name": "youtube_web_uploads", | |
| "version": str(self.version), | |
| "token": str(self.token), | |
| }, | |
| "queries": [ | |
| { | |
| "id": {"frontendKey": self.frontend_upload_id}, | |
| "choice": { | |
| "editorSuggestions": True, | |
| "videoId": True, | |
| "videoInfo2": True, | |
| "videoIssues": True, | |
| "processingProgress": True, | |
| "youtubeStatus": True, | |
| "thumbnailsDone": True, | |
| }, | |
| } | |
| ], | |
| } | |
| check = True | |
| while check: | |
| videoid_req = self.session.post( | |
| "https://www.googleapis.com/videofeedback/v1/feedback/list", | |
| data=json.dumps(self.list_payload), | |
| headers={"Content-Type": "application/json"}, | |
| ) | |
| id_json = videoid_req.json() | |
| if videoid_req.status_code == 200: | |
| if id_json.has_key("items"): | |
| if id_json["items"][0]["feedback"]: | |
| check = False | |
| time.sleep(2) | |
| self.video_id = id_json["items"][0]["feedback"]["videoId"]["youtubeId"] | |
| if ( | |
| id_json["items"][0]["feedback"]["videoId"]["registrationStatus"] | |
| == "STATUS_SUCCESS" | |
| ): | |
| print("Video posting status success") | |
| self.post_yummyAjaxWithVideoId() | |
| def find_youtube_web_uploads(self): | |
| script = self.soup.findAll("script") | |
| script_id = self.find_word_fr_script(script, "youtube_web_uploads") | |
| loc = script[script_id].text.find("youtube_web_uploads") | |
| if loc: | |
| keep = script[script_id].text[loc + 20 : loc + 38] | |
| keep = keep.split(":") | |
| if len(keep) >= 2: | |
| self.version = keep[0] | |
| self.token = keep[1] | |
| else: | |
| print("version and token not found try again!") | |
| self.logout() | |
| def setRupioData(self, file_name): | |
| self.filename = file_name | |
| self.rupio_formdata["createSessionRequest"]["fields"][2]["inlined"][ | |
| "content" | |
| ] = str(self.user_token) | |
| self.rupio_formdata["createSessionRequest"]["fields"][19]["inlined"][ | |
| "content" | |
| ] = str(self.ssn_token) | |
| self.frontend_upload_id = "web_upload:" + str(self.frontend_upload_id) + ":0" | |
| self.rupio_formdata["createSessionRequest"]["fields"][5]["inlined"][ | |
| "content" | |
| ] = self.frontend_upload_id | |
| self.rupio_formdata["createSessionRequest"]["fields"][0]["external"][ | |
| "filename" | |
| ] = file_name | |
| self.rupio_formdata["createSessionRequest"]["fields"][0]["external"][ | |
| "size" | |
| ] = int(os.stat(file_name).st_size) | |
| self.rupio_formdata["createSessionRequest"]["fields"][10]["inlined"][ | |
| "content" | |
| ] = self.video_name | |
| self.rupio_formdata["createSessionRequest"]["fields"][18]["inlined"][ | |
| "content" | |
| ] = self.privacy | |
| self.rupio_formdata["createSessionRequest"]["fields"][11]["inlined"][ | |
| "content" | |
| ] = self.description | |
| self.rupio_formdata["createSessionRequest"]["fields"][12]["inlined"][ | |
| "content" | |
| ] = self.tag | |
| def post_rupio(self): | |
| req = self.session.post( | |
| self.rupio_url, | |
| data=json.dumps(self.rupio_formdata), | |
| params={"authuser": "0"}, | |
| ) | |
| search = req.json() | |
| self.upload_id = search["sessionStatus"]["upload_id"] | |
| print("upload_id -> ", self.upload_id) | |
| def post_creator_suggestions_ajax(self): | |
| print("posting creator sugg ajax") | |
| req = self.session.post( | |
| self.csa_url, | |
| params={"action_video_rules": "1", "location": "LOCATION_UPLOAD"}, | |
| data={"session_token": self.ssn_token}, | |
| ) | |
| print("creator sugg ajax code -> ", req.status_code) | |
| def post_yummyAjax(self): | |
| print("posting yummy_ajax") | |
| yummyajax_req = self.session.post( | |
| self.yummyajax_url, | |
| data={ | |
| "action_report": "1", | |
| "event_type": "UPLOAD_INTENT_DRAG_AND_DROP", | |
| "frontend_id": self.frontend_upload_id, | |
| "version": "1", | |
| "filename": self.filename, | |
| "session_token": str(self.ssn_token), | |
| }, | |
| ) | |
| print("yummy return ->", yummyajax_req.content) | |
| def post_yummyAjaxWithVideoId(self): | |
| yummywith_req = self.session.post( | |
| self.yummyajax_url, | |
| data={ | |
| "action_report": "1", | |
| "event_type": "REGISTRATION_INFO_RECEIVED", | |
| "frontend_id": self.frontend_upload_id, | |
| "version": "1", | |
| "video_id": str(self.video_id), | |
| "session_token": str(self.ssn_token), | |
| }, | |
| ) | |
| print("yummy ajax result -> ", yummywith_req.json()) | |
| self.doLastYummyPost() | |
| def doLastListPostYoutubeStat(self): | |
| find_feedback = True | |
| while find_feedback: | |
| last_req = self.session.post( | |
| "https://www.googleapis.com/videofeedback/v1/feedback/list", | |
| data=json.dumps(self.list_payload), | |
| headers={"Content-Type": "application/json"}, | |
| ) | |
| last_json = last_req.json() | |
| if last_json["items"][0].has_key("feedback"): | |
| if last_json["items"][0]["feedback"].has_key("youtubeStatus"): | |
| find_feedback = False | |
| print( | |
| "Youtube status -> video status : ", | |
| last_json["items"][0]["feedback"]["youtubeStatus"]["videoStatus"], | |
| ) | |
| def doListPostWhileFeedBack(self): | |
| find_feedback = True | |
| while find_feedback: | |
| last_req = self.session.post( | |
| "https://www.googleapis.com/videofeedback/v1/feedback/list", | |
| data=json.dumps(self.list_payload), | |
| headers={"Content-Type": "application/json"}, | |
| ) | |
| last_json = last_req.json() | |
| if last_json.has_key("items"): | |
| if last_json["items"][0].has_key("feedback"): | |
| find_feedback = False | |
| time.sleep(2) | |
| self.doLastYummyPost() | |
| def doLastYummyPost(self): | |
| yummy_with_req = self.session.post( | |
| self.yummyajax_url, | |
| data={ | |
| "action_report": "1", | |
| "event_type": "UPLOAD_MESSAGE", | |
| "frontend_id": self.frontend_upload_id, | |
| "version": "1", | |
| "upload_message_key": "HINT_NON_STREAMABLE_MOV", | |
| "transfer_id": "scotty:" + str(self.upload_id), | |
| "video_id": str(self.video_id), | |
| "filename": self.video_name, | |
| "session_token": str(self.ssn_token), | |
| }, | |
| ) | |
| print("Return ->", yummy_with_req.json()["code"]) | |
| self.doLastListPostYoutubeStat() | |
| def doOptions(self): | |
| self.session.options( | |
| "https://www.googleapis.com/videofeedback/v1/feedback/list" | |
| ) | |
| time.sleep(0.5) | |
| self.session.options( | |
| "https://upload.youtube.com/", | |
| params={ | |
| "authuser": "0", | |
| "upload_id": str(self.upload_id), | |
| "origin": "CidodHRwczovL3VwbG9hZC55b3V0dWJlLmNvbS91cGxvYWQvcnVwaW8SDXZpZGVvLXVwbG9hZHM", | |
| }, | |
| ) | |
| self.session.post("https://www.googleapis.com/videofeedback/v1/feedback/list") | |
| def postVideo(self): | |
| print("Posting video...") | |
| files = open(self.file_name, "rb") | |
| check_req = self.session.post( | |
| "https://upload.youtube.com", | |
| data=files, | |
| headers={"Content-Type": "application/octet-stream"}, | |
| params={ | |
| "authuser": "0", | |
| "upload_id": str(self.upload_id), | |
| "origin": "CidodHRwczovL3VwbG9hZC55b3V0dWJlLmNvbS91cGxvYWQvcnVwaW8SDXZpZGVvLXVwbG9hZHM", | |
| }, | |
| ) | |
| if check_req.json().has_key("sessionStatus"): | |
| print( | |
| "Video posting status ->", | |
| check_req.json()["sessionStatus"]["externalFieldTransfers"][0][ | |
| "status" | |
| ], | |
| ) | |
| print( | |
| "Transfered byte ->", | |
| check_req.json()["sessionStatus"]["externalFieldTransfers"][0][ | |
| "bytesTransferred" | |
| ], | |
| ) | |
| else: | |
| print("Video posting status -> REJECTED") | |
| self.logout() | |
| self.get_videoId() | |
| def setVideoParamaters(self): | |
| print("Sending video parameter") | |
| self.session.get( | |
| self.setvideoparams_url, | |
| params={ | |
| "title": self.video_name, | |
| "description": self.description, | |
| "language": "tr", | |
| "privacy": self.privacy, | |
| "tags": self.tag, | |
| "exp_bucket": "747", | |
| "youtube_category": 20, | |
| "want_content_tags": "true", | |
| "user_id": self.get_userId(), | |
| }, | |
| ) | |
| def setVideoMetaData( | |
| self, | |
| title="video", | |
| description="", | |
| keywords="", | |
| privacy="public", | |
| privacy_draft="none", | |
| still_id="2", | |
| thumbnail_preview_version="", | |
| allow_comments="yes", | |
| allow_comments_detail="all", | |
| allow_rating="yes", | |
| reuse="all_right_reserved", | |
| captions_certificate_reason="", | |
| allow_embedding="yes", | |
| creator_share_feeds="yes", | |
| category="20", | |
| location_longitude="", | |
| location_latitude="", | |
| location_altitude="", | |
| audio_language="", | |
| recorded_date="", | |
| allow_public_stats="yes", | |
| creator_share_gplus="yes", | |
| creator_share_twitter="no", | |
| self_racy="no", | |
| modified_fields="privacy_draft", | |
| ): | |
| if self.tag != "": | |
| self.modified_fields = "keywords" | |
| self.session.post( | |
| "https://www.youtube.com/metadata_ajax", | |
| params={"action_edit_video": "1"}, | |
| data={ | |
| "title": self.video_name, | |
| "description": self.description, | |
| "keywords": self.tag, | |
| "privacy": self.privacy, | |
| "privacy_draft": privacy_draft, | |
| "still_id": still_id, | |
| "thumbnail_preview_version": thumbnail_preview_version, | |
| "allow_comments": allow_comments, | |
| "allow_comments_detail": allow_comments_detail, | |
| "allow_rating": allow_rating, | |
| "reuse": reuse, | |
| "captions_certificate_reason": captions_certificate_reason, | |
| "allow_embedding": allow_embedding, | |
| "creator_share_feeds": creator_share_feeds, | |
| "category": category, | |
| "location_longitude": location_longitude, | |
| "location_latitude": location_latitude, | |
| "location_altitude": location_altitude, | |
| "audio_language": audio_language, | |
| "recorded_date": recorded_date, | |
| "allow_public_stats": allow_public_stats, | |
| "creator_share_gplus": creator_share_gplus, | |
| "creator_share_twitter": creator_share_twitter, | |
| "self_racy": self_racy, | |
| "modified_fields": modified_fields, | |
| "video_id": str(self.video_id), | |
| "session_token": str(self.getSessionToken()), | |
| }, | |
| ) | |
| def publishVideo(self): | |
| share_req = self.session.post( | |
| "https://www.youtube.com/video_ajax", | |
| params={"action_publish": "1", "o": "U"}, | |
| data={"video_id": str(self.video_id), "session_token": str(self.ssn_token)}, | |
| ) | |
| print("Video is publishing...") | |
| if share_req.json()["success"] is True: | |
| print("Video publishing status -> ", share_req.json()["messages"][0]) | |
| else: | |
| print("Video is not published") | |
| def logout(self): | |
| self.session.post( | |
| "https://www.youtube.com/logout", | |
| params={"action_logout": "1", "session_token": str(self.ssn_token)}, | |
| ) | |
| print("Logout") | |
| y = YoutubeUpload( | |
| "[email protected]", | |
| "xxx", | |
| "video.mp4", | |
| "pythonVideo Upload", | |
| "video", | |
| "private", | |
| "test", | |
| ) | |
| y.postVideo() | |
| y.setVideoMetaData() | |
| y.publishVideo() | |
| time.sleep(1) | |
| y.logout() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment