WebDriverException: Message: The command 'GET

2019-01-19 12:15发布

问题:

I am using explicit wait like below to check if element is clickable.

WebDriverWait(driver, 30).until(
        expected_conditions.element_to_be_clickable((By.CSS_SELECTOR, "#search")))

But I get error

 <class 'selenium.common.exceptions.WebDriverException'>
Message: The command 'GET /session/.../displayed' was not found.

If I use time.sleep() it works fine instead of explicir wait it works fine. I have initialized safari driver as

from selenium.webdriver import Safari
driver = Safari()

Here is stacktrace

  File "/Users/Library/Python/2.7/lib/python/site-packages/selenium/webdriver/support/wait.py", line 71, in until
    value = method(self._driver)
  File "/Users/Library/Python/2.7/lib/python/site-packages/selenium/webdriver/support/expected_conditions.py", line 283, in __call__
    element = visibility_of_element_located(self.locator)(driver)
  File "/Users/Library/Python/2.7/lib/python/site-packages/selenium/webdriver/support/expected_conditions.py", line 127, in __call__
    return _element_if_visible(_find_element(driver, self.locator))
  File "/Users/Library/Python/2.7/lib/python/site-packages/selenium/webdriver/support/expected_conditions.py", line 147, in _element_if_visible
    return element if element.is_displayed() == visibility else False
  File "/Users/Library/Python/2.7/lib/python/site-packages/selenium/webdriver/remote/webelement.py", line 490, in is_displayed
    return self._execute(Command.IS_ELEMENT_DISPLAYED)['value']
  File "/Users/Library/Python/2.7/lib/python/site-packages/selenium/webdriver/remote/webelement.py", line 628, in _execute
    return self._parent.execute(command, params)
  File "/Users/Library/Python/2.7/lib/python/site-packages/selenium/webdriver/remote/webdriver.py", line 314, in execute
    self.error_handler.check_response(response)
  File "/Users/Library/Python/2.7/lib/python/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
WebDriverException: Message: The command 'GET /session/7.../displayed' was not found.

回答1:

This error message...

 <class 'selenium.common.exceptions.WebDriverException'>
Message: The command 'GET /session/.../displayed' was not found.

...implies that the GET request to /session/{session id}/element/{element id}/displayed failed.


element displayed

As per the WebDriver W3C Editor's Draft the element displayed algorithm is a boolean state where true signifies that the element is displayed and false signifies that the element is not displayed. To compute the state on element, invoke the Call(bot.dom.isShown, null, element). If doing so does not produce an error, return the return value from this function call. Otherwise return an error with error code unknown error.

This function is typically exposed to GET requests with a URI Template of

/session/{session id}/element/{element id}/displayed

Analysis

You have invoked:

WebDriverWait(driver, 30).until(expected_conditions.element_to_be_clickable((By.CSS_SELECTOR, "#search")))

element_to_be_clickable() class internally invokes visibility_of_element_located() and is defined as:

class element_to_be_clickable(object):
    """ An Expectation for checking an element is visible and enabled such that you can click it."""
    def __init__(self, locator):
    self.locator = locator

    def __call__(self, driver):
    element = visibility_of_element_located(self.locator)(driver)
    if element and element.is_enabled():
        return element
    else:
        return False

Now, visibility_of_element_located() class returns _element_if_visible(_find_element(driver, self.locator)) which is defined as:

class visibility_of_element_located(object):
    """ An expectation for checking that an element is present on the DOM of a
    page and visible. Visibility means that the element is not only displayed
    but also has a height and width that is greater than 0.
    locator - used to find the element
    returns the WebElement once it is located and visible
    """
    def __init__(self, locator):
    self.locator = locator

    def __call__(self, driver):
    try:
        return _element_if_visible(_find_element(driver, self.locator))
    except StaleElementReferenceException:
        return False

Again, _element_if_visible() returns element if element.is_displayed() == visibility else False which is defined as:

def _element_if_visible(element, visibility=True):
    return element if element.is_displayed() == visibility else False

So, as the if() condition of element.is_displayed() == visibility failed hence you see the error as GET request to the /session/{session id}/element/{element id}/displayed endpoint failed.

Without the relevant HTML and previous steps it is tough to guess the exact reason but possibly can be either of the following:


Reason

The reason for NoSuchElementException can be either of the following :

  • The Locator Strategy you have adopted doesn't identifies any element in the HTML DOM.
  • The Locator Strategy you have adopted is unable to identify the element as it is not within the browser's Viewport.
  • The Locator Strategy you have adopted identifies the element but is invisible due to presence of the attribute style="display: none;".
  • The Locator Strategy you have adopted doesn't uniquely identifies the desired element in the HTML DOM and currently finds some other hidden / invisible element.
  • The WebElement you are trying to locate is within an <iframe> tag.

Solution

The solution to address NoSuchElementException can be either of the following :

  • Adopt a Locator Strategy which uniquely identifies the desired WebElement. You can take help of the Developer Tools (Ctrl+Shift+I or F12) and use Element Inspector.

    Here you will find a detailed discussion on how to inspect element in selenium3.6 as firebug is not an option any more for FF 56?

  • Use execute_script() method to scroll the element in to view as follows :

    elem = driver.find_element_by_xpath("element_xpath")
    driver.execute_script("arguments[0].scrollIntoView();", elem)
    

    Here you will find a detailed discussion on Scrolling to top of the page in Python using Selenium

  • Incase element is having the attribute style="display: none;", remove the attribute through executeScript() method as follows :

    elem = driver.find_element_by_xpath("element_xpath")
    driver.execute_script("arguments[0].removeAttribute('style')", elem)
    elem.send_keys("text_to_send")
    
  • To check if the element is within an <iframe> traverse up the HTML to locate the respective <iframe> tag and switchTo() the desired iframe through either of the following methods :

    driver.switch_to.frame("iframe_name")
    driver.switch_to.frame("iframe_id")
    driver.switch_to.frame(1) // 1 represents frame index
    

    Here you can find a detailed discussion on How can I select a html element no matter what frame it is in in selenium?.