Selenium:正确的定位器,但不能与元素交互(输入字段)
Posted
技术标签:
【中文标题】Selenium:正确的定位器,但不能与元素交互(输入字段)【英文标题】:Selenium: Correct locator but cannot interact with the element (input-field) 【发布时间】:2021-11-16 14:20:47 【问题描述】:我尝试使用以下脚本与输入字段交互:
from selenium import webdriver
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.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from time import sleep
username = "****"
password = "****"
url = "https://www.wikifolio.com/dynamic/de/de/login/login?ReturnUrl=/de/de/home&_=1632037782306"
driver = webdriver.Chrome(executable_path=r'\Users\Benjamin\Downloads\chromedriver_win32\chromedriver.exe')
wait = WebDriverWait(driver, 20)
driver.get(url)
driver.find_element_by_name("Username").send_keys(username)
driver.find_element_by_name("Password").send_keys(password)
driver.find_element_by_css_selector("button").click()
driver.get("https://www.wikifolio.com/de/de/meine-wikifolios/trade/wf00wiking")
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".c-disclaimer .js-disclaimer__abort, .c-disclaimer .js-disclaimer__change"))).click()
wait.until(EC.visibility_of_element_located((By.XPATH, "//a[@data-description='AKER CARB.CAPT.AS NK1']"))).click()
wait.until(EC.presence_of_element_located((By.XPATH, "//div[@id='trading-modal-root' and(contains(@style,'block'))]//select[@class='js-order-type-select order-type-selector']")))
select1 = Select(driver.find_element_by_xpath("//div[@id='trading-modal-root' and(contains(@style,'block'))]//select[@class='js-order-type-select order-type-selector']"))
select1.select_by_value('quote')
#to select purchase or sale action:
select2 = Select(driver.find_element_by_xpath("//div[@id='trading-modal-root' and(contains(@style,'block'))]//select[@class='js-order-type-buysell order-buysell-selector']"))
# select by value "buy"
select2.select_by_value('buy')
buttonnew = wait.until(EC.presence_of_element_located((By.XPATH, "/html/body/div[3]/div[4]/div/div/div/div/div[2]/div[3]/div/div/div[2]/div[2]/input")))
newaction = ActionChains(driver)
newaction.move_to_element(buttonnew).send_keys(int(22)).perform()
脚本执行正确,除非它到达最后一部分:
buttonnew = wait.until(EC.presence_of_element_located((By.XPATH, "/html/body/div[3]/div[4]/div/div/div/div/div[2]/div[3]/div/div/div[2]/div[2]/input")))
newaction = ActionChains(driver)
newaction.move_to_element(buttonnew).send_keys(int(22)).perform()
这里执行停止。
我用浏览器检查了 XPATH。它是独一无二的。我通过“检查”检查了 Chrome,然后按 >CRTL + F
这是一个屏幕截图,Chrome 确实找到了定位器,而且它似乎是独一无二的:
这似乎表明,XPATH 是正确的,这不是“找到”正确 XPATH 的问题,而是代码执行或错误编程的问题。
我还想知道,输入字段是否包装在 Shadow DOM 或任何其他形式的隐藏结构中。
但如果是这种情况,为什么在前面的步骤中可以选择所有其他字段(如从下拉列表中选择)?
为了让您检查是否正确,我将提供该面板的完整 html(因为它是在该页面中打开的窗口):
<div>
<div id="trade-dialog-container">
<div id="trading-modal-root" role="dialog" class="modal fade publish trading-modal-root in" tabindex="-1" style="display: block; padding-right: 17px;">
<div class="modal-dialog">
<div class="modal-content">
<div class="authorization-request-panel" style="display: none;">
<div class="spinner-modal-wrapper">
<div class="spinner"></div>
</div>
</div>
<div class="trading-panel clearfix" style="">
<div class="trading-panel-close modal-close-button" data-dismiss="modal">
<i class="icon-close4"></i>
</div>
<div class="col-xs-12 col-sm-6 col-sm-push-6 col-md-push-6 col-lg-push-6 trading-panel-preview-col trade-panel-col">
<div class="trading-panel-preview">
<div class="trading-panel-preview-wrapper">
<div id="trade-main-modal-header" class="trading-panel-header">
<h4 class="trade-popup-title-shortdesc">AKER CARB.CAPT.AS NK1</h4>
<span class="trade-popup-title-sub">
<span id="js-underlying-isin" data-issuer="1900">
NO0010890304 (L&S Kurse)
</span>
</span>
</div>
<div class="row trading-panel-price-container">
<div class="col-xs-6 trading-panel-price-wrapper">
<div class="trading-panel-price">
<div class="currentBid text-center">2,392<small>EUR</small></div>
<span class="trading-panel-price-sub">Verkaufskurs (Bid)</span>
</div>
</div>
<div class="col-xs-6 trading-panel-price-wrapper">
<div class="trading-panel-price">
<div class="currentAsk text-center">2,423<small>EUR</small></div>
<span class="trading-panel-price-sub">Kaufkurs (Ask)</span>
</div>
</div>
</div>
<div class="trading-panel-summary">
<table class="trading-summary-panel">
<tbody>
<tr class="js-switch-nobuysell-row" style="display: none;">
<td colspan="2">Bestand (aktuell)</td>
<td class="text-bold text-right">
<span class="js-amount-underlying">14.477</span> Stk.
</td>
</tr>
<tr style="" class="js-switch-buysell-row">
<td>Bestand</td>
<td class="text-right trading-prev-value">
<span class="js-amount-underlying">14.477</span> Stk.
<i class="icon-right"></i>
</td>
<td class="text-bold text-right js-hideable-cell" style="visibility: visible;">
<span class="js-trade-amount-sum">14.478</span> Stk.
</td>
</tr>
<tr class="js-switch-nobuysell-row" style="display: none;">
<td colspan="2">Cash (aktuell)</td>
<td class="text-bold text-right">
<span data-value="264258.715" class="trade-popup-wikifolio-cash">264.258,715</span>
</td>
</tr>
<tr style="" class="js-switch-buysell-row">
<td>Cash</td>
<td class="text-right trading-prev-value">
<span data-value="264258.715" class="trade-popup-wikifolio-cash">264.258,715</span>
<i class="icon-right"></i>
</td>
<td class="text-bold text-right js-hideable-cell" style="visibility: visible;">
<span data-value="264258.715" class="trade-popup-cash-after-trade" data-cash="264256.292">264.256,292</span> *
</td>
</tr>
<tr>
<td colspan="2">Orderwert</td>
<td class="text-bold text-right js-hideable-cell" style="visibility: visible;">
<span class="js-order-value">2,423</span><span class="js-order-value-hidden" style="display: none;"> *</span>
</td>
</tr>
</tbody>
</table>
</div>
<div class=" row trading-panel-notice hidden-xs">
<div class="col-sm-6">
Alle Preise in EUR
</div>
<div class="col-sm-6 text-right">
* abhängig vom Ausführungspreis
</div>
</div>
<div class="trading-panel-message-container hidden-xs">
<ul class="list-unstyled"></ul>
</div>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-6 col-sm-pull-6 col-md-pull-6 col-lg-pull-6 trading-panel-detail-col trade-panel-col">
<div class="trading-panel-settings">
<div class="trading-panel-settings-wrapper">
<div class="row u-mb-3">
<div class="col-xs-6">
<div class="dropdown bootstrap-select js-order-type-select order-type-selector bs3" style="width: 100%;"><select class="js-order-type-select order-type-selector" style="opacity: 0" data->
<option value="quote" selected="selected">Quote</option>
<option value="limit">Limit</option>
<option value="stop">Stop-Limit</option>
</select><button type="button" tabindex="-1" class="btn dropdown-toggle btn-default" data-toggle="dropdown" role="combobox" aria-owns="bs-select-5" aria-haspopup="listbox" aria-expanded="false" title="Quote"><div class="filter-option"><div class="filter-option-inner"><div class="filter-option-inner-inner">Quote</div></div> </div><span class="bs-caret"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 5"><polyline fill="none" stroke="#BBC4C7" stroke- points="2.5 -.5 5.5 2.5 2.5 5.5" transform="rotate(90 4 2.5)"></polyline></svg></span></button><div class="dropdown-menu open" style="max-height: 592px; overflow: hidden; min-height: 0px;"><div class="inner open" role="listbox" id="bs-select-5" tabindex="-1" aria-activedescendant="bs-select-5-0" style="max-height: 592px; overflow-y: auto; min-height: 0px;"><ul class="dropdown-menu inner " role="presentation" style="margin-top: 0px; margin-bottom: 0px;"><li class="selected active"><a role="option" class="dropdown-item active selected" id="bs-select-5-0" tabindex="0" aria-setsize="3" aria-posinset="1" aria-selected="true"><span class="text">Quote</span></a></li><li><a role="option" class="dropdown-item" id="bs-select-5-1" tabindex="0"><span class="text">Limit</span></a></li><li><a role="option" class="dropdown-item" id="bs-select-5-2" tabindex="0"><span class="text">Stop-Limit</span></a></li></ul></div></div></div>
</div>
<div class="col-xs-6">
<div class="dropdown bootstrap-select js-order-type-buysell order-buysell-selector bs3" style="width: 100%;"><select class="js-order-type-buysell order-buysell-selector" style="opacity: 0" data- tabindex="null">
<option selected="selected">Bitte wählen...</option>
<option value="buy">Kauf</option>
<option value="sell">Verkauf</option>
</select><button type="button" tabindex="-1" class="btn dropdown-toggle btn-default" data-toggle="dropdown" role="combobox" aria-owns="bs-select-4" aria-haspopup="listbox" aria-expanded="false" title="Kauf"><div class="filter-option"><div class="filter-option-inner"><div class="filter-option-inner-inner">Kauf</div></div> </div><span class="bs-caret"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 5"><polyline fill="none" stroke="#BBC4C7" stroke- points="2.5 -.5 5.5 2.5 2.5 5.5" transform="rotate(90 4 2.5)"></polyline></svg></span></button><div class="dropdown-menu open" style="max-height: 592px; overflow: hidden; min-height: 0px;"><div class="inner open" role="listbox" id="bs-select-4" tabindex="-1" aria-activedescendant="bs-select-4-1" style="max-height: 592px; overflow-y: auto; min-height: 0px;"><ul class="dropdown-menu inner " role="presentation" style="margin-top: 0px; margin-bottom: 0px;"><li><a role="option" class="dropdown-item" id="bs-select-4-0" tabindex="0"><span class="text">Bitte wählen...</span></a></li><li class="selected active"><a role="option" class="dropdown-item active selected" id="bs-select-4-1" tabindex="0" aria-setsize="3" aria-posinset="2" aria-selected="true"><span class="text">Kauf</span></a></li><li><a role="option" class="dropdown-item" id="bs-select-4-2" tabindex="0"><span class="text">Verkauf</span></a></li></ul></div></div></div>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<span class="settings-label">Stück</span>
</div>
<div class="col-xs-6">
<input class="js-order-amount trading-amount trading-price-field textbox pull-left" type="text" maxlength="9" required="required" placeholder="Menge" value="1" data-toggle="tooltip" data-html="true" data-trigger="manual" data-container="body" data-placement="right" title="" data-original-title="Wie viele Stück möchten Sie kaufen?">
</div>
</div>
<div class="row js-stop-order-row" style="display: none">
<div class="col-xs-6">
<span class="settings-label"><span class="trade-popup-stop-price-text">Stop-Limit</span></span>
</div>
<div class="col-xs-6">
<input class="js-trade-popup-stop-price js-trading-decimal-field trading-price-field textbox" maxlength="15" type="text" value="" data-toggle="tooltip" data-html="true" data-trigger="manual" data-container="body" data-placement="right" title="<div class=' wikifolio-tooltip-icon'></div>
<div class='wikifolio-tooltip-text'>***</div>">
</div>
</div>
<div class="row js-limit-or-stop-order-row" style="display: none">
<div class="col-xs-6">
<span class="settings-label">Limit</span>
</div>
<div class="col-xs-6">
<input class="js-trade-popup-limit-price js-trading-decimal-field trading-price-field textbox" type="text" maxlength="15" value="" data-toggle="tooltip" data-html="true" data-trigger="manual" data-container="body" data-placement="right" title="<div class=' wikifolio-tooltip-icon'></div>
<div class='wikifolio-tooltip-text'>***</div>">
</div>
</div>
<div class="row js-limit-or-stop-order-row" style="display: none">
<div class="col-xs-6">
<span class="settings-label limit-trade-valid-until-text hidden-xs">Gültig bis (Tagesende)</span>
<span class="settings-label limit-trade-valid-until-text hidden-sm hidden-md hidden-lg">Gültig bis</span>
</div>
<div class="col-xs-6">
<div class="js-datepicker-valid-until">
<span class="textbox-icon-left textbox-icon-clickable js-valid-until-icon">
<i class="icon-calendar2"></i>
</span>
<input class="limit-order-valid-until-date js-limit-order-valid-until textbox" type="text" maxlength="10" value="23.10.2021" data-toggle="tooltip" data-html="true" data-trigger="manual" data-container="body" data-placement="right" title="<div class=' wikifolio-tooltip-icon'></div>
<div class='wikifolio-tooltip-text'>Ihre Order läuft zum gewählten Tag, um 23:59 Uhr automatisch ab.</div>">
</div>
</div>
</div>
<div class="trade-popup-tpsl-xs-border u-mt-3" style="display: none">
<div class="row js-trade-popup-tp-row" style="display: none">
<div class="col-xs-12">
<div class="trading-dialog-tpsl-row checkbox" data-toggle="tooltip" data-html="true" data-trigger="manual" data-container="body" data-placement="right" title="<div class=' wikifolio-tooltip-icon'></div>
<div class='wikifolio-tooltip-text'>***</div>">
<input id="modal-dialog-take-profit-checkbox" type="checkbox" class="trade-popup-take-profit-checkbox">
<label for="modal-dialog-take-profit-checkbox" class="trading-dialog-take-profit-label">Take Profit platzieren</label>
</div>
</div>
</div>
<div class="js-trade-popup-cell-tp-active js-trade-popup-cell-tp-deleted-container" style="display: none">
<div class="row js-trade-popup-tp-row" style="display: none;">
<div class="col-xs-6">
<span class="settings-label">
<span class="js-trade-popup-cell-tp-active" style="display: none;">
<span class="limit-trade-amount-sum-text">Limit</span>
</span>
<span class="trade-popup-cell-tp-inactive js-trade-popup-cell-tp-deleted" style="display: none;"></span>
</span>
</div>
<div class="col-xs-6 js-trade-popup-cell-tp-active" style="display: none;">
<input class="inline js-take-profit-limit-price js-trading-decimal-field trading-price-field textbox" maxlength="15" type="text" value="" data-toggle="tooltip" data-html="true" data-trigger="manual" data-container="body" data-placement="right" title="<div class=' wikifolio-tooltip-icon'></div>
<div class='wikifolio-tooltip-text'>Z***</div>">
</div>
</div>
</div>
</div>
<div class="trade-popup-tpsl-xs-border u-mt-2" style="display: none;">
<div class="row js-trade-popup-sl-row js-trade-popup-sl-row-first" style="display: none">
<div class="col-xs-12">
<div class="trading-dialog-tpsl-row checkbox" data-toggle="tooltip" data-html="true" data-trigger="manual" data-container="body" data-placement="right" title="<div class=' wikifolio-tooltip-icon'></div>
<div class='wikifolio-tooltip-text'>***</div>">
<input id="modal-dialog-stop-loss-checkbox" type="checkbox" class="trade-popup-stop-loss-checkbox">
<label for="modal-dialog-stop-loss-checkbox" class="trading-dialog-stop-loss-label">Stop-Loss platzieren</label>
</div>
</div>
</div>
<div class="js-trade-popup-cell-sl-active js-trade-popup-cell-sl-deleted-container" style="display: none">
<div class="row js-trade-popup-sl-row trade-popup-sl-row js-trade-popup-sl-row-first" style="display: none;">
<div class="col-xs-6">
<span class="settings-label">
<span style="display: none;" class="js-trade-popup-cell-sl-active">Stop-Limit</span>
<span class="js-trade-popup-cell-sl-inactive js-trade-popup-cell-sl-deleted" style="display: none;"></span>
</span>
</div>
<div class="col-xs-6 js-trade-popup-cell-sl-active" style="display: none;">
<input class="inline js-trade-popup-sl-stop-price js-trading-decimal-field trading-price-field textbox" maxlength="15" type="text" value="" data-toggle="tooltip" data-html="true" data-trigger="manual" data-container="body" data-placement="right" title="<div class=' wikifolio-tooltip-icon'></div>
<div class='wikifolio-tooltip-text'>***</div>">
</div>
</div>
<div class="row js-trade-popup-row-sl-active js-trade-popup-sl-row js-trade-popup-sl-row-second" style="display: none;">
<div class="col-xs-6">
<span class="settings-label">
<span style="display: none;" class="js-trade-popup-cell-sl-active">Limit</span>
<span class="js-trade-popup-cell-sl-inactive"></span>
</span>
</div>
<div class="col-xs-6 js-trade-popup-cell-sl-active" style="display: none;">
<input class="inline js-trade-popup-sl-limit-price js-trading-decimal-field trading-price-field textbox" maxlength="15" type="text" value="" data-toggle="tooltip" data-html="true" data-trigger="manual" data-container="body" data-placement="right" title="<div class=' wikifolio-tooltip-icon'></div>
<div class='wikifolio-tooltip-text'>***</div>">
</div>
</div>
</div>
</div>
<div class="trading-panel-notice trading-panel-notice-tutorial js-tutorial-row text-center visible-xs" style="display: none;">
<div class="js-limit-order-tutorial-row" style="display: none;">
***
<br>
***
<a class="area capitalized" href="/de/de/hilfe/tutorials-trader/limit-orders" target="_blank"><span>mehr...</span></a>
</div>
<div class="js-stop-limit-order-tutorial-row" style="display: none;">
***
<br>
***
<a class="area capitalized" href="/de/de/hilfe/tutorials-trader/stop-limit-orders" target="_blank"><span>mehr...</span></a>
</div>
</div>
</div>
</div>
</div>
.......
现在的问题是:在与输入字段交互之前,我是否需要先处理父元素或祖先元素之一(例如 div)?
我也想知道 HTML 中的这部分是关于什么的:
<div class="authorization-request-panel" style="display: none;">
<div class="spinner-modal-wrapper">
<div class="spinner"></div>
</div>
</div>
这是直接写在 HTML 中的“modal-dialog”div 之后。
我还在 *** 中检查了多个威胁。所有的解决方案都会导致一个 incorecct XPATH Locator。但是,当我直接将它插入浏览器时,为什么 XPATH 会唯一地指向正确的输入字段,就像在屏幕截图中一样?
谁能帮我解决这个问题?
非常感谢,我很感激, 本杰明
【问题讨论】:
【参考方案1】:-
Xpath 本质上是脆弱的,尽量使用relative xpath 而不是absolute xpath。
请务必在需要时使用
element_to_be_clickable
。
需要先清空输入框,然后send_keys
使用explicit waits
。
以全屏模式启动浏览器。
首选是css selector
,最不首选的选择是xpath。
代码:
driver = webdriver.Chrome(driver_path)
#driver.maximize_window()
driver.implicitly_wait(30)
wait = WebDriverWait(driver, 30)
driver.get("https://www.wikifolio.com/dynamic/de/de/login/login?ReturnUrl=/de/de/home&_=1632037782306")
wait.until(EC.element_to_be_clickable((By.NAME, "Username"))).send_keys('******')
wait.until(EC.element_to_be_clickable((By.ID, "Password"))).send_keys('******')
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.gtm-login"))).click()
driver.get("https://www.wikifolio.com/de/de/meine-wikifolios/trade/wf00wiking")
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.js-disclaimer__change"))).click()
wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@data-description='AKER CARB.CAPT.AS NK1']"))).click()
select1 = Select(driver.find_element_by_css_selector("div.dropdown>select.order-type-selector"))
select1.select_by_value('quote')
#to select purchase or sale action:
select2 = Select(driver.find_element_by_css_selector("div.dropdown>select.order-buysell-selector"))
# select by value "buy"
select2.select_by_value('buy')
buttonnew = wait.until(EC.element_to_be_clickable((By.XPATH, "(//input[contains(@class,'trading-amount')])[2]")))
buttonnew.clear()
buttonnew.send_keys("22")
【讨论】:
【参考方案2】:不,没有必要在与输入字段交互之前寻址父元素或祖先元素之一(除非该元素位于框架集的框架内)。您能否将“22”作为字符串而不是整数传递?
# passing "22" as a string
newaction.move_to_element(buttonnew).send_keys(str(22)).perform()
【讨论】:
以上是关于Selenium:正确的定位器,但不能与元素交互(输入字段)的主要内容,如果未能解决你的问题,请参考以下文章