Created
October 18, 2018 14:52
-
-
Save claraj/4b3de30f88341d69f2eef6b7de21a6c8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Download the latest ChromeDriver and put in the same place as this script. Or, in a location on your computer's path. | |
# http://chromedriver.chromium.org/ | |
# Install Selenium with | |
# pip install selenium | |
from selenium import webdriver | |
from selenium.webdriver.support.ui import Select | |
from selenium.webdriver.support.ui import WebDriverWait | |
from selenium.webdriver.support import expected_conditions as EC | |
from selenium.webdriver.common.by import By | |
import sys | |
import os | |
import time | |
# First page is the search form. | |
# Enter information into form | |
""" | |
Configuration: modify these variables as needed. | |
""" | |
PARK_NAME = 'Tettegouche State Park' # Change park name if needed | |
ACTIVITY = "1" # "Camping and Lodging", don't need to change | |
ARRIVAL_DATE = "5/24/2019" # Change date if needed | |
STAY_LENGTH = "2" # Change number of nights if needed | |
WAIT = 5 # * 60 # Seconds to wait between checks. Repeatedly running the same query too often is a good way to get blocked. | |
""" | |
End config | |
""" | |
def check_camping(): | |
while True: | |
check_availiability() | |
print('Press Control+C to stop the program') | |
time.sleep(WAIT) | |
def check_availiability(): | |
browser = webdriver.Chrome() | |
browser.implicitly_wait(10) # How long to wait for elements that aren't immediately on the page, to account for page loading as the site is navigated. | |
browser.get('https://reservemn.usedirect.com/MinnesotaWeb/Default.aspx') | |
try: | |
park_name = browser.find_element_by_id('txtSearchparkautocomplete') | |
activity = Select(browser.find_element_by_id('ddlFacilityCategory')) | |
arrival_date = browser.find_element_by_id('mainContent_txtArrivalDate') | |
stay_length = Select(browser.find_element_by_id('ddlHomeNights')) | |
search_button = browser.find_element_by_link_text('Go') | |
#mainContent_divDefaultSearchpart > div.sim_banner_data_box > div > div > div > div:nth-child(5) > div.search_new_go.no_btn_a > a | |
park_name.send_keys(PARK_NAME) | |
time.sleep(0.5) # Javascript on the page runs to autocomplete to the text input, so wait for that to complete. | |
activity.select_by_value(ACTIVITY) | |
arrival_date.send_keys(ARRIVAL_DATE) | |
stay_length.select_by_value(STAY_LENGTH) | |
search_button.click() | |
# Next page is a list of state parks, including nearby parks. The first | |
# park should be the one searched for. If you care about nearby parks, this | |
# would be a good place to check those out too. | |
wait = WebDriverWait(browser, 15) | |
reserve_button = wait.until(EC.presence_of_element_located((By.XPATH, "//a[text()=' Reserve']"))) # find_elements_by_link_text would get all the reserve buttons, but only care about the first one here, which should be for the park searched for. | |
# Parks that are full display the link button with class btn btn-danger and the font awesome icon fa fa-times-circle | |
# Parks with availability display the link button with class btn btn-success and the font awesome icon fa fa-check-circle | |
# So we don't even need to look at the dates - it's either available for the search or not. Check either the button class or the presence of the either icon. Class is easier to check. | |
reserve_button_class = reserve_button.get_attribute('class') | |
if reserve_button_class == 'btn btn-danger': | |
print('%s is not available for %s nights starting %s' % (PARK_NAME, STAY_LENGTH, ARRIVAL_DATE)) | |
if reserve_button_class == 'btn btn-success': | |
message = '%s is available for %s nights starting %s' % (PARK_NAME, STAY_LENGTH, ARRIVAL_DATE) | |
print(message) | |
notify(message) | |
except: | |
print('Error!', *sys.exc_info()) | |
browser.quit() | |
sys.exit(1) # Something went wrong, print message and exit program. | |
browser.close() | |
def notify(message): | |
# This is up to you. On a Mac/Linux/Windows Bash Shell you can call the say program and get yelled at | |
# On a PC, some alternatives https://superuser.com/questions/223913/os-x-say-command-for-windows | |
# Or with powershell https://learn-powershell.net/2013/12/04/give-powershell-a-voice-using-the-speechsynthesizer-class/ | |
os.system('say ' + message) # Won't work on a PC, check out alternatives above. | |
# Other notification approaches: Use Twillio to send a text message, use Twitter API to send a DM... | |
if __name__ == '__main__': | |
check_camping() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment