pythonselenium-webdriver

Check if timeslot is available (type free)


free

Hereby the HTML code, I would like to select a timeslot (at 21:00) which is free, in the code below. Only Padel Buiten 2 and Padel Buiten 3 are available. I prefer to book PAdel Buiten 3 at 21:00 hr. My question is how can I use python to determine if a timeslot is empty, or not. The right order should be, Padel Buiten 3, Padel Buiten 2, Padel Buiten 4, Padel Buiten 6, Padel Buiten 7. Is PAdel Buiten 3 free? Then he has to make aa booking, otherwise, PAdel Buiten 2 is it's free.

<tr utc="1732564800" data-time="21:00">
    <th class="matrix-timeslot empty"></th>
    <td class="slot normal r-2992 s-1280 taken" type="taken" finishes="1732568400" id="matrix-res-11317517" tooltip="Padel Buiten 1:::" rowspan="4"><div class="slot-period"> 21:00</div><div class="players"> <b>Gereserveerd</b></div></td>
    <td class="slot normal r-4435 s-1280 free peak" type="free" slot="4435" title="Padel Buiten 2" rowspan="4"><div class="slot-period"> 21:00</div></td>
    <td class="slot normal r-4436 s-1280 free peak" type="free" slot="4436" title="Padel Buiten 3" rowspan="4"><div class="slot-period"> 21:00</div></td>
    <td class="slot normal r-4437 s-1280 taken" type="taken" finishes="1732568400" id="matrix-res-11310116" tooltip="Padel Buiten 4:::" rowspan="4"><div class="slot-period"> 21:00</div><div class="players"> <b>Gereserveerd</b></div></td>
    <td class="slot normal r-4616 s-1280 blocked b-133207 by-blockcourt" type="blocked" slot="133207" tooltip="Padel lessen (11-11-2024 - 10-02-2025)<br>(17:00 - 22:00)"><div class="reason"> Padel lessen</div></td>
    <td class="slot normal r-4617 s-1280 taken" type="taken" finishes="1732568400" id="matrix-res-11310115" tooltip="Padel Buiten 6:::" rowspan="4"><div class="slot-period"> 21:00</div><div class="players"> <b>Gereserveerd</b></div></td>
    <td class="slot normal r-4618 s-1280 taken" type="taken" finishes="1732568400" id="matrix-res-11311773" tooltip="Padel Buiten 7:::" rowspan="4"><div class="slot-period"> 21:00</div><div class="players"> <b>Gereserveerd</b></div></td>
    <td class="slot normal r-4619 s-1280 blocked b-126740 by-blockcourt" type="blocked" slot="126740" tooltip="Reserveren via Playtomic (21-06-2024 - 31-12-2024)<br>(07:00 - 23:55)"><div class="reason"> Reserveren via Playtomic</div></td>
</tr>

New information: Free spaces

As you can see (for test I'm using 18:00), but the courts 4 and 6 are available. But still I'm receiving the no courts available print.

Could you have a look at this code? I'm a python dummy :-) and verey thankfull for your help!!

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import sys

# Bepaal Webdriver
driver = webdriver.Chrome()  

# Open de website
driver.get("https://bent.baanreserveren.nl")  

# Tijd om scherm goed te stellen
time.sleep(1)

# START BOEKING 21:00 UUR
# Vul Gebruikersnaam in
driver.find_element(By.NAME, "username").send_keys("kbolk")

# Vul Wachtwoord in
driver.find_element(By.NAME, "password").send_keys("pw")

# Klik op Inloggen
driver.find_element(By.CSS_SELECTOR, ".form-submit3 > .button3").click()

# Juiste dag (3x klikken)
for _ in range(3):
    element = driver.find_element(By.CSS_SELECTOR, ".matrix-date-nav:nth-child(3)")
    element.click()
    time.sleep(1) 

# Selecteer Padel Buiten uit Dropdown lijst
dropdown_element = driver.find_element(By.ID, "matrix-sport")
dropdown_element.click()
element = dropdown_element.find_element(By.XPATH, "//option[. = 'Padel Buiten']")
element.click()
dropdown_element = driver.find_element(By.ID, "matrix-sport")
dropdown_element.click()
time.sleep(1)

court_preferences = ['3', '2', '4', '6', '7']
booked = False
for court in court_preferences:
    available = driver.find_elements(By.XPATH, "//td[@type='free'][@title='Padel Buiten "+ court +"'][./div[text()='18:00']]")
if available:
    baan_boeking = court_preferences #here I would like to have the court number which is free
    print (baan_boeking)
    booked = True
    
if not booked:
    print("No available courts found") 
    sys.exit() #no courts availabe? No action needed, end of script

#Here I would like to add the next steps if booked if true.
print ("Execute next steps")

Solution

  • I've completed the script to automate this process. I've commented out the final confirmation click because I'm assuming it will cost you money to create the reservation. This works for me consistently.

    import datetime
    import time
    from selenium import webdriver
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.ui import Select
    
    #url = f'file:///C:/Users/jbcro/Desktop/sample.html'
    url = 'https://bent.baanreserveren.nl'
    driver = webdriver.Chrome()
    driver.maximize_window()
    driver.get(url)
    
    wait = WebDriverWait(driver, 10)
    
    # set script values here
    reservation_length_in_minutes = 60
    reservation_time = datetime.time(hour=21, minute=0) # hour=21, minute=0 is 21:00
    
    def set_court_time(court_time_in_minutes: int):
        # court_time must be 30, 45, or 60
        if court_time_in_minutes != 30 and court_time_in_minutes != 45 and court_time_in_minutes != 60:
            raise ValueError("Court time must be 30, 45, or 60")
        end_time = datetime.datetime.combine(datetime.date.today(), reservation_time) + datetime.timedelta(minutes=court_time_in_minutes)
        select = wait.until(EC.visibility_of_element_located((By.NAME, "end_time")))
        Select(select).select_by_visible_text(end_time.strftime("%H:%M"))
    
    def set_player(player_number: int, name: str, member: bool):
        # player_number must be 2, 3, or 4
        if player_number != 2 and player_number != 3 and player_number != 4:
            raise ValueError("Player number must be 2, 3, or 4")
        e = driver.find_element(By.NAME, "players[" + str(player_number) + "]")
        member_select = Select(e)
        wait.until(EC.visibility_of_element_located((By.XPATH, "//tr[./td[contains(text(),'Speler " + str(player_number) + "')]]//input"))).send_keys(name)
        wait.until(lambda x: member_select.options[0].text != "--")
        if member:
            member_select.select_by_visible_text(name)
        else:
            member_select.select_by_value("-1")
    
    # login
    driver.find_element(By.NAME, "username").send_keys("kbolk")
    driver.find_element(By.NAME, "password").send_keys("Test@123")
    driver.find_element(By.XPATH, "//button[text()='Inloggen']").click()
    
    # click Friday of this week
    wait.until(EC.element_to_be_clickable((By.XPATH, "//tr[./td[@title='SELECTED']]/td[5]"))).click()
    
    # select PADEL BUITEN
    Select(driver.find_element(By.ID, "matrix-sport")).select_by_visible_text("Padel Buiten")
    
    time.sleep(2)
    court_preferences = ['3', '2', '4', '6', '7']
    booked = False
    for court in court_preferences:
        available = driver.find_elements(By.XPATH, "//td[@type='free'][@title='Padel Buiten " + court + "'][./div[text()=' " + reservation_time.strftime("%H:%M") + "']]")
        if available:
            # print("Book court: " + court) # for debugging
            available[0].click()
            # add steps to finish booking here
    
            set_court_time(reservation_length_in_minutes)
            set_player(2, "Player 2 name", False) # sample non-member as Player 2
            set_player(3, "Player 3 name", False) # sample non-member as Player 3
            set_player(4, "Player 4 name", False) # sample non-member as Player 4
            driver.find_element(By.ID, "__make_submit").click()
            # driver.find_element(By.ID, "__make_submit2").click() # this confirms the reservation. Don't click this until you're sure everything is correct.
            booked = True
            break # exit the for loop
    
    if booked:
        print("Court <" + court + "> booked for " + reservation_length_in_minutes + " minutes.")
    if not booked:
        print("No available courts found")