通过ID找不到元素


我知道因为这段代码而报错
self.driver.find_element(By.ID, 'memberAdd_biz_mail').send_keys(member.mail)
应该将代码修改为
·self.driver.find_element(By.NAME,‘biz_mail’).send_keys(member.mail)·

我的疑惑
我查看了网页代码上下文,发现这里的email的id是唯一的,所以我不能理解为什么这里不可以使用By.ID的方式进行定位。而必须使用By.NAME的方式定位

报错日志如下(多次run发现有两个报错内容):


C:\Users\takeu\PycharmProjects\selenium\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2022.1.1\plugins\python\helpers\pycharm\_jb_pytest_runner.py" --target test_contact_page.py::TestMemberAdd.test_add_member
Testing started at 19:27 ...
Launching pytest with arguments test_contact_page.py::TestMemberAdd::test_add_member --no-header --no-summary -q in C:\Users\takeu\PycharmProjects\selenium\wework\tests

============================= test session starts =============================
collecting ... collected 1 item

test_contact_page.py::TestMemberAdd::test_add_member FAILED              [100%]
test_contact_page.py:15 (TestMemberAdd.test_add_member)
self = <wework.tests.test_contact_page.TestMemberAdd object at 0x000001DD7BB9F7F0>

    def test_add_member(self):
        random = str(datetime.now().timestamp()).split('.')[0]
        member = Member()
        member.name = 'shanks'
        member.account = 'shanks'+random
        member.mail = 'shanks'
        member.phone = random+'0'
>       self.contact_page.add_member(member)

test_contact_page.py:23: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
..\page\contact_page.py:17: in add_member
    self.driver.find_element(By.NAME, 'username').send_keys(member.name)
..\..\venv\lib\site-packages\selenium\webdriver\remote\webdriver.py:856: in find_element
    return self.execute(Command.FIND_ELEMENT, {
..\..\venv\lib\site-packages\selenium\webdriver\remote\webdriver.py:434: in execute
    self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x000001DD7BBD3E50>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...jectPath [0x77947A9E+286]\\n\\tRtlGetAppContainerNamedObjectPath [0x77947A6E+238]\\n\\t(No symbol) [0x00000000]\\n"}}'}

    def check_response(self, response: Dict[str, Any]) -> None:
        """
        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 not status or status == ErrorCode.SUCCESS:
            return
        value = None
        message = response.get("message", "")
        screen: str = response.get("screen", "")
        stacktrace = None
        if isinstance(status, int):
            value_json = response.get('value', None)
            if value_json and isinstance(value_json, str):
                import json
                try:
                    value = json.loads(value_json)
                    if len(value.keys()) == 1:
                        value = value['value']
                    status = value.get('error', None)
                    if not status:
                        status = value.get("status", ErrorCode.UNKNOWN_ERROR)
                        message = value.get("value") or value.get("message")
                        if not isinstance(message, str):
                            value = message
                            message = message.get('message')
                    else:
                        message = value.get('message', None)
                except ValueError:
                    pass
    
        exception_class: Type[WebDriverException]
        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_SHADOW_ROOT:
            exception_class = NoSuchShadowRootException
        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 not value:
            value = response['value']
        if isinstance(value, str):
            raise exception_class(value)
        if message == "" and 'message' in value:
            message = value['message']
    
        screen = None  # type: ignore[assignment]
        if 'screen' in value:
            screen = value['screen']
    
        stacktrace = None
        st_value = value.get('stackTrace') or value.get('stacktrace')
        if st_value:
            if isinstance(st_value, str):
                stacktrace = st_value.split('\n')
            else:
                stacktrace = []
                try:
                    for frame in st_value:
                        line = frame.get("lineNumber", "")
                        file = frame.get("fileName", "<anonymous>")
                        if line:
                            file = f"{file}:{line}"
                        meth = frame.get('methodName', '<anonymous>')
                        if 'className' in frame:
                            meth = "{}.{}".format(frame['className'], meth)
                        msg = "    at %s (%s)"
                        msg = msg % (meth, file)
                        stacktrace.append(msg)
                except TypeError:
                    pass
        if exception_class == UnexpectedAlertPresentException:
            alert_text = None
            if 'data' in value:
                alert_text = value['data'].get('text')
            elif 'alert' in value:
                alert_text = value['alert'].get('text')
            raise exception_class(message, screen, stacktrace, alert_text)  # type: ignore[call-arg]  # mypy is not smart enough here
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[name="username"]"}
E         (Session info: chrome=104.0.5112.81)
E       Stacktrace:
E       Backtrace:
E       	Ordinal0 [0x002978B3+2193587]
E       	Ordinal0 [0x00230681+1771137]
E       	Ordinal0 [0x001441A8+803240]
E       	Ordinal0 [0x001724A0+992416]
E       	Ordinal0 [0x0017273B+993083]
E       	Ordinal0 [0x0019F7C2+1177538]
E       	Ordinal0 [0x0018D7F4+1103860]
E       	Ordinal0 [0x0019DAE2+1170146]
E       	Ordinal0 [0x0018D5C6+1103302]
E       	Ordinal0 [0x001677E0+948192]
E       	Ordinal0 [0x001686E6+952038]
E       	GetHandleVerifier [0x00540CB2+2738370]
E       	GetHandleVerifier [0x005321B8+2678216]
E       	GetHandleVerifier [0x003217AA+512954]
E       	GetHandleVerifier [0x00320856+509030]
E       	Ordinal0 [0x0023743B+1799227]
E       	Ordinal0 [0x0023BB68+1817448]
E       	Ordinal0 [0x0023BC55+1817685]
E       	Ordinal0 [0x00245230+1856048]
E       	BaseThreadInitThunk [0x7711FA29+25]
E       	RtlGetAppContainerNamedObjectPath [0x77947A9E+286]
E       	RtlGetAppContainerNamedObjectPath [0x77947A6E+238]
E       	(No symbol) [0x00000000]

..\..\venv\lib\site-packages\selenium\webdriver\remote\errorhandler.py:243: NoSuchElementException




============================== 1 failed in 1.95s ==============================

Process finished with exit code 1

这里是第二个日志





···
C:\Users\takeu\PycharmProjects\selenium\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2022.1.1\plugins\python\helpers\pycharm\_jb_pytest_runner.py" --target test_contact_page.py::TestMemberAdd.test_add_member
Testing started at 20:02 ...
Launching pytest with arguments test_contact_page.py::TestMemberAdd::test_add_member --no-header --no-summary -q in C:\Users\takeu\PycharmProjects\selenium\wework\tests

============================= test session starts =============================
collecting ... collected 1 item

test_contact_page.py::TestMemberAdd::test_add_member FAILED              [100%]
test_contact_page.py:15 (TestMemberAdd.test_add_member)
self = <wework.tests.test_contact_page.TestMemberAdd object at 0x00000147ABD1F8B0>

    def test_add_member(self):
        random = str(datetime.now().timestamp()).split('.')[0]
        member = Member()
        member.name = 'shanks'
        member.account = 'shanks'+random
        member.mail = 'shanks'
        member.phone = random+'0'
>       self.contact_page.add_member(member)

test_contact_page.py:23: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
..\page\contact_page.py:16: in add_member
    self.driver.find_element(By.LINK_TEXT, '添加成员').click()
..\..\venv\lib\site-packages\selenium\webdriver\remote\webelement.py:88: in click
    self._execute(Command.CLICK_ELEMENT)
..\..\venv\lib\site-packages\selenium\webdriver\remote\webelement.py:396: in _execute
    return self._parent.execute(command, params)
..\..\venv\lib\site-packages\selenium\webdriver\remote\webdriver.py:434: in execute
    self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x00000147ABD50460>
response = {'status': 404, 'value': '{"value":{"error":"stale element reference","message":"stale element reference: element is n...jectPath [0x77947A9E+286]\\n\\tRtlGetAppContainerNamedObjectPath [0x77947A6E+238]\\n\\t(No symbol) [0x00000000]\\n"}}'}

    def check_response(self, response: Dict[str, Any]) -> None:
        """
        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 not status or status == ErrorCode.SUCCESS:
            return
        value = None
        message = response.get("message", "")
        screen: str = response.get("screen", "")
        stacktrace = None
        if isinstance(status, int):
            value_json = response.get('value', None)
            if value_json and isinstance(value_json, str):
                import json
                try:
                    value = json.loads(value_json)
                    if len(value.keys()) == 1:
                        value = value['value']
                    status = value.get('error', None)
                    if not status:
                        status = value.get("status", ErrorCode.UNKNOWN_ERROR)
                        message = value.get("value") or value.get("message")
                        if not isinstance(message, str):
                            value = message
                            message = message.get('message')
                    else:
                        message = value.get('message', None)
                except ValueError:
                    pass
    
        exception_class: Type[WebDriverException]
        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_SHADOW_ROOT:
            exception_class = NoSuchShadowRootException
        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 not value:
            value = response['value']
        if isinstance(value, str):
            raise exception_class(value)
        if message == "" and 'message' in value:
            message = value['message']
    
        screen = None  # type: ignore[assignment]
        if 'screen' in value:
            screen = value['screen']
    
        stacktrace = None
        st_value = value.get('stackTrace') or value.get('stacktrace')
        if st_value:
            if isinstance(st_value, str):
                stacktrace = st_value.split('\n')
            else:
                stacktrace = []
                try:
                    for frame in st_value:
                        line = frame.get("lineNumber", "")
                        file = frame.get("fileName", "<anonymous>")
                        if line:
                            file = f"{file}:{line}"
                        meth = frame.get('methodName', '<anonymous>')
                        if 'className' in frame:
                            meth = "{}.{}".format(frame['className'], meth)
                        msg = "    at %s (%s)"
                        msg = msg % (meth, file)
                        stacktrace.append(msg)
                except TypeError:
                    pass
        if exception_class == UnexpectedAlertPresentException:
            alert_text = None
            if 'data' in value:
                alert_text = value['data'].get('text')
            elif 'alert' in value:
                alert_text = value['alert'].get('text')
            raise exception_class(message, screen, stacktrace, alert_text)  # type: ignore[call-arg]  # mypy is not smart enough here
>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
E         (Session info: chrome=104.0.5112.81)
E       Stacktrace:
E       Backtrace:
E       	Ordinal0 [0x002978B3+2193587]
E       	Ordinal0 [0x00230681+1771137]
E       	Ordinal0 [0x001441A8+803240]
E       	Ordinal0 [0x00146BB4+814004]
E       	Ordinal0 [0x00146A72+813682]
E       	Ordinal0 [0x00146D00+814336]
E       	Ordinal0 [0x00173F19+999193]
E       	Ordinal0 [0x00169146+954694]
E       	Ordinal0 [0x0018D7AC+1103788]
E       	Ordinal0 [0x00168C04+953348]
E       	Ordinal0 [0x0018D9C4+1104324]
E       	Ordinal0 [0x0019DAE2+1170146]
E       	Ordinal0 [0x0018D5C6+1103302]
E       	Ordinal0 [0x001677E0+948192]
E       	Ordinal0 [0x001686E6+952038]
E       	GetHandleVerifier [0x00540CB2+2738370]
E       	GetHandleVerifier [0x005321B8+2678216]
E       	GetHandleVerifier [0x003217AA+512954]
E       	GetHandleVerifier [0x00320856+509030]
E       	Ordinal0 [0x0023743B+1799227]
E       	Ordinal0 [0x0023BB68+1817448]
E       	Ordinal0 [0x0023BC55+1817685]
E       	Ordinal0 [0x00245230+1856048]
E       	BaseThreadInitThunk [0x7711FA29+25]
E       	RtlGetAppContainerNamedObjectPath [0x77947A9E+286]
E       	RtlGetAppContainerNamedObjectPath [0x77947A6E+238]
E       	(No symbol) [0x00000000]

..\..\venv\lib\site-packages\selenium\webdriver\remote\errorhandler.py:243: StaleElementReferenceException




============================== 1 failed in 3.25s ==============================

Process finished with exit code 1




···

你的错误在这,应该是找到了,但是在后面的页面变化中又变动了, 导致原来定位到的控件不存在了。我觉得你加个显式等待可能就可以支持id定位了。