2

I want to locate (and click) the "Reoni" element, but I do not know what function to use it for

I tried with

driver.find_element_by_class_name("oe_menu_leaf")  

and

driver.find_element_by_class_name("oe_menu_text")

but then selenium raise an error element cant be located, and I tried

driver.find_element_by_link_text("Reoni")

This is the element I want to locate:

<a href="/web#menu_id=86&amp;action=99" class="oe_menu_leaf" data-menu="86" data-action-model="ir.actions.act_window" data-action-id="99">
    <span class="oe_menu_text">
    Reoni
    </span>
</a>

and full html:

html

If I was not clear enough or if you needed my code, please let me know.

Guy
  • 46,488
  • 10
  • 44
  • 88
Dejan Dakovic
  • 145
  • 1
  • 11
  • Please post your code. – Brian Jan 07 '19 at 19:39
  • I see "collapse" in some of the other class names. Is this a menu item that doesn't appear until you hover or click over the same menu with the mouse? If so, that could explain why Selenium doesn't "see" it. – Bill M. Jan 07 '19 at 19:49
  • 1
    no, this item is all the time there @BillM. – Dejan Dakovic Jan 07 '19 at 20:02
  • This is a generic web code (html) from Odoo i have xml file with which I added "Reoni" item, but it will not be of any help because html is automatically generated @Brian – Dejan Dakovic Jan 07 '19 at 20:07
  • 2
    Try to [explicitly wait for link to be clickable](https://selenium-python.readthedocs.io/waits.html#explicit-waits) – Andersson Jan 07 '19 at 20:13

2 Answers2

1

Try something like this:

Clicking the button

From Chrome :

Right click "inspect" on the item you are trying to find the xpath.

Right click on the highlighted area on the console.

Go to Copy xpath

selectElem=browser.find_element_by_xpath('x-path-here').click()

Reading Values Only

from bs4 import BeautifulSoup

innerHTML = browser.execute_script("return document.body.innerHTML")
soup = BeautifulSoup(str(innerHTML.encode('utf-8').strip()), 'lxml')
value = soup.find('span', attrs={'class':'fxst-calendarpro fxst-table-s1'}).text
Daniel Scott
  • 979
  • 7
  • 16
  • 1
    But Dejan is using Selenium, which means he may be doing automation that requires interaction with this and other objects. BeautifulSoup is a great parsing tool, but it's not a web automation tool. – Bill M. Jan 07 '19 at 19:47
  • That's a great point @Bill M. - i'm not sure if he needs web automation, or just values. – Daniel Scott Jan 07 '19 at 19:50
  • 2
    hy,thank you, but I need to click on the item, not just the value @DanielScott – Dejan Dakovic Jan 07 '19 at 20:01
  • 2
    @Dejan Dakovic No prob :) I've updated my answer. I've had pretty good success selected by x-path over class. – Daniel Scott Jan 07 '19 at 20:08
  • Getting XPath from browser dev tools is a really bad advice that can hardly solve this issue – Andersson Jan 07 '19 at 20:11
  • 1
    @Andersson You made a great suggestion about trying explicit wait time. Why is it so bad to select using xpath? Would you have preffered I write it as dynamic? – Daniel Scott Jan 07 '19 at 20:15
  • 1
    Because such XPath expressions looks awful :) it's hard to maintain such XPath and you never know which element exactly it suppose to select. Also I see no class duplicates and `NoSuchElementException` means that no elements were found (not even one with required class name). All 3 selectors seem to be OK, so no need to use other selectors – Andersson Jan 07 '19 at 20:23
1

As the desired element is a dynamic element you need to induce WebDriverWait for the desired element to be clickable and you can use either of the following solutions:

  • Using CSS_SELECTOR:

    WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a.oe_menu_leaf[href*='/web#menu_id=']>span.oe_menu_text"))).click()
    
  • Using XPATH and text():

    WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[@class='oe_menu_leaf' and starts-with(@href,'/web#menu_id=')]/span[@class='oe_menu_text' and text()='Reoni']"))).click()
    
  • Using XPATH and normalize-space():

    WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[@class='oe_menu_leaf' and contains(@href,'/web#menu_id=')]/span[@class='oe_menu_text' and normalize-space()='Reoni']"))).click()
    
  • Note : You have to add the following imports :

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    

Reference

You can find a relevant detailed discussion in:

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • 1
    thank you very much @DabanjanB , example three works, i do not know why the first two do not work, come without a error but no action is done – Dejan Dakovic Jan 08 '19 at 15:45
  • @DejanDakovic Well, this observation was expected. The _webpage_ is dynamic. There is a delta difference between the text based _HTML_ and the snapshot of the _HTML_ you have provided. So considering both the _usecases_ either Option 1 & 2 or Option 3 must have worked. – undetected Selenium Jan 08 '19 at 15:49