Reputation: 265
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()
Upvotes: 0
Views: 826
Reputation: 21
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.
Don't use the Selenium
click method:
some_element_name.click()
Do this instead:
driver.execute_script("arguments[0].click();", some_element_name)
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>')))
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
Upvotes: 0
Reputation: 33384
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")
Upvotes: 1
Reputation: 2678
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".
Upvotes: 0
Reputation: 197
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()
Upvotes: 0