I'm interacting with an online site to get a dataset to filter offline. I'm using Selenium webdriver to input values into a javascript date selector form, submitting the form and downloading the csv file. Through my tests, I've had intermittent issues with errors from the webdriver saying: "Unable to locate the element through xpath, element does not exist". It works about half the time, while I'm using the debugger, but when I run the program it seems to try and grab it before it's available. I can inspect the source and see that the element is available, but the webdriver doesn't seem to find it.
I created a loop to wait 3 seconds before trying again, and I only let it run about 15 seconds before it times out and kills the program. I previously input a counter to see if the program looped the correct amount of times. On occasion, it terminated the program execution on the first iteration. The last handful of tests seem to be working fine, but I'm wondering if there isn't a better way to accomplishing the same task?
This is the function that is causing a problem. In the for loop, download = driver.find_element_by_xpath('//*[@id=\"pagination-element-top\"]/div/div[1]/a')
seems to throw an error, but only on occasion.
def search_dates(url, date):
options = webdriver.ChromeOptions()
prefs = {"download.default_directory": os.getcwd()}
options.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(options=options)
driver.get(url)
date_selector = driver.find_element_by_class_name("date-range-container ")
start_date = date_selector.find_element_by_id("startDateId")
if datetime.now().year == 2019:
start_date.send_keys("1//1/2019")
else:
start_date.send_keys("1/1/" + str(datetime.now().year))
end_date = date_selector.find_element_by_id("endDateId")
end_date.send_keys(date)
button = driver.find_element_by_class_name("msl-button.msl-button-green")
button.send_keys(Keys.ENTER)
csv_fn = ''
for i in range(5):
time.sleep(3)
download = driver.find_element_by_xpath('//*[@id=\"pagination-element-top\"]/div/div[1]/a')
download.send_keys(Keys.ENTER)
# Gets the name of the csv file
csv_fn = download.get_attribute("download")
try:
if os.path.exists(csv_fn):
driver.close()
break
else:
continue
except Exception as e:
print(str(e))
sys.exit(0)
return csv_fn
This is my function to parse the csv file. I'm using python pandas to parse the csv file into a DataFrame.
def process_csv(csv_file):
csv_dict = {}
if os.path.exists(csv_file):
try:
with open(csv_file, 'r') as f:
numbers = pd.read_csv(f, delimiter=',')
for i, row in numbers.iterrows():
if (datetime.strptime(row['Draw Date'], '%m/%d/%Y').strftime('%A')) == 'Saturday':
csv_dict[row['Draw Date']] = row['Winning Numbers'].replace(',', '')
else:
pass
except IOError as e:
print("I/O error({0}): {1}".format(e.errno, e.strerror))
except Exception as e:
print(str(e))
return csv_dict
The intent is to input a start and end date into the webform, press the submit button, and press the download button to download the csv file into the current working directory. Once the csv is downloaded, I parse the data to align with the dates that I'm looking for to run my test.
Is using xpath the best way to grab what I'm looking for? I tried using element_by_name, and element_by_class_name, but it didn't seem to work. Would this be easier or better using python requests? I'm looking to creating a single executable, and would like some opinion on if this is correct, or if requests would help fix some issues I'm having.
Thanks!