I'm trying to automate the following site - https://apps.royalbank.com/apps/home-value-estimator#!/
It works fine with the following code - but when i get to the site where I have to choose the radio-button I am not able to click on this radio-button:
link = "https://apps.royalbank.com/apps/home-value-estimator#!/"
WAIT = 1
RUN = True
driver = webdriver.Chrome (service=srv, options=options)
waitWebDriver = WebDriverWait (driver, 10)
print(f"\nChecking value for address: {address} on {link}...")
if MINIMIZE:
driver.minimize_window()
driver.get (link)
print(f"Input address...")
time.sleep(WAIT)
driver.find_element(By.XPATH, "//input[@name='address']").send_keys(address)
time.sleep(WAIT)
driver.find_element(By.XPATH, "//input[@name='address']").send_keys(Keys.ARROW_DOWN)
time.sleep(WAIT)
driver.find_element(By.XPATH, "//input[@name='address']").send_keys(Keys.ENTER)
time.sleep(WAIT)
driver.find_element(By.XPATH, "//form[@name='addressForm']//following-sibling::button").click()
time.sleep(WAIT)
print(f"Select type...")
if inpData[1] == "Detached House":
driver.find_element(By.XPATH, "//label[@for='detached']").click()
elif inpData[1] == "Condo Townhouse":
driver.find_element(By.XPATH, "//label[@for='townhouse']").click()
elif inpData[1] == "Semi Detached":
driver.find_element(By.XPATH, "//label[@for='semidetached']").click()
elif inpData[1] == "Condo Apt.":
tmpElem = driver.find_element(By.XPATH, "//label[@for='condo']")
if tmpElem.is_displayed():
tmpElem.click()
else:
print(f"Error - Address not found... - skipped...")
RUN = False
else:
print(f"Error - Wrong Property Type {inpData[1]} in B2... - stopped...")
RUN = False
if RUN:
time.sleep(WAIT)
print(f"Select value and date...")
driver.find_element(By.XPATH, "(//form[@name='typeForm']//following::button)[1]").click()
time.sleep(WAIT)
driver.find_element(By.XPATH, "//input[@name='price']").send_keys(str(inpData[3]))
time.sleep(WAIT)
driver.find_element(By.XPATH, "//select[@name='month']").send_keys(str(inpData[4]))
time.sleep(WAIT)
driver.find_element(By.XPATH, "//select[@name='year']").send_keys(str(inpData[5]))
time.sleep(WAIT)
driver.find_element(By.XPATH, "(//form[@name='priceForm']//following::button)[1]").click()
time.sleep(WAIT)
# driver.find_element(By.XPATH, "//input[@id='no-renovate']").click()
driver.find_element(By.XPATH, "//label[@for='no-renovate']").click()
time.sleep(WAIT)
driver.find_element(By.XPATH, "(//form[@name='renovatingForm']//following::button)[1]").click()
time.sleep(WAIT)
print(f"Wait for value...")
It crashes at this statement:
# driver.find_element(By.XPATH, "//input[@id='no-renovate']").click()
driver.find_element(By.XPATH, "//label[@for='no-renovate']").click()
with the error message:
File "C:\Users\Polzi\Documents\DEV\Fiverr\TRY\Collector85\checkAddrGS.py", line 231, in <module>
driver.find_element(By.XPATH, "//label[@for='no-renovate']").click()
File "C:\Users\Polzi\Documents\DEV\.venv\NormalScraping\lib\site-packages\selenium\webdriver\remote\webelement.py", line 80, in click
self._execute(Command.CLICK_ELEMENT)
File "C:\Users\Polzi\Documents\DEV\.venv\NormalScraping\lib\site-packages\selenium\webdriver\remote\webelement.py", line 693, in _execute
return self._parent.execute(command, params)
File "C:\Users\Polzi\Documents\DEV\.venv\NormalScraping\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 400, in execute
self.error_handler.check_response(response)
File "C:\Users\Polzi\Documents\DEV\.venv\NormalScraping\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 236, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <label for="no-renovate">...</label> is not clickable at point (1148, 360). Other element would receive the click: <div id="loader" ng-show="loading" tabindex="-1" aria-labelledby="loading-msg" role="alert" aria-live="assertive" style="">...</div>
The part of the html-sourcecode looks like this:
<form name="renovatingForm" style="">
<fieldset >
<legend > Are You Planning on Doing Any Home Renovations?</legend>
<input type="radio" id="yes-renovate" name="plannedRenos" ng-model="data.hasPlannedRenos" value="1" style="">
<label for="yes-renovate">Yes, I plan on renovating my home</label>
<input type="radio" id="no-renovate" name="plannedRenos" ng-model="data.hasPlannedRenos" value="0" style="">
<label for="no-renovate">No, I do not plan on renovating my home right now</label>
</fieldset>
<!-- ngIf: boughtAfter2005 --><p ng-bind-html="content.note_plan_on_renovating | trusted" ng-if="boughtAfter2005" style=""><span >Note:</span> If you’ve previously renovated your home, you will be able to add in those renovations later.</p><!-- end ngIf: boughtAfter2005 -->
<div >
<div >
<a href="javascript:void(0);" data-dig-id="mortgages-sSX5mfsS7sZM-38" ng-click="setStep(2, data);">
Back<span >Click for previous Step</span>
</a>
</div>
<div>
<button href="javascript:void(0);" ng-show="data.hasPlannedRenos == 0" ng-click="$root.GA4CustomEventTrigger('HVE - Planned Renovations - No Button'); setStep(5, data);" style="">
Continue<span >Next Step</span>
</button>
<button href="javascript:void(0);" ng-show="data.hasPlannedRenos == 1" ng-click="$root.GA4CustomEventTrigger('HVE - Planned Renovations - Yes Button'); setStep(4, data);">
Continue<span >Next Step</span>
</button>
<button href="javascript:void(0);" ng-show="data.hasPlannedRenos < 0" disabled="disabled">
Continue<span >Next Step</span>
</button>
</div>
</div>
<div >
<div>
<button href="javascript:void(0);" ng-show="data.hasPlannedRenos == 0" ng-click="setStep(5, data);" style="">
Continue<span >Next Step</span>
</button>
<button href="javascript:void(0);" ng-show="data.hasPlannedRenos == 1" ng-click="setStep(4, data);">
Continue<span >Next Step</span>
</button>
<button href="javascript:void(0);" ng-show="data.hasPlannedRenos < 0" disabled="disabled">
Continue<span >Next Step</span>
</button>
</div>
<div >
<a href="javascript:void(0);" data-dig-id="mortgages-sSX5mfsS7sZM-38" ng-click="setStep(2, data);">
Back<span >Click for previous Step</span>
</a>
</div>
</div>
<!--
<a role="button" href="javascript:void(0);" ng-hide="showSanityError" ng-click="setStep(3, data);"
ng-><span >{{content.get_results}}</span></a>
<a role="button" href="javascript:void(0);" ng-show="showSanityError" ng-click=""
ng-><span >{{content.get_results}}</span></a>
-->
<div ng-show="showSanityError">
The value entered appears to be outside the typical range for this neighbourhood (<span ng-show="lang == 'fr'" >de </span> <span ng-show="lang == 'fr'" >à</span><span ng-hide="lang == 'fr'">-</span> ), do you still want to continue? <a href="javascript:void(0);" ng-click="sendData(false);" >Yes</a>
</div>
</form>
How can i select the radio-button using Selenium?
CodePudding user response:
Walking through I was not able to repro your issue...and I believe it may be because you are using time.sleep to wait for elements to appear; drawback to this is sometimes it waits too long (a pain when debugging); or sometimes not long enough (and you error and have to iterate through testing attempts).
A better approach might be to leverage expected conditions to be met before interacting with an element. Might want to try something like below...
from selenium.common import exceptions
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def ClickByXPATH(NameOfObject):
try:
item = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.XPATH, NameOfObject)))
item.click()
except TimeoutException as e:
print("Couldn't Click by name on: " str(NameOfObject))
pass
#....
#driver.find_element(By.XPATH, "//label[@for='no-renovate']").click()
ClickByXPATH("//label[@for='no-renovate']")
#...
CodePudding user response:
This error message...
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <label for="no-renovate">...</label> is not clickable at point (1148, 360). Other element would receive the click: <div id="loader" ng-show="loading" tabindex="-1" aria-labelledby="loading-msg" role="alert" aria-live="assertive" style="">...</div>
...implies that the click event on the <label>
element is being intercepted by a loader-overlay.
To click() on the <label>
element:
First you have to induce WebDriverWait for the invisibility_of_element_located() for the loader element.
Then induce WebDriverWait for the desired element_to_be_clickable() and you can use either of the following locator strategies:
CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.invisibility_of_element_located((By.CSS_SELECTOR, "div.loader-overlay#loader[ng-show='loading'][aria-labelledby='loading-msg']"))) WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "label[for='no-renovate']"))).click()
XPATH:
WebDriverWait(driver, 20).until(EC.invisibility_of_element_located((By.XPATH, "//div[@class='loader-overlay' and @id='loader'][@ng-show='loading' and @aria-labelledby='loading-msg']"))) WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//label[@for='no-renovate']"))).click()
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC