Reputation: 362
I am having a trouble trying to figure out how to continue the script if an element is not found using selenium in Python.
This code cycles through reports, finds the refresh button and then clicks on the download the button. The only problem is, that some reports do not have a refresh button. So, I would like the script to continue if the button is not found.
I am still new to python/selenium so that is why I am posting the entire code. I need to know what to slip in to make this work! Thanks in advance for the help with this head banging problem
This is where selenium will try to click the refresh button
browser.find_element_by_css_selector("#ctl00_PlaceHolderMain_ReportViewer1_HtmlOutputReportResults2_updateFilters_TitleAnchor").click()
The complete code:
import time
import os
import os.path
import glob
import shutil
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import MoveTargetOutOfBoundsException
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
files = glob.glob('/Users/me/Desktop/AUTOREPORTS/*')
for f in files:
os.remove(f)
open('/Users/me/Desktop/AUTOREPORTS/report.csv', "w")
for x in range(1, 73):
while True:
try:
fp = webdriver.FirefoxProfile('C:/Users/me/Documents/FirefoxProfile')
browser = webdriver.Firefox(fp)
browser.get('https://websitething.com/')
time.sleep(8)
browser.find_element_by_id("ctl00_PlaceHolderMain_login_UserName").clear()
browser.find_element_by_id("ctl00_PlaceHolderMain_login_UserName").send_keys("usr")
browser.find_element_by_id("ctl00_PlaceHolderMain_login_password").clear()
browser.find_element_by_id("ctl00_PlaceHolderMain_login_password").send_keys("paswd")
browser.find_element_by_id("ctl00_PlaceHolderMain_login_login").click()
#gets user to reporting front end
ReportMgr= browser.find_element_by_partial_link_text('Report Manager')
ReportMgr.click()
time.sleep(5)
CustomReport= browser.find_element_by_partial_link_text('Custom Report')
CustomReport.click()
time.sleep(5)
ProgramManagement= browser.find_element_by_partial_link_text('Program Management')
ProgramManagement.click()
ProgramManagement= browser.find_element_by_partial_link_text('Program Management').send_keys(Keys.ARROW_LEFT)
#pulls reports
browser.find_element_by_partial_link_text('Program Management').click()
time.sleep(60)
browser.find_element_by_partial_link_text('Program Management').send_keys(Keys.ARROW_DOWN * x, Keys.ENTER)
time.sleep(60)
browser.find_element_by_css_selector("#ctl00_PlaceHolderMain_ReportViewer1_HtmlOutputReportResults2_updateFilters_TitleAnchor").click()
time.sleep(60)
browser.find_element_by_css_selector("#ctl00_PlaceHolderMain_ReportViewer1_HtmlOutputReportResults2_CSVButton_ImageAnchor > img").click()
fname = "Report(%s).csv" % (x)
os.chdir('/Users/me/Desktop/AUTOREPORTS')
time.sleep(60)
#browser.find_element_by_partial_link_text('Program Management').click()
#time.sleep(30)
browser.quit()
except:
browser.quit()
continue
else:
break
Upvotes: 12
Views: 27784
Reputation: 42518
You could check that at least one item is returned by find_elements:
elements = driver.find_elements_by_css_selector("...")
if elements :
elements[0].click()
And if you are concerned that it is more expensive than a try/catch, well it's not, so both methods are valid.
Chrome 49.0.2623 Windows 8.1 (1000 samples) :
| find_element | find_elements |
Sum | 10077.4544ms | 9895.2903ms | diff: -182.1641ms
Mean | 10.0775ms | 9.8953ms | diff: -0.1822ms
Mediam | 9.7563ms | 9.5361ms | diff: -0.2202ms
Min | 9.0264ms | 9.0220ms | diff: -0.0044ms
Std | 2.2050ms | 2.4411ms |
Firefox 44.0.2 Windows 8.1 (1000 samples) :
| find_element | find_elements |
Sum | 9146.3389ms | 8860.2409ms | diff: -286.0981ms
Mean | 9.1463ms | 8.8602ms | diff: -0.2861ms
Mediam | 8.0231ms | 7.8351ms | diff: -0.1880ms
Min | 6.3442ms | 6.1565ms | diff: -0.1877ms
Std | 5.3030ms | 6.2566ms |
The code to compare find_element vs find_elements:
from selenium import webdriver
from statistics import mode, mean, pstdev, median
import time
driver = webdriver.Chrome()
driver.get("http://stackoverflow.com")
time.sleep(1)
selectors = [
'#nav-questions', # present
'#abcdef', # not present
'div.nav:nth-child(2)', # present
'div.nav:nth-child(10)', # not present
'.youarehere', # present
'.abcdef' # not present
];
timesA = []
timesB = []
samples = 1000
for i in range(samples):
start = time.clock()
try:
element = driver.find_element_by_css_selector(selectors[i % 6])
except:
pass
timesA.append((time.clock()-start) * 1000.0)
start = time.clock()
elements = driver.find_elements_by_css_selector(selectors[i % 6])
if not elements :
pass
timesB.append((time.clock()-start) * 1000.0)
print("\n".join([
" | find_element vs find_elements",
"Sum | {:10.4f}ms | {:10.4f}ms | diff: {:10.4f}ms".format(sum(timesA), sum(timesB), sum(timesB)-sum(timesA)),
"Mean | {:10.4f}ms | {:10.4f}ms | diff: {:10.4f}ms".format(mean(timesA), mean(timesB), mean(timesB)-mean(timesA)),
"Mediam | {:10.4f}ms | {:10.4f}ms | diff: {:10.4f}ms".format(median(timesA), median(timesB), median(timesB)-median(timesA)),
"Min | {:10.4f}ms | {:10.4f}ms | diff: {:10.4f}ms".format(min(timesA), min(timesB), min(timesB)-min(timesA)),
"Std | {:10.4f}ms | {:10.4f}ms | ".format(pstdev(timesA), pstdev(timesB))
]))
Upvotes: 3
Reputation: 5207
Use a try
/ except
block to handle the exception and continue.
try:
browser.find_element_by_css_selector("#ctl00_PlaceHolderMain_ReportViewer1_HtmlOutputReportResults2_updateFilters_TitleAnchor").click()
except NoSuchElementException:
# do stuff
Note that Florent B.'s answer will find multiple elements on the page instead of one. So depending on what you need to find, and how many of them there are, it may cause minor performance issues. If you actually need to find multiple elements, his solution will work just fine, but for OP's question best practices dictate that we use the method designed to handle the task at hand instead of the method designed to handle multiples of the same task. It's like greedy matching vs lazy matching with regex. If you only need the first match, write a lazy pattern and it will be more efficient, even if writing the greedy pattern still works out technically.
Upvotes: 8
Reputation: 3927
As known whenever element is not available then it will throw exception. In this situation we know element is some times not available so we need to handle this exception.
In Java, we can handle it by using try/catch.
try{
driver.findElement(By.xpath(".//*[@id='menu-item-92']/a")).click(); //your element here
}catch(Exception e){
System.out.println(e.getMessage()); //printing exception
}
Please make a note: if any case this element is to display but not, then still execution goes to next line as we handled exception.
Thank You, Murali
Upvotes: 1