Python3 Selenium Button Clicking Issue - python

I want to click a button as the following picture shows with Selenium
I write my code like that:
try:
browser.find_element_by_xpath("//a[#href='/portal/site/16/801']").click()
except Exception as e:
print(e)
But it always shows error, it cannot locate the element.
Here is the html code of what I want to click.
<a href="/portal/site/16/801" data-blackname="16" title="课程网站">
<img src="/access/img//site/16.png" class="media-icon" onerror="this.src='/resources/images/app-default-icon2.png'">
<h5><i class="icon-ok"></i>课程网站</h5>
​
Could somebody help me fix the problem? Thanks in advance!

Adding a random sleep after using Selenium to send username, password and ENTER. It works
time.sleep(random.randint(3,6))

As supputuri mentioned, Use explicit waits instead of random sleep. If the lower limit is not enough for the button to be clickable then it will surely make the error random.
The explicit wait is used to tell the Web Driver to wait for certain conditions (Expected Conditions). In this case, the button to be clickable. explicit waits by default check every half a second if the condition is fulfilled or not.
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//a[#href='/portal/site/16/801']"))).click()
To use this you have to import the followings:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

Related

Cannot use WebDriverWait library properly in Python Selenium

Hello everyone I'm learning selenium recently and as I bet is a classic newbie mistake I filled my code with time.sleep which made everything really slow. So I started to learn about webdriverWait. I took some sample code and I have tried multiple things but I still get the error of "what you clicked is blocked by this other thing" meaning that the library did not crash but it also did not do anything. Which must mean I am doing something wrong. This is an error I can avoid if use the time.sleep function.
I'm using expected conditions, BY and action chains alongside WebDriverWait, though in my last test I tried to not use Acton chains to lower the possibilities of why its failing.
I'm using a company site that is probably under NDA so I don't have a public example to show this on, I tried searching for "pages with cover openings" but I couldn't find any, so if you guys know of any that I can use to illustrate this I would also find that really helpful. What is happening is that the site loads with a "cover" animation and after a few seconds the animation goes away to reveal the Button I'm looking for.
Environment info:
Using Pycharm community latest version
Using Selenium 4.0.0b2.post1 (I also tried in 3.9 to no results)
Using ChromeDriver 89 as my google chrome version is 89 as well [Version 89.0.4389.114 for Chrome]
Here are my code snippets:
Attempt #1:
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
import selenium.webdriver.support.ui as ui
def test(driver, actions, delay):
cart = "//header/div[1]/div[1]/a[2]/*[1]"
cartxp = WebDriverWait(driver, delay).until(EC.visibility_of_element_located((By.XPATH, cart)))
actions.move_to_element(cartxp).perform()
cartclk = driver.find_element_by_xpath(cart).click()
Attempt #2: Using UI library
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
import selenium.webdriver.support.ui as ui
def test2(driver, delay, actions):
cart = "//header/div[1]/div[1]/a[2]/*[1]"
cartxp = ui.WebDriverWait(driver, delay).until(EC.visibility_of_element_located((By.XPATH, cart)))
actions.move_to_element(cartxp).perform()
cartclk = driver.find_element_by_xpath(cart).click()
Attempt #3: Not using Action chains
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
from selenium.webdriver.common.by import By
def test3(driver, delay):
wait = WebDriverWait(driver, delay)
cart = "//header/div[1]/div[1]/a[2]/*[1]"
button = wait.until(EC.element_to_be_clickable((By.XPATH, cart)))
cartclk = driver.find_element_by_xpath(cart).click()
All of these have a main method that just has:
driver = webdriver.Chrome()
test3(driver, 30)
driver.get('Site that I cant reveal cuz of NDA')
action = ActionChains(driver)
The error I get is:
Message: element click intercepted: Element ... is not clickable at point (1183, 27). Other element would receive the click
Thanks in advance for any help!
Edit: After some comments changed my xpath to //a[#class='header__cart'] both the previous and this one leads to a single result If I use it on chrome inspect to look for the button, additionally it works as intended if I use it to actually click the button after using time.sleep() to wait out the animation
Additionally just in case tried using the try catch as they did on the suggested question. It also failed
Attempt 4: surrounding in a try-catch
def test4(driver, delay):
cart = "//a[#class='header__cart']"
try:
my_elem = WebDriverWait(driver, delay).until(EC.visibility_of_element_located((By.XPATH, cart)))
print
"Page is ready!"
except TimeoutException:
print
"Loading took too much time!"
cart_btn = driver.find_element_by_xpath(cart)
cart_btn.click()
Error: selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <a href="/cart" class="header__cart" data-items-in-cart="0" )="">... is not clickable at point (1200, 27). Other element would receive the click
To clarify what I meant earlier this works:
cart = "//a[#class='header__cart']"
time.sleep(20)
cartclk = driver.find_element_by_xpath(cart).click()

How to select an option from dropdown

I have a problem navigating a website using selenium. This is my code:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get('https://webtrader.binary.com/v2.2.8/main.html#')
resources = driver.find_element_by_id('ui-id-1')
resources.click()
However, I get the exception:
selenium.common.exceptions.ElementNotInteractableException: Message: Element <ul id="ui-id-1" class="ui-menu ui-widget ui-widget-content ui-menu-icons"> could not be scrolled into view
I don't understand where I went wrong. I am trying to access 'Historical data' from the dropdown menu labeled "Resources". Could someone please help me access it. Maybe I got the id for Resources wrong. You could also check that out.
The element you want to click to open the dropdown is the previous sibling of the element resources
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.select import By
from selenium.webdriver.support.ui import WebDriverWait
wait = WebDriverWait(driver, 10)
driver.find_element_by_class_name('resources').click()
historical_data = wait.until(ec.visibility_of_element_located((By.ID, 'ui-id-4')))
There are many things happening here. First of all, your code is lacking a wait. Without it will always fail, as the page is dynamically loaded. Read about Waits.
Secondly, here resources = driver.find_element_by_id('ui-id-1') you are finding the element from the dropdown menu, and then you are trying to click it. But the dropdown menu is not opened. You should click on it, then wait for the option to appear, only then click on the 'Historical data'.

Selenium not able to locate element that actually exists

I am automating a boring data entry task, so I created a program that basically clicks and types for me using selenium. It runs great! except for when it reaches this specific "Edit Details..." element that I need clicked, however, selenium is unable to locate the element regardless of whatever method I try.
I've tried using a CSS selector that tried to access the ID to no avail. I also tried using XPATH, as well as trying to be more specific by giving it a 'contains' statement with the button text. As last resort, I used the selenium IDE to see what locator it registers when I physically click the button and it used the exact same ID that I state in my code. I am completely lost on how to go about fixing this.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import *
import pyautogui as py
import time, sys, os, traceback
#Launching Browser
browser = webdriver.Ie()
wait = WebDriverWait(browser, 15) #Waiting
#Laziness Functions
def clickCheck(Method, Locator, elemName):
wait.until(EC.element_to_be_clickable((Method, Locator)))
print(elemName + ' Clickable')
#Commence main function
try:
#Do alot of Clicks and Stuff until it reaches "Edit Details..." element
"""THIS IS WHERE THE PROBLEM LIES"""
time.sleep(3)
clickCheck(By.CSS_SELECTOR, 'td[id="DSCEditObjectSummary"]', "Edit Details")
elemEdit = browser.find_element_by_css_selector('td[id="DSCEditObjectSummary"]')
elemEdit.click()
#FAILSAFES
except:
print('Unknown error has Occured')
exc_info = sys.exc_info()
traceback.print_exception(*exc_info)
del exc_info
finally: #Executes at the end and closes all processes
print('Ending Program')
browser.quit()
os.system("taskkill /f /im IEDriverServer.exe")
sys.exit()
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: Unable to find element with css selector == [id="DSCEditObjectSummary"]
This is what I get as an error, all I want is for the element to be clicked just like all other elements are being located by CSS_Selectors. The image below indicates in blue the exact line for the "Edit Details..." button.
Edit Details Button
It looks like the issue may be with the page loading slowly, or as another commenter mentioned it's in an iFrame, etc. I typically try clicking by using X/Y coordinates with a macro tool like AppRobotic if you're running this on Windows. If it's an issue with the page loading slowly, I usually try stopping the page load, and interacting with the page a bit, something like this should work for you:
import win32com.client
from win32com.client import Dispatch
x = win32com.client.Dispatch("AppRobotic.API")
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import *
import pyautogui as py
import time, sys, os, traceback
#Launching Browser
browser = webdriver.Ie()
wait = WebDriverWait(browser, 15) #Waiting
#Laziness Functions
def clickCheck(Method, Locator, elemName):
wait.until(EC.element_to_be_clickable((Method, Locator)))
print(elemName + ' Clickable')
driver.get('https://www.google.com')
# wait 20 seconds
x.Wait(20000)
# scroll down a couple of times in case page javascript is waiting for user interaction
x.Type("{DOWN}")
x.Wait(2000)
x.Type("{DOWN}")
x.Wait(2000)
# forcefully stop pageload at this point
driver.execute_script("window.stop();")
# if clicking with Selenium still does not work here, use screen coordinates
x.MoveCursor(xCoord, yCoord)
x.MouseLeftClick
x.Wait(2000)
I am posting this answer more so for other folks who might be running into the same problem and stumble upon this post. As #PeterBejan mentioned, the element I was trying to click was nested in an iframe. I tried accessing the iframe except I was thrown a NoSuchFrameException. Further digging revealed that this frame was nested inside 3 other frames and I had to switch to each frame from top level down, to access the element. This was the code I used
wait.until(EC.frame_to_be_available_and_switch_to_it("TopLevelFrameName"))
wait.until(EC.frame_to_be_available_and_switch_to_it("SecondaryFrameName"))
wait.until(EC.frame_to_be_available_and_switch_to_it("TertiaryFrameName"))
wait.until(EC.frame_to_be_available_and_switch_to_it("FinalFrameName"))
clickCheck(By.ID, 'ElementID', "Edit Details")
elemEdit = browser.find_element_by_id("ElementID")
elemEdit.click()

