Forums

Uploading images using Pythion Selenium

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

Hi Rowan -- is this regarding a program running on your own computer? These are the forums for PythonAnywhere, an online hosting environment, and we can only really give tech support on that.

That said, other people here might have encountered similar problems on their own and might be able to help -- but you'd probably get more responses on a general programming Q&A site like Stack Overflow