Home > Software engineering >  How to loop a python action until a button is clickable (selenium)
How to loop a python action until a button is clickable (selenium)

Time:08-31

I am very much not experienced in coding and all my work here is done by research.

I am creating a python script which helps me add a ticket to basket via selenium however coming across some things im not sure how to do.

The ticketing website requires to sit and refresh the page until a ticket becomes available from another user and then a button becomes clickable which then allows you to reserve it.

I have created the 1st part of the script which opens up and link and click the button when its available however when its not available i need to page to refresh and attempt to click the button if available and repeat until hopefully succesful which by that point the script can stop.

When a ticket is added to basket the URL changes so that could be a condition for the script to check before stopping.

Below is the python code which contains the URL link where the button is not clickable.

To test the script working change the URL to this: https://ticketing.liverpoolfc.com/en-GB/events/liverpool women v everton women/2022-9-25_18.45/anfield?hallmap

The button that needs to be clicked is CHOOSE SEAT FOR ME

from selenium.webdriver.common.keys import Keys
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
import time

PATH = "D:\chromedriver.exe"

driver = webdriver.Chrome(PATH)

driver.get("https://ticketing.liverpoolfc.com/en-GB/events/liverpool v newcastle united/2022-8-31_20.00/anfield?hallmap")


try:
    element = WebDriverWait(driver, 25).until(
        EC.element_to_be_clickable((By.XPATH,"/html/body/div[7]/div/button"))
    )
finally:
    print("Page loaded")

button = driver.find_element(By.XPATH, "/html/body/div[7]/div/div[4]/div[1]/div[3]/div[2]/div[2]/div/div[3]/div[1]/button[2]")
button.click()```




CodePudding user response:

As I see from your code, you do not actually clicking the /html/body/div[7]/div/button button. All what you trying to actually do here is to click the /html/body/div[7]/div/div[4]/div[1]/div[3]/div[2]/div[2]/div/div[3]/div[1]/button[2] button.
This element is disabled if This event is sold out. Please try again later notification is presented.
If so, you can make your code more clear and simple.
You can wait for a short time to find the /html/body/div[7]/div/div[4]/div[1]/div[3]/div[2]/div[2]/div/div[3]/div[1]/button[2] button enabled. In case this element is found disabled - refresh the page.
In case the button is found enabled - click it.
You can also improve your locators. As following:

from selenium.webdriver.common.keys import Keys
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
import time

PATH = "D:\chromedriver.exe"

driver = webdriver.Chrome(PATH)

driver.get("https://ticketing.liverpoolfc.com/en-GB/events/liverpool v newcastle united/2022-8-31_20.00/anfield?hallmap")

while true:
    try:
        #try to find the button enabled
        #in case you found it enabled - click it
        WebDriverWait(driver, 5).until(
        EC.element_to_be_clickable((By.XPATH,"//button[@class='areas-filter-panel__find-button' and(not(@disabled))]")).click()
        #break the loop in case of successful click
        break
    except:
        #if button found disabled exception is thrown, catch catches it and performs a refresh
        driver.refresh()

CodePudding user response:

To refresh the website for the element Choose seats for me to be clickable you need to induce WebDriverWait for the element_to_be_clickable() and wrapping up the click event within a while-try-except{} block and you can use the following locator strategy:

driver.get('https://ticketing.liverpoolfc.com/en-GB/events/liverpool women v everton women/2022-9-25_18.45/anfield?hallmap')
while True:
    try:
        WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.areas-filter-panel__find-button"))).click()
        break
    except TimeoutException:
        WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[@class='ui-button showPopupMessage-redbutton ui-corner-all ui-widget' and text()='OK']"))).click()
        driver.refresh()
        continue
# other lines of code
driver.quit()

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
from selenium.common.exceptions import TimeoutException

CodePudding user response:

 from selenium import webdriver
 from selenium.webdriver.common import action_chains
 from selenium.webdriver.common.keys import Keys
 from selenium.webdriver.common.by import By
 from selenium.webdriver.support.ui import WebDriverWait
 from selenium.webdriver.support import expected_conditions as EC
 import time
 from selenium.webdriver.common.action_chains import ActionChains
  
 driver = webdriver.Chrome()

While True:
 try:

 time.sleep(5)

 ActionChains(driver).move_to_element(
 driver.find_element(By.XPATH,'button').perform()

 if driver.find_element(By.XPATH,'button').is_enabled():
    driver.find_element(By.XPATH,'button').click()
    print('clicked')
    break
 else:
   driver.refresh()
 except Exception as e:
 print(f'button not found: {e}')
 continue  
  • Related