Python, selenium chrome driver to fill form (element ids' changing) - python

a part of company internal webpage looks like this:
It's the first form of the webpage. I want to key in numbers into this form.
The problem is that, the element id is changing when the webpage is refreshed. So I tired driver.find_element_by_xpath and driver.find_element_by_css_selector, it's not catching the form everytime.
So I am thinking maybe locate the line of text "Customer No.", then move to its next element, could be a choice. but again, the element id of "Student No." is also changing.
Is there a way to catch the form by the text "Student No."? Or there's a better option? thank you.
part of HTML code as below:
<div class="labeledField">
<div class="fieldLabel beanRequiredField">Student No.</div>
<div class="field"><span id="id16">
<div>
<input type="text" class="inputField" value="" name="tabs:r:0:c:0:c:field:c:p:r:0:c:0:c:field:c:frag:component" id="id4e" customid="StudentId" autocomplete="off">
</div>
</span></div>
</div>

driver.find_elements_by_class_name('inputField')[0].send_keys('Text')
It works!

Maybe this will solve your problem:
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//input[#id='text3']")));

If you want to base on "Student No." string, then you can go with XPath selector:
//div[text()="Student No."]/../div[2]/span/div/input
So for Python it would be something like this:
input = driver.find_element(By.XPATH, '//div[text()="Student No."]/../div[2]/span/div/input')

Related

Python, Selenium: How to get text next to element

I'm fairly new to selenium and I'm trying to get the text of a cell next to a known element.
This is an excerpt of a webtable:
<div class="row">
<div class="cell">
text-to-copy
</div>
<div class="cell">
<input type="text" size="10" id="known_id" onchange="update(this.id);" onclick="setElementId(this.id);"/>
X
</div>
<div class="cell right">
<div id="some_id">?</div>
</div>
</div>
It looks something like this:
From this table I would like to get the text-to-copy with selenium. As the composition of the table can vary, there is no way to know that cells xpath. Therefore I can not use selenium_driver.find_element_by_xpath(). The only known thing is the id of the cell next to it (id=known_id).
The following pseudo code is to illustrate what I'm looking for:
element = selenium_driver.find_element_by_id("known_id")
result = element.get_visible_text_from_cell_before_element()
Is there a way to get the visible text (text-to-copy) with selenium?
I believe you can fairly use xpath, all other locators that Selenium supports would not work, becasue we have to traverse upward in DOM.
The below xpath is dependent on known_id
//input[contains(#id,'known_id')]/../preceding-sibling::div
You have to either use .text or .get_attribute etc to get the text.
Sample code :
time.sleep(5)
element = selenium_driver.find_element_by_xpath("//input[contains(#id,'known_id')]/../preceding-sibling::div").get_attribute('innerText')
print(element)

How do I tick a checkbox in a table and modal window?

On a website, I need to click a checkbox in a modal window that pops up.
I can't seem to get the proper xpath for it.
I've tried:
req_checkbox = driver.find_element_by_xpath("//td/div/input[#data-id='34970']")
driver.execute_script("arguments[0].click();", req_checkbox)
Also tried:
req_checkbox = WebDriverWait(usedriver, 15).until(EC.presence_of_element_located((By.XPATH,'//div[#class="grid-check-box"]/input[#data-id="34970" and type="checkbox"]')))
The data-id is what would make that checkbox unique as there is more than one checkbox with the same class. Here is the code snippet:
<td role="gridcell" id="AddFromFirmMasterListGrid_active_cell" class="">
<div class="grid-check-box">
<input class="LinkServiceContactToEnvelopeMap" data-id="34970" data-idtoken="5F3244E8BF5E488D14E28C05BE2DD2C524B5E9F0" data-envelopeidtoken="0A1257B11E29C56650A270E56FD12007CDF2F917" type="checkbox">
<span></span>
</div>
</td>
How do I solve this problem?
You can try with this css selector :
div.grid-check-box input.LinkServiceContactToEnvelopeMap[type='checkbox']
Xpath would be :
//div[#class='grid-check-box']/input[#class='LinkServiceContactToEnvelopeMap' and #type='checkbox']
First check that in DOM, if there are multiple enteries then you will have to make necessary changes.
Let me know, if you have any more concerns.

ElementNotVisibleException: element not visible Python

I'm new to Python and Selenium and I've come across an issue when trying to click on a button via webdriver.
The HTML of the div I'm trying to click through is:
<div class="">
<form method="POST">
<input class="hide" id="accept" name="accept" type="text" value="yes" readonly="">
<a href="/" class="btn btn-red">
<div class="svg-group group icn-bg-circle" data-png-fallback="">
<svg width="8" height="8">
<use xmlns:xlink=" " xlink:href=""></use>
</svg>
</div>
Decline
</a>
<button class="btn btn-green" type="submit">
<div class="svg-group group icn-bg-circle" data-png-fallback="">
<svg width="8" height="8">
<use xmlns:xlink="" xlink:href=""></use>
</svg>
</div>
Accept
</button>
</form>
</div>
I want to use .click() on the button with class name 'class="btn btn-green"'.
I have used the following code to select the element (after following the solutions in other similar SO questions.
driver.find_element_by_css_selector(".btn-green")
It looks like webdriver can find the element but when I try to apply .click() I get:
ElementNotVisibleException: element not visible
I then did some digging into the element (thinking I could bypass by using x, y coordinates to click through) but after using .size and .location I get:
{'x': 0, 'y': 0}
{'height': 0, 'width': 0}
Any help you could give on how to get around this would be really appreciated.
Thanks
The error hints to the potential problem, selenium does find it but it is not visible so you cannot click on it. You could check for visibility with is_displayed before clicking on it. Another possibility is if there is another button with that class that is hidden, try to see if you can select a visible element in the browser console (Control+Shift+J) with $(".btn-green")
Some xpaths that might work that are more robust for your problem:
//button[#type="submit" and text()="Accept"]
//button[#type="submit" and contains(#class, "btn-green")]
To click on the button with text as Accept you can use the following line of code :
driver.find_element_by_css_selector("button.btn.btn-green[type='submit']")

Send_keys() doesn´t send the full string

I´m trying to login to a website with selenium and Chrome in Python. I´m able to locate the user and password field, and the button. The only thing I´m not capable of is filling the password field with all the string. It writes a substring, with varying lengths.
My code
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
browser=webdriver.Chrome(r"C:\Users\Visente\Desktop\Pablito Python\chromedriver.exe")
urlbet='https://www.bet365.es/?&cb=103265469#/HO/'
browser.get(urlbet)
sport=WebDriverWait(browser, 10).until(
EC.presence_of_element_located((By.XPATH,'//*[#id="dv1"]/a')))
sport.click()
user=WebDriverWait(browser,
10).until(EC.presence_of_element_located((
By.XPATH,'/html/body/div[1]/div/div[1]/div/div[1]/div[2]/div/div[1]/input')))
passw=browser.find_element_by_xpath(
'/html/body/div[1]/div/div[1]/div/div[1]/div[2]/div/div[2]/input[1]')
user.send_keys('my_user')
passw.send_keys('password')
submit=browser.find_element_by_xpath(
'/html/body/div[1]/div/div[1]/div/div[1]/div[2]/div/div[2]/button')`
submit.click()
So, in short, the line where y use send_keys() on variable passw is not writing the full length of the password and I don´t know why.
By the way, how do I get back the text I just sent with sed_keys() in order to know what is being passed and what is missing from the string?
I had the same problem, I first click in the element then I send the text, it solved the problem.
el_search_wo.driver = driver.find_element_by_xpath("//*[#id='arid_WIN_0_302258625']")
el_search_wo.click()
el_search_wo.send_keys('TEXT HERE')
You're not supposed to type the password in the field you've selected. As you've noted in the comments, the xpath switches from input[1] to input[2]. The latter is where you're supposed to put the password. I don't understand the mechanism by which the xpath changes when you try to send keys there, but it does. Depending on how quickly it changes, anything from 0 to a few characters will be sent to the wrong input, which explains why the password field ends up with a substring of your password.
From the html, we can see there are 3 input fields, all belonging to the class 'hm-Login_InputField'.
<div class="hm-Login ">
<div class="hm-Login_UserNameWrapper ">
<input type="text" class="hm-Login_InputField ">
<div class="hm-Login_InputText " style="">
Registrarse
</div>
</div>
<div class="hm-Login_PasswordWrapper ">
<input type="text" class="hm-Login_InputField Hidden ">
<input type="password" class="hm-Login_InputField ">
<button tabindex="0" class="hm-Login_LoginBtn ">
IR
</button>
<div class="hm-Login_InputText ">
Recordar contraseña
</div>
</div>
</div>
If you collect them all, from top to bottom, they are the username, the field you tried to put the password in and the password field.
Now, if you try to send the keys directly to the password field, input[2], you will get an error that the element is not visible. You have to first click on input[1] in order to make input[2] visible.
You can easily do it with xpaths, but I find the following approach cleaner.
login = WebDriverWait(browser, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, 'hm-Login')))
fields = login.find_elements_by_css_selector('.hm-Login_InputField')
button = login.find_element_by_css_selector('.hm-Login_LoginBtn')
fields[0].send_keys('user_name')
fields[1].click()
fields[2].send_keys('password')
button.click()

Error trying to login to webpage using selenium with python

I get an element isn't visible error:
ElementNotVisibleException: Message: u'Element is not currently visible and so may
not be interacted with'
For every find element line when I run this code:
from selenium import webdriver
browser = webdriver.Firefox()
browser.get('http://www.example.com')
browser.find_element_by_name('username').send_keys('myusername')
browser.find_element_by_name('password').send_keys('mypassword')
browser.find_element_by_class_name('welcomeLoginButton').click()
The HTML for the login section of the page looks like this:
<div class='welcomeLoginUsername'>
<div class='welcomeLoginUsernameLabel'><b>Username:</b></div>
<div class='welcomeLoginUsernameInput'><input type='text' name='username' tabindex='1'>
<br><a class='sf' href='javascript: void(0);' onclick='showUsernamePopup();'>
<b>Forgot Username?</b></a>
</div>
</div>
<div class='welcomeLoginPassword'>
<div class='welcomeLoginPasswordLabel'>
<b>Password:</b>
<br><span class='sf'>(It's cAsE sEnSitIvE!)</span>
</div>
<div class='welcomeLoginPasswordInput'>
<input type='password' name='password' tabindex='2'>
<br><a class='sf' href="javascript: void(0);" onclick="showPasswordPopup();">
<b>Forgot Password?</b></a>
</div>
</div>
</div>
<input type="submit" value="" class='welcomeLoginButton' style='border: 0px;
padding: 0px; margin: 0px;) no-repeat;' onclick='document.forms["login"].submit()'>
Selenium interacts with the web browser in a similar way that the user would. So if there is an html element you're trying to interact with that is not visible then the simplest explanation is that when youre writing your selenium code you're not interacting with the web page like a normal user would.
In the end this isn't about the html of your web page its about the DOM and an element's hidden attribute. I suggest you download firebug or some other html viewer program, and then highlight the button you want to press. Use the DOM lookup for the html viewer and go through the sign in process manually. Notice what you have to do to make the element visible in order to interact with it then mimic the same steps in your selenium code.
If it is a matter of the fact that you did everything you needed to do, but selenium is interacting with the web page faster than the javascript will make the element visible then there is a wait that you have to programmed in.
Naive way:
import time
time.sleep(1) # this is done in seconds
More scalable manner:
import time
welcome_button = browser.find_element_by_class_name('welcomeLoginButton')
wait_for_element_visibility(welcome_button).click()
def wait_for_element_visibility(element):
if element.is_visible():
return element
else:
for i in range(10):
if not element.is_visible():
time.sleep(.5)
else:
return element

Categories

Resources