I am trying to automat the use of a web site (that I have no control over) using Python Selenium. The work flow involves uploading a number of images. The code I am using to do this is:
def waiting(message_queue, text, timeout):
message_queue.clear() # Clear any messages left in the queue from a previous run.
sys.stdout.write(text + " ")
sys.stdout.flush()
i = timeout
while True:
# sys.stdout.write("\b" + whizzer[i % len(whizzer)])
sys.stdout.write("\b\b\b\b" + str(i).rjust(4))
sys.stdout.flush()
# time.sleep(sleeptime)
time.sleep(1)
i = i - 1
if i <= 0:
logmsg(L_TRACE, "Waiting thread finishing, task took longer than " + str(timeout) + " seconds.")
print()
print("Timeout. Task took longer than " + str(timeout) + " seconds.")
break
if message_queue.empty():
continue
else:
flag = message_queue.get(block = False)
if flag is _finished:
sys.stdout.write("\r")
sys.stdout.flush()
logmsg(L_TRACE, "Waiting thread finishing, task is finished, took " + str(timeout - i) + " seconds")
print ()
print("Task is complete. Took " + str(timeout - i) + " seconds")
# for i in range(len(text) + 3):
# sys.stdout.write(" ")
# sys.stdout.flush()
break
if flag is _interrupted:
logmsg(L_TRACE, "Waiting thread finishing, interrupt detected")
break
def upload4(image_text, add_image_xpath, upload_xpath):
"""
Uploads an image using the Cloudinary upload widget.
Parameters
----------
image : str
The path of the image file to upload, rerlative to image_path
add_image_xpath : str
The xpath of the "Add Image" element on the web page
upload_xpath : str
The xpath of the file drop area on the web page
Returns
-------
int
0 Success
non-0 Failure
"""
# Click where it says "Click to add image".
if image_text != None:
if len(image_text) > 0:
framenum = 0
logmsg(L_TRACE, "Locating 'Add Image' button")
driver.switch_to.parent_frame()
# add_image_button = driver.find_element_by_xpath("//a[contains(text(),'Click to add image')]")
add_image_button = None
try:
# add_image_button = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//a[contains(text(),'Click to add image')]")))
add_image_button = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, add_image_xpath)))
except TimeoutException:
logmsg(L_TRACE, "Timeout exception occurred, continuing")
if add_image_button == None:
# add_image_button = driver.find_element_by_xpath(add_image_xpath)
# add_image_button = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, add_image_xpath)))
add_image_button = driver.find_element_by_xpath(add_image_xpath)
logmsg(L_TRACE, "Add Image button is: " + add_image_button.get_attribute("outerHTML"))
logmsg(L_TRACE, "Clicking 'Add Image' button")
driver.execute_script("arguments[0].click();", add_image_button)
driver.switch_to.default_content()
# driver.switch_to.frame(9)
time.sleep(5)
if for_upload_use == "browse":
logmsg(L_TRACE, "Looking for Browse button")
browse_xpath = "//input[@type='file' and @name='file' and @class='cloudinary_fileupload']"
logmsg(L_TRACE, "Looking for browse button, xpath = " + browse_xpath)
browses = driver.find_elements_by_xpath(browse_xpath)
browse = None
if len(browses) > 0:
if len(browses) > 1:
logmsg(L_ERROR, "Expecting only one browse button, " + str(len(drag_heres)) + " found")
else:
logmsg(L_TRACE, "One browse button found")
browse = browses[0]
found = 1
else:
found = 0
if found == 0:
logmsg(L_TRACE, "No browse buttons found in master frame, looking in sub-frames")
frames = driver.find_elements_by_xpath("//iframe")
logmsg(L_TRACE, "Found " + str(len(frames)) + " subframes in parent frame number " + str(framenum))
for i in range(10):
found = 0
for framenum in range(len(frames)):
if framenum > 0 or i > 0:
driver.switch_to.parent_frame()
logmsg(L_TRACE, "Try " + str(i) + ", trying subframe number " + str(framenum))
frame = frames[framenum]
logmsg(L_TRACE, "Frame " + str(framenum) + ": " + frame.get_attribute('outerHTML')[:64])
driver.switch_to.frame(framenum)
browses = driver.find_elements_by_xpath(browse_xpath)
if len(browses) > 0:
if len(browses) > 1:
logmsg(L_ERROR, "Expecting only one browse button, " + str(len(drag_heres)) + " found in subframe " + str(framenum))
else:
logmsg(L_TRACE, "One browse button found in subframe number " + str(framenum))
browse = browses[0]
found += 1
else:
logmsg(L_TRACE, "No browse buttons found in subframe " + str(framenum))
continue
if found > 0:
break
if found > 1:
logmsg(L_TRACE, str(found) + " browse buttons found in subframes, using the most recent subframe")
if found <= 0:
logmsg(L_ERROR, "No browse button found anywhere")
if browse == None:
logmsg(L_ERROR, "Browse button is None")
attempts = 0
result = False;
while attempts < 5:
try:
logmsg(L_TRACE, "Try " + str(attempts) + ". Browsing to file " + image_path + image_text + " using element " + browse.get_attribute('outerHTML'))
driver.execute_script("arguments[0].scrollIntoView();", browse)
browse.send_keys(image_path + image_text)
result = True
break;
except StaleElementReferenceException:
attempts += 1
if not result:
logmsg(L_ERROR, "browse element is stale")
time.sleep(5)
elif method == "drag":
logmsg(L_TRACE, "Looking for drag here element, xpath = " + upload_xpath)
drag_heres = driver.find_elements_by_xpath(upload_xpath)
if len(drag_heres) > 0:
if len(drag_heres) > 1:
logmsg(L_ERROR, "Expecting only one drag-here element, " + str(len(drag_heres)) + " found")
drag_here = drag_heres[0]
found = 1
else:
found = 0
if found == 0:
logmsg(L_TRACE, "No drag-here elements found in master frame, looking in sub-frames")
frames = driver.find_elements_by_xpath("//iframe")
logmsg(L_TRACE, "Found " + str(len(frames)) + " subframes in parent frame number " + str(framenum))
for framenum in range(len(frames)):
logmsg(L_TRACE, "Trying subframe number " + str(framenum))
driver.switch_to.frame(framenum)
elements = driver.find_elements_by_xpath("//*")
for i in range(len(elements)):
element = elements[i]
msg = "Element " + str(i) + " in frame: "
msg += str(element.tag_name)
msg += ", name: " + str(element.get_attribute('name'))
msg += ", data-test: " + str(element.get_attribute('data-test'))
msg += ", id: " + element.get_attribute('id')
msg += ", href: " + str(element.get_attribute('href'))
msg += ", src: " + str(element.get_attribute('src'))
msg += ", class: " + str(element.get_attribute('class'))
msg += ", style: " + str(element.get_attribute('style'))
logmsg(L_DETAIL, msg)
drag_heres = driver.find_elements_by_xpath(upload_xpath)
if len(drag_heres) > 0:
if len(drag_heres) > 1:
logmsg(L_ERROR, "Expecting only one drag-here element, " + str(len(drag_heres)) + " found in subframe " + str(framenum))
found = 1
break
logmsg(L_TRACE, "One drag-here element found in subframe number " + str(framenum))
drag_here = drag_heres[0]
found = 1
break
else:
logmsg(L_TRACE, "No drag-here elements found in subframe " + str(framenum))
found = 0
if found == 1:
break
else:
driver.switch_to.parent_frame()
continue
if found == 0:
logmsg(L_ERROR, "Failed to find drag-here element in any top level frame")
else:
logmsg(L_TRACE, "Found drag-here element in subframe " + str(framenum))
logmsg(L_TRACE, "Dropping file " + image_path + image_text + " on element " + drag_here.get_attribute('outerHTML'))
driver.execute_script("arguments[0].scrollIntoView();", drag_here)
# driver.execute_script("arguments[0].click();", drag_here)
drop_files(drag_here, image_path + image_text)
time.sleep(5)
else:
logmsg(L_FATAL, "Method " + method + " not supported")
logmsg(L_TRACE, "Locating the Skip button")
# Get all the elements in the frame.
elements = driver.find_elements_by_xpath('//*')
num_elems = len(elements)
# Find the skip button.
for index in range(num_elems):
element = elements[index]
if element.get_attribute('data-test') == 'skip-button':
break
# Log properties of skip button (for debugging).
msg = "Button is tag: " + str(element.tag_name)
msg += ", name: " + str(element.get_attribute('name'))
msg += ", data-test: " + str(element.get_attribute('data-test'))
msg += ", id: " + element.get_attribute('id')
msg += ", href: " + str(element.get_attribute('href'))
msg += ", src: " + str(element.get_attribute('src'))
msg += ", class: " + str(element.get_attribute('class'))
msg += ", style: " + str(element.get_attribute('style'))
logmsg(L_TRACE, msg)
# Click the skip button.
logmsg(L_TRACE, "Clicking skip button ")
driver.execute_script("arguments[0].click();", element)
driver.switch_to.default_content()
else:
logmsg(L_ERROR, "image_text length must be > 0, was " + str(len(image_text)))
else:
logmsg(L_TRACE, "There was no image element in the XML file")
Main code: logmsg(L_TRACE, "Sending cover image: " + cover_image.text) wait = Thread(target = waiting, args = (messages, "Waiting for image to upload", 90)) wait.start() "//a[text() = 'Click to add image']" # upload4(cover_image.text, "//a[@class='upload-widget-opener']", '//div[@data-test="drag-area"]') upload4(cover_image.text, "//a[text() = 'Click to add image']", '//div[@data-test="drag-area"]') messages.put(_finished) time.sleep(5)
It takes a long long time to upload the images. It can take up to 180 seconds, whereas when I use the web site manually, it only seems to take 1 o 2 seconds to upload each image. What am I doing wrong? How do I get Selenium to upload the images as fast as manual use?
Thank you - Rowan