检查 Python Selenium 中是否存在元素

我遇到了一个问题: 我正在使用 Selenium (Firefox)网页驱动程序打开一个网页,点击一些链接等,然后捕捉一个截图。

我的脚本在 CLI 中运行得很好,但是当通过 混蛋运行时,它没有通过第一个 find _ element ()测试。我需要添加一些调试,或者一些东西来帮助我找出失败的原因。

基本上,在进入登录页面之前,我必须点击一个“登录”锚。元素的结构是:

<a class="lnk" rel="nofollow" href="/login.jsp?destination=/secure/Dash.jspa">log in</a>

我使用的是 Find _ element By LINK _ TEXT 方法:

login = driver.find_element(By.LINK_TEXT, "log in").click()

A)如何检查该链接实际上是由 Python 拾取的? 我应该使用 try/catch 块吗?

B)是否有比 LINK _ TEXT 更好或更可靠的方法来定位 DOM元素?例如,在 JQuery中,您可以使用一个更具体的选择器 $(‘ a.lnk: include (log in)’)。做某事() ;


我已经解决了主要的问题,只是手指的问题。我用不正确的参数调用脚本-一个简单的错误。

我仍然需要一些关于如何检查元素是否存在的指导。另外,隐式/显式 Waits 的示例/解释,而不是使用蹩脚的 time.sleep ()调用。

293970 次浏览

A) Yes. The easiest way to check if an element exists is to simply call find_element inside a try/catch.

B) Yes, I always try to identify elements without using their text for two reasons:

  1. the text is more likely to change and;
  2. if it is important to you, you won't be able to run your tests against localized builds.

The solution is either:

  1. You can use XPath to find a parent or ancestor element that has an ID or some other unique identifier and then find its child/descendant that matches or;
  2. you could request an ID or name or some other unique identifier for the link itself.

For the follow-up questions, using try/catch is how you can tell if an element exists or not and good examples of waits can be found here: http://seleniumhq.org/docs/04_webdriver_advanced.html

For a):

from selenium.common.exceptions import NoSuchElementException
def check_exists_by_xpath(xpath):
try:
webdriver.find_element_by_xpath(xpath)
except NoSuchElementException:
return False
return True

For b): Moreover, you can take the XPath expression as a standard throughout all your scripts and create functions as above mentions for universal use.

I recommend to use CSS selectors. I recommend not to mix/use "by id", "by name", etc. and use one single approach instead.

You can grab a list of elements instead of a single element. An empty list in python is falsey. Example:

if driver.find_elements(By.CSS_SELECTOR, '#element'):
print "Element exists!"

You can also use By.ID and By.NAME, but that just turns your id or name into a css selector anyway. Source

The same as Brian, but add to this answer from tstempko:

I tried and it works quickly:

driver.implicitly_wait(0)


if driver.find_element_by_id("show_reflist"):
driver.find_element_by_id("show_reflist").find_element_by_tag_name("img").click()

After this, I restore my default value:

driver.implicitly_wait(30)

You could also do it more concisely using

driver.find_element_by_id("some_id").size != 0

driver.find_element_by_id("some_id").size() is a class method.

We need:

driver.find_element_by_id("some_id").size which is a dictionary, so:

if driver.find_element_by_id("some_id").size['width'] != 0:
print 'button exist'

A solution without try&catch and without new imports:

if len(driver.find_elements_by_id('blah')) > 0: # Pay attention: find_element*s*
driver.find_element_by_id('blah').click # Pay attention: find_element

You could use is_displayed() like below:

res = driver.find_element_by_id("some_id").is_displayed()
assert res, 'element not displayed!'

You can find elements by available methods and check response array length if the length of an array equal the 0 element not exist.

element_exist = False if len(driver.find_elements_by_css_selector('div.eiCW-')) > 0 else True

When you know the element could not be there, the implicit wait could be a problem. I've created a simple context manager to avoid those waiting times

class PauseExplicitWait(object):
"""
Example usage:


with PauseExplicitWait(driver, 0):
driver.find_element(By.ID, 'element-that-might-not-be-there')
"""
def __init__(self, driver, new_wait=0):
self.driver = driver
self.original_wait = driver.timeouts.implicit_wait
self.new_wait = new_wait
      

def __enter__(self):
self.driver.implicitly_wait(self.new_wait)
  

def __exit__(self, exc_type, exc_value, exc_tb):
self.driver.implicitly_wait(self.original_wait)
  

You can check by find_elements. If the result is null, that element does not exist.

if driver.find_elements(By.SOMETHING, "#someselector") == []:
continue   # That element does not exist

With the latest Selenium, you can now use you can now use .is_displayed():

https://www.selenium.dev/documentation/webdriver/elements/information/

A) Use .is_displayed() as explained at Information about web elements:

# After navigating to the URL,
# get the Boolean value for if this element is displayed
is_button_visible = driver.find_element(By.CSS_SELECTOR, "[name='login']").is_displayed()

Continue your Visual Studio Code logic using "is_button_visible" for branching.

B) Refer to Sam Woods's answer

el = WebDriverWait(driver, timeout=3).until(lambda d: d.find_element(By.TAG_NAME,"p"))

doc