Python Selenium – why the button is not being clicked

Question:

Please refer to the following webpage: https://prolineplus.olg.ca/en-ca/event/?e177405-Basketball-NBA-USA-Miami-Heat-Chicago-Bulls

I have two functions to click on either the Chicago bulls or Miami Heat as seen on the webpage from the link above. Why is my current code no longer clicking on either? I need to be able to use the team variable as the names will constantly change.

Main:

driver = startup_login('https://prolineplus.olg.ca/en-ca/event/?e177405-Basketball-NBA-USA-Miami-Heat-Chicago-Bulls')

team = "Chicago"
proline_go_to_match2(driver,team)

Functions:

def proline_go_to_match2(driver, team):
    #print(team)
    try:
        
        match = WebDriverWait(driver, 15).until(
            EC.presence_of_element_located((By.XPATH, "//ul[@class='fdjgs-markets']/li[@class='fdjgs-market']//ul[@class='fdjgs-outcomes']//descendant::li[1]//span[@class='fdjgs-outcome-wrapper' and contains(@aria-label, '"+ team +"')]/span[starts-with(., '"+ team +"')]"))        )
        match.click()
    except:
        driver.quit()


def proline_go_to_match3(driver, team):
    #print(team)
    try:
        
        match = WebDriverWait(driver, 15).until(
            EC.presence_of_element_located((By.XPATH, "//ul[@class='fdjgs-markets']/li[@class='fdjgs-market']//ul[@class='fdjgs-outcomes']//descendant::li[2]//span[@class='fdjgs-outcome-wrapper' and contains(@aria-label, '"+ team +"')]/span[starts-with(., '"+ team +"')]"))        )
        match.click()
    except:
        driver.quit()
Asked By: jwalman

||

Answers:

for your xpath, it can find two elements, you can try the following code, it can work well, opening browser will implicit to wait for page ready.

from clicknium import clicknium as cc

if not cc.chrome.extension.is_installed():
    cc.chrome.extension.install_or_update()

def get_elements(tab,team):
    xpath = "//ul[@class='fdjgs-markets']/li[@class='fdjgs-market']//ul[@class='fdjgs-outcomes']//descendant::li//span[@class='fdjgs-outcome-wrapper' and contains(@aria-label, '"+ team +"')]/span[starts-with(., '"+ team +"')]"
    return tab.find_elements_by_xpath(xpath)

tab = cc.chrome.open("https://prolineplus.olg.ca/en-ca/event/?e177405-Basketball-NBA-USA-Miami-Heat-Chicago-Bulls")
elements = get_elements(tab, "Chicago")
for elem in elements:
    elem.click()

elements = get_elements(tab, "Miami")
for elem in elements:
    elem.click()
Answered By: justin

You have to add some wait time in the function and you don’t need to use 2 functions to do click operations on 2 different team names, you can use just one, like below:

def proline_go_to_match(driver, team):
    try:
        time.sleep(4)
        match = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.XPATH,"(.//span[@class='fdjgs-outcome-wrapper' and @title=contains(.,'" + team + "')])[1]")))
        match.click()
    except:
        driver.quit()

Always, try to use simplified Xpath.

You can pass any value to the argument – ‘team’ like "Chicago" or "Miami".

Answered By: AbiSaran

Check for consent and click on that if exists.
use python format() function to change the parameter.
Use js executor to click else will get element intercepted error you can use actionchain as well.

driver.get("https://prolineplus.olg.ca/en-ca/event/?e177405-Basketball-NBA-USA-Miami-Heat-Chicago-Bulls")
wait=WebDriverWait(driver,20)

#check for consent
try:
    wait.until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Continue']"))).click()
except:
    pass
team="Chicago"
items=wait.until(EC.visibility_of_all_elements_located((By.XPATH, "//span[contains(@aria-label, '{0}')]//span[starts-with(., '{0}')]".format(team))))

for item in items:
    driver.execute_script("arguments[0].click();", item)
    print("Button clicked")
Answered By: KunduK

Three things that could help: (1) Using equivalent JavaScript rather than the Selenium click method; (2) using an explicit wait in finding the element you want to be clicked; and (3) injecting driver options that make you appear more like a legitimate user, less like a bot.

(1) Executing JS to click

Don’t use the Selenium click method:

some_element_name.click() 

Do this instead:

driver.execute_script("arguments[0].click();", some_element_name) 

(2) Add waits

We want to give the page time to render first. We could use, say, time.sleep(n) but it’s significantly better to do an explicit wait, that waits until <condition>. So, don’t do this:

click_target = driver.find_element(By.<method>, '<tag>')

Do this instead:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 15)
click_target = wait.until(EC.presence_of_element_located((By.<method>, '<tag>')))

(3) Optimizing driver options for covertness

Keep it discreet that we’re a bot.

from selenium.webdriver.chrome.options import Options # chrome example

options = Options()
options.add_argument("--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36") # legit looking user agent
options.add_argument('--disable-dev-shm-usage') 
options.add_argument('--disable-blink-features=AutomationControlled') 
options.add_argument("disable-infobars") 
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False) 

driver = webdriver.Chrome(options=options) # then init with options
Answered By: Hemanth B