I have created a small selenium script that checks for available times to write a test for a drivers license. The program runs every minute and takes approx 50 seconds to run. I have noticed that it's quite unstable, and do not preform optimally because the web-page loads elements dynamically. Even if I use seleniums wait I am unable to optimise it fully as connectivity vary on my wifi, and may lead to longer loading times than expected. Feedback on error-handling and code optimisation for greater stability would be highly appreciated and how to schedule the task to run without a back-log of jobs waiting to be executed as memory is small on my mac-book air 2013.
import datetime import schedule import threading from datetime import date import smtplib import time import multiprocessing as mp from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from selenium import webdriver from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import TimeoutException from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait def selenium_get_time(ort): """Checks if time is available for a county""" options = Options() options.headless = True driver = webdriver.Chrome(chrome_options=options, executable_path='/Users/andreas/.wdm/chromedriver/83.0.4103.39/mac64/chromedriver') driver.get("https://fp.trafikverket.se/boka/#/search/dIccADaISRCIi/5/0/0/0") element = WebDriverWait(driver, 40).until(EC.element_to_be_clickable((By.CLASS_NAME, "form-control"))) driver.find_element_by_xpath("//select[@id='examination-type-select']/option[@value='3']").click() driver.find_element_by_xpath("//select[@id='language-select']/option[@value='13']").click() driver.find_element_by_id('id-control-searchText').clear() inputElement = driver.find_element_by_id("id-control-searchText") inputElement.send_keys(ort) inputElement.send_keys(Keys.ENTER) # time.sleep(10) try: element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='col-sm-3 text-center']/button[@data-bind='click:$parent.select']"))) first_time = driver.find_element_by_xpath("//div[@class='col-xs-6']/strong") return first_time.text except (NoSuchElementException, TimeoutException) as e: driver.close() if NoSuchElementException: print('Nothing found for: ', ort, ' NoElemFound') driver.close() driver.quit() else: print('Nothing found for: ', ort, ' TimedOut') driver.close() driver.quit() def convert_time(time_stamp): """converts a timestamp""" date_time_obj = datetime.datetime.strptime(time_stamp, '%Y-%m-%d %H:%M') return date_time_obj def check_schedule(date, start_date, end_date): start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d') end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d') if start_date <= date <= end_date: return True else: return False def send_email(first_availible, ort): """sends an email""" gmailUser = 'nor###rov@###.com' gmailPassword = '######' recipient = '###########' message=msg = 'Första lediga tid i'+' '+ str(ort) +' '+ str(first_availible) +' '+ 'https://fp.trafikverket.se/boka/#/search/SPHHISiPAfhpP/5/0/0/0' msg = MIMEMultipart() msg['From'] = gmailUser msg['To'] = recipient msg['Subject'] = "Ledig tid körkortsprov" msg.attach(MIMEText(message)) mailServer = smtplib.SMTP('smtp.gmail.com', 587) mailServer.ehlo() mailServer.starttls() mailServer.ehlo() mailServer.login(gmailUser, gmailPassword) mailServer.sendmail(gmailUser, recipient, msg.as_string()) mailServer.close() def main(ort): """main program""" first_availible = selenium_get_time(ort) if first_availible: date = convert_time(first_availible) if check_schedule(date, '2020-07-01', '2020-07-05'): print('FOUND: ', ort +' '+ first_availible) send_email(first_availible, ort) else: now = datetime.datetime.now() dt_string = now.strftime("%H:%M:%S") print('Found Nothing for: ', ort, ' ', dt_string) def run(): """runs program""" ORTER = ['Södertälje', 'Stockholm', 'Järfälla', 'Sollentuna'] for ort in ORTER: main(ort) def worker(): """"spans processes for program""" p = mp.Process(target=run) # run `worker` in a subprocess p.start() # make the main process wait for `worker` to end p.join() # all memory used by the subprocess will be freed to the OS if __name__ == '__main__': """schedule to run every minute""" schedule.every(55).seconds.do(worker) while True: try: schedule.run_pending() time.sleep(1) except Exception as e: schedule.run_pending() time.sleep(1)