Python - Selenium WebDriver - 检查元素存在

non*_*ter 55 html python selenium webdriver

我有一个问题 - 我使用selenium(firefox)网络驱动程序打开网页,点击几个链接等然后捕获截图.

我的脚本在CLI中运行良好,但是当通过cronjob运行时,它没有超过第一个find_element()测试.我需要添加一些调试,或者某些东西来帮助我找出它失败的原因.

基本上,我必须在进入登录页面之前单击"登录"锚点.元素的构造是:

<a class="lnk" rel="nofollow" href="/login.jsp?destination=/secure/Dash.jspa">log in</a>
Run Code Online (Sandbox Code Playgroud)

我正在使用find_element By LINK_TEXT方法:

login = driver.find_element(By.LINK_TEXT, "log in").click()
Run Code Online (Sandbox Code Playgroud)

我有点像Python Noob,所以我正在与语言作斗争......

A)如何检查链接是否实际被python拾取?我应该使用try/catch块吗?

B)是否有比LINK_TEXT更好/更可靠的方法来定位DOM元素?例如,在JQuery中,您可以使用更具体的选择器$('a.lnk:contains(登录)').do_something();


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

我仍然喜欢一些关于如何检查元素是否存在的指针.另外,隐式/显式Waits的示例/解释而不是使用糟糕的time.sleep()调用.

干杯,ns

Ale*_*hko 80

一个)

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
Run Code Online (Sandbox Code Playgroud)

b)使用xpath - 最可靠的.此外,您可以在所有脚本中将xpath作为标准,并创建上述功能,以便通用.

更新:我写了4年前的初步答案,当时我认为xpath是最好的选择.现在我建议使用css选择器.我仍然建议不要混合/使用"by id","by name"等,而是使用一种方法代替.


Sam*_*ods 50

A)是的.要检查元素是否存在,最简单的方法就是简单地调用find_element里面try/catch.

B)是的,我总是尝试在不使用文本的情况下识别元素,原因有两个:

  1. 文本更有可能改变;
  2. 如果它对您很重要,您将无法针对本地化版本运行测试.

解决方案:

  1. 您可以使用xpath查找具有ID或其他唯一标识符的父元素或祖先元素,然后找到匹配或的子元素/子元素;
  2. 您可以为链接本身请求ID或名称或其他唯一标识符.

对于后续问题,使用try/catch是如何判断元素是否存在,并且可以在此处找到良好的等待示例:http://seleniumhq.org/docs/04_webdriver_advanced.html


Bri*_*ica 46

提供的解决方案对我来说似乎都不是最简单的,所以我想添加自己的方式.

基本上,您获取元素列表而不仅仅是元素,然后计算结果; 如果它为零,则它不存在.例:

if driver.find_elements_by_css_selector('#element'):
    print "Element exists"
Run Code Online (Sandbox Code Playgroud)

注意"s" find_elements_by_css_selector以确保它可以计数.

编辑:我正在检查len(列表,但我最近了解到一个空列表是假的,所以你根本不需要得到列表的长度,留下更简单的代码.

另外,另一个答案说使用xpath更可靠,这是不正确的.看看css-selector和Xpath有什么区别?哪个更好(根据性能和跨浏览器测试)?

  • 当未找到元素时,find-element(单数)形式会引发异常。find-elements(复数形式带有“s”)将返回一个空列表。以我的拙见,所有其他使用 try-catch 来查看元素是否存在的示例都是糟糕的编程风格。Try-catch 只应用于捕获意外情况。如果您认为该元素可能不存在,则应该编写代码来处理这种情况。 (9认同)
  • 这比上面的Exceptions处理方法快吗? (2认同)
  • @GalBracha好问题,我假设它可能取决于版本和平台,所以如果速度差异对您来说很重要,我建议您在目标平台上测试它以获得最佳效果.但是,这里有一个关于预优化的要点,代码可读性可能比在这种情况下可忽略的性能改进更重要 (2认同)

Sup*_*rio 17

没有 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
Run Code Online (Sandbox Code Playgroud)

  • 很好的解决方案,但我同意布赖恩关于“你找到了两次”的看法。 (3认同)
  • 你发现它两次,存储集合肯定会更有效,如果它是真的,点击第一个,例如`e = driver.find_elements_by_id('blah') if e: e[0].click` (2认同)
  • @BrianLeishman我同意你的方式,它更有效,但我认为我的方式更容易阅读和理解 (2认同)
  • 从[评论](/sf/ask/2100161941/#comment128785684_30025430):*“`find_element_by_*`和`find_elements_by_*`被删除在 Selenium 4.3.0 中。使用 `find_element` 代替。"*。 (2认同)

小智 8

与布赖恩相同,但从 tstempko 添加到这个答案:

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

所以我试了一下,效果很快:

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()
Run Code Online (Sandbox Code Playgroud)

在此之后我恢复了我的默认值

driver.implicitly_wait(30)
Run Code Online (Sandbox Code Playgroud)


cod*_*ord 6

您还可以使用更简洁地做到这一点

driver.find_element_by_id("some_id").size != 0
Run Code Online (Sandbox Code Playgroud)