There is error “Invalid locator values passed in” in case we use find_element instead of find_element_by

前端 未结 2 1381
花落未央
花落未央 2020-12-11 23:49

I\'m using Python-Webdriver to automate a \"click\" action. Here is my code:

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


        
相关标签:
2条回答
  • 2020-12-12 00:25

    According to the documentation, you can use either find_element_by_* shortcuts, or find_element() and find_elements() "private" methods directly:

    Apart from the public methods given above, there are two private methods which might be useful with locators in page objects. These are the two private methods: find_element and find_elements.

    Example usage:

    from selenium.webdriver.common.by import By
    
    driver.find_element(By.XPATH, '//button[text()="Some text"]')
    driver.find_elements(By.XPATH, '//button')
    

    But, in your case, instead of passing 2 parameters to find_element(), you are passing a single one - a tuple NEWS_OPTION. You just need to unpack the tuple into positional arguments:

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

    Or, just as an alternative, you could use keyword arguments also:

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

    And, also, whenever you have any doubts how things should work, just dig up the source code and clarify it for yourself. In this case, see how find_element_by_id() method is 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_)
    
    0 讨论(0)
  • 2020-12-12 00:40

    According to the api doc private method find_elements and find_element takes two parameters each and you are passing one which is obviously wrong.

    And,

    myDynamicElement = driver.find_element(NEWS_OPTION)

    and

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

    are NOT same. driver.find_element_by_id takes one parameter and thus this work and find_element takes two so that fails.

    So, literally you should be using

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

    EDIT

    NEWS_OPTION = (By.ID, 'blq-nav-news') will return you ('id', 'blq-nav-news') whereas find_element() expects the first parameter to be the implementation of By class mechanism to locate the element not simply a string.

    A direct call of NEWS_OPTION = (By.ID, 'blq-nav-news') has returned me a tuple and the attribute of By.ID which is 'id' A simple print out of NEWS_OPTION = (By.ID, 'blq-nav-news') provided me

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

    And, here is the source of By class

    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
    
    0 讨论(0)
提交回复
热议问题