首页 > 解决方案 > 如何使用 Selenium 和 Python 在复杂网站中定位下拉选择元素并选择一个选项

问题描述

我有一个非常复杂的网站,我正在尝试用 Selenium 进行测试。但是,当我尝试获取 XPath 时,例如,我得到了这样的结果。

//*[@id="datatable1595356931082"]/div[1]/div[2]/table/tbody/tr[3]/td[2]/div/select/option[8]

绝对 XPath:

/html/body/div[4]/div[2]/div[2]/div/div[2]/div[2]/div/div/div[1]/div[2]/table/tbody/tr[3]/td[2]/div/select/option[8]

在 Selenium 中,我尝试使用绝对路径,例如

driver.find_element_by_xpath("/html/body/div[4]/div[2]/div[2]/div/div[2]/div[2]/div/div/div[1]/div[2]/") 

它试图出错,说它无法找到 XPath。数据表似乎在运行时创建了一个动态数字。我在这里要做的是选择一个看起来像这样的下拉列表

<div role="columnheader" class="webix_hcell webix_ss_filter">
<select>
<option value=""></option>
<option value="A">A</option>
<option value="B">B</option>
.
.
.
</select>
</div>

我也试过

driver.find_element_by_class_name('webix_hcell webix_ss_filter')

但这也出错了

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".webix_hcell webix_ss_filter"}

对于上述一个

selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: Unable to locate an element with the xpath expression /html/body/div[4]/div[2]/div[2]/div/div[2]/div[2]/div/div/div[1]/div[2]/ because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string '/html/body/div[4]/div[2]/div[2]/div/div[2]/div[2]/div/div/div[1]/div[2]/' is not a valid XPath expression.
  (Session info: chrome=84.0.4147.89)

标签: pythonseleniumselenium-webdriverxpathhtml-select

解决方案


您需要考虑以下几点:

  • 从您的第一次尝试开始,由于id属性值 as的存在, WebElement显示为动态元素,这可能会在每次访问时或定期更改:datatable1595356931082

    //*[@id="datatable1595356931082"]/div[1]/div[2]/table/tbody/tr[3]/td[2]/div/select/option[8]
    
  • 在您的第二次尝试中,您使用了绝对。由于网站是动态的,元素将在每次访问时或定期重新定位:

    /html/body/div[4]/div[2]/div[2]/div/div[2]/div[2]/div/div/div[1]/div[2]/table/tbody/tr[3]/td[2]/div/select/option[8]
    
  • 在您的第三次尝试中,xpath/不需要的结尾。因此你面临InvalidSelectorException

  • 在您的第四次尝试中,您通过driver.find_element_by_class_name('webix_hcell webix_ss_filter')where asdriver.find_element_by_class_name()仅接受一个类名作为参数传递了多个类。

您可以在Invalid selector: Compound class names not allowed error using Selenium中找到详细讨论

  • 最后,它是一个<select>节点,所以你需要使用Select类。

您可以在How to select a drop-down menu value with Selenium using Python中找到详细讨论?


解决方案

基于相关文本的 HTML 将帮助我们构建规范的答案。但是,根据提供的 HTML 来单击文本为A的选项,您可以使用以下任一定位器策略

  • 使用XPATHselect_by_visible_text()

    select = Select(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='webix_hcell webix_ss_filter' and @role='columnheader']//following::select[1]"))))
    select.select_by_visible_text('A')
    
  • 使用CSS_SELECTORselect_by_value()

    select = Select(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "div.webix_hcell.webix_ss_filter[role='columnheader'] +select"))))
    select.select_by_value('A')
    
  • 注意:您必须添加以下导入:

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

推荐阅读