How do I click on a dynamically loaded link? - python

I am currently working on web automation via Selenium.
I have a html file where the relevant part is this:
<table>
<tbody>
<tr>
<td class="tabon" nowrap="">
<div class="tabon">
<a id="tab" href="(long dynamically generated string)">
<b>Main Page</b>
</a>
</div>
</td>
<td class="taboff" nowrap="">
<div class="taboff">
<a id="tab" href="(another long string)">Info</a>
</div>
</td>
</tr>
</tbody>
</table>
I want to be able to access the second tab. Using Selenium I can't actually "click" on the div tag.
try:
browser.find_element_by_xpath(
'//table/tbody/tr/td[2]/div/a').click()
except NoSuchElementException:
print ('error')
This always results in an error. It has something to do with the fact that when the div tag is interacted with, it clicks on the URL anchor which changes the div such that the clicked on tag has a "tabon" property. How can Selenium mimic this?
EDIT: I neglected to note that the class with "tabon" has the title of the page in a separate bold tag.

Try this code, in case the tab "My Info" is visible on the webpage:
browser.find_element_by_xpath("//a[.='My Info']").click()
This will click on the element with tag 'a' and having exact innerHTML/text as My Info.

You need to be passing click on a tag not on div and in addition to the solution Subh provided you can use .taboff a as cssselector. This selector walks you down to a tag from second td of pasted html

Related

Python Selenium, select the next element in html DOM

i have to make some automation on a page.
The page consists of table where inside each td element i have 2 a tags, the first one with a class, the second one has no class or id.
i can easily select the one with the class, but how to get the other one? is there a way to select the element next to another one like in css?
this is a draft of the structure of the page
<table>
<tr>
<td>
<a class="mylink"> element 1 </a>
<a>
<img src="">
</a>
</td>
</tr>
<tr>
<td>
<a class="mylink"> element 2 </a>
<a>
<img src="">
</a>
</td>
</tr>
</table>
I can select the first one with
fileLinkClass = "mylink"
driver.find_element(by=By.CLASS_NAME, value=fileLinkClass)
but i need to select and click the a link without the class. How can i accomplish this?
Thank you so much
You can use xpath selector
'//td/a[2]'
to find all second 'a's under a 'td'
Try using css selector
For single element selection
driver.find_element(By.CSS_SELECTOR,'.mylink + a')
For multiple elements selection
driver.find_elements(By.CSS_SELECTOR,'.mylink + a')
Make a list slicing then click. For example:
element = driver.find_elements(By.CSS_SELECTOR,'.mylink + a')
element = element[0].clik()
element = element[1].clik()

Selenium Python find text on page and click next ahref link

I am trying to use selenium to find the text 'APPELLANT'S BRIEF FILED" and then have selenium click the very next ahref link. Below is the table class code on the page and the relevant td align code that I am focused on.
<table class="gridview" cellspacing="0" align="Center"
id="SheetContentPlaceHolder_caseDocket_gvDocketInformation"
style="border-collapse:collapse;">
<tbody><tr class="gridview_header">
This is the code I am focused on.
<tr style="background-color:Gainsboro;">
<td align="left" valign="top" style="width:75px;">04/10/2015</td>
<td align="left" valign="top">A1</td>
<td align="left" valign="top">EV</td>
<td align="left">**APPELLANT'S BRIEF FILED**. APPELLANT'S BRIEF</td>
<td align="center">
<a href="**DisplayImageList.aspx?q=IXEpMLEtUn6VTtFyd8FAyx5-hPNZuKfx0**"
target="_blank"><img src="images/ImageSheet.png" alt=""></a>
</td>
</tr>
Try this xpath //td[contains(., "APPELLANT'S BRIEF FILED")]/following-sibling::td[1]/a
driver.find_element_by_xpath("""//td[contains(., "APPELLANT'S BRIEF FILED")]/following-sibling::td[1]/a""")
To find any text within the table e.g. APPELLANT'S BRIEF FILED and then have invoke click() on the very next href link you can write a function which will accept the desired text as an input and click on the next href as follows :
def test_me(string):
driver.find_elements_by_xpath("//td[.='" + myString + "']//following::td[1]/a").click()
Now you can call the function test_me() from anywhere within your program with any of the text item from the table to click on the relevant href as follows :
test_me("APPELLANT'S BRIEF FILED")

Get td class text with selenium

So I want to take the text of td class.
The html page
<table class="table table-striped">
<tbody>
<tr>
<td class="text-center">
<img .....>
</td>
<td>text</td>
<td>text</td>
<td class="text-center">
<a ....></a>
</td>
<td class="text-center">
TEXT I WANT TO TAKE HERE
</td>
<td class="text-center">
<a ....><i class="fa fa-times"></i></a>
</td>
</tr>
</tbody>
</table>
The text I want to take is "TEXT I WANT TO TAKE HERE".
I tried using the xpath like below but it didnt work
table = browser.find_element_by_xpath(("//div[#class='table table-striped']/tbody/tr/td[5]"));
I got an error saying:
no such element: Unable to locate element: {"method":"xpath","selector":"//div[#class='table table-striped']/tbody/tr/td[5]"}
Is it because I have multiple classes in the selector and I have to use dot?
(I tried: 'table.table-striped' but it still didnt work)
Your xpath is incorrect. You have a table tag but, you are looking for a div tag. So, you just need to replace div with table.
table = browser.find_element_by_xpath(("//table[#class='table table-striped']/tbody/tr/td[5]"));
Use below xpath to get the text
browser.find_element_by_xpath("//td[#class='text-center']").text
And use the index as well to better find your row e.g.
browser.find_element_by_xpath("//td[#class='text-center'][3]").text
Use Below xpath to get the text TEXT I WANT TO TAKE HERE
//table//tr/td[contains(text(), 'TEXT I WANT TO TAKE HERE')]
Updated Answer: You can refer any of these below mentioned xpath to get your webelement.
//td[5]
OR
//table[#class='table table-striped']//td[5]
OR
//table[#class='table table-striped']/..//following-sibling::td[5]
OR
//td[#class='text-center'][3]
In your XPath expression you are looking for a div tag, but your HTML does not have that. Perhaps you are looking to the table tag:
table = browser.find_element_by_xpath(("//table[#class='table table-striped']/tbody/tr/td[5]"));

check if text contained in a font tag

Im using selenium in python in order to check if a text between font tags in contained and getting the tag tbody back if it is.
the html code:
<table width="100%" border="0" cellspacing="1" cellpadding="1" bgcolor="#000000" height="80">
<tbody>
<tr bgcolor="#666699">
<td height="17" bgcolor="#CCCC99">
<font size="2"><b><font face="Arial, Helvetica, sans-serif">PARTY 1</font></b></font>
</td>
</tr>
<tr>
some html code...
</tr>
</tbody>
</table>
As you can see the this is an example i need to check in the html page if the has PARTY 1 in it and if so getting the tbody element back.
I should say that there is no way to get the element using id because there are other tables written in the same way.
I'v already tried using //font[contains(.,'PARTY 1')] but as it didnt worked
what is the best way to use selenium and check if PARTY 1 is in the and get tbody elment back??
This xpath return TBODY tag which contains FONT tag with 'PARTY 1' text:
//tbody[.//font[contains(.,'PARTY 1')]]
First get the font element using el = driver.find_element_by_xpath('insert xpath here') and then use el.text to get the text. You're code should look like this:
el = driver.find_element_by_xpath('insert xpath of font tag here')
if el.text == 'PARTY 1':
return driver.find_element_by_xpath('insert xpath of tbody here')

python BeautifulSoup4 break for loop when tag found

I have a problem breaking a for loop when going trough a html with bs4.
I want to save a list separated with headings.
The HTML code can look something like below, however it contains more information between the desired tags:
<h2>List One</h2>
<td class="title">
<a title="Title One">This is Title One</a>
</td>
<td class="title">
<a title="Title Two">This is Title Two</a>
</td>
<h2>List Two</h2>
<td class="title">
<a title="Title Three">This is Title Three</a>
</td>
<td class="title">
<a title="Title Four">This is Title Four</a>
</td>
I would like to have the results printed like this:
List One
This is Title One
This is Title Two
List Two
This is Title Three
This is Title Four
I have come this far with my script:
import urllib2
from bs4 import BeautifulSoup
html = urllib2.urlopen('some webiste')
soup = BeautifulSoup(html, "lxml")
quote1 = soup.h2
print quote1.text
quote2 = quote1.find_next_sibling('h2')
print quote2.text
for quotes in soup.findAll('h2'):
if quotes.find(text=True) == quote2.text:
break
if quotes.find(text=True) == quote1.text:
for anchor in soup.findAll('td', {'class':'title'}):
print anchor.text
print quotes.text
I have tried to break the loop when "quote2" (List Two) is found. But the script gets all the td-content and ignoring the next h2-tags.
So how do I break the for loop with next h2-tag?
In my opinion the problem lies in your HTML syntax. According to https://validator.w3.org it's not legal to mix "td" and "h3" (or generally any header tag). Also, implementing list with tables is most likely not a good practice.
If you can manipulate your input files, the list you seem to need could be implemented with "ul" and "li" tags (first 'li' in 'ul' containing the header) or, if you need to use tables, just put your header inside of "td" tag, or even more cleanly with "th"s:
<table>
<tr>
<th>Your title</th>
</tr>
<tr>
<td>Your data</td>
</tr>
</table>
If the input is not under your control, your script could perform search and replace on the input text anyway, putting the headers into table cells or list items.

Categories