Question

Below is a snippet of code from my python script that is reading an excel file and assigning cells in a row to a variable that is then used to be typed into a field in the browser. it works great ... for the most part. what i would like to do is setup some sort of loop after the browser loads the page to do the following:

find the element by some ID. if this fails, wait 5 seconds then try again. if it succeeds carry on with the rest of the script. now go easy on me, this is my first real attempt. i have tried to nest try/except statements but that got really messy fast.

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.keys import Keys
import time
import xlrd

workbook = xlrd.open_workbook("my_excel_file.xlsx")
worksheet = workbook.sheet_by_name('Sheet1')
x = 0
for current_row in range(worksheet.nrows):
    try:
        cmt = worksheet.row(current_row)[2].value
        browser = webdriver.Firefox() # Get local session of firefox
        browser.get("http://www.somewebsite.com") # Load page
        time.sleep(5)
        #this timer is the issue, if the field takes 6 seconds to be ready, script fails
        comment = browser.find_element_by_id("slow_comment_box") # Find the comment box
        comment.send_keys(str(cmt) + Keys.RETURN)
        x += 1
    except:
        print ("Error on " + str(x))
        quit ()

is there a way to set this to behave the way i stated above? i know selenium waits for the page to load but the text box is not a normal one and appears to have its own loading, spinning wheel.

summary and solution the answer is below. my dumb stuff had some syntax errors. this page was extremely useful as well.

Was it helpful?

Solution

You want to use WebDriverWait

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

element = WebDriverWait(driver, 60).until(EC.visibility_of_element_located((By.Id, 'id')))

OTHER TIPS

After trying Erki M.'s response I went here to learn more about waiting in Selenium:

http://selenium-python.readthedocs.org/en/latest/waits.html

The article mentions another alternative that is nice and simple:

from selenium import webdriver

browser = webdriver.Firefox() 
browser.implicitly_wait(30)
browser.get("http://www.somewebsite.com")

From the time you specify an implicit wait time onward, the browser will be patient and poll the site to see if it can find the element you are looking for. This method avoids the need for extra imports and also the necessity of specifying what element you are waiting for ahead of time.

One thing that I should mention is that sometimes I still fall back to time.sleep(1), for example, after keying in an input. Implicitly_wait will give time for an element to appear, but it will not cause commands to wait long enough for the UI to be responsive.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top