How do I get Selenium in Python to select a dropdown that doesn't appear to have <select> and <option> tags?

huangapple go评论85阅读模式
英文:

How do I get Selenium in Python to select a dropdown that doesn't appear to have <select> and <option> tags?

问题

网站的下拉框代码如下:

<div id="ctl00_MainContent_basicSettingsCntrl_divAddressVerficationLbl" class="rowLeftPad50 label" data-argosy-tooltip="25">
    Address Verification
</div>
<div id="ctl00_MainContent_basicSettingsCntrl_divAddressVerficationCombo" class="rowLeft ">
    <div id="ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification" class="RadComboBox RadComboBox_Default" style="width:153px;white-space:normal;">
        <table summary="combobox" style="border-width:0;border-collapse:collapse;width:100%">
            <tr class="rcbReadOnly">
                <td style="width:100%;" class="rcbInputCell rcbInputCellLeft"><input name="ctl00$MainContent$basicSettingsCntrl$rdComboAddressVerification" type="text" class="rcbInput radPreventDecorate" id="ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification_Input" value="Yes" readonly="readonly" tabindex="7" /></td>
                <td class="rcbArrowCell rcbArrowCellRight"><a id="ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification_Arrow" style="overflow: hidden;display: block;position: relative;outline: none;">select</a></td>
            </tr>
        </table>
        <div class="rcbSlide" style="z-index:6000;"><div id="ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification_DropDown" class="RadComboBoxDropDown RadComboBoxDropDown_Default " style="display:none;"><div class="rcbScroll rcbWidth" style="width:100%;"><ul class="rcbList" style="list-style:none;margin:0;padding:0;zoom:1;"><li class="rcbItem ">Yes</li><li class="rcbItem ">No</li></ul></div></div></div><input id="ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification_ClientState" name="ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification_ClientState" type="hidden" />
    </div>
</div>

根据你的描述,这个下拉框看起来不是标准的HTML selectoption 元素创建的,而是通过JavaScript生成和维护的。你尝试使用 Selenium 的 send_keys(Keys.ARROW_UP) 方法来模拟向上箭头键,但遇到了 selenium.common.exceptions.ElementNotInteractableException 错误,表示无法与元素交互。

如果这个下拉框不是标准的HTML select 元素,Selenium 的 Select 类可能无法正常使用。你可以尝试以下方法来操作这个下拉框:

  1. 使用 JavaScript 来操作下拉框:

    # 导入 JavaScript 执行函数
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    # 找到下拉框元素
    dropdown = driver.find_element(By.ID, "ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification")
    
    # 使用 JavaScript 来选中下拉框中的选项
    driver.execute_script("arguments[0].click();", dropdown)
    option_to_select = "No"  # 替换成你想选择的选项
    option_element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, f'//li[text()="{option_to_select}"]')))
    driver.execute_script("arguments[0].click();", option_element)
    
    # 点击提交按钮
    driver.find_element(By.ID, "btnSaveCustomerDetails").click()
    
  2. 如果上述方法也不起作用,尝试模拟键盘输入全选项的第一个字母,然后再按 Enter 键,看看是否能够选择正确的选项。

    dropdown = driver.find_element(By.ID, "ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification")
    dropdown.click()
    dropdown.send_keys("N")  # 输入选项的首字母
    dropdown.send_keys(Keys.ENTER)
    

请根据你的具体情况选择上述方法之一,以便操作这个特殊的下拉框。

英文:

The code for the website's dropdown is:

&lt;div id=&quot;ctl00_MainContent_basicSettingsCntrl_divAddressVerficationLbl&quot; class=&quot;rowLeftPad50 label&quot; data-argosy-tooltip=&quot;25&quot;&gt;
        Address Verification
