'Fill or ignore required random field with selenium python
I am practicing with selenium to log into a website and grab the mortage ticket (print/save/download it as pdf).
The logging page is as follows:
Field 1: Contract number
Field 2: National user-id
Botton: Botton to validate the contract
Field 3: Requests some aleatory personal info (day of birh, mother's name, zip code, National Health ID, voter registration etc.) each time the page is accessed/refreshed
When I log to it (every month) throughout the user page, when it comes to some aleatory info that I don't know by heart (such as National Heatlh ID or voter registration), I refresh the page until it brings me some easy to remember info(phone number, zip code, etc.).
What can I do to go through this last field that requests personal information in a random way(some that I know by heart, others I do not)?
The website code referring to the 3rd field is as follows. The parameters name="zipCode" and placeholder="Zip Code" parts are the ones that keeps changing their values each time the page is refreshed.
input id="aleatoryField" class="mat-input-element mat-form-field-autofill-control
ng-tns-c4-1 cdk-text-field-autofill-monitored ng-dirty ng-invalid ng-touched"
_ngcontent-iqu-c4="" autocomplete="off"
formcontrolname="aleatoryField" inputmode="decimal" matinput=""
pattern="[0-9]*" required="" name="zipCode" placeholder="Zip Code"
aria-describedby="mat-error-2" aria-invalid="true" aria-required="true"
input id="aleatoryField" class="mat-input-element mat-form-field-autofill-control ng-tns-c4-1 cdk-text-field-autofill-monitored ng-dirty ng-invalid ng-touched"
_ngcontent-iqu-c4="" autocomplete="off"
formcontrolname="aleatoryField" inputmode="decimal" matinput=""
pattern="[0-9]*" required="" name="voterId" placeholder="Voter Registration"
aria-describedby="mat-error-2" aria-invalid="true" aria-required="true"
input id="aleatoryField" class="mat-input-element mat-form-field-autofill-control ng-tns-c4-1 cdk-text-field-autofill-monitored ng-dirty ng-invalid ng-touched"
_ngcontent-iqu-c4="" autocomplete="off"
formcontrolname="aleatoryField" inputmode="decimal" matinput=""
pattern="[0-9]*" required="" name="yearBirth" placeholder="Year of Birth"
aria-describedby="mat-error-2" aria-invalid="true" aria-required="true"
# MY CURRENT CODE
from selenium import webdriver
driver = webdriver.Firefox(executable_path="./geckodriver.exe" )
# open the website
driver.get("https://www.habitacaodigital.caixa.gov.br/acesso-cliente")
# FIELD 1: contract info
contract = driver.find_element_by_id("contract")
national_id = driver.find_element_by_id("nationalId")
# FIELD 2: filling the contract info
contract.send_keys("123")
national_id.send_keys("321")
# botton
validate_contract = driver.find_element_by_id("validate_contract")
validate_contract.click()
# FIELD 3: aleatory personal info field (cellphone number, zip code, day of birth, mother's name...)
# aleatory_field = driver.find_element_by_id("aleatoryField")
# aleatory_field.send_keys("HOW TO DEAL WITH THIS PART OVER HERE?")
# undetected Selenium suggestion
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input#aleatoryField[formcontrolname='aleatoryField']"))).send_keys("234567")
# LOGGING BOTTON
btn_logging = driver.find_element_by_id("btn_access")
btn_logging.click()
Solution 1:[1]
It seems you have no problem with dynamic element since element id was never changed. you have problem with input values based on type of the field name appeared on the screen on each login.
You can use python switch case and configured all return type attribute name and then call the function and if it matches the specific name then execute that block only with your input.
def SetInputValue(element, elementAttVal):
match elementAttVal:
case "zipCode":
element.send_keys("400910")
case "voterId":
element.send_keys("1234588999")
case "yearBirth":
element.send_keys("1990")
//identify the element
element=WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "input#aleatoryField")))
//Get the name attribute value
elementAttVal=element.get_attribute("name")
print(elementAttVal)
//Set the input based on name attribute
SetInputValue(element,elementAttVal)
Update: with if..block like that you have add the remaining config as well
def SetInputValue(element, elementAttVal):
if elementAttVal=="zipCode":
element.send_keys("400910")
if elementAttVal=="voterId":
element.send_keys("1234588999")
if elementAttVal=="yearBirth":
element.send_keys("1990")
//identify the element
element=WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "input#aleatoryField")))
//Get the name attribute value
elementAttVal=element.get_attribute("name")
print(elementAttVal)
//Set the input based on name attribute
SetInputValue(element,elementAttVal)
Solution 2:[2]
To send a character sequence to the <input> element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input#aleatoryField[formcontrolname='aleatoryField']"))).send_keys("234567")Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@id='aleatoryField' and @formcontrolname='aleatoryField']"))).send_keys("234567")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
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |

