Select Dropdown Item from "Select" with No ID, Name, or XPATH? - python-3.x

I'm trying to select an item from a drop down menu on a webpage. The select element has no "id", "class" or any other identifier. The div class that it resides under does however. The structure of the element looks like this:
<div class="dropdown_menu_one">
<i>
<select>
<option value="ALL" selected="selected">All Sports</option>
<option value="MLB">MLB</option>
<option value="NBA">NBA</option>
<option value="NFL">NFL</option>
</select>
</i>
</div>
I'm just trying to select, for example, MLB from this dropdown list, but my code isn't working. I found this solution where (theoretically) it tries to select the choice from any select element on the page that has that option, but it's not working for me. Looks like this:
select_element = browser.find_element_by_xpath("//select[option[#value = '%s']]" % "MLB")
select = Select(select_element)
select.select_by_value(sports_selection)
Another added layer of complexity to this is that the xpath constantly changes for this thing too, so I can't rely on just grabbing an xpath or css selector because sometimes it just won't find that element at all on the page. Any ideas? Thanks!

There are couple of alternatives to locate an element even unique attribute not present for it
Strategy: Look surrounding element like parent, child, sibling etc which makes it unique. In your case <select> don't have any attribute but its embedded under a <div> tag which has class attribute so you can use it as given below-
Using xpath : //div[#class='dropdown_menu_one']/i/select or //div[#class='dropdown_menu_one']//select
Even you can locate select based on the option which you are trying. for that first you need to locate the option tag and then have to move to its parent i.e. select. Refer this : //option[contains(.,'All Sports')]/parent::select
Using css selector : div[class='dropdown_menu_one'] select or .dropdown_menu_one>i>select
Using tag name based on the div which contains Select tag :
select_container = browser.find_element_by_css_selector("div.dropdown_menu_one")
select_element = select_container.find_element_by_tag_name("select")
select = Select(select_element)
For more locator strategies please refer this document.

Grab it by css selector like this. Use webdriver waits to let the element load onto the page.
select_element = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "div.dropdown_menu_one>i>select")))
select = Select(select_element)
select.select_by_value('MLB')
Import
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

Related

Click on outer element with inner element with specific text in Puppeteer

How can I click on an outer element that contains a span with specific text via puppeteer?
For example I have the following HTML code:
<div role="button">
<div>
<span>
<span>OK</span>
</span>
</div>
</div>
And I would like to click on the most outer element (role = button). In order to click on the span with the Ok text I would do the next thing:
const [button] = await page.$x("//span[contains(., 'Ok')]");
if (button) {
await button.click();
}
But how can I click on the outer element using this text identifier?
You can use the descendant expression to query for child elements. Quote from the link:
The descendant axis indicates all of the children of the context node, and all of their children, and so forth.
Your XPath expression then looks like this:
//div[#role='button' and descendant::span[contains(., 'Ok')]]
Depending on your use case you might also want to check out this information about the difference of contains(text(), ...) and contains(., ...).

Unable to locate element error while trying to locate an input box element using Selenium through Python

I´m trying to find a text box with Python and Selenium.. I Tried by_css_selector, bY XPATH, by ID, by name but the message is always the same:
Unable to locate element: #x-auto-225-input
this is the piece of html. I Want to find the textbox to fill it.
<td class="x-table-layout-cell" role="presentation" style="padding: 2px;">
<div role="presentation" class=" x-form-field-wrap x-component" id="x-auto-225" style="width: 150px;"></div>
<input type="text" class=" x-form-field x-form-text " id="x-auto-225-input" name="PURCHASE_ORDER_CODE_NAME" tabindex="0" style="width: 150px;">
</td>
My last attempt was:
pc = browser.find_element_by_css_selector("#x-auto-225-input").click()
pc.send_keys("7555425-1")
Looking at the html, id mentioned can be dynamic, so you can't put the static id in your identifier.
However, as name attribute is present in the html, you can use that to identify your element, like:
browser.find_element_by_name("PURCHASE_ORDER_CODE_NAME").click()
Updated answer as per discussion with the OP
As an iframe is present on the UI, you need to first switch to the iframe and then click on the element.
To switch to iframe you can use:
browser.switch_to.frame(browser.find_element_by_tag_name('iframe'))
and then use:
pc = browser.find_element_by_name("PURCHASE_ORDER_CODE_NAME")
pc.click()
pc.send_keys("7555425-1")
if you want to switch back to the default content, you can use:
browser.switch_to.default_content()
The desired element is a dynamic element so to invoke click() on the element you have to induce WebDriverWait for the element to be clickable and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input.x-form-field.x-form-text[id$='-input'][name='PURCHASE_ORDER_CODE_NAME']"))).click();
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#class=' x-form-field x-form-text ' and contains(#id,'-input')][#name='PURCHASE_ORDER_CODE_NAME']"))).click();
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Maybe you can try another "selector" approach. Ex(Javascript):
selenium.By.xpath('//*[#data-icon="edit"]')
driver.findElement(by).click()

Python Selenium can't select dropdown (chrome webdriver)

I have a dropdown element, I want to select the All option, the corresponding HTML code is:
<div class="dataTables_length" id="indicators_length">
<label>
<span class="result-mune">
<span>Results </span>per page:
</span>
<select name="indicators_length" aria-controls="indicators" class="jcf-hidden">
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="200">200</option>
<option value="-1">All</option>
</select>
<span class="jcf-select jcf-unselectable">
<span class="jcf-select-text">
<span class="">25</span>
</span>
<span class="jcf-select-opener"></span>
</span>
</label>
</div>
the select element is not highlighted using the browser Inspect method, looks like this drop down is triggered by js.
I tried to use the Select class described here:
select = Select(self._wait.until(EC.presence_of_element_located_by((By.XPATH, "//div[#id = 'indicators_length']//select[#name = 'indicators_length']")))
select.select_by_value('-1')
not working. and ActionChain method and even execute_script method, all not working. This bothers me a lot, hope somebody can help.
you don't really need to select the option just click the span and it will set the option automatically.
driver = webdriver.Chrome()
driver.get("......")
# click "OK, I Agree" cookies
driver.find_element_by_css_selector('.agree-button.eu-cookie-compliance-default-button').click()
# scroll down to make dropdown option visible
driver.find_element_by_css_selector('h4.pane-title').location_once_scrolled_into_view
select = driver.find_element_by_xpath('//span[#class="result-mune"]/following-sibling::span')
select.click()
# wait until javascript generate fake option element because it actually span
time.sleep(1)
select.find_element_by_css_selector('ul li span[data-index="4"]').click()
try this one:
driver.execute_script('document.getElementsByName("indicators_length")[0].value = 50;
If its created and loaded after page load make sure you add some sleep to let it render;
I tried using the Selenium Select class, it can find the element but it cannot select an option from the element. Not sure whats going on, could be the class "jcf-hidden" on the element.
Having said that, I took a stab at it and below is my approach. Try it out, it worked on my system, you have to handle the clicking of "OK, I Agree" button click, I did that manually.
import time
from selenium.webdriver import Chrome
driver = Chrome()
driver.get('https://www.topuniversities.com/university-rankings/world-university-rankings/2019')
# Remove this nasty time.sleep and implement webdriver wait
# Handle the OK, I Agree
time.sleep(5)
i_agree = driver.find_element_by_css_selector('button[class*="eu-cookie-compliance-default-button"]')
i_agree.click()
time.sleep(5)
# Open the Select
rankings_length = driver.find_element_by_id('qs-rankings_length')
select_opener = rankings_length.find_element_by_class_name('jcf-select-opener')
select_opener.click()
# loop through the list
select_content = rankings_length.find_element_by_class_name('jcf-list-content')
for content in select_content.find_elements_by_tag_name('li'):
if content.text == 'All':
content.click()

how to click on the first result of a search on metacritc with selenium

how do I click on the first search result on metacritc's search bar?
this is what I have so far:
self.search_element = self.driver.find_element_by_name("search_term")
self.search_element.clear()
self.search_element.send_keys(self.game_line_edit.text())
self.link_to_click = self.driver.find_element_by_name("search_results_item")
self.link_to_click.click()
# self.game.setText(self.driver.find_element("search_results_item"))
self.game_line_edit.setText("")
self.driver.close()
but I'm getting this error:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"name","selector":"search_results_item"}
I realize selenium can't find the link but I am not sure what element it is
this is the HTML I'm trying to click on:
<a class="search_results_item" href="https://www.metacritic.com/game/pc/into-the-breach">
<span class="metascore_w score_outstanding">90</span>
<span class="title" data-mctitle="Into the Breach"><b>Into the</b> Breach</span>
<span class="type secondary">PC Game</span>
<span class="separ secondary">,</span>
<span class="date secondary">2018</span>
</a>
can someone help?
Thanks!
You are searching by name when you are referring to a class. Instead use a CSS selector, e.g.
.find_element_by_css_selector(".search_results_item")
.search_results_item indicates a class with the name 'search_results_item'.
If that doesn't work, you probably need a wait. See this answer for more info.
If you're fine with using xPath, you can select by index.
(//a[contains(#class,'search_results_item')])[1]
#JeffC is also correct as well. You should not select by name because this element has no name. At the very least, select by class or tag.

Python to click a button/link in JavaScript

I want to show more page by click a button to run a JavaScript function as below:
<div class="loading" style="display:none;">
<p class="btn blue"><span>さらに表示</span></p>
</div>
I tried the code, it doesn't work, what can I do?
more_info_button = driver.find_element_by_tag_name('a').get('href=javascript:void(0);')
more_info_button.click()
If you want to click link that contains attribute #href equal to "javascript:void(0);", try
more_info_button = driver.find_element_by_xpath('//a[#href="javascript:void(0);"]')
more_info_button.click()
Same with CSS selector:
more_info_button = driver.find_element_by_css_selector('a[href="javascript:void(0);"]')
To locate link by text in preceding paragraph:
more_info_button = driver.find_element_by_xpath('//a[preceding-sibling::p[.="さらに表示"]]')
Update
Try below code to get extended topics list after clicking the button:
from selenium.webdriver.support.ui import WebDriverWait
topics_number = len(driver.find_elements_by_class_name('topics'))
more_info_button.click()
WebDriverWait(driver, 10).until(lambda driver: len(driver.find_elements_by_class_name('topics')) > topics_number)
extended_list = driver.find_elements_by_class_name('topics')

Resources