Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Post Youtube Comment with Selenium

I am trying to post a Youtube comment with Selenium. The following is the gist of the code (the lines about logging into Google are omitted):

comment_url = "https://www.youtube.com/all_comments?v=LAr6oAKieHk"
profile = webdriver.FirefoxProfile()
driver = webdriver.Firefox(firefox_profile=profile)

driver.get(comment_url)
assert "All comments" in driver.title

textbox = driver.find_element_by_class_name("box")
textbox.click()
textbox.send_keys("My comment")

textbox.click() worked as expected and set the focus to the comment box. However, textbox.send_keys("My comment") doesn't input the text into the box, but somehow deviate the focus away.

Could anyone give any suggestion?

like image 414
chenaren Avatar asked Sep 28 '22 21:09

chenaren


1 Answers

First, you need to click into the box to make it editable. Then, switch to the appropriate iframe and set the innerHTML attribute of an underlying "textbox". You also have to use Explicit Waits throughout the code since youtube is heavily using AJAX and there are asynchronous dynamic DOM updates happening on every action:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

comment = 'test'

box = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "box")))
box.click()

frame = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//iframe[@title="+1"]')))
driver.switch_to.frame(frame)

driver.find_element_by_xpath('//div[@onclick]').click()

element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//div[@jsname="msEQQc"]/following-sibling::div//div[@g_editable="true"]')))
driver.execute_script("arguments[0].innerHTML='%s';" % comment, element)

The complete code (including the authentication):

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


driver = webdriver.Firefox()
driver.get('https://accounts.google.com/ServiceLogin?continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Fhl%3Den%26feature%3Dcomment%26app%3Ddesktop%26next%3D%252Fall_comments%253Fv%253DLAr6oAKieHk%26action_handle_signin%3Dtrue&uilel=3&service=youtube&passive=true&hl=en')

# log in
driver.find_element_by_id('Email').send_keys('username')
driver.find_element_by_id('Passwd').send_keys('password')
driver.find_element_by_id('signIn').click()

# post a comment
comment = "test"

box = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "box")))
box.click()

frame = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//iframe[@title="+1"]')))
driver.switch_to.frame(frame)

driver.find_element_by_xpath('//div[@onclick]').click()

element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//div[@jsname="msEQQc"]/following-sibling::div//div[@g_editable="true"]')))
driver.execute_script("arguments[0].innerHTML='%s';" % comment, element)
like image 96
alecxe Avatar answered Oct 03 '22 02:10

alecxe