无法在 Python 应用程序中选择下拉菜单
Posted
技术标签:
【中文标题】无法在 Python 应用程序中选择下拉菜单【英文标题】:Can't select drop-down menu in Python app 【发布时间】:2020-02-19 14:52:51 【问题描述】:我有一个从网站上抓取值的脚本,它带有一个下拉悬停菜单,需要将父菜单悬停在其中并选择一个下拉选项。直到几天前,这一切都很好。但是现在随机失败了。
这是我当前的代码:
def select_dropdown():
WebDriverWait(driver, 10).until(ec.visibility_of_element_located(
(By.CSS_SELECTOR, "div.menu.menuTopCenter > ul > li:nth-child(3) > a")))
investment = WebDriverWait(driver, 10).until(ec.element_to_be_clickable(
(By.CSS_SELECTOR, "div.menu.menuTopCenter > ul > li:nth-child(3) > a")))
actions.move_to_element(investment).perform()
WebDriverWait(driver, 10).until(
ec.element_to_be_clickable((By.CSS_SELECTOR, "li:nth-child(3) > div > div:nth-child(1) > a"))).click()
父菜单见下面的 html:
<a class="menuLink mainMenuItem" href="#" renderstyle="NONE" action=""
controller="" clientmodulesubid="0" renderlocation=""
clearcontentheader="False"
lobsystemuserids="Ls6EVzOdmMPVcdHshYcUbg==">Investment</a>
请参阅下面的 HTML 以了解要选择的选项(子菜单):
<a class="menuLink mainMenuItem" href="#" renderstyle="REPLACE" action="Index"
controller="Portfolio" clientmodulesubid="6109"
renderlocation="contentHeaderContainer" clearcontentheader="True"
lobsystemuserids="Ls6EVzOdmMPVcdHshYcUbg==">Investment summary</a>
这是我得到的错误:
Traceback (most recent call last):
File "C:/Users/SChogle/PycharmProjects/Web Scraping All Sites (With BDay).py", line 55, in <module>
select_dropdown()
File "C:/Users/SChogle/PycharmProjects/Web Scraping All Sites (With BDay).py", line 29, in select_dropdown
ec.element_to_be_clickable((By.CSS_SELECTOR, "li:nth-child(3) > div > div:nth-child(1) > a"))).click()
File "C:\Users\SChogle\AppData\Roaming\Python\Python37\site-packages\selenium\webdriver\support\wait.py", line 80, in until
raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message:
这是父菜单和所有子菜单的完整 HTML:
<li class="has-children">
<a class="menuLink mainMenuItem" href="#"
renderstyle="NONE" action="" controller="" clientmodulesubid="0"
renderlocation="" clearcontentheader="False"
lobsystemuserids="8qWAwlpk6Jdje8MVVaH1Tw==">Investment</a>
<div class="subMenu">
<div>
<a class="menuLink mainMenuItem" href="#" renderstyle="REPLACE"
action="Index" controller="Portfolio" clientmodulesubid="6109"
renderlocation="contentHeaderContainer" clearcontentheader="True"
lobsystemuserids="8qWAwlpk6Jdje8MVVaH1Tw==">Investment summary</a>
</div>
<div>
<a class="menuLink mainMenuItem" href="#" renderstyle="REPLACE"
action="GetLazyTransactionHistoryByAccountGroup" controller="Transactions"
clientmodulesubid="6108" renderlocation="contentHeaderContainer"
clearcontentheader="True"
lobsystemuserids="8qWAwlpk6Jdje8MVVaH1Tw==">Transaction history</a>
</div>
<div>
<a class="menuLink mainMenuItem" href="#" renderstyle="REPLACE"
action="LoadIncomeDistribution" controller="IncomeDistribution"
clientmodulesubid="7005" renderlocation="contentHeaderContainer"
clearcontentheader="True" lobsystemuserids="8qWAwlpk6Jdje8MVVaH1Tw==">Income
distribution</a>
</div>
<div>
<a class="menuLink mainMenuItem" href="#"
renderstyle="REPLACE" action="PortfolioFees" controller="Fees"
clientmodulesubid="6159" renderlocation="contentHeaderContainer"
clearcontentheader="True" lobsystemuserids="8qWAwlpk6Jdje8MVVaH1Tw==">Advisor
charges</a>
</div>
<div><a class="menuLink mainMenuItem" href="#"
renderstyle="REPLACE" action="GetRecurringInstructionsDetail"
controller="RecurringInstructions" clientmodulesubid="6158"
renderlocation="contentHeaderContainer" clearcontentheader="True"
lobsystemuserids="8qWAwlpk6Jdje8MVVaH1Tw==">Recurring instructions</a>
</div>
<div>
<a class="menuLink mainMenuItem" href="#" renderstyle="REPLACE"
action="GenerateAdHocWebStatement_SAIP" controller="AdHocWebStatement"
clientmodulesubid="6121" renderlocation="contentHeaderContainer"
clearcontentheader="True" lobsystemuserids="8qWAwlpk6Jdje8MVVaH1Tw==">Investor
statement</a>
</div>
<div>
<a class="menuLink mainMenuItem" href="#"
renderstyle="REPLACE" action="GenerateAdHocWebStatement_SAIP"
controller="AdHocWebStatement" clientmodulesubid="8939"
renderlocation="contentHeaderContainer" clearcontentheader="True"
lobsystemuserids="8qWAwlpk6Jdje8MVVaH1Tw==">Tax certificate</a>
</div>
</div>
</li>
我认为可能发生的事情是脚本试图在页面加载之前找到元素,但我不确定。正如我所说,它有时有效,有时失败。
【问题讨论】:
可以分享网址吗? 您在哪里遇到什么错误? 您是否尝试增加超时?你能与菜单和子菜单共享完整的 HTML 吗? @Sers 是的,我尝试将超时时间增加到 50 秒,但仍然没有运气。我已将完整的 HTML 包含在父菜单和上面的所有子菜单中。让我知道这是否是你想要的?还是您在寻找其他东西? 【参考方案1】:试试下面的select_menu
方法:
def select_menu(menu: str = None, submenu: str = None):
menu_locator = f"//div[contains(@class,'menu')]//a[.='menu']"
submenu_locator = f"menu_locator/ancestor::li[1]/div[@class='subMenu']//a[.='submenu']"
wait = WebDriverWait(driver, 20)
wait.until(lambda d: d.execute_script("return document.readyState === 'complete' && jQuery.active === 0;"))
menu_element = wait.until(EC.element_to_be_clickable((By.XPATH, menu_locator)))
actions.move_to_element(menu_element).perform()
wait.until(EC.visibility_of_element_located((By.XPATH, submenu_locator))).click()
如何调用方法:
select_menu(menu="Investment", submenu="Investment summary")
【讨论】:
非常感谢您的回答,但不幸的是仍然出现超时错误。由于某种原因,它找不到该父菜单。我尝试单击页面上刷新页面的按钮。然后几乎总能找到父菜单。但是,当“刷新”按钮引发元素点击拦截错误时,可靠地找到“刷新”按钮存在问题 我添加了一张菜单外观的图片,它是一个悬停菜单。因此,将鼠标悬停在“投资”上会显示以下所有选项【参考方案2】:您可以尝试通过以下步骤进行调试以缩小解决方案: 1. 使用try catch重试同一块代码:
count=0, max=5;
while(true)
try
//drop down click
catch(Exception e)
if(count++==max) throw e;
您也可以尝试重新加载页面然后执行直到成功。
driver.navigate().refresh();
【讨论】:
以上是关于无法在 Python 应用程序中选择下拉菜单的主要内容,如果未能解决你的问题,请参考以下文章