Python Selenium navigate and click a menu voice - python

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.

Related

Selenium clicking a specific button object from a list of objects with python

I am grabbing a list of buttons, then I am attempting to click a specific button object, I collect all buttons (which contain details such as a name). I check the name, if I have already clicked on this button, pass, or else click this button object.
The problem I am having is that the button doesn't have an ID so I am unsure of how to dynamically identify the button to click it (from the object in the loop). It doesn't have an HREF either.
If it had an ID, I could grab the ID value and build a selenium click even such as browser.find_element(By.ID, "button-ID").click().
Any pointers would be appreciated.
html = browser.page_source
soup = BeautifulSoup(html, "lxml")
buttons = soup.find_all('button', {'class', 'full-width'})
for button in buttons:
button_soup = BeautifulSoup(str(button), 'lxml')
name_div = button_soup.find('div', {'class': 'artdeco-entity-lockup__title'})
name = name_div.find('span', {'aria-hidden': 'true'}).text
if name in lead_check:
pass
else:
"""HERE IS WHERE I NEED TO CLICK THE BUTTON OBJECT"""
browser.find_element(By.CSS_SELECTOR, "button.full-width").click()
Button Object (one button from loop) example
<button class="full-width member-analytics-addon__cta-list-item-content member-analytics-addon-entity-list__link member-analytics-addon-entity-list__link--no-underline-hover" role="button" type="button">
<div class="member-analytics-addon-entity-list__entity artdeco-entity-lockup artdeco-entity-lockup--size-3 ember-view" id="112">
<div class="artdeco-entity-lockup__image artdeco-entity-lockup__image--type-circle ember-view" id="113" type="circle">
<div class="ivm-image-view-model">
<div class="ivm-view-attr__img-wrapper ivm-view-attr__img-wrapper--use-img-tag display-flex">
<!-- --> <img alt="" class="ivm-view-attr__img--centered EntityPhoto-circle-3 EntityPhoto-circle-3 lazy-image ember-view" height="48" id="114" loading="lazy" src="linktopic" width="48"/>
</div>
</div>
<!-- -->
</div>
<div class="artdeco-entity-lockup__content ember-view member-analytics-addon-entity-list__entity-content" id="115">
<div>
<div class="artdeco-entity-lockup__title ember-view member-analytics-addon-entity-list__entity-content-title" id="116">
<span dir="ltr"><span aria-hidden="true"><!-- -->John Smith<!-- --></span><span class="visually-hidden"><!-- -->View Johns’s profile<!-- --></span></span>
</div>
<div class="artdeco-entity-lockup__badge ember-view t-normal" id="117"><!-- --> <span aria-hidden="false" class="artdeco-entity-lockup__degree">
· 3rd
</span>
<!-- --><!-- --></div>
<div class="artdeco-entity-lockup__subtitle ember-view" id="118">
<!-- -->Loves cats<!-- -->
</div>
<!-- --> </div>
<!-- --> </div>
</div>
</button>
I solved this by identifying a unique variable in each button, in this instance an IMG URL then dynamically located each with selenium.
img_src = button_soup.find('img')['src']
path_location = "//img[contains(#src,'{}')]".format(img_src)
browser.find_element(By.XPATH, path_location).click()

How to get parents of an element with xpath in selenium (python)

I have a script that takes all the images I want on a webpage, then I have to take the link that enclose the image.
I actually click on every image, take the current page link and then I go back and continue with the work. This is slow but I have an a tag that "hug" my image, I don't know how to retrieve that tag. With the tag it could be easier and faster. I attach the html code and my python code!
HTML code
<div class="col-xl col-lg col-md-4 col-sm-6 col-6">
<a href="URL I WANT TO GET ">
<article>
<span class="year">2017</span>
<span class="quality">4K</span>
<span class="imdb">6.7</span>
<img width="190" height="279" src="THE IMAGE URL" class="img-full wp-post-image" alt="" loading="lazy"> <h2>TITLE</h2>
</article>
</a></div>
<div class="col-xl col-lg col-md-4 col-sm-6 col-6">
<a href="URL I WANT TO GET 2">
<article>
<span class="year">2019</span>
<span class="quality">4K</span>
<span class="imdb">8.0</span>
<img width="190" height="279" src="THE IMAGE URL 2" class="img-full wp-post-image" alt="" loading="lazy"> <h2>TITLE</h2>
</article>
</a></div>
Python code
self.driver.get(category_url)
WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, 'div.archivePaging'))) # a div to see if page is loaded
movies_buttons = self.driver.find_elements_by_css_selector('img.img-full.wp-post-image')
print("Getting all the links!")
for movie in movies_buttons:
self.driver.execute_script("arguments[0].scrollIntoView();", movie)
movie.click()
WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, 'infoFilmSingle')))
print(self.driver.current_url)
self.driver.back()
WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, 'div.archivePaging')))
Note that this code don't work now because i'm calling a movie object of an old page but that's not a problem because if i would just see the link i don't need to change page and so the session don't change.
An example based on what I understand you want to do - You wanna get the parent a tags href
Example
from selenium import webdriver
driver = webdriver.Chrome(executable_path=r'C:\Program Files\ChromeDriver\chromedriver.exe')
html_content = """
<div class="col-xl col-lg col-md-4 col-sm-6 col-6">
<a href="https://www.link1.de">
<article>
<span class="year">2017</span>
<span class="quality">4K</span>
<span class="imdb">6.7</span>
<img width="190" height="279" src="THE IMAGE URL" class="img-full wp-post-image" alt="" loading="lazy"> <h2>TITLE</h2>
</article>
</a>
</div>
<div class="col-xl col-lg col-md-4 col-sm-6 col-6">
<a href="https://www.link2.de">
<article>
<span class="year">2019</span>
<span class="quality">4K</span>
<span class="imdb">8.0</span>
<img width="190" height="279" src="THE IMAGE URL 2" class="img-full wp-post-image" alt="" loading="lazy"> <h2>TITLE</h2>
</article>
</a>
</div>
"""
driver.get("data:text/html;charset=utf-8,{html_content}".format(html_content=html_content))
Locate the image elements with its class and and walk up the element structur with .. in this case /../..
driver.get("data:text/html;charset=utf-8,{html_content}".format(html_content=html_content))
aTags = driver.find_elements_by_xpath("//img[contains(#class,'img-full wp-post-image')]/../..")
for ele in aTags:
x=ele.get_attribute('href')
print(x)
driver.close()
Output
https://www.link1.de/
https://www.link2.de/

python selenium find elements by xpath returns a list of a links but element not interactable

I am using this xpath //a[contains(., 'Download Python')]
on www.python.org/downloads
in chrome developer tools I get 4 matches, each one match the following
<a class="button" href="https://www.python.org/ftp/python/3.7.4/python-3.7.4-macosx10.9.pkg">Download Python 3.7.4</a>
<a class="button" href="https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tar.xz">Download Python 3.7.4</a>
<a class="button" href="https://www.python.org/ftp/python/3.7.4/python-3.7.4.exe">Download Python 3.7.4</a>
<a class="button" href="https://www.python.org/ftp/python/3.7.4/python-3.7.4.exe">Download Python 3.7.4</a>
the problem is only the third is clickable, the others give an error ElementNotInteractableException: Message: element not interactable
if I print the text of each element only the third one displays the text 'Download Python 3.7.4'
the rest print blank
elems = driver.find_elements_by_xpath(
"//a[contains(., 'Download Python')]")
for elem in elems:
print("-------")
print(elem.text)
print(elem.tag_name)
-------
a
-------
a
-------
Download Python 3.7.4
a
-------
a
as a result only elems[3].click works
This problem is not with your code, the python download page detects the OS you are browsing from and shows you the download link for that OS only. It has total 4 such buttons
<div class="download-os-mac-osx" style="display: none;">
<h1 class="call-to-action">Download the latest version for Mac OS X</h1>
<p class="download-buttons">
<a class="button" href="https://www.python.org/ftp/python/3.7.4/python-3.7.4-macosx10.9.pkg">Download Python 3.7.4</a>
</p>
</div>
<div class="download-os-source" style="display: none;">
<h1 class="call-to-action">Download the latest source release</h1>
<p class="download-buttons">
<a class="button" href="https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tar.xz">Download Python 3.7.4</a>
</p>
</div>
<div class="download-os-windows" style="">
<h1 class="call-to-action">Download the latest version for Windows</h1>
<p class="download-buttons">
<a class="button" href="https://www.python.org/ftp/python/3.7.4/python-3.7.4.exe">Download Python 3.7.4</a>
</p>
</div>
<div class="download-unknown" style="display: none;">
<h1 class="call-to-action">Download the latest version of Python</h1>
<p class="download-buttons">
<a class="button" href="/downloads/release/python-374/">Download Python 3.7.4</a>
</p>
</div>
You need to select the one which has style = "" rest others wont be displayed on the page.
You can also use the xpath with index and it will point to the button corresponding to the index
(Xpath)[index]
Eg: (//*[#class="button"])[0] -for first button
Let me know if it was helpful

Using Splinter to select from a dynamic menu

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

Not able to select drop-down option using select : UnexpectedTagNameException selenium : python

I apologize if I am doing very basic mistake, i am still new learning webdriver and python.
I am trying to select an option from dropdown using Select Class of python, but i am getting Unexpected TagName exception.
There is no ID present on the Tag, so i cannot detect it using any other method except class or attribute.
HTML Code :
<div class="select-pixels-container ng-scope">
<div class="action group">
<table class="org-agency-advertiser">
<tbody style="background-color: transparent;">
<tr style="background-color: transparent;">
<tr>
<td style="background-color: transparent;">
<select class="mm-select ng-valid localytics-chosen ng-dirty" ng-disabled="disabled('organizations')" ng-options="org.id as org.name for org in logic.organizations | orderBy:'name'" ng-model="logic.organization" chosen="" style="display: none;" data-placeholder="Select an Option">
<div class="chosen-container chosen-container-single" style="width: 175px; background-color: transparent;" title="">
<a class="chosen-single" tabindex="-1" style="background-color: transparent;">
<span style="background-color: transparent;">Select</span>
<div>
</a>
<div class="chosen-drop">
<div class="chosen-search">
<input type="text" autocomplete="off">
</div>
<ul class="chosen-results">
<li class="active-result" style="" data-option-array-index="0">Select</li>
<li class="active-result" style="" data-option-array-index="1">1-800 Hnunagk 100278</li>
<li class="active-result result-selected" style="" data-option-array-index="2">10tc Tatgaa 100179</li>
The code which I have wrote for this section is :
self.driver.find_element_by_css_selector("tbody>tr>td>div>a.chosen-single").click()
select=Select(self.driver.find_element_by_css_selector("tbody>tr>td>div>a[tabindex='-1']"))
select.select_by_index(0)
The exception I am getting is
selenium.common.exceptions.UnexpectedTagNameException: Message: Select only works on <select> elements, not on <a>`
Any help will be appreciated.
All HTML codes hadn't shared but, the basic idea should like this:
self.driver.find_element_by_xpath('//*[#class="chosen-single"]').click()
listItems = self.driver.find_element_by_xpath('//div[#class="chosen-drop"]/ul/li')
for item in listItems: # <li> tags list
if item.get_attribute("data-option-array-index") == "0": # select index
item.click() # if index=0 click
break

Categories