You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Selenium中visibility_of_element_located与element_to_be_clickable的选择方案探讨——针对tvn24.pl登录场景的技术问询

Solution to Your Selenium Visibility & Popup Interaction Issues

Let's tackle your questions first, then refine your code to handle edge cases like disappearing popups.

1. visibility_of_element_located vs element_to_be_clickable in Your Scenario

You're right to question this! Here's the breakdown:

  • visibility_of_element_located checks if the element exists in the DOM, has dimensions >0, and is visible (including all parent elements being visible). But if your login button exists in the DOM with valid dimensions but is hidden by a parent container (e.g., the popup is collapsed without the --visible class), this condition might still pass incorrectly if the parent's visibility is controlled via CSS (like overflow: hidden or height: 0 instead of display: none).
  • element_to_be_clickable adds an extra check: the element must also be enabled (not disabled via the disabled attribute). This is more aligned with your goal of clicking the button, but the real fix is to wait for the popup container to be visible first (using the div.account-standard--visible selector). This ensures the entire popup is expanded before you try to interact with the login button, which is far more reliable than checking the button alone.

2. Handling Disappearing Popups After Hover

If the popup collapses unexpectedly before you can click the button, here's how to mitigate it:

  • Use explicit waits instead of time.sleep: Waits ensure you only interact with elements when they're ready, reducing race conditions.
  • Capture interaction exceptions: Catch errors like ElementNotInteractableException or StaleElementReferenceException and retry the hover-click flow.
  • Keep the mouse within the popup: After hovering the initial button, move the mouse directly to the login button before clicking—this prevents the popup from closing due to mouse exit.
  • Retry with page refresh: If repeated attempts fail, refresh the page to reset the state and try again.

Refined Code Implementation

Here's an optimized version of your function that addresses these issues following Selenium best practices:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import (
    ElementNotInteractableException,
    StaleElementReferenceException,
    TimeoutException
)
import time

def move_to_login_page_from_main_page(driver):
    wait = WebDriverWait(driver, 10)
    # Selectors
    CSS_ACCOUNT_TOGGLE = "button.account-standard__toggle-button"
    CSS_VISIBLE_POPUP = "div.account-standard--visible"
    CSS_LOGIN_BUTTON = "div.account-standard__popup button.account-content__button.account-content__button--large"
    EXPECTED_URL_FRAGMENT = "account.tvn.pl"
    MAX_ATTEMPTS = 3  # Limit retries to avoid infinite loops

    for attempt in range(MAX_ATTEMPTS):
        try:
            # Wait for the account toggle button to be ready for interaction
            account_toggle = wait.until(ec.element_to_be_clickable((By.CSS_SELECTOR, CSS_ACCOUNT_TOGGLE)))
            
            # Hover the toggle to expand the popup
            ActionChains(driver).move_to_element(account_toggle).perform()
            
            # Wait for the popup to become visible (via the --visible class)
            wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, CSS_VISIBLE_POPUP)))
            
            # Wait for the login button to be clickable
            login_button = wait.until(ec.element_to_be_clickable((By.CSS_SELECTOR, CSS_LOGIN_BUTTON)))
            
            # Move to the login button then click to keep the popup open
            ActionChains(driver).move_to_element(login_button).click().perform()
            
            # Wait for the page to navigate to the login URL
            wait.until(ec.url_contains(EXPECTED_URL_FRAGMENT))
            print("Successfully redirected to login page!")
            return
        except (ElementNotInteractableException, StaleElementReferenceException, TimeoutException) as e:
            print(f"Attempt {attempt + 1} failed: {str(e)}. Retrying...")
            time.sleep(1)
            # Optional: Refresh the page if state seems broken
            driver.refresh()

    # If all attempts fail, raise an exception
    raise Exception(f"Failed to access login page after {MAX_ATTEMPTS} attempts")

Key Improvements:

  • Replaced while loops with a controlled retry loop using MAX_ATTEMPTS
  • Used explicit waits (WebDriverWait) instead of time.sleep for better reliability
  • Added checks for the popup's visible state before interacting with the login button
  • Captured common exceptions to handle unexpected popup behavior
  • Kept the mouse within the popup area to prevent collapse

内容的提问来源于stack exchange,提问作者Łukasz Gil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 07:37:47