So I am trying to fill out a form on this site. Every time I try to click the submit button at the end, using what I believe is the correct id, it just gives me an error. Here is a code snippet:
from selenium import webdriver
thePassword = "asdf123"
print("Desired name: ")
name = raw_input()
print("Desired Last Name: ")
userLastName = raw_input()
browser = webdriver.Firefox()
browser.get('https://www.panerabread.com/en-us/mypanera/registration-page.html')
firstName = browser.find_element_by_id('join_first_name')
firstName.send_keys(name)
lastName = browser.find_element_by_id('join_last_name')
lastName.send_keys(userLastName)
emailElem = browser.find_element_by_id('join_email')
emailElem.send_keys("asdafasda" + "#gmail.com")
emailConfirm = browser.find_element_by_id("join_confirm_email")
emailConfirm.send_keys("asdafasda" + "#gmail.com")
password = browser.find_element_by_id("join_password")
password.send_keys("thePassword")
passwordConfirm = browser.find_element_by_id("join_confirm_password")
passwordConfirm.send_keys("thePassword")
phoneA = browser.find_element_by_id("phone_number_a")
phoneA.send_keys("231")
phoneB = browser.find_element_by_id("phone_number_b")
phoneB.send_keys("123")
phoneC = browser.find_element_by_id("phone_number_c")
phoneC.send_keys("2310")
tos = browser.find_element_by_id("join_i_agree")
tos.click()
browser.execute_script("$('#join_password').get(0).scrollIntoView();")
#browser.implicitly_wait(10)
# And then perform the click
browser.find_element_by_id("join_card_not_available").click()
browser.find_elements_by_css_selector("#join-now-primary")[1].click()
print "Your email is: " + "asdafasda" + "#gmail.com"
print "Your password is: " + thePassword
My question is, how can I submit the form at the end of my script?
Edit: There is no error. The problem is that it doesn't click the button I want it to at all. I tried running the below code on a seperate file and it worked, however when you run it with this entire script it does not work.
This was a weird one... it took me a minute to figure out what was going on. The problem is that there are actually two elements that have that id on the page (which is a no-no according to the HTML standard... but alas it happens). One on the bottom of the page that you are looking at and another on the Sign In popup. If you click the Sign In button at the top of the page, you will see the (first) Sign In button on the popup. Because it is hidden, your code wouldn't click on it. Anyway... to the solution.
There are a few ways you can handle this, any of them valid. I would do this.
browser.find_elements_by_css_selector("#join-now-primary")[1].click()
What this is doing is using a CSS selector to get all the elements with ID=join-now-primary. The CSS selector is #join-now-primary which means id (#) of join-now-primary. Because it uses .find_elements (plural), it will get both. We then use [1] to get the 2nd element (0-based index, so 1 is the 2nd) and then click on it.
EDIT
My guess is that it's a timing issue that is causing the code to work on its own but not in your script. Put a breakpoint on the first line and step through each line and make sure that it executes. Does it work? If I were to guess again... it's likely the line right before the Join Now click. That click has an animation that closes the credit card picture. I would wait for that section to become invisible using the code below
element = WebDriverWait(browser, 5).until(EC.invisibility_of_element_located(By.ID('panera-card-section')))
browser.find_elements_by_css_selector("#join-now-primary")[1].click()
You didn't really ask a question but it's likely you need to look at the WebElement class's methods and properties.
Looks like the button might not be in the visible portion of the window based on your code.
WebElement Has a property call that scrolls until an element moves into view.
If an element is not visible by Selenium definition, it is not clickable.
Even though you use the guts of the page to drive it, selenium wants to pretend it is testing human like interaction and so provides an artificial constraint.
You can bypass that by executing JavaScript click() on the element.
Related
SOLVED:
It seems like this single input field would be not interactable unless it was clicked in the most recent 0.1 seconds. To solve that the following code was used:
ActionChains(self.driver).move_to_element(input).click().send_keys("200").perform()
This way the focus stays on the element and the input works. Interestingly, if input.send_keys() is called this still does not work.
Problem:
After pressing a button on the website, a popup window opens up which contains multiple input fields which are generated by react. Most of these are accessible. However, one of them is not and returns an ElementNotInteractableException error. I have tried the most common solutions but those do not work.
The interesting part is that when the element is accessed manually from the front end, it can be interacted with. The element also is shown normally in a screenshot which is taken upon an exception being thrown
Solutions tried:
Increase implicit wait until 1 minute,
Add explicit wait untill 1 minute
Use different finding methods for the element
Reorder test to see if other elements influence it (all possible orders have failed)
Add Actionchains Move to and Click. The move to and click work (I can see the element being selected with a blue outline, but the input still feels)
Use Javascript to insert the string into the input fields.value
Code block on which the error occurs:
#this input element is next to it in the same parent element
dropdownparent = elems[2].find_element_by_xpath(".//div[#role='combobox']")
dropdowninput = dropdownparent.find_element_by_css_selector("input")
f.inputtext(dropdowninput, "Coulance", True )
#reobtain the parent items to avoid a stale element reference error
modal = self.driver.find_element_by_class_name("component-window")
body = modal.find_element_by_class_name("body")
elems = body.find_elements_by_xpath("./div")
required = elems[2].find_elements_by_class_name("required")
inputparent = required[1].find_element_by_class_name("input")
input = inputparent.find_element_by_css_selector("input")
#error occurs on next line
f.inputtext(input, "200")
Error log:
https://pastebin.com/ihqCvjfj
its long but its a very standard elementnotaccessible
Any suggestions would be appreciated, I will update the solutions tried section whenever I try something
Element not interactable comes when the element is out of clickable area or some other element is covering up that element.
You can try by scrolling the page to an element or you can set input value by executing javascript, something like this:
element = inputparent.find_element_by_css_selector("input")
driver.execute_script("""arguments[0].value = arguments[1];""", element, "some input value")
Selenium must enter text in the search field, press enter, then clear it and enter new text. But here's the problem when I use firefox everything works fine, but the chromedriver for some reason does not want to delete the old text.
def test_pacient_search(app):
app.patient_search(patient_fullname="Name1")
time.sleep(2)
app.patient_search(patient_fullname="Name2")
def patient_search(self, patient_fullname):
wd = self.wd
patient_search = wd.find_element_by_class_name("components__input__input")
patient_search.click()
patient_search.clear()
patient_search.send_keys(patient_fullname)
patient_search.send_keys(Keys.ENTER)
This is a weird issue, but I have observed quite few time that .clear() does not work properly.
In those cases generally what I'd do, is to simulate ctrl+a and then delete, make sense ?
so instead of
patient_search.clear()
do this :
patient_search.send_keys(Keys.CONTROL + "a")
patient_search.send_keys(Keys.DELETE)
I am trying to get followers with python selenium. But sometimes python clicks by itself.
I want to make an error-free program. I try to I've tried "try catch" constructs but it didn't work. Here is my code:
def getFollowers(self):
try:
self.browser.get(f"https://www.instagram.com/{self.username}")
time.sleep(2)
followers=self.browser.find_element_by_xpath("//*[#id='react-root']/section/main/div/header/section/ul/li[2]/a").click()
time.sleep(2)
dialog=self.browser.find_element_by_xpath("/html/body/div[5]/div/div/div[2]")
followerCount=len(dialog.find_elements_by_tag_name("li"))
print(f"first count:{followerCount}")
action=webdriver.ActionChains(self.browser)
//*******************************************Probly my problem is here****************************************
while True:
dialog.click()
action.key_down(Keys.SPACE).key_up(Keys.SPACE).perform()
time.sleep(3)
newCount=len(dialog.find_elements_by_tag_name("li"))
if followerCount!=newCount or newCount==24:
print(f"New count:{newCount}")
time.sleep(3)
followerCount=newCount
else:
break
//**********************************************************************************************************
followers=dialog.find_elements_by_tag_name("li")
followersList=[]
for user in followers:
link=user.find_element_by_css_selector("a").get_attribute("href")
# print(link)
followersList.append(link)
with open("followers.txt","w",encoding="UTF-8") as file:
for item in followersList:
file.write(item+"\n")
time.sleep(5)
except:
pass
I also have def getfollowing and it works flawlessly. If you want I can show it too. But they are almost same.
EDIT: #RohanShah solved my problem. At the bottom of the page you can see the solution.
Edit: I am new here thats why sometimes my questions could be meanless.But please dont decrease my points. Stackoverflow not gonna accept my questions anymore. Please increase my points.
I've had this exact same problem while scrolling the popups. What happens is your dialog.click(), while attempting to focus your key down on the popup, occasionally clicks a user and loads their profile. Your script then crashes as the popup is no longer on the screen.
After a lot of research into solving this problem, I noticed it only happens with usernames that are long. Regardless, I implemented a simple hack to get around this problem.
First we get the url of what the standard scroll looks like. When opening and scrolling the popup, this is the url we are on.
https://www.instagram.com/some_username/followers/
2.Now I have created a function to hold the code for opening the popup. This will be very useful so trap the necessary code into a function. (I don't have the classnames or xpath's on me so please customize the function for yourself)
def openPopup():
self.browser.get(f"https://www.instagram.com/{self.username}")
global popup # we will need to access this variable outside of the function
popup = driver.find_element_by_class_name('popupClass') #you don't have to use class_name
popup.click()
Now we have to tell our while loop to not scan when Selenium accidentally clicks on a user. We will use our URL from step 1. Please make sure the following if-statement is inserted at the TOP of your loop so if there is a break, it will handle it first before trying to access the popup.
while True:
check_url = self.browser.current_url #returns string with current_url
if check_url != 'https://www.instagram.com/some_username/followers/':
#if this code is executed, this means there has been an accidental click
openPopup() #this will bring back to the page and reopen popup
#the rest of your code
popup.click() # variable from our function
action.key_down(Keys.SPACE).key_up(Keys.SPACE).perform()
time.sleep(3)
newCount=len(dialog.find_elements_by_tag_name("li"))
if followerCount!=newCount or newCount==24:
print(f"New count:{newCount}")
time.sleep(3)
followerCount=newCount
else:
break
check_url = self.browser.current_url #we must recheck the current_url every time the loop runs to see if there has been a misclick
Now, whenever your loop detects the URL is no longer one of the popup, it will automatically call openPopup() which will get you back to the page and back in the popup, and your loop will continue as if nothing happened.
I am trying to automate a task which can save me thousands of clicks.
I searched a bit for available modules in Python and I have selected to work with Selenium.
I installed Firefox drivers and did some progress but I am stuck for a long time. I finally gave up, opened a Stack Overflow account and wanted to bring this problem into this helpful medium.
My code can successfully do some clicks, but I could not make the code click a button like element. I have to click such items so that page opens some new elements. (Hopefully I am going to click on these new elements to save some excels files automatically).
Here is the part which works as expected:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
browser = webdriver.Firefox()
url = "https://www.tbb.org.tr/tr/bankacilik/banka-ve-sektor-bilgileri/istatistiki-raporlar/59"
browser.get(url)
time.sleep(2)
bank_reports_element_xpath = "//*[#title= 'Tüm Raporlar']"
bank_reports_element = browser.find_element_by_xpath(bank_reports_element_xpath)
bank_reports_element.click()
time.sleep(2)
second_item = "//div[#data-catid = '52']"
finance_tables_element = browser.find_element_by_xpath(second_item)
finance_tables_element.click()
years_item = "//div[#class = 'years']"
years_element = finance_tables_element.find_element_by_xpath(years_item)
year_elements = years_element.find_elements_by_xpath("a")
There I would like to click on the years.
a screenshot of the years that I can't click using Selenium
As an example, I get the element related to year 2004.
year2004 = year_elements[2]
Issuing a year2004.click() command gives an ElementNotInteractableException exception.
year2004.click() # ElementNotInteractableException: Element could not be scrolled into view
Based on searching similar posts, I tried the following (executing the click via javascript). I got no error but it does not do anything. When I click the year2004 button with mouse, a list pops-up in the page. But when I run the below code, no list pops up in the page.
browser.implicitly_wait(4)
browser.execute_script("arguments[0].scrollIntoView();", year2004)
browser.execute_script("arguments[0].click()", year2004)
I tried also the following code. I get "TypeError: rect is undefined"
browser.implicitly_wait(4)
action = ActionChains(browser)
action.move_to_element(year2004) # gives: TypeError: rect is undefined
action.click(on_element = year2004) # gives: TypeError: rect is undefined
action.perform()
I tried using Chrome Driver and got similar results. The errors definitions were not exactly the same. Instead of the above "rect is undefined" error, Chrome error is like: "Javascript error: Failed to execute 'elementsFromPoints' on 'Document': Provided double value is non-finite"
I don't know if it is relevant but year2004.location dictionary has a 0 value for "x".
I would appreciate any answer,
Keep safe
Use this xpath will give you all the elements of year in 52 category
//div[#data-catid='52']/descendant-or-self::*/div[#class='years']/child::a
for scrolling try
browser.send_keys(Keys.PAGE_DOWN)
I checked manually and page down button is working for me press it twice for desire element
I have tried to make my script click the log in button on the Spotify login page. I have been searching all day for a solution, but no matter what class, css or whatever I put in, it is just saying it could not find the object.
My code:
import selenium
from selenium import webdriver
browser = webdriver.Firefox()
browser.get("https://accounts.spotify.com/en/login?
continue=https:%2F%2Fwww.spotify.com%2Fdk%2Faccount%2Foverview%2F")
username = browser.find_element_by_id("login-username")
password = browser.find_element_by_id("login-password")
username.send_keys("myUser")
password.send_keys("myPass")
login = browser.find_element_by_class_name('ng-pristine ng-valid-sp-
disallow-chars ng-invalid ng-invalid-required').click()
It is the last line I have a problem with. Note: This is just one of the options I tried.
You can try this code that have xpath:
login = browser.find_element_by_xpath("//button[contains(.,'Log In')]");
login.click();
You're using multiple classes in your class selector. Try using only one class. Something like this:
browser.find_element_by_class_name('btn-green').click()
If it still doesn't work, perhaps the element has not yet been rendered when you try to click it, so you may want to try with an explicit wait
Also, I checked out your selector and it looks like you weren't even pointing to the button, but to the form.
And finally, a class selector may not be the optimal way to locate your element here. I'd probably go with a XPath selector to find the button that contains the text Log In, using the following XPath
//button[text()='Log In']
Use this, i Updated the answer:
login = browser.find_element_by_xapth("//button[#class='btn btn-sm btn-block btn-green ng-binding']")
login .click()
browser.find_element_by_xpath(".//button[contains(text(), 'Log In'])").click()
This should work so give it a try. :)
As #Verv stated, you could be having timing issues. So just for the test try with time.sleep() to see if this is it.