Using Splinter to select from a dynamic menu - python

I am trying to run a splinter script in order to find a menu option in this webpage.
The menu's HTML looks like this:
<table border="0" cellpadding="0" cellspacing="0" width="100%" class="logo">
<tbody><tr>
<td align="left" style="background : url('gfx/tab_fill.png'); background-repeat : repeat-x;">
...
<a href="variants">
<img src="gfx/tab_variants_F.png" alt="View variants" id="tab_variants" width="58" height="25" align="left" class="">
</a>
...
</td>
</tr>
</tbody></table>
<ul id="menu_tab_variants" class="jeegoocontext" style="display: none; left: 180px; top: 90px;">
<li class="icon"><a href="/variants" class="">
<span class="icon" style="background-image: url(gfx/menu_magnifying_glass.png);"></span>View all genomic variants</a></li>
<li class="icon"><a href="/variants/in_gene" class="">
<span class="icon" style="background-image: url(gfx/menu_magnifying_glass.png);"></span>View all variants affecting transcripts</a></li>
<li class="icon"><a href="/submit" class="">
<span class="icon" style="background-image: url(gfx/plus.png);"></span>Create a new data submission</a></li>
...
</ul>
The script should hover over a menu header, show what is visible, and then hover out of it and show what elements are visible. But nothing appears visible.
from splinter import Browser
browser = Browser('firefox', wait_time=10)
browser.visit("http://databases.lovd.nl/shared/variants")
tab_variants = browser.find_link_by_href("variants")
print tab_variants
tab_variants.first.mouse_over()
print browser.find_link_by_partial_text(
"View all genomic variants").first.visible
print browser.find_link_by_partial_text(
"View all variants affecting transcripts").first.visible
tab_variants.mouse_out()
print browser.find_link_by_partial_text(
"View all genomic variants").first.visible
print browser.find_link_by_partial_text(
"View all variants affecting transcripts").first.visible
I get this output:
[<splinter.driver.webdriver.WebDriverElement object at 0x18c29d0>]
False
False
False
False
Am I using the mouse_over method as it is intended in splinter or is there something about this particular menu that splinter can't deal with.

The menu is not yet visible at the time you are checking the .visible property. You can however wait for it by moving the mouse to the sub menu:
from splinter import Browser
browser = Browser('firefox', wait_time=10)
browser.visit("http://databases.lovd.nl/shared/variants")
# move over the menu "Variant"
browser.find_by_id('tab_variants').mouse_over()
# move over the sub menu
browser.find_by_id('menu_tab_variants').mouse_over()
# print the menu items visibility
print browser.find_link_by_text("View all genomic variants").visible
print browser.find_link_by_text("View all variants affecting transcripts").visible
# move the mouse out of the sub menu
browser.find_by_id('menu_tab_variants').mouse_out()
# print the menu items visibility
print browser.find_link_by_text("View all genomic variants").visible
print browser.find_link_by_text("View all variants affecting transcripts").visible

Related

Python Selenium navigate and click a menu voice

i have a website made of a table. Each row has two a link elements.
Clicking on the second one it triggers a javascript which opens a menu.
With selenium i should navigate that menu till the "Properties" voice and to its relative submenu voice "Versions".
i tried with a simple find_element by Link_text, but it won't find the item
driver.find_element(by=By.LINK_TEXT, value="Properties").click()
i also tried with a try block but still won't find my element
try:
myElem = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.LINK_TEXT, "Properties")))
print("Found")
except TimeoutException:
print("Not Found!")
how can i access that element?
I need to select the menu voice "Properties", this way will be showed a submenu with the voice "Versions" which is the one i need to click.
How to do that?
here i attach a sample of the html code of the page
<td class="browseItemName" scope="rowgroup" nowrap="" width="100%">
<a class="mylink1" href="/test/">test link</a>
<div class="functionMenuDiv" style="left: 359px; top: 516px; z-index: 5; visibility: visible;">
<span class="functionMenu">
<div
class="menuItem"
onclick="javascript:popup_callback( escape( '/testlink/test12' ),'');return false;"
onmouseover="javascript:hiLight( 'mymenu0' );doSubMenu( 'mymenu0', 'funMenu4124' );"
onmouseout="javascript:loLight( 'mymenu0' );"
width="100%"
>
Download
</div>
<div id="mymenu14" class="menuItem" onmouseover="javascript:hiLight( 'mymenu14' );doSubMenu( 'mymenu14', 'funMenu4124' );" width="100%">
<div class="menuItemWithSubmenu" onclick="javascript:doKeyboardSubMenu( 'mymenu14', 'funMenu4124', event );return false;">
Properties
</div>
</div>
<div class="lastItemHilite"><img src="/tessst/spacer.gif" alt="" width="1" height="1" /></div>
</span>
<span class="subMenu" id="mymenu14Sub">
<div
class="menuItem"
onclick="javascript:popup_callback( escape( '/testlink/viewType%3D1' ), '' );return false;"
onmouseover="javascript:hiLight( 'mymenu14.0' );doSubMenu( 'mymenu14.0', 'mymenu14Sub' );"
onmouseout="javascript:loLight( 'mymenu14.0' );"
width="100%"
>
General
</div>
<div
class="menuItem"
onclick="javascript:popup_callback( escape( '/testlink/3D1' ), '' );return false;"
onmouseover="javascript:hiLight( 'mymenu14.5' );doSubMenu( 'mymenu14.5', 'mymenu14Sub' );"
onmouseout="javascript:loLight( 'mymenu14.5' );"
width="100%"
>
Versions
</div>
<div class="lastItemHilite"><img src="/tessst/spacer.gif" alt="" width="1" height="1" /></div>
</span>
</div>
</td>
Try doing the following:
driver.find_element(By.XPATH, f"{xpath}")
In this case xpath would be the link's xpath. If your wondering how to get xpath then go right-click inspect the link element. Then the elements "source code" will come up on the right. Right-click that and click copy > copy full xpath.

html - get text color using python selenium?

Anyone know how to get the text color for both "office" and "room"?
office_color = "#FD7C04"
room_color = "green"
HTML code:
<tr style="background-color:#999" id="tagging">
<td><b style="white-space: nowrap;"> tag_table</b></td>
<td style="text-align:center;">
<span class="big" style="font-size:24px; font-weight:700; color: #FD7C04">office</span></td>
<td style="text-align:center;">
<span class="big" style="font-size:24px; font-weight:700; color: green" id="rigan">room</span></td>
</tr>
First, get the element you want to extract your atribute from, in this case the span. You choose your prefered method for that. One of them is:
selector="body > span:nth-child(2)"
element1=driver.find_element_by_css_selector(selector)
element2=driver.find_element_by_id("#rigan")
One way to get this is opening the html on your browser, right click on the element and "copy selector" to get a css selector.
Then get the atribute from the elements:
color1=element1.get_attribute("color")
color2=element2.get_attribute("color")

Find dynamic content in div not iframe (python, selenium)

I am trying to scrape dynamic content from a webpage. The page shows the 10 first elements and then I have to click a 'next' button to access the next 10 and so on. The button clicking works fine. However, afterwards, it returns only empty lists after the button is clicked.
I would like to get the content of the following element:
//*[#id="bt-collapse-442112-slider"]/div[1]/div/div/div[1]/table/tbody/tr[1]/td[3]/div/h3
I noticed that the first div has the attribute "data-currentslidecount" which is "10" in the beginning but is added 10 each time the button is clicked.
My initial code looked like this:
> for a in range(100):
> WebDriverWait(driver, mywaits).until(EC.presence_of_element_located((By.XPATH,
> '//*[#id="bt-collapse-442112-slider"]/div[1]')))
> print(driver.find_element_by_xpath('//*[#id="bt-collapse-442112-slider"]/div[1]/div/div/div[1]/table/tbody/tr[1]/td[3]/div/h3').text)
> WebDriverWait(driver, mywaits).until(EC.element_to_be_clickable((By.XPATH,
> '//*[#id="bt-collapse-442112-slider"]/div[1]/button[2]')))
> button = driver.find_element_by_xpath('//*[#id="bt-collapse-442112-slider"]/div[1]/button[2]')
> button.click()
> button_count += 1
> print(button_count) driver.close()
Trying to find a solution I found out that often, this problem occurs when content is embedded in iframes, and that one needs to switch frames to get dynamic content. However, in, my case, there seems to be no iframe.
Also, I tried using find_element_by_css_selector instead of by_xpath because I thought I could access the div like this or maybe even loop over the slide count. However, `
find_element_by_css_selector(div[data-currentslidecount="10")
produced a syntax error. I didn't find a solution online for this specific css selector and also, I am not very hopeful that this will be the solution to my problem.
Edit:
Here is the HTML:
<div class="bt-slider row slick-initialized slick-slider" data-allitemcount="4184" data-currentslidecount="10"><button type="button" class="slick-prev slick-arrow slick-disabled" aria-disabled="true" style="display: block;"><span class="bab-slick-arrow-text">Zurück</span></button>
<div class="slick-list draggable">
<div class="slick-track" style="opacity: 1; width: 2264px; left: 0px;">
<div class="bt-slide col-xs-12 bt-standard-content slick-slide slick-current slick-active" data-slick-index="0" aria-hidden="false" style="width: 1132px;" tabindex="-1">
<table class="table bt-table-data">
<thead>
<tr>
<th>
<p>Veröffentlichung</p>
</th>
<th>
<p>Sitzung</p>
</th>
<th>
<p>Beschreibung</p>
</th>
</tr>
</thead>
<tbody>
<tr>
<td data-th="04.02.2019">
<p>
04.02.2019<br>Montag</p>
</td>
<td data-th="Sitzung">
<p>19/78</p>
</td>
<td data-th="Beschreibung">
<div class="bt-documents-description">
<h3>
78. Sitzung, 19. Wahlperiode, 01.02.2019</h3>

Selenium python click icon next to a certain text

I have the following structure, where I am trying to click the second trash icon which is a button next to Test1.
<tr class=“ng-scope”>
<td class=“ng-scope”></td>
<td class=“ng-scope”></td>
<td class=“ng-scope”>
<span class=“ng-binding”>Test0</span>
</td>
<td class=“ng-scope”>
<button class=“bin btn-xs”>
<i class="glyphicon glyphicon-trash"></i>
</button>
</td>
</tr>
<tr class=“ng-scope”>
<td class=“ng-scope”></td>
<td class=“ng-scope”></td>
<td class=“ng-scope”>
<span class=“ng-binding”>Test1</span>
</td>
<td class=“ng-scope”>
<button class=“bin btn-xs”>
<i class="glyphicon glyphicon-trash"></i>
</button>
</td>
</tr>
Currently how I am implementing is by doing find_element_by_xpath where xpath is //i#class="glyphicon glyphicon-trash" and do an index searching with the given results.
This however I find quit inefficient, especially the given results can be theoretically many and I have to loop through the result list.
I tried also the following lines:
myxpath = "//*[contains(text(), 'Test1')]/following-sibling::tr/button[#class='glyphicon glyphicon-trash']"
driver.find_by_xpath(myxpath)
which does not work (because the trash icon is not actually the sibling of Test1.
How can I implement this in a better way (i.e. I want to use Test1 as anchor and click the trash button next to it and not next to Test0)?
To select the button in the row having the text:
//tr[.//text()='Test1']//button
To select the button in cell 4 in the row having the text in cell 3:
//tr[td[3]//text()='Test1']/td[4]//button
To select the cell having the text and then the button in the following cell:
//td[.//text()='Test1']/following-sibling::td[1]//button"
I'm not very clear whether you want the button or the icon...
here is for the i tag
try
//i[#class='glyphicon glyphicon-trash' and ../../../td/span/text() = "Test1"]
ps note also that:
<span class="ng-binding">Test1</span>
and
<span class="ng-binding"> Test1 </span>
are different.

How to verify in selenium if the image is shown on the page?

I need to verify if a particular image is shown on page with selenium in python. HTML code looks like this when the image is displayed in a table cell:
<td role="gridcell">
<div style="text-align: center">
<img class="grid-center-image" border="0" ng-show="dataItem.device_protected" src="resources/images/icon_supported.png"/>
</div>
</td>
When the image is not displayed it looks like:
<td role="gridcell">
<div style="text-align: center">
<img class="grid-center-image ng-hide" border="0" ng-show="dataItem.device_protected" src="resources/images/icon_supported.png"/>
</div>
</td>
I do not understand how to approach this? How do I verify if the image is present on the screen?
You have to get class attribute of your img tag and then have to check that whether 'ng-hide' is present in it or not. That'll decide the presence of image on screen.
Below is the sample code in python to check visibility of image on screen.
elem = driver.find_element_by_xpath('//your/xpath/to/img/tag')
if 'ng-hide' in elem.get_attribute('class'):
print 'Image is not visible on screen'
else:
print 'Image is visible on screen'
To find out if the image icon_supported.png is hidden with a single call:
if driver.find_elements_by_css_selector("img[src$='icon_supported.png'].ng-hide") :
print "image hidden"
else :
print "image displayed"

Categories