Reputation: 41
First of all, sorry for my English. I'm from Buenos Aires, and I've started learning Python just a few weeks ago. Furthermore, I have a really basic knowledge in programming. All I was able to do so far was by getting the info from internet (no formal education in this matter-I was studying Accounting last year).
As of this post, I want to find an element in a web page but I can't seem to get it right. I've even tried to click on "space" key-the simplest thing to do in this case.
I want to click on "OK" button.
I have from "Inspect element":
<div class="alert" id="popup_content">
<div id="popup_message">No Pending Documents</div>
<div id="popup_panel">
<input id="popup_ok" type="button" value="OK">
</div>
</div>
print: I've tried these 5 codes:
from selenium.webdriver.common.action_chains import ActionChains
element_ok = driver.find_element_by_xpath("//input[@id='popup_ok']")
Action.Chains(driver).move_to_element(element_ok).perform()
element.click()
driver.find_element_by_xpath(".//*[@id='popup_ok']/div/input").click()
driver.find_element_by_css_selector(".button_main[value='OK']").click()
clear_button = driver.find_element_by_xpath("//input[@id='popup_panel'][@type='button']")
clear_button = driver.find_element_by_xpath("//form[@id='popup_ok']/input[1]")
import keyboard
keyboard.press_and_release('shift+s, space')
Would someone help me get through this?
PS: I'm using selenium (read from it in the book 'Automate the Boring Stuff with Python. Practical Programming for Total Beginners'. And chrome webdriver.
Upvotes: 0
Views: 1995
Reputation: 5139
Let's take a look at each approach.
from selenium.webdriver.common.action_chains import ActionChains
element_ok = driver.find_element_by_xpath("//input[@id='popup_ok']")
Action.Chains(driver).move_to_element(element_ok).perform()
element.click()
This has two problems.
First, you import ActionChains
, but then try to use it as Action.Chains
. Because you didn't import anything called Action
, you'll likely see this error:
NameError: name 'Action' is not defined
Removing the extra inner .
should fix it:
ActionChains(driver).move_to_element(element_ok).perform()
Second, you find the element and save it to a variable named element_ok
. Then, however, you try to call click()
on a variable named element
. Because you haven't defined a variable with that name, you'll likely see this error:
NameError: name 'element' is not defined
Calling element_ok.click()
should fix it:
element_ok.click()
Note: You probably don't need to use ActionChains
at all. You should only need to tell Selenium to move to the element if the element is outside of the viewport, e.g., "below the fold":
element_ok = driver.find_element_by_xpath("//input[@id='popup_ok']")
element_ok.click()
driver.find_element_by_xpath(".//*[@id='popup_ok']/div/input").click()
This XPath query tells Selenium to:
id
of "popup_ok"
(A),<div>
(B),<input>
(C), thenThis does not make sense for your HTML. The element with id
"popup_ok"
is an <input>
, which has neither a child <div>
nor a grandchild <input>
.
Since the element with id
"popup_ok"
(A) is the <input>
you want, you can simply remove the remainder of the XPath query:
driver.find_element_by_xpath(".//*[@id='popup_ok']").click()
driver.find_element_by_css_selector(".button_main[value='OK']").click()
This CSS selector tells Selenium to find and return the element that:
button_main
andvalue
of "OK"
(A).Your button meets requirement 2, but not 1. It has no class button_main
. (There is no element with class button_main
.)
Instead, you can use *
to match any element regardless of class name:
driver.find_element_by_css_selector("*[value='OK']").click()
However, this is not a great CSS selector. Because *
matches any element, it has the potential to be slow.
Instead, you can match by the tag:
driver.find_element_by_css_selector("input[value='OK']").click()
clear_button = driver.find_element_by_xpath("//input[@id='popup_panel'][@type='button']")
clear_button = driver.find_element_by_xpath("//form[@id='popup_ok']/input[1]")
The first XPath query tells Selenium to:
<input>
element that
a. has id
"popup_panel"
and
b. has type
"button"
.Your button meets requirements 1 and 1b, but not 1a. The id
"popup_panel"
is used by the grandparent <div>
.
To fix it, you could just remove that requirement:
clear_button = driver.find_element_by_xpath("//input[@type='button']")
The second XPath query tells Selenium to:
<form>
element (A) that
a. has id
"popup_ok"
, then<input>
(B).Your button meets requirement 2, but not 1. Its parent is neither a <form>
tag nor has an id
of "popup_ok"
.
Instead, the <input>
has that id
:
clear_button = driver.find_element_by_xpath("//input[@id='popup_ok'][1]")
Note: [1]
selects the first matching element. Since id
attributes should be unique, this is redundant and can be removed:
clear_button = driver.find_element_by_xpath("//input[@id='popup_ok']")
import keyboard
keyboard.press_and_release('shift+s, space')
This might not work for a lot of reasons, which are probably not worth getting into. Selenium has the ability to simulate keyboard events, so you probably don't need to use another Python package.
If you have the element that should receive the keyboard events, you can call send_keys()
on it:
from selenium.webdriver.common.keys import Keys
element.send_keys(Keys.SPACE)
If you don't have the element, you can use ActionChains
to send keyboard events to the currently active element:
ActionChains(driver).send_keys(Keys.SPACE).perform()
Upvotes: 1
Reputation: 4739
There are multiple ways to locate element
1. Use by id
ok_btn = driver.find_element_by_id("popup_ok")
2. Use by xpath
ok_btn = driver.find_element_by_xpath("//input[@value='OK']")
OR
ok_btn = driver.find_element_by_xpath("//input[@id='popup_ok']")
Upvotes: 0
Reputation: 193058
As per the HTML you have shared to click on the button with text as OK you have to induce WebDriverWait for the element to be clickable and you can use the following line of code :
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='alert' and @id='popup_content']//div[@class='popup_panel']/input[@id='popup_ok' and @value='OK']"))).click()
Upvotes: 0
Reputation: 116
if you know id of element try with:
driver.find_element_by_id('popup_ok').click()
Upvotes: 0