简体   繁体   English

检查元素是否存在 Python Selenium

[英]Checking if an element exists with Python Selenium

I have a problem;我有个问题; I am using the Selenium (Firefox) web driver to open a webpage, click a few links, etc., and then capture a screenshot.我是用Selenium(Firefox)web驱动打开一个网页,点击几个链接等,然后截图。

My script runs fine from the CLI, but when run via a cron job it is not getting past the first find_element() test.我的脚本在 CLI 中运行良好,但是当通过cron 作业运行时,它没有通过第一个 find_element() 测试。 I need to add some debug, or something to help me figure out why it is failing.我需要添加一些调试,或帮助我找出失败原因的东西。

Basically, I have to click a 'log in' anchor before going to the login page.基本上,在进入登录页面之前,我必须单击“登录”锚点。 The construct of the element is:元素的构造是:

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

I am using the find_element By LINK_TEXT method:我正在使用find_element By LINK_TEXT 方法:

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

A) How do I check that the link is actually being picked up by Python? A) 我如何检查链接是否真的被 Python 拾取了? Should I use try/catch block?我应该使用 try/catch 块吗?

B) Is there a better/more reliable way to locate the DOM element than by LINK_TEXT? B) 是否有比 LINK_TEXT 更好/更可靠的定位DOM元素的方法? Eg, in jQuery , you can use a more specific selector, $('a.lnk:contains(log in)').do_something();例如,在jQuery中,您可以使用更具体的选择器 $('a.lnk:contains(log in)').do_something();


I have solved the main problem and it was just finger trouble.我已经解决了主要问题,这只是手指的麻烦。 I was calling the script with incorrect parameters - a simple mistake.我用不正确的参数调用脚本 - 一个简单的错误。

I'd still like some pointers on how to check whether an element exists.我仍然想要一些关于如何检查元素是否存在的指示。 Also, an example/explanation of implicit / explicit Waits instead of using a crappy time.sleep() call.此外,还有一个隐式/显式等待的示例/解释,而不是使用糟糕的 time.sleep() 调用。

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

b) use xpath - the most reliable. b) 使用 xpath - 最可靠的。 Moreover you can take the xpath as a standard throughout all your scripts and create functions as above mentions for universal use.此外,您可以将 xpath 作为所有脚本的标准,并创建如上所述的通用函数。

UPDATE : I wrote the initial answer over 4 years ago and at the time I thought xpath would be the best option.更新:我在 4 年前写了最初的答案,当时我认为 xpath 是最好的选择。 Now I recommend to use css selectors .现在我建议使用css selectors I still recommend not to mix/use "by id", "by name" and etc and use one single approach instead.我仍然建议不要混合/使用“按 id”、“按名称”等,而是使用一种方法。

None of the solutions provided seemed at all easiest to me, so I'd like to add my own way.提供的解决方案对我来说似乎都不是最简单的,所以我想添加我自己的方式。

Basically, you get the list of the elements instead of just the element and then count the results;基本上,您获得元素列表,而不仅仅是元素,然后计算结果; if it's zero, then it doesn't exist.如果它为零,则它不存在。 Example:例子:

if driver.find_elements_by_css_selector('#element'):
    print "Element exists"

Notice the "s" in find_elements_by_css_selector to make sure it can be countable.注意find_elements_by_css_selector的“s”以确保它是可数的。

EDIT : I was checking the len( of the list, but I recently learned that an empty list is falsey, so you don't need to get the length of the list at all, leaving for even simpler code.编辑:我正在检查列表的len( ,但我最近了解到空列表是错误的,因此您根本不需要获取列表的长度,而是使用更简单的代码。

Also, another answer says that using xpath is more reliable, which is just not true.另外,另一个答案说使用 xpath 更可靠,但事实并非如此。 See What is the difference between css-selector & Xpath?请参阅css-selector 和 Xpath 有什么区别? which is better(according to performance & for cross browser testing)? 哪个更好(根据性能和跨浏览器测试)?

A) Yes. A) 是的。 The easiest way to check if an element exists is to simply call find_element inside a try/catch .检查元素是否存在的最简单方法是在try/catch简单地调用find_element

B) Yes, I always try to identify elements without using their text for 2 reasons: B) 是的,我总是尝试在不使用文本的情况下识别元素,原因有两个:

  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.如果这对您很重要,您将无法针对本地化构建运行测试。

solution 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 it's child/descendant that matches or;您可以使用 xpath 查找具有 ID 或其他唯一标识符的父元素或祖先元素,然后找到匹配的子元素/后代元素或;
  2. you could request an ID or name or some other unique identifier for the link itself.您可以为链接本身请求 ID 或名称或其他一些唯一标识符。

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对于后续问题,使用try/catch可以判断元素是否存在,并且可以在此处找到等待的好示例: http : //seleniumhq.org/docs/04_webdriver_advanced.html

Solution without try&catch and without new imports:没有 try&catch 和没有新导入的解决方案:

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

The same as Brian, but add to this answer from tstempko:与布赖恩相同,但从 tstempko 添加到这个答案:

https://sqa.stackexchange.com/questions/3481/quicker-way-to-assert-that-an-element-does-not-exist https://sqa.stackexchange.com/questions/3481/quicker-way-to-assert-that-an-element-does-not-exist

So 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)

你也可以更简洁地使用

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

driver.find_element_by_id("some_id").size() is class method. driver.find_element_by_id("some_id").size()是类方法。

What we need is :我们需要的是:

driver.find_element_by_id("some_id").size which is dictionary so : driver.find_element_by_id("some_id").size是字典所以:

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

With the latest Selenium, you can now use you can now use .is_displayed() :使用最新的 Selenium,您现在可以使用您现在可以使用.is_displayed()

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

you could use is_displayed() like below你可以像下面这样使用 is_displayed()

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

如果数组的长度等于 0 元素不存在,您可以通过可用的方法查找元素并检查响应数组长度。

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 is not exist您可以通过 find_elements 检查,如果结果为空,则该元素不存在

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

A) Use .is_displayed() as explained at A)使用.is_displayed()如解释

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

# After navigating to the url
# Get boolean value for is element display
is_button_visible = driver.find_element(By.CSS_SELECTOR, "[name='login']").is_displayed()

continue your Code logic using "is_button_visible" for branching.使用“is_button_visible”继续您的代码逻辑进行分支。

B) refer to @Sam Woods's accepted answer B)参考@Sam Woods 接受的答案

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

doc文件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM