-
Notifications
You must be signed in to change notification settings - Fork 216
Description
I spent my afternoon struggling to figure ou how to make this old lib work again. Thought I'd share my working configuration with you.
Setup
- Python 3.8
- Youtube-uploader-selenium 0.1.0 (abbreviated YUS from now on)
- Selenium 4.0.0
- Selenium-firefox 2.0.8
- Geckodriver win64 0.30
The Geckodriver file is in the root directory of my project
Getting the code to run
I struggled to even have selenium display a window. Turned out that prior to starting the session, YUS has to make a copy of the given Firefox profile directory. By default, this directory is the root of your project. In my case, it was quite big already (1GB), too big actually. YUS raised an urllib3 error. The connection was initiated before starting to copy the working dir, and expired during the copy. Two options:
- Make so that your working directory becomes light
- Specify another Firefox profile directory.
To do the latter you need to open the YouTubeUploader class, go to init and manually set it in this way: self.browser = Firefox(your_profile_path)
Another problem was that the classes By and Keys were not present in "selenium_firefox.firefox import Firefox, By, Keys". Simply replace this line by:
from selenium_firefox.firefox import Firefox
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
Bypassing Google's check "This browser or app may not be secure"
Many solutions for this online, none of them worked for me. Misc: use chromium-undetected, stealth-selenium, login to Google from another app (Stackoverflow, Spotify, ...).
What worked for me was to create a brand new firefox profile, connect to my account from there, and use this new directory as your_profile_path (in the YouTubeUploader class). On windows: type "firefox.exe -p" to open the profile manager, create a new profile, and check the new folder created in %appdata%/Mozilla/Firefox/Profiles/[profile_name]. Use this directory as your_profile_path -- you should now be connected to Youtube in your Selenium window.
Things that did not work due to YUS being too old
The core of the interaction between YUS and Youtube is in your YouTubeUploader's method '__upload()'. I cannot really help extensively here because it's too machine-dependent and version-dependent, but here are some tips.
- The delay between uploading the video and giving it a title it too short. time.sleep(5) here made it work
- The various fields' names are stored in the file Constant.py. Note how YUS finds them by name, id or class (literally By.ID, By.NAME, ...). In order to find them by yourself, go to Youtube, upload a dummy video, and press ctrl+maj+C (on Firefox), navigate to the code corresponding to the button/field you're looking for, and finally report its id or name in your Constant.py file. Depending on the method you chose, don't forget to change the By.xxx method in __upload(). My config is at the bottom of this message (note that it also tells you how to upload a thumbnail and how to schedule a video).
- Take care of handling the waiting times before pressing the buttons, like, a large video will make your code fail if you don't wait until the "publish" button is no more grayed out. Basically, pause your code for 1s after every action and for a couple of seconds (or more) after each significant interface interaction.
I think that's all, hope I spared you an afternoon!
class Constant:
"""A class for storing constants for YoutubeUploader class"""
YOUTUBE_URL = 'https://www.youtube.com'
YOUTUBE_STUDIO_URL = 'https://studio.youtube.com'
YOUTUBE_UPLOAD_URL = 'https://www.youtube.com/upload'
USER_WAITING_TIME = 1
VIDEO_TITLE = 'title'
VIDEO_DESCRIPTION = 'description'
DESCRIPTION_CONTAINER = '/html/body/ytcp-uploads-dialog/paper-dialog/div/ytcp-animatable[1]/' \
'ytcp-uploads-details/div/ytcp-uploads-basics/ytcp-mention-textbox[2]'
MORE_OPTIONS_CONTAINER = '/html/body/ytcp-uploads-dialog/paper-dialog/div/ytcp-animatable[1]/' \
'ytcp-uploads-details/div/div/ytcp-button/div'
TEXTBOX = 'textbox'
TEXT_INPUT = 'text-input'
RADIO_LABEL = 'radioLabel'
STATUS_CONTAINER = '/html/body/ytcp-uploads-dialog/paper-dialog/div/ytcp-animatable[2]/' \
'div/div[1]/ytcp-video-upload-progress/span'
NOT_MADE_FOR_KIDS_LABEL = 'NOT_MADE_FOR_KIDS'
NEXT_BUTTON = 'next-button'
PUBLIC_BUTTON = 'PUBLIC'
VIDEO_URL_CONTAINER = "//span[@class='video-url-fadeable style-scope ytcp-video-info']"
VIDEO_URL_ELEMENT = "//a[@class='style-scope ytcp-video-info']"
HREF = 'href'
UPLOADED = 'uploaded'
ERROR_CONTAINER = '//*[@id="error-message"]'
VIDEO_NOT_FOUND_ERROR = 'Could not find video_id'
DONE_BUTTON = 'done-button'
INPUT_FILE_VIDEO = "//input[@type='file']"
ID_DATE_SCHEDULE = "datepicker-trigger"
ID_HOUR_SCHEDULE = "time-of-day-container"
ID_SCHEDULE_BUTTON = "second-container-expand-button"
INPUT_FILE_THUMBNAIL = "file-loader"