I am trying to use Python Selenium to input a custom value in an input box on a website.
The html shows this element is stored within a table. The html and my code are shown below. I have tried sending keys on the element with class 'filterLink' and the class 'value'. Is it possible to send keys on a table data element?
Or should I be looking somewhere else in the html to send keys on this field?
The error I am getting is "Message: unknown error: cannot focus element"
Thanks very much!!
<div class="ContentSourceTypeData show" group="Provider Type">
<ul>
<li>
<table class="listItem">
<tbody>
<tr>
<td class="label">
<a class="filterLink" href="javascript:void(0);" value="bank" name="Banks" address="true">
<span class="value">Banks</span> (1831)
</a>
</td>
</tr>
.....
My code...
index_details_elem = browser.find_element_by_class_name('ContentSourceTypeData')
nameTable = index_details_elem.find_elements_by_class_name("listItem")[0] #
Select first listItem as element
nameDataElem = nameTable.find_element_by_class_name("label")
#nameInputElem = nameDataElem.find_elements_by_class_name("value") #used the above line instead of this one as the 'span' element seemed to be causing an issue
#print nameElem.location()
#nameDataElem.click() # removed as I can't click in a table
nameDataElem.send_keys("lookup value")
I would expect that you are able to send_keys to any selenium webelement. I would probably use a css selector (Maybe there is another element on the page with a name of "label"). Try doing:
webelement = "a[class=\"filterLink\"]"
webelement.send_keys("lookup value")
That will select all "a" elements, with a class value of "filterLink", and then send the keys "lookup value" to it.
Related
<div id="ccodeinput">
<input class="dropdownheader2" type="TEXT" name="CCODE" value="435435" size="14" maxlength="22">
</div>
This is the code for the Search field(see screenshot - upper right side). I am unable to pass values from a list to this search bar. But I am able to press the search button beside it.
How can I enter values in the search field?
This is what I have tried:
inputElement = chrome_driver.find_element_by_id('ccodeinput')
inputElement.send_keys(435435)
As per the HTML you have shared the <input> tag is a child of <div> tag, so to put text within the intended element you can use :
chrome_driver.find_element_by_xpath("//input[#class='dropdownheader2' and #name='CCODE']").send_keys("435435")
Given this code ("sleep" instances used to help display what's going on):
from splinter import Browser
import time
with Browser() as browser:
# Visit URL
url = "https://mdoe.state.mi.us/moecs/PublicCredentialSearch.aspx"
browser.visit(url)
browser.fill('ctl00$ContentPlaceHolder1$txtCredentialNumber', 'IF0000000262422')
# Find and click the 'search' button
button = browser.find_by_name('ctl00$ContentPlaceHolder1$btnSearch')
# Interact with elements
button.first.click()
time.sleep(5)
#Only click the link next to "Professional Teaching Certificate Renewal"
certificate_link = browser.find_by_xpath("//td[. = 'Professional Teaching Certificate Renewal']/following-sibling::td/a")
certificate_link.first.click()
time.sleep(10)
I am now trying to get the values from the table that shows after this code runs. I am not well-versed in xpath commands, but based on the response to this question, I have tried these, to no avail:
name = browser.find_by_xpath("//td[. ='Name']/following-sibling::td/a")
name = browser.find_by_xpath("//td[. ='Name']/following-sibling::td/[1]")
name = browser.find_by_xpath("//td[. ='Name']/following-sibling::td/[2]")
I tried [2] because I do notice a colon (:) sibling character between "Name" and the cell containing the name. I just want the string value of the name itself (and all other values in the table).
I do notice a different structure (span is used within td instead of just td) in this case (I also tried td span[. ='Name']... but no dice):
Updated to show more detail
<tr>
<td>
<span class="MOECSBold">Name</span>
</td>
<td>:</td>
<td>
<span id="ContentPlaceHolder1_lblName" class="MOECSNormal">MICHAEL WILLIAM LANCE </span>
</td>
</tr>
This ended up working:
browser.find_by_xpath("//td[span='Name']/following-sibling::td")[1].value
I want to recover a number that is located in the following table:
the site
<table class="table table-hover table-inx">
<tbody><tr>
</tr>
<tr>
</tr>
<tr>
</tr>
<tr>
<td class=""><label for="RentNet">Miete (netto)</label></td>
<td>478,28 €</td>
</tr>
<tr>
</tr>
<tr>
</tr>
<tr>
<td class=""><label for="Rooms">Zimmer</label></td>
<td>4</td>
</tr>
</tbody></table>
I suppose this strange format happens because the table entries are optional. I get to the table with driver.find_element_by_css_selector("table.table.table-hover") and I see how one could easily iterate through the <tr> tags. But how do I find the second <td> holding the data, in the <tr> with the <label for="Rooms"> ?
Is there a more elegant way than "find the only td field with a one-digit number" or load the detail page?
This similar question didn't help me, because there the tag in question has an id
EDIT:
I just found out about a very helpful cheat sheet for Xpath/CSS selectors posted in an answer to a related question: it contains ways to reference child/parent, next table entry etc
You can select the appropriate td tag using driver.find_element_by_xpath(). The XPath expression that you should use is as follows:
`'//label[#for="Rooms"]/parent::td/following-sibling::td'`
This selects the label tag with for attribute equal to Rooms, then navigates to its parent td element, then navigates to the following td element.
So your code will be:
elem = driver.find_element_by_xpath(
'//label[#for="Rooms"]/parent::td/following-sibling::td')
An example of the XPath expression in action is here.
With xpath, you can create a search for an element that contains another element, like so:
elem = driver.find_element_by_xpath('//tr[./td/label[#for="Rooms"]]/td[2]')
The elem variable will now hold the second td element within the "Rooms" label row (which is what you were looking for). You could also assign the tr element to the variable, and then work with all of the data in the row since you know the cell structure (if you would like to work with the label and data).
Have you tried xpath? Firebug is a great tool for copying xpaths. It will use indices to select the element you want. It's especially useful when your element has no name or ID.
Edit: not sure why I was down voted? I went on the site and found the XPath Firebug gave me:
/html/body/div[2]/div[7]/div[2]/div[3]/div/div[1]/div/div[3]/div[3]/div/table/tbody/tr[7]/td[2]
To get that 4, just:
xpath = "/html/body/div[2]/div[7]/div[2]/div[3]/div/div[1]/div/div[3]/div[3]/div/table/tbody/tr[7]/td[2]"
elem = driver.find_element_by_xpath(xpath)
print elem.text # prints '4'
And to get all the elements for "rooms", you can simply driver.find_elements_by_xpath using partial xpath, so like this:
xpath = "/div/div[1]/div/div[3]/div[3]/div/table/tbody/tr[7]/td[2]"
elems = driver.find_elements_by_xpath(xpath) # returns list
for elem in elems:
print elem.text # prints '3', '3', '4'
Finally, you might be able to get the data with page source.
First, let's make a function that outputs a list of rooms when we input the page source:
def get_rooms(html):
rooms = list()
partials = html.split('''<label for="Rooms">''')[1:]
for partial in partials:
partial = partial.split("<td>")[1]
room = partial.split("</td>")[0]
rooms.append(room)
return rooms
Once we have that function defined, we can retrieve the list of room numbers by:
html = driver.page_source
print get_rooms(html)
It should output:
["3", "3", "4"]
This HTML block:
<td class="tl-cell tl-popularity" data-tooltip="9,043,725 plays" data-tooltip-instant="">
<div class="pop-meter">
<div class="pop-meter-background"></div>
<div class="pop-meter-overlay" style="width: 57%"></div>
</div>
</td>
equates to this XPath:
xpath = '//*[#id="album-tracks"]/table/tbody/tr[5]/td[6]'
Trying to extract the text: 9,043,725 plays with
find_element_by_xpath(xpath).text()
returns an empty string. This text is only generated when a user hovers their mouse over the HTML block.
Is there a way to alter the XPath so that an empty string is not returned but the actual string is returned?
Try using get_attribute instead. The intended element can be located using any find_elements mechanisms. See the API DOC
element = browser.find_elements_by_css_selector('.tl-cell.tl-popularity')
text = element.get_attribute('data-tooltip')
I'm trying to get WebDriver to hover over a table row in order to make a "delete" link appear. Each row contains a hidden input with an item name as the value, and since the item name will be known by people writing tests (but the specific row in which it appears will not) I am trying to locate the row using the item name.
My basic plan is to locate the input and then look for its ancestor .
I've tried with both Xpath and CSS, and while I can get close (I can get the input) I can't seem to get back up to the element. Since the input is hidden I can't simply hover over it.
Here's what I've got:
def delete_row_by_item_or_task_name(self, item_name=None, task_name=None):
try:
if item_name:
name = item_name
table_id = 'invoice-items'
if task_name:
name = task_name
table_id = 'invoice-time'
# tr = self.driver.find_element_by_css_selector("#" + table_id + " input[value=" + name + "]")
tr = self.driver.find_element_by_xpath("//*[#id='" + table_id + "']/tbody/tr/td/div/div/input[contains(.,'" + name + "')]")
import pdb; pdb.set_trace()
self.hover(tr)
self.driver.find_element_by_link_text('Delete line').click()
The CSS selector works, if I drop a pdb in and check the variable 'td' is a web element. But as I mentioned I can't hover over a hidden input and trying to add /ancestor::tr results in an exception (WebDriverException).
The Xpath results in a NoSuchElement exception with or without the /ancestor::tr
Please let me know if any information needed is missing, I would be happy to provide more detail.
Based on your xpath, I am assuming your HTML looks something like:
<table id="table_id">
<tbody>
<tr>
<td>
<div>
<div>
<input value="item_name" type="hidden" >
</div>
</div>
</td>
</tr>
</tbody>
</table>
If you want the <tr> that contains the input with value "item_name", then you can use the following xpath:
"//table[#id='" + table_id + "']/tbody/tr[./td/div/div/input[contains(#value, '" + name + "')]]"
This will return the <tr> element directly, so you do not need to find the ancestor of the input element. Basically this is saying, 'find me the tr that contains the input element'.