Frame Switch to click on a Box (Python Selenium)

I have a problem trying to automate my browser with Selenium on Python. It's been several hours that I block, and since I'm a beginner .. :(
I explain my problem:
I have to reach click on a box of Recaptcha. To do this, my bot must click on a button on the site, which then displays the recaptcha that I have to validate.
Here are the source page screenshot:
The popup of the recaptcha, in which the checkbox is located
The location of the checkbox that I have to click
I try this code:
time.sleep(5)
browser.switch_to_frame(browser.find_element_by_tag_name("CaptchaPopup"))
browser.switch_to_frame(browser.find_element_by_tag_name("iframe"))
CheckBox = WebDriverWait(browser, 10).until(
browser.find_element_by_id('recaptcha-anchor').click())
time.sleep(0.7)
CheckBox.click()
But the latter returns me an error :(
selenium.common.exceptions.NoSuchFrameException: Message: no such frame
I use Python 2.7.
Do you have a solution ?
Thank you very much in advance!
Try to use below code to handle required check-box:
from selenium.webdriver.support.ui import WebDriverWait as wait
from selenium.webdriver.support import expected_conditions as EC
wait(browser, 10).until(EC.frame_to_be_available_and_switch_to_it(browser.find_element_by_xpath('//iframe[contains(#src, "google.com/recaptcha")]')))
wait(browser, 10).until(EC.element_to_be_clickable((By.ID, 'recaptcha-anchor'))).click()

Python selenium: wait until element is clickable - not working

I will test a web-app. there is a button available in my table to select all entries.
I've tried:
driver.wait.until(ExpectedCondition.element_to_be_clickable((By.XPATH, "myXpath"))).click()
selenium clicks on the button, but nothing happens. (also with send_Keys(Keys.Return)) the application is developed with GXT, I thing that there is much javascript behind the button. Is there is possibility to wait until a eventloader is ready? waiting before a click solves the problem, but not a solution for automated testing.
Correct syntax for explicit wait in python is :
element = WebDriverWait(driver, 20).until(
EC.presence_of_element_located((By.ID, "myElement")))
Better that After above you do :
element.click();
So in your case :
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.XPATH, "myXpath")))
element.click();
Better you follow it. Also share your whole code so I can correct it. Your just 1 line code doing little confuse.
I had also that problem... Web apps have views over views and Appium sometimes gets wrong.
This worked for me:
x = webElement.location['x'] + (webElement.size['width']/2)
y = webElement.location['y'] + (webElement.size['height']/2)
print("x: "+x+" - y: "+y)
//I have setted a 200 milli duration for the click...
//I use tap just for Android... If is iOS for me it works better touchAction
driver.tap([(x,y)], 200)
Edit:
I misunderstood your question... Sorry...
Maybe modifying your Xpath to:
(don't know if this will work at a web app)
xpath = "//whatever_goes_here[#clickable='true']"
I know it is probably too late, but for me the solution was to add this line before all the elements clicks:
driver.execute_script('document.getElementsByTagName("html")[0].style.scrollBehavior = "auto"')
Nowadays, sites tend to have a scrholl-behavior set to auto. Drivers do not know that, though they do know when an element is outside the view. So, what happens is a driver tries to click the element. The driver sees that the element is outside the view, so it calls a scroll method and after that immediately clicks the element without waiting for scrolling to finish. And the scrolling does take some time because of its behavior set to auto.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait=WebDriverWait(driver,5)
a= wait.until(EC.element_to_be_clickable(('id or xpath or class or any thing else ','enabled_trigger')))
a.click()
please note you must have two parentheses in element.to_be_clickable(())

Categories