Noelia
Noelia

Reputation: 41

Unable to find_element in web through Python (selenium)

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

Answers (4)

Ian Lesperance
Ian Lesperance

Reputation: 5139

Let's take a look at each approach.


1.

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()

2.

driver.find_element_by_xpath(".//*[@id='popup_ok']/div/input").click()

This XPath query tells Selenium to:

  1. find an element with an id of "popup_ok" (A),
  2. find a child of A that is a <div> (B),
  3. find a child of B that is an <input> (C), then
  4. return C.

This 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()

3.

driver.find_element_by_css_selector(".button_main[value='OK']").click()

This CSS selector tells Selenium to find and return the element that:

  1. has the class button_main and
  2. has a value 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()

4.

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:

  1. find an <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:

  1. find a <form> element (A) that a. has id "popup_ok", then
  2. find the first child of A that is an <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']")

5.

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

iamsankalp89
iamsankalp89

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

undetected Selenium
undetected Selenium

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

Arkadiusz Tymieniecki
Arkadiusz Tymieniecki

Reputation: 116

if you know id of element try with:

driver.find_element_by_id('popup_ok').click()

Upvotes: 0

Related Questions