Automate your fitness after lockdown
Published: 2021-04-25 00:00:00

---
title: "Automate your fitness after lockdown"
date: "2021-04-25"
og:
  description: "Use selenium and Python to register for crossfit class"
  image: ""
author:
  twitter: "einargudni"
  name: "Einar Guðni"
---

We have to have short storytime, to talk about the scenario for this project.
Lockdowns have been on and off here in Iceland over the last year. Crossfit boxes here closed, and when the lockdowns lifted they opened again but not in a full capacity.
That meant that the demand for places in the classes was very high.

Of course, we can't automate our own fitness, we must show up and put in the work. But this will help us to reserve a spot in class when the demand is very high.

One point that plays in my hands is that I can reserve a place in class 72 hours ahead of time. So in theory I could reserve my place in classes for three days at a time, as long as they are not more than 72 hours ahead of the current time. _So why not try to automate the process?_ That would at least save me the time of fighting to get the few places in the classes.

I had done a similar project when I was finishing my computer science degree. To build a small script that sent me an email when I received my grades. So that was a fine starting point.

The first was to set up [selenium](https://selenium-python.readthedocs.io/). This link has quite good information on the process of setting up selenium, but [here](https://www.geeksforgeeks.org/how-to-install-selenium-in-python/) are also some rather detailed steps to get started with selenium.

I decided to use the [chromedriver](https://chromedriver.chromium.org/downloads) you could use the geckodriver for firefox if you want.

These are the packages we need to import. We will use selenium a lot, more on that later...

The [time](https://docs.python.org/3/library/time.html) module we use to make sure the website does go to its correct state before we select and click values.

The [os](https://docs.python.org/3/library/os.html) module we use to access the environmental values that keep our username and password for the login. [Read](https://able.bio/rhett/how-to-set-and-get-environment-variables-in-python--274rgt5) about how to use the os module.

```python
from selenium import webdriver
import time
import os
```

After this, we can test if the selenium works. It is best to just start to open a website, you could try `google.com` or whatever.

```python
driver = webdriver('./chromedriver')

driver.get('https://app.wodify.com/Schedule/CalendarListView.aspx')

time.sleep(4)

driver.quit()
```

Here we just try to open the Wodify website we plan on using later, but since we need to log into it only opens up on the login page.

![Wodify Log In](https://res.cloudinary.com/dik9usnqz/image/upload/v1618438906/selenium1.png)

If everything worked you should see the website open up in a new browser
So now we have selenium working.

### How can we use Selenium to log in to this website?

Selenium lets us select and interact with the HTML of the website.
We can inspect the website with the [Chrome DevTools](https://developer.chrome.com/docs/devtools/) by using ctrl + shift + I

The first step is to log in.

![](https://res.cloudinary.com/dik9usnqz/image/upload/v1619215452/wodifylogin1.png)

We can use the DevTools to inspect the website and select the login field and input the username we had stored as an environmental value earlier.

```python
elementLoginInput = driver.find_element_by_id("Input_UserName")
elementLoginInput.send._keys(WODIFY_UERNAME)
```

`driver.find_element_by_id` comes from the selenium module we imported earlier

We do the same for the password field, select the id and input the password.

![](https://res.cloudinary.com/dik9usnqz/image/upload/v1619215452/wodifylogin2.png)

```python
elementPwInput = driver.find_element_by_id("Input_Password")
elementPwInput.send_keys(WODIFY_PASSWORD)
```

After we have sent our login information to the correct fields we have to locate the login button.

![](https://res.cloudinary.com/dik9usnqz/image/upload/v1619269248/wodifylogin3.png)

Here we can however see that the Login Button does not have an Id, but we can use the [xPath](https://www.lambdatest.com/blog/complete-guide-for-using-xpath-in-selenium-with-examples/) to select the button without the Id.

```python
driver.find_element_by_xpath('//*[@id="FormLogin"]/div[2]/div[5]/button).click()
time.sleep(3)
```

After we login, we can go straight and find what element we need to select to register for said class.

However, since we could end up needing to scroll down on the page, especially if the class is two or three days from now, remember - we can reserve for classes 72 hours from the current class, but only one a day.

![](https://res.cloudinary.com/dik9usnqz/image/upload/v1619279563/wodifylogin4.png)

So here below you can see us find an element by its xPath, this element contains the day and class we want to select.

```python
tableRow = driver.find_element_by_xpath('//*[@id="AthleteTheme_wt6_block_wtMainContent_wt9_wtClassTable_ctl45_wtAddReservationLink2"]')
driver.execute_script("arguments[0].scrollIntoView();", tableRow)
```

And since we need to scroll the particular day and class into view we must use `.scrollIntoView()`.
Because of the element we are searching for is not in view on the page we must scroll it into view. We can not click an element that is no in view.

We can see what the element for the button is, but however, it is important to notice that the buttons have not identical ids. Which we can understand because they all stand for different classes.

But this helps us to just go to the day and time we are registering for.

We can inspect the element we want and simply copy its xPath.

Here we have two different classes, one that we can register for and another one that is not accessible yet.

![](https://res.cloudinary.com/dik9usnqz/image/upload/v1619352359/wodifylogin5.png)

In the code snippet below we can see xPath for both classes.
Note, that when the classes are available for registration the xPath is different.

```python
tableRowAvailable = driver.find_element_by_xpath('//*[@id="AthleteTheme_wt6_block_wtMainContent_wt9_wtClassTable_ctl15_wtAddReservationLink2"]')
tableRowUnavailable = driver.find_element_by_xpath('//*[@id="AthleteTheme_wt6_block_wtMainContent_wt9_wtClassTable_ctl17_wt3"]')
```

This does mean that we must figure out how the xPath will be after the registration opens. We figured out that `AddReservationLink2` is added to the element and the xPath as soon as the registration opens up.

This is rather a simple step and a good starting place. We could add more to this to make it more robust.
Right now it returns an error if it doesn't find the element straight away. Wy could handle it with a [try-except](https://www.w3schools.com/python/python_try_except.asp) to make sure that we try to click the button until it becomes availabe if the programs run few seconds too early and it tries to register for a class when the registration period is not opened yet it would return an error and 'crash'. The try-except could make sure we would not have this error happen if we try to register too soon.

### Scheduling

How could we automate the process of scheduling the task?

![](https://res.cloudinary.com/dik9usnqz/image/upload/v1619354073/wodifylogin6.png)

Since I have a windows machine, I used [Task Scheduler](https://www.windowscentral.com/how-create-automated-task-using-task-scheduler-windows-10) there are probably more ways to schedule a python script to run at a certain time, especially if you have a different OS. I know that you can figure that out. 🤠

### Conclusion

It is not the perfect way but I feel like this is a good starting point.

This is a super simple way to start to automate things with simple yet effective python scripts.
I recommend you play around with it and use it as you like.
It is not super hard to get started with selenium, which is why it is a good starting place.

There are probably multiple ways to automate a lot of things in a different way, so Selenium is not the only way. I think is just one place to start.

Automation small tasks like this are fun to do. I hope you can use this to automate something in your life, or just to play around and have fun. 

Check out my [site](www.einargudni.com) for more upcoming posts about things I'm doing 🤓