&lt;/div&gt;
&lt;div id=&quot;ctl00_MainContent_basicSettingsCntrl_divAddressVerficationCombo&quot; class=&quot;rowLeft &quot;&gt;
     &lt;div id=&quot;ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification&quot; class=&quot;RadComboBox RadComboBox_Default&quot; style=&quot;width:153px;white-space:normal;&quot;&gt;
	&lt;table summary=&quot;combobox&quot; style=&quot;border-width:0;border-collapse:collapse;width:100%&quot;&gt;
		&lt;tr class=&quot;rcbReadOnly&quot;&gt;
			&lt;td style=&quot;width:100%;&quot; class=&quot;rcbInputCell rcbInputCellLeft&quot;&gt;&lt;input name=&quot;ctl00$MainContent$basicSettingsCntrl$rdComboAddressVerification&quot; type=&quot;text&quot; class=&quot;rcbInput radPreventDecorate&quot; id=&quot;ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification_Input&quot; value=&quot;Yes&quot; readonly=&quot;readonly&quot; tabindex=&quot;7&quot; /&gt;&lt;/td&gt;
			&lt;td class=&quot;rcbArrowCell rcbArrowCellRight&quot;&gt;&lt;a id=&quot;ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification_Arrow&quot; style=&quot;overflow: hidden;display: block;position: relative;outline: none;&quot;&gt;select&lt;/a&gt;&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;
	&lt;div class=&quot;rcbSlide&quot; style=&quot;z-index:6000;&quot;&gt;&lt;div id=&quot;ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification_DropDown&quot; class=&quot;RadComboBoxDropDown RadComboBoxDropDown_Default &quot; style=&quot;display:none;&quot;&gt;&lt;div class=&quot;rcbScroll rcbWidth&quot; style=&quot;width:100%;&quot;&gt;&lt;ul class=&quot;rcbList&quot; style=&quot;list-style:none;margin:0;padding:0;zoom:1;&quot;&gt;&lt;li class=&quot;rcbItem &quot;&gt;Yes&lt;/li&gt;&lt;li class=&quot;rcbItem &quot;&gt;No&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;input id=&quot;ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification_ClientState&quot; name=&quot;ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification_ClientState&quot; type=&quot;hidden&quot; /&gt;
&lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

From the guides I've seen on Selenium, most of them are accessing a dropdown that has a Select tag, with options have an option tag. I'm guessing this dropdown is created or maintained in javascript? Is there a way to manipulate this using Selenium? Or can I use something else within Python to change the dropdown?

Here's my relevant code, most recently when I tried a workaround to simply use sending an ARROW_UP key to select something else, which throws an error:

#find and click dropdown
driver.find_element(By.ID, &quot;ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification&quot;).click()
element = driver.find_element(By.ID, &quot;ctl00_MainContent_basicSettingsCntrl_rdComboAddressVerification&quot;) 
#will move selector up to yes. If already at top, will remain at top
element.send_keys(Keys.ARROW_UP)    
#click submit
driver.find_element(By.ID, &quot;btnSaveCustomerDetails&quot;).click()    

The usual Select does not work for obvious reasons, at least from what I've tried from a few various guides on youtube and the Selenium documentation. I am not seeing a way to interact with it in general.

I thought I might have a workaround- to simply send an ARROW_UP to select the above item in the list but it throws an error: selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable

答案1

得分: 0

最有可能的情况是,您需要创建一个XPath定位器来定位“fancybox”内部的&lt;span class=&quot;k-icon k-i-arrow-60-down&quot;&gt;&lt;/span&gt;元素。也许可以像这样:

//div[@class=&#39;fancybox-outer&#39;]//span[@class=&#39;k-icon k-i-arrow-60-down&#39;]

一旦您获得了这个元素,发送一个点击事件以展开它。

接下来,定位列表项。使用显式等待来设置超时并等待元素可见。最后,定位所需的列表元素并点击它。对于评论中的示例,您可以通过其data-offset-index属性来定位所需的列表项。例如,要选择第二个列出的项,您需要使用如下表达式:

//div[@class=&#39;fancybox-outer&#39;]/following::ul/li[@data-offset-index=&quot;2&quot;]

之所以这样做是因为列表不是嵌套在“fancybox”内部的。它实际上在这个元素之后。following XPath轴使用相对位置(在本例中为“fancybox”元素)并搜索仅在基本元素之后存在的给定元素。实际上,您在寻找一个在“fancybox”之后存在的包含具有给定data_offset_indexli元素的ul元素。

英文:

Most likely, you will need to create an XPath locator to locate the
&lt;span class=&quot;k-icon k-i-arrow-60-down&quot;&gt;&lt;/span&gt; element inside the "fancybox". Perhaps something like this:

//div[@class=&#39;fancybox-outer&#39;]//span[@class=&#39;k-icon k-i-arrow-60-down&#39;]

Once you obtain this element, send a click to it to expand.

Next, locate the list items. Use an explicit wait to set timeout and wait for elements to be visible. Lastly, locate the desired listed element and click on it. For the example in the comments, you could locate the desired listed item by its data-offset-index attribute. For example, to select the second listed item, you will need an expression like this

//div[@class=&#39;fancybox-outer&#39;]/following::ul/li[@data-offset-index=&quot;2&quot;]

The reason for this is because the list is not nested inside the "fancybox." It is actually after this element. The following XPath axes uses a relative position (in this case the "fancybox" element) an searches for the given element that exist only after the base element. In essence, you are looking for a ul element that exist after the "fancybox" that contains an li element with the given data_offset_index.

huangapple
  • 本文由 发表于 2023年7月14日 03:15:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76682582.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定