0

I'm trying to make an auto-login twitter bot. But when I try to send_keys to passwords field, I can't. (Only passwords field doesn't work, the similar code for send_keys to username and phone_number works).

Error Message: "selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable".

So I tried to use execute_script instead.

driver.execute_script("arguments[0].value=arguments[1];", password_input, TWITTER_PASSWORD)

The line above works too. But I don't know how to send Enter key to arguments[0]

driver.execute_script("arguments[0].submit();", password_input)

Tried this but doesn't work. (Forgive me if this line is completely wrong cause it looks like this method take JS code and I don't know JS)

Please help me with this. Any help for this problem or just my code in general would be appreciated.

""" If you want to test the code, remember to give values to TWITTER_EMAIL, TWITTER_PHONE_NUMBER and TWITTER_PASSWORD. """

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time

TWITTER_EMAIL = 
TWITTER_PHONE_NUMBER =
TWITTER_PASSWORD = 

URL = r"https://twitter.com/i/flow/login"

s = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=s)

driver.get(url=URL)


def twitter_auto_login():

    time.sleep(10)

    username_input = driver.find_element(By.CSS_SELECTOR, "input")
    username_input.send_keys(TWITTER_EMAIL)
    time.sleep(2)
    username_input.send_keys(Keys.ENTER)

    time.sleep(5)

    phone_num_input = driver.find_element(By.CSS_SELECTOR, "input")
    phone_num_input.send_keys(TWITTER_PHONE_NUMBER)
    time.sleep(2)
    phone_num_input.send_keys(Keys.ENTER)

    time.sleep(5)

    password_input = driver.find_element(By.CSS_SELECTOR, "input")
    # driver.execute_script("arguments[0].click();", password_input)
    driver.execute_script("arguments[0].value=arguments[1];", password_input, TWITTER_PASSWORD)
    # https://stackoverflow.com/questions/52273298/what-is-arguments0-while-invoking-execute-script-method-through-webdriver-in

    time.sleep(2)

    driver.execute_script("arguments[0].submit();", password_input)

UPDATE: So I found exactly what is my stupid mistake here, in the third time entering input (the password input time), username is also an input tag will appear again and will be an unreachable tag. just use find_elements and select the second element of that list will get us the right password input tag. But the solution from wado is better, just use it in case u face the same problem

  • Hello! Have a look at this answer and see if any of the answers work for you: https://stackoverflow.com/questions/44119081/how-do-you-fix-the-element-not-interactable-exception – Mahmud Alptekin Sep 05 '22 at 13:57
  • Ahh, I can do .click() and it worked for me but i don't know how to do the same thing with "Enter" button. – Random Name Sep 05 '22 at 14:19

3 Answers3

1

Via JQuery, you can use the following Javascript to simulate the enter event:

driver.execute_script("var script = document.createElement('script');
script.src = 'https://code.jquery.com/jquery-3.6.0.min.js';
var e = $.Event( 'keypress', { which: 13 } );
arguments[0].trigger(e);", password_input)
C. Peck
  • 3,641
  • 3
  • 19
  • 36
1

No need to use driver.execute_script. In your case you're just locating the elements in a wrong way. You should do something like this:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


TWITTER_EMAIL = "email@email.com"
TWITTER_PASSWORD = "lalala"

URL = r"https://twitter.com/i/flow/login"

s = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=s)

driver.get(url=URL)


def twitter_auto_login():
    username_input = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//input[@autocomplete='username']")))
    username_input.send_keys(TWITTER_EMAIL)
    username_input.send_keys(Keys.ENTER)

    password_input = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//input[@autocomplete='current-password']")))
    password_input.send_keys(TWITTER_PASSWORD)
    password_input.send_keys(Keys.ENTER)


twitter_auto_login()

Note that I used explicit waits that are way better than those implicit waits (that makes you waste a lot of time senseless).

Carapace
  • 377
  • 2
  • 9
  • thank you, your code worked well. I just need to add phone_number since twitter detected my log-in action as unusual. I read about that "wait" method but didnt have a chance to implement it since i'm fixing another bug. So nice you help fixed that in my code too, now i understand about it and have a sample for later. – Random Name Sep 05 '22 at 14:34
  • guessed that i detect passwords field wrong way too but since it worked for username and phone-number I didnt check it well. Thought it has something to do with passwords alone. – Random Name Sep 05 '22 at 14:38
  • Yeah, I removed the phone part because it wasn't asking me for it but it's exactly the same I wrote for username and password. Of course the `autocomplete` value will be different. To check it just right click the input bar in the site and click on inspect. It will show you the part of html dom referring to that specific element and among the tags you'll find the one named autocomplete with its value. Lemme know if you manage to find it. – Carapace Sep 05 '22 at 14:43
  • yeah, i did that to phone-num too, and the attribute autocomplete='on', quite weird compares to the other two but can't complain since it still works well. – Random Name Sep 05 '22 at 14:45
  • phone_input = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//input[@autocomplete='on']"))) phone_input.send_keys(TWITTER_PHONE_NUMBER) phone_input.send_keys(Keys.ENTER) – Random Name Sep 05 '22 at 14:46
  • It's already near 10 PM here, but thanks. You too, Have a nice day :D – Random Name Sep 05 '22 at 14:48
0

It sounds like you want to submit whatever form that input is part of:

arguments[0].closest('form').submit()
pguardiario
  • 53,827
  • 19
  • 119
  • 159
  • password_input = driver.find_elements(By.CSS_SELECTOR, "input")[1] # driver.execute_script("arguments[0].click();", password_input) driver.execute_script("arguments[0].value=arguments[1];", password_input, TWITTER_PASSWORD) driver.execute_script("arguments[0].closest('form').submit()", password_input) – Random Name Sep 07 '22 at 09:35
  • raise exception_class(message, screen, stacktrace) selenium.common.exceptions.JavascriptException: Message: javascript error: Cannot read properties of null (reading 'submit') – Random Name Sep 07 '22 at 09:36
  • here is my error code – Random Name Sep 07 '22 at 09:37
  • guess i will just use send_keys(Keys.Enter) until I learn some JS. – Random Name Sep 07 '22 at 09:37