有错误"传入的无效定位器值"以防我们使用find_element而不是find_element_by

时间:2015-02-21 04:38:16

标签: python selenium-webdriver

我正在使用Python-Webdriver自动执行“点击”操作。这是我的代码:

from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.common.exceptions import InvalidSelectorException


LOGIN_BUTTON = (By.XPATH, '//a[contains(@class,"aui-nav-link login-link")]')
NEWS_OPTION = (By.ID, 'blq-nav-news')

driver = webdriver.Chrome()
driver.implicitly_wait(30)
driver.get("http://bbc.co.uk/")
myDynamicElement = driver.find_element(NEWS_OPTION)
myDynamicElement.click()

控制台会生成如下例外

    raise InvalidSelectorException("Invalid locator values passed in")
selenium.common.exceptions.InvalidSelectorException: Message: Invalid locator values passed in

但是,如果我改变了行

  

“myDynamicElement = driver.find_element(NEWS_OPTION)”

  

“myDynamicElement = driver.find_element_by_id('blq-nav-news')”

,没有异常,脚本按预期工作。

我找出根本原因是我们不使用

  

find_element_by _ *

。所以我想知道这是Python-Webdriver的限制?我是否有解决方案来修复我的问题而不像我一样改变我的代码。

2 个答案:

答案 0 :(得分:3)

根据documentation,您可以使用find_element_by_*个快捷方式,find_element()find_elements()"私有"方法直接:

  

除了上面给出的公共方法外,还有两个私人方法   可能对页面对象中的定位器有用的方法。这些是   两个私有方法:find_element和find_elements。

     

使用示例:

from selenium.webdriver.common.by import By

driver.find_element(By.XPATH, '//button[text()="Some text"]')
driver.find_elements(By.XPATH, '//button')

但是,在您的情况下,不是将2个参数传递给find_element(),而是传递一个参数 - tuple NEWS_OPTION。你只需要将元组解压缩为位置参数:

NEWS_OPTION = (By.ID, 'blq-nav-news')
myDynamicElement = driver.find_element(*NEWS_OPTION)

或者,作为替代方案,您也可以使用关键字参数:

NEWS_OPTION = {'by': By.ID, 'value': 'blq-nav-news'}
myDynamicElement = driver.find_element(**NEWS_OPTION)

而且,每当你对事情应该如何运作有任何疑问时,只需挖掘源代码并为自己澄清。在这种情况下,请参阅find_element_by_id()方法的actually implemented

def find_element_by_id(self, id_):
    """Finds an element by id.

    :Args:
     - id\_ - The id of the element to be found.

    :Usage:
        driver.find_element_by_id('foo')
    """
    return self.find_element(by=By.ID, value=id_)

答案 1 :(得分:1)

根据api doc隐私方法find_elementsfind_element每个方法需要两个parameters,而您传递的方法显然是错误的。

  

myDynamicElement = driver.find_element(NEWS_OPTION)

  

myDynamicElement = driver.find_element_by_id(' blq-nav-news')

不一样。 driver.find_element_by_id需要一个参数,因此这项工作和find_element需要两个参数才能失败。

所以,字面意思是你应该使用

myDynamicElement = driver.find_element(By.ID,'blq-nav-news')

修改

NEWS_OPTION = (By.ID, 'blq-nav-news')将返回('id', 'blq-nav-news'),而find_element()期望第一个参数是By类机制的实现,以便不仅仅是字符串来定位元素。

NEWS_OPTION = (By.ID, 'blq-nav-news')的直接致电已向我返回tupleBy.ID的属性为'id' NEWS_OPTION = (By.ID, 'blq-nav-news')的简单打印为我提供了

  

('id', 'blq-nav-news')

而且,这是By

的来源
class By(object):
    """
    Set of supported locator strategies.
    """

    ID = "id"
    XPATH = "xpath"
    LINK_TEXT = "link text"
    PARTIAL_LINK_TEXT = "partial link text"
    NAME = "name"
    TAG_NAME = "tag name"
    CLASS_NAME = "class name"
    CSS_SELECTOR = "css selector"

    @classmethod
    def is_valid(cls, by):
        for attr in dir(cls):
            if by == getattr(cls, attr):
                return True
        return False