Python-Selenium查找无法单击的可单击元素

时间:2018-08-14 12:49:55

标签: python selenium

我正在使用python-selenium来运行自动化测试。在复杂的非公开环境中,这些测试正在运行中,我发现了一些我将其标记为硒中的错误的东西。

基本上,我想做的是在DOM中变得可单击时在其中找到一些元素,然后单击它。代码如下:

....
what = (By.XPATH, '//button/span[contains(text(), "Load")]')
element = WebDriverWait(bspdriver.webdriver, 60).\
                until(EC.element_to_be_clickable(what))
element.click()
....

但是,click方法几乎立即失败,并显示以下错误消息:

ElementClickInterceptedException: Message: Element <button class="ivu-btn ivu-btn-primary ivu-btn-long ivu-btn-small" type="button"> is not clickable at point (1193.3332901000977,522) because another element <div class="ivu-modal-wrap vertical-center-modal circuit-loading-modal"> obscures it

我虽然正在等待该元素 可点击 !我假设EC.element_to_be_clickable就是这个意思。但事实并非如此。那是硒中的错误吗?

解决方法是以下代码:

    mustend = time.time() + 60
    while time.time() < mustend:
        try:
            WebDriverWait(bspdriver.webdriver, 60).\
                until(EC.element_to_be_clickable(what)).click()
            break
        except (TimeoutException, NoSuchElementException,
                StaleElementReferenceException,
                ElementClickInterceptedException) as e:
            time.sleep(1.0)

这对我来说不太好。有没有办法改善代码?硒中有虫子吗?如果是这样,我可以举报...

使用过的软件包:

  • 硒3.8.0和3.11.0
  • geckodriver 0.19.1
  • python 2.7.12
  • py.test 3.6.1

完整错误消息:

....
>       element.click()
selenium/test_pair_recording.py:66: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../venvs/linux_selenium/local/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py:80: in click
    self._execute(Command.CLICK_ELEMENT)
../venvs/linux_selenium/local/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py:501: in _execute
    return self._parent.execute(command, params)
../venvs/linux_selenium/local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py:311: in execute
    self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7fe69694fd90>
response = {'status': 400, 'value': '{"value":{"error":"element click intercepted","message":"Element <button class=\"ivu-btn ivu...gate@chrome://marionette/content/listener.js:414:13\nclickElement@chrome://marionette/content/listener.js:1220:5\n"}}'}

    def check_response(self, response):
        """
            Checks that a JSON response from the WebDriver does not have an error.

            :Args:
             - response - The JSON response from the WebDriver server as a dictionary
               object.

            :Raises: If the response contains an error message.
            """
        status = response.get('status', None)
        if status is None or status == ErrorCode.SUCCESS:
            return
        value = None
        message = response.get("message", "")
        screen = response.get("screen", "")
        stacktrace = None
        if isinstance(status, int):
            value_json = response.get('value', None)
            if value_json and isinstance(value_json, basestring):
                import json
                try:
                    value = json.loads(value_json)
                    if len(value.keys()) == 1:
                        value = value['value']
                    status = value.get('error', None)
                    if status is None:
                        status = value["status"]
                        message = value["value"]
                        if not isinstance(message, basestring):
                            value = message
                            message = message.get('message')
                    else:
                        message = value.get('message', None)
                except ValueError:
                    pass

        exception_class = ErrorInResponseException
        if status in ErrorCode.NO_SUCH_ELEMENT:
            exception_class = NoSuchElementException
        elif status in ErrorCode.NO_SUCH_FRAME:
            exception_class = NoSuchFrameException
        elif status in ErrorCode.NO_SUCH_WINDOW:
            exception_class = NoSuchWindowException
        elif status in ErrorCode.STALE_ELEMENT_REFERENCE:
            exception_class = StaleElementReferenceException
        elif status in ErrorCode.ELEMENT_NOT_VISIBLE:
            exception_class = ElementNotVisibleException
        elif status in ErrorCode.INVALID_ELEMENT_STATE:
            exception_class = InvalidElementStateException
        elif status in ErrorCode.INVALID_SELECTOR \
                or status in ErrorCode.INVALID_XPATH_SELECTOR \
                or status in ErrorCode.INVALID_XPATH_SELECTOR_RETURN_TYPER:
            exception_class = InvalidSelectorException
        elif status in ErrorCode.ELEMENT_IS_NOT_SELECTABLE:
            exception_class = ElementNotSelectableException
        elif status in ErrorCode.ELEMENT_NOT_INTERACTABLE:
            exception_class = ElementNotInteractableException
        elif status in ErrorCode.INVALID_COOKIE_DOMAIN:
            exception_class = InvalidCookieDomainException
        elif status in ErrorCode.UNABLE_TO_SET_COOKIE:
            exception_class = UnableToSetCookieException
        elif status in ErrorCode.TIMEOUT:
            exception_class = TimeoutException
        elif status in ErrorCode.SCRIPT_TIMEOUT:
            exception_class = TimeoutException
        elif status in ErrorCode.UNKNOWN_ERROR:
            exception_class = WebDriverException
        elif status in ErrorCode.UNEXPECTED_ALERT_OPEN:
            exception_class = UnexpectedAlertPresentException
        elif status in ErrorCode.NO_ALERT_OPEN:
            exception_class = NoAlertPresentException
        elif status in ErrorCode.IME_NOT_AVAILABLE:
            exception_class = ImeNotAvailableException
        elif status in ErrorCode.IME_ENGINE_ACTIVATION_FAILED:
            exception_class = ImeActivationFailedException
        elif status in ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS:
            exception_class = MoveTargetOutOfBoundsException
        elif status in ErrorCode.JAVASCRIPT_ERROR:
            exception_class = JavascriptException
        elif status in ErrorCode.SESSION_NOT_CREATED:
            exception_class = SessionNotCreatedException
        elif status in ErrorCode.INVALID_ARGUMENT:
            exception_class = InvalidArgumentException
        elif status in ErrorCode.NO_SUCH_COOKIE:
            exception_class = NoSuchCookieException
        elif status in ErrorCode.UNABLE_TO_CAPTURE_SCREEN:
            exception_class = ScreenshotException
        elif status in ErrorCode.ELEMENT_CLICK_INTERCEPTED:
            exception_class = ElementClickInterceptedException
        elif status in ErrorCode.INSECURE_CERTIFICATE:
            exception_class = InsecureCertificateException
        elif status in ErrorCode.INVALID_COORDINATES:
            exception_class = InvalidCoordinatesException
        elif status in ErrorCode.INVALID_SESSION_ID:
            exception_class = InvalidSessionIdException
        elif status in ErrorCode.UNKNOWN_METHOD:
            exception_class = UnknownMethodException
        else:
            exception_class = WebDriverException
        if value == '' or value is None:
            value = response['value']
        if isinstance(value, basestring):
            if exception_class == ErrorInResponseException:
                raise exception_class(response, value)
            raise exception_class(value)
        if message == "" and 'message' in value:
            message = value['message']

        screen = None
        if 'screen' in value:
            screen = value['screen']

        stacktrace = None
        if 'stackTrace' in value and value['stackTrace']:
            stacktrace = []
            try:
                for frame in value['stackTrace']:
                    line = self._value_or_default(frame, 'lineNumber', '')
                    file = self._value_or_default(frame, 'fileName', '<anonymous>')
                    if line:
                        file = "%s:%s" % (file, line)
                    meth = self._value_or_default(frame, 'methodName', '<anonymous>')
                    if 'className' in frame:
                        meth = "%s.%s" % (frame['className'], meth)
                    msg = "    at %s (%s)"
                    msg = msg % (meth, file)
                    stacktrace.append(msg)
            except TypeError:
                pass
        if exception_class == ErrorInResponseException:
            raise exception_class(response, message)
        elif exception_class == UnexpectedAlertPresentException and 'alert' in value:
            raise exception_class(message, screen, stacktrace, value['alert'].get('text'))
>       raise exception_class(message, screen, stacktrace)
E       ElementClickInterceptedException: Message: Element <button class="ivu-btn ivu-btn-primary ivu-btn-long ivu-btn-small" type="button"> is not clickable at point (1193.3332901000977,522) because another element <div class="ivu-modal-wrap vertical-center-modal circuit-loading-modal"> obscures it

../venvs/linux_selenium/local/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py:237: ElementClickInterceptedException

1 个答案:

答案 0 :(得分:3)

由于ElementToBeClickable正在等待元素被启用而失败的原因,它并不是在真正检查元素是否可点击,而是假设元素被启用时假设元素是可点击的,实际上是正确的,但是在这里失败了,因为即使另一个元素叠加在所需元素上,元素也会启用。

所以请编写此代码以使覆盖消失

WebDriverWait(bspdriver.webdriver,10).until(EC.invisibility_of_element_located((By.XPATH, "//div[@class='ivu-modal-wrap vertical-center-modal circuit-loading-modal']")));

然后您编写代码

what = (By.XPATH, '//button/span[contains(text(), "Load")]')
element = WebDriverWait(bspdriver.webdriver, 60).\
                until(EC.element_to_be_clickable(what))
element.click()

如果覆盖层是临时的,则上述解决方案将起作用;如果覆盖层是永久的,则执行Javascript单击,因为WebDriver内部检查将阻止您进行单击。