无法检测元素并通过 Selenium 将输入发送到信用卡号字段
Not able to detect the element and send input to the Credit Card Number field through Selenium
我正在尝试在 this website 上自动执行结帐流程。我在第 4 阶段,您单击 "Payment Information" 中的 "Credit Card" 选项,我正在尝试 send_keys
输入我的信用卡号码。
但是,我注意到在单击 CC 选项后,页面加载了一点,所以我使用了显式等待该元素,但它不起作用。任何帮助将不胜感激。
ccNumber = session.find_element_by_css_selector('input[name=credit-card-number]')
wait = WebDriverWait(session, 100)
wait.until(EC.element_to_be_selected(ccNumber))
这是错误:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"input[name=credit-card-number]"}
您可以等到加载微调器不再出现在页面上,然后再检查信用卡输入。我们有一个 C# 解决方案,您可以尝试适应 python,您可以在循环中等待元素显示,捕获异常直到达到超时。
//Assert an element is displayed before the timeout milliseconds run out.
public void AssertElementIsDisplayed(int timeout, IWebElement element, string elementName = "element")
{
Action<IWebElement> target = delegate (IWebElement e) {
if (e == null)
{
throw new AssertionException("Failed to find " + elementName + ". It is null");
}
if (!e.Displayed)
{
elementName = (elementName == "element" && !String.IsNullOrEmpty(e.GetAttribute("title"))) ? e.GetAttribute("title") : elementName;
throw new AssertionException("Expected (" + elementName + ") to be displayed but it was not");
}
};
AssertInLoop(element, (long)timeout, 100L, target);
}
//Assert some Action on a WebElement for as long as the timeoutMillis allow.
private void AssertInLoop(IWebElement element, long timeoutMillis, long millisBetweenAttempts, Action<IWebElement> callable)
{
AssertionException lastAssertionError = null;
WebDriverException lastWebDriverException = null;
long startTime = DateTimeOffset.Now.Ticks / TimeSpan.TicksPerMillisecond;
if (timeoutMillis < 500 || timeoutMillis > 120 * 1000)
{
throw new ArgumentException("Timeout outside expected range. timeout_millis=" + timeoutMillis);
}
long millisLeft = timeoutMillis;
while (millisLeft >= 1)
{
long lastAttemptStartMillis = DateTimeOffset.Now.Ticks / TimeSpan.TicksPerMillisecond;
try
{
callable(element);
return;
}
catch (AssertionException e)
{
lastAssertionError = e;
lastWebDriverException = null;
}
catch (StaleElementReferenceException e)
{
lastAssertionError = null;
lastWebDriverException = e;
}
catch (NotFoundException e)
{
lastAssertionError = null;
lastWebDriverException = e;
}
catch (SystemException e)
{
throw e;
}
long elapsedMillis = (DateTimeOffset.Now.Ticks / TimeSpan.TicksPerMillisecond) - startTime;
millisLeft = timeoutMillis - elapsedMillis;
if (millisLeft >= 1)
{
long millisElapsedDuringThisAttempt = (DateTimeOffset.Now.Ticks / TimeSpan.TicksPerMillisecond) - lastAttemptStartMillis;
long millisToSleep = millisBetweenAttempts - millisElapsedDuringThisAttempt;
if (millisToSleep > 0)
{
Thread.Sleep((int)millisToSleep);
}
}
}
if (lastAssertionError != null)
{
throw lastAssertionError;
}
else if (lastWebDriverException != null)
{
throw lastWebDriverException;
}
}
信用卡号码的<input>
字段在<iframe>
内,因此您必须:
- 诱导 WebDriverWait 等待所需的 框架可用并切换到它。
- 诱导 WebDriverWait 使所需的元素可点击,您可以使用以下解决方案:
代码块:
WebDriverWait(session, 20).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"braintree-hosted-field-number")))
WebDriverWait(session, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input.number#credit-card-number"))).send_keys("0000000000000000")
我正在尝试在 this website 上自动执行结帐流程。我在第 4 阶段,您单击 "Payment Information" 中的 "Credit Card" 选项,我正在尝试 send_keys
输入我的信用卡号码。
但是,我注意到在单击 CC 选项后,页面加载了一点,所以我使用了显式等待该元素,但它不起作用。任何帮助将不胜感激。
ccNumber = session.find_element_by_css_selector('input[name=credit-card-number]')
wait = WebDriverWait(session, 100)
wait.until(EC.element_to_be_selected(ccNumber))
这是错误:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"input[name=credit-card-number]"}
您可以等到加载微调器不再出现在页面上,然后再检查信用卡输入。我们有一个 C# 解决方案,您可以尝试适应 python,您可以在循环中等待元素显示,捕获异常直到达到超时。
//Assert an element is displayed before the timeout milliseconds run out.
public void AssertElementIsDisplayed(int timeout, IWebElement element, string elementName = "element")
{
Action<IWebElement> target = delegate (IWebElement e) {
if (e == null)
{
throw new AssertionException("Failed to find " + elementName + ". It is null");
}
if (!e.Displayed)
{
elementName = (elementName == "element" && !String.IsNullOrEmpty(e.GetAttribute("title"))) ? e.GetAttribute("title") : elementName;
throw new AssertionException("Expected (" + elementName + ") to be displayed but it was not");
}
};
AssertInLoop(element, (long)timeout, 100L, target);
}
//Assert some Action on a WebElement for as long as the timeoutMillis allow.
private void AssertInLoop(IWebElement element, long timeoutMillis, long millisBetweenAttempts, Action<IWebElement> callable)
{
AssertionException lastAssertionError = null;
WebDriverException lastWebDriverException = null;
long startTime = DateTimeOffset.Now.Ticks / TimeSpan.TicksPerMillisecond;
if (timeoutMillis < 500 || timeoutMillis > 120 * 1000)
{
throw new ArgumentException("Timeout outside expected range. timeout_millis=" + timeoutMillis);
}
long millisLeft = timeoutMillis;
while (millisLeft >= 1)
{
long lastAttemptStartMillis = DateTimeOffset.Now.Ticks / TimeSpan.TicksPerMillisecond;
try
{
callable(element);
return;
}
catch (AssertionException e)
{
lastAssertionError = e;
lastWebDriverException = null;
}
catch (StaleElementReferenceException e)
{
lastAssertionError = null;
lastWebDriverException = e;
}
catch (NotFoundException e)
{
lastAssertionError = null;
lastWebDriverException = e;
}
catch (SystemException e)
{
throw e;
}
long elapsedMillis = (DateTimeOffset.Now.Ticks / TimeSpan.TicksPerMillisecond) - startTime;
millisLeft = timeoutMillis - elapsedMillis;
if (millisLeft >= 1)
{
long millisElapsedDuringThisAttempt = (DateTimeOffset.Now.Ticks / TimeSpan.TicksPerMillisecond) - lastAttemptStartMillis;
long millisToSleep = millisBetweenAttempts - millisElapsedDuringThisAttempt;
if (millisToSleep > 0)
{
Thread.Sleep((int)millisToSleep);
}
}
}
if (lastAssertionError != null)
{
throw lastAssertionError;
}
else if (lastWebDriverException != null)
{
throw lastWebDriverException;
}
}
信用卡号码的<input>
字段在<iframe>
内,因此您必须:
- 诱导 WebDriverWait 等待所需的 框架可用并切换到它。
- 诱导 WebDriverWait 使所需的元素可点击,您可以使用以下解决方案:
代码块:
WebDriverWait(session, 20).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"braintree-hosted-field-number"))) WebDriverWait(session, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input.number#credit-card-number"))).send_keys("0000000000000000")