消息:尝试通过 Selenium 单击下拉菜单中的选项时,无法将元素 <option> 滚动到视图中

Message: Element <option> could not be scrolled into view while trying to click on an option within a dropdown menu through Selenium

我正在尝试 select 下拉菜单并选择一个选项。我用的是最新版的Selenium,最新版的Firefox,最新版的geckodriver,最新版的Python。

这是我的问题:当我尝试选择一个选项时,出现以下错误:

selenium.common.exceptions.ElementNotInteractableException: Message: Element <option> could not be scrolled into view.

我尝试了多种方法来解决这个问题,但 none 似乎行得通。以下是我尝试过的一些方法。

mySelectElement = browser.find_element_by_id('providerTypeDropDown')
dropDownMenu = Select(mySelectElement)
dropDownMenu.select_by_visible_text('Professional')

mySelectElement = browser.find_element_by_id('providerTypeDropDown')
dropDown = Select(mySelectElement)
for option in dropDown.options:
    message = option.get_attribute('innerText')
    print(message)
    if message == 'Professional':
        print("Exists")
        dropDown.select_by_visible_text(message) 
        break

element = browser.find_element_by_id('providerTypeDropDown')
browser.execute_script("var select = arguments[0]; for(var i = 0; i < select.options.length; i++){ if(select.options[i].text == arguments[1]){ select.options[i].selected = true; } }", element, "Professional")

HTML 代码遵循通常的 select 标签和选项标签。任何帮助表示赞赏。 HTML 代码包含在下面。

<select data-av-chosen="providerTypes" id="providerTypeDropDown" data-placeholder="Please Select a Provider Type" name="providerTypeDropDown"
class="chzn-select input-full ng-pristine chzn-done ng-invalid ng-invalid-provider-type" data-ng-options="providerType.value for providerType in request.models.providerTypes"
data-ng-model="request.models.providerType" data-av-validator-field="providerType" data-disable-search-threshold="5" style="display; none;">
    <option value="" class="">Please Select a Provider Type</option>
    <option value="0">Professional</option>
    <option value="1">Institutional</option>
</select> 

打印语句用于 testing/code 跟踪目的。

尝试加个等待:

mySelectElement = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "providerTypeDropDown")))
mySelectElement.click()

它会等待至少 10 秒直到元素可点击然后点击。

我在您的代码中也没有看到您单击打开下拉菜单的下拉按钮。找到这个按钮,也添加一个等待,然后在你select选项之前点击它。希望对你有帮助。

注意:对于此代码,您必须添加一些导入:

from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

这个错误信息...

selenium.common.exceptions.ElementNotInteractableException: Message: Element <option> could not be scrolled into view.

...表示您的程序试图与之交互的 <option> 项无法滚动到视图中。

所需元素的 HTML 会给我们一些错误背后的想法。然而,似乎所需的元素不在 clickable / Viewport 中。要解决此问题,您必须引入 WebDriverWait 以使 元素可点击 ,您可以使用以下解决方案:

mySelectElement = browser.find_element_by_id('providerTypeDropDown')
dropDownMenu = Select(mySelectElement)
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//select[@id='providerTypeDropDown']//options[contains(.,'Professional')]")))
dropDownMenu.select_by_visible_text('Professional')

注意:您必须添加以下导入:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.select import Select

我遇到了同样的问题。我无法使用 selectByValue、selectByIndex 和 selectByVisible 文本 select 下拉值。我也使用 Javascript 执行器尝试了操作 class 和 scrollBy。没有任何效果。经过 1 天的反复试验,我想出了以下解决方法,

public static void selectDropDownByVisibleText(WebElement element, String text){
        waitForPageLoad();
        String firstCharacterDropDownVal = ""+text.charAt(0);
        HashSet<String> uniqueDropDownVals = new HashSet<>();
        try {
            Select select = new Select(element);
            select.selectByVisibleText(text);
        }catch (ElementNotInteractableException e){
            Select select = new Select(element);
            while(!select.getFirstSelectedOption().getText().equalsIgnoreCase(text) &&
                    uniqueDropDownVals.add(select.getFirstSelectedOption().getText())) {
                element.sendKeys(firstCharacterDropDownVal);
            }
        }
        log.info("Selected dropdown by visible text "+text);
    }


public static void waitForPageLoad() {
        log.debug("Waiting for page to get loaded..");
        new WebDriverWait(Driver.getDriver(), Duration.ofSeconds(FIND_ELEMENT_WAIT_TIME)).
                ignoring(NoSuchElementException.class).ignoring(StaleElementReferenceException.class).
                until(webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));
        log.debug("Page loaded successfully");
    }

我会解释工作原理。首先它会尝试 select 通过可见文本。如果我们得到异常,它将进入 catch 块。我们在下拉网络元素上发送所需文本的第一个字符。所以下拉元素改变了。假设下拉值是 Apple、Aeroplane、Adam,我想 select Adam。我第一次在网络元素上发送 'A' 时,下拉列表更改为 Apple。然后我将它添加到 HashSet 并检查 selected 元素是否是所需的元素。如果匹配则我们跳出 while 循环。如果同一个元素被添加两次,那么HashSet的add方法就会return false。这将使我们跳出 while 循环,避免进入死循环。因此,每次我输入 'A' 时,下拉值都会更改为下一个以 'A' 开头的值。这就是方法。