0

I'm trying to select EU Odds from the dropdown in this HTML:

<div id="user-header-r1">
            <div>
                <a class="user-header-fakeselect" onclick="ElementSelect.expand( 'user-header-oddsformat' , 'user-header-oddsformat-expander' )" id="user-header-oddsformat-expander"><span>UK Odds</span></a>
                <ul class="user-header-fakeselect-options hidden" id="user-header-oddsformat">
                    <li><a href="#" onclick="changeOddsFormat(1); return false;"><span>EU Odds</span></a></li>
                    <li><a href="#" onclick="changeOddsFormat(2); return false;"><span>UK Odds</span></a></li>
                    <li><a href="#" onclick="changeOddsFormat(3); return false;"><span>US Odds</span></a></li>
                    <li><a href="#" onclick="changeOddsFormat(4); return false;"><span>HK Odds</span></a></li>
                    <li><a href="#" onclick="changeOddsFormat(5); return false;"><span>MA Odds</span></a></li>
                    <li><a href="#" onclick="changeOddsFormat(6); return false;"><span>IN Odds</span></a></li>

                </ul>
            </div>
            <div><label>Time:</label></div>
            <div>
                <a href="#" class="user-header-fakeselect" onclick="op.showHideTimeZone();ElementSelect.expand( 'user-header-timezone' , 'user-header-timezone-expander' , null , function(){op.hideTimeZone()} );this.blur();return false;" id="user-header-timezone-expander"><span>23 Aug 08:33, GMT +1</span></a>
            </div>


        </div>

I've tried following the answer here with the following code:

target = 'EU Odds'
self.driver.find_element_by_css_selector("user-header-r1 > ul").find_element_by_xpath("./li[.="+target+"]").click()

But I get the following error:

Exception has occurred: NoSuchElementException
Message: no such element: Unable to locate element: {"method":"css selector","selector":"user-header-r1 > ul"}

Where am I going wrong?

DebanjanB
  • 118,661
  • 30
  • 168
  • 217
Jossy
  • 201
  • 4
  • 13
  • `user-header-r1` is an id, not a CSS class, you are trying to find element by CSS selector, which doesn't exist. Try finding by `id` – Romit Aug 23 '20 at 08:20
  • Thanks. Tried this: ```self.driver.find_element_by_id("user-header-r1 > ul").find_element_by_xpath("./li[.="+target+"]").click()``` but got ```Unable to locate element: {"method":"css selector","selector":"[id="user-header-r1 > ul"]"}```. As you can tell I'm really new to scraping so I might need baby steps! – Jossy Aug 23 '20 at 08:26

4 Answers4

1

Expand dropdown and make li elements visible. WebDriverWait will wait for required element conditions, in your the case it's a visibility. To get element by text using xpath you need to use quotas //li[.='Some Text'] in text:

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

driver = webdriver.Chrome()
wait = WebDriverWait(driver, 5)
driver.get("..")

target = "EU Odds"
driver.find_element(By.ID, "user-header-oddsformat-expander").click()
wait.until(ec.element_to_be_clickable((By.XPATH, "//li[.='" + target + "']"))).click()
Sers
  • 10,960
  • 2
  • 8
  • 25
  • I get the following error on the last line: ```Exception has occurred: TypeError 'str' object is not callable``` – Jossy Aug 23 '20 at 10:38
  • Typo with method arguments. Fixed – Sers Aug 23 '20 at 11:06
  • Thanks! Ended up using this as I was having issues with the accepted answer. The clickable element was not loading before that snippet tried to click it. – Jossy Sep 11 '20 at 12:41
  • Spoke to soon! Seems to be intermittent - sometimes it selects ```EU Odds``` and sometimes it doesn't :( ```driver.find_element(By.ID, "user-header-oddsformat-expander").click()``` definitely selects the dropdown. If I step through ```wait.until(ec.element_to_be_clickable((By.XPATH, "//li[.='" + target + "']"))).click()``` then it always selects ```EU Odds```. Strange as my understanding of that line is that Selenium is supposed to wait until it can select ```EU Odds```? – Jossy Sep 11 '20 at 13:13
  • MAnaged to get round this by putting a ```while``` loop in that checks the right element has been selected or it reruns the selection code. Always manages to get it right after 2-3 attempts but definitely no consistency! – Jossy Sep 11 '20 at 13:47
1

Your element target having attribute with hidden value:

...<ul class="user-header-fakeselect-options hidden"...

So I think you need trigger from another element first before attack the element target, try following code:

#click this first
self.driver.find_element_by_css_selector('div#user-header-r1 > div > a#user-header-oddsformat-expander > span').click()

target = 'EU Odds'
self.driver.find_element_by_xpath('//ul[@id="user-header-oddsformat"]//span[text()="' +target +'"]').click()
frianH
  • 5,901
  • 6
  • 13
  • 36
0

To select the element with text as EU Odds you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:

  • Using CSS_SELECTOR:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "ul#user-header-oddsformat li:first-child>a[onclick^='changeOddsFormat']>span"))).click()
    
  • Using XPATH:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//ul[@id='user-header-oddsformat']//li/a[starts-with(@onclick, 'changeOddsFormat')]/span[text()='EU Odds']"))).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
    
DebanjanB
  • 118,661
  • 30
  • 168
  • 217
0

Form the HTML element, the element you are trying to select has an ID named user-header-r1 not a CSS class, try using find_element_by_id('user-header-r1') Then if the element is found, then try using find_element_by_tag_name('ul') on the same search, like so:

head_elem = self.driver.find_element_by_id("user-header-r1")
head_elem.find_element_by_tag_name("ul")

This will first scan the HTML tree for an ID of user-header-r1 which is the first div then finds the ul element inside the div

Romit
  • 120
  • 1
  • 10