How to Automate Gym Reservations with Selenium: A Google‑Style Design Doc
This article translates a Google engineer's design document that explains how to build a Python‑based Selenium bot for automatically booking gym slots two days in advance, covering problem description, requirements, architecture choices, detailed implementation, and operational workflow.
Problem Description
During the COVID‑19 pandemic gyms required members to pre‑book slots two days in advance, opening at midnight. The author needed a way to secure a 6 am slot without staying up late.
Requirements
Automatically book a gym slot two days ahead at midnight.
Run without human interaction, be fault‑tolerant and retry intelligently.
Run on macOS.
Allow user to specify username, password, sport, date, time, and other parameters.
Out of scope:
Booking only 1‑2 days ahead or same‑day.
Tolerating OS or network failures.
Operating after the booking server stops.
Working after the website HTML structure changes.
Overview Design
Comparison of browser automation vs. simulated HTTP requests. Browser automation was chosen because it runs a real browser, making debugging easier and handling JavaScript‑rendered controls, even though it depends on the page’s HTML structure.
The implementation uses Python, Selenium (Firefox + GeckoDriver), and the macOS caffeinate utility to prevent sleep.
Detailed Design
User Input
Username, password, date, etc. are supplied via command‑line arguments.
Retry Logic
The program catches all exceptions and retries up to 100 times until the booking succeeds, identified by confirming a specific DOM element.
Browser Choice
Firefox was selected after testing Chrome and Safari, which required extra driver steps.
Logging
Each loop logs what action was performed and what it is waiting for, facilitating debugging.
Preventing Sleep
The macOS caffeinate tool is launched as a subprocess to keep the computer awake until midnight:
subprocess.Popen(['caffeinate', '-d', '-w', '%d' % os.getpid()])Element Location
Selenium’s find_element_by_xpath is used with robust text‑based locators to find buttons, inputs, and other controls.
Waiting for Page Load
The WebDriverWait API waits up to 120 seconds for the appointment button to become clickable:
book_btn = WebDriverWait(driver, 120).until(EC.element_to_be_clickable((By.XPATH, "//button[@ng-reflect-router-link='/Appointments']")))Additional Details
Logic handles month selection, date‑cell identification, and edge cases when the target date falls in the next month.
Operation Flow
Run the script the day before the desired slot, for example:
python book.py --username xxxx --password xxxx --day 14 --time '5:00 PM' --sport small_poolThe script wakes every second, uses caffeinate to keep the Mac awake until midnight, launches Firefox, completes the booking, then exits. After execution the system can sleep normally.
Booking is highly competitive; only six slots per time slot are available and they fill within the first minute.
Relevant links:
https://github.com/luanjunyi/smac_booking_robot
https://docs.google.com/document/d/1NRj-NdDW_wD1-GwZAJc-Nfrbq8xMiX1Hggrzguh-fjY/edit?usp=sharing
https://www.selenium.dev/
https://ss64.com/osx/caffeinate.html
https://selenium-python.readthedocs.io/locating-elements.html
https://selenium-python.readthedocs.io/waits.html?highlight=WebDriverWait#explicit-waits
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java High-Performance Architecture
Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
