I would like to select an <option>
child of a <select>
using the Python WebDriver.
I have a reference to the option WebElement
I wish to select and have tried select()
and click()
methods but neither works.
What is the correct way to select an <option>
?
6 Answers 6
The easiest way that I have found was to do something along the lines of:
el = driver.find_element_by_id('id_of_select')
for option in el.find_elements_by_tag_name('option'):
if option.text == 'The Options I Am Looking For':
option.click() # select() in earlier versions of webdriver
break
This may have some runtime issues if there are a large number of options, but for us it suffices.
Also this code will work with multi-select
def multiselect_set_selections(driver, element_id, labels):
el = driver.find_element_by_id(element_id)
for option in el.find_elements_by_tag_name('option'):
if option.text in labels:
option.click()
Then you can transform the following field
# ERROR: Caught exception [ERROR: Unsupported command [addSelection | id=deformField7 | label=ALL]]
Into this call
multiselect_set_selections(driver, 'deformField7', ['ALL'])
Multiple selection errors like the following:
# ERROR: Caught exception [ERROR: Unsupported command [addSelection | id=deformField5 | label=Apr]]
# ERROR: Caught exception [ERROR: Unsupported command [addSelection | id=deformField5 | label=Jun]]
Will be fixed with a single call:
multiselect_set_selections(driver, 'deformField5', ['Apr', 'Jun'])
-
@JasonWard How are you iterating over the Web Element object in for loop. I tried the same and got a exception that the object is not iterable. Any suggestion. Thanksabhi– abhi2013年04月18日 09:53:43 +00:00Commented Apr 18, 2013 at 9:53
-
1@abhi Make sure you are using
find_elements_by_tag_name
and notfind_element_by_tag_name
(Thes
inelements
matters).Jason Ward– Jason Ward2013年07月24日 01:43:44 +00:00Commented Jul 24, 2013 at 1:43 -
1Good solution, but not as good as Daniel Abel's proposed solution. Better off using the built in
Select
functionChris Bier– Chris Bier2014年03月27日 16:04:31 +00:00Commented Mar 27, 2014 at 16:04 -
@ChrisB you are correct that his solution is better, however I am fairly certain that when this was response was written the
Select
function did not exist :)Jason Ward– Jason Ward2014年03月28日 20:11:25 +00:00Commented Mar 28, 2014 at 20:11 -
Why did you edit my answer instead of adding your own?Jason Ward– Jason Ward2015年04月28日 22:03:56 +00:00Commented Apr 28, 2015 at 22:03
I think using selenium.webdriver.support.ui.Select
is the cleanest way:
from selenium import webdriver
from selenium.webdriver.support.ui import Select
b = webdriver.Firefox()
# navigate to the page
select = Select(b.find_element_by_id(....))
print select.options
print [o.text for o in select.options] # these are string-s
select.select_by_visible_text(....)
Using this approach is also the fastest way. I wrote fast_multiselect
as analogous function to multiselect_set_selections
. On a test with 4 calls to multiselect_set_selections
on lists of about 20 items each, the average running time is 16.992 seconds, where fast_multiselect
is only 10.441 seconds. Also the latter is much less complicated.
from selenium.webdriver.support.ui import Select
def fast_multiselect(driver, element_id, labels):
select = Select(driver.find_element_by_id(element_id))
for label in labels:
select.select_by_visible_text(label)
-
3Nice. Selenium auto-generated documentation just sucks.Stan– Stan2012年09月27日 13:07:55 +00:00Commented Sep 27, 2012 at 13:07
-
1This is the idiomatic approach. Too bad it isn't the accepted answer.Lucas Schwarz– Lucas Schwarz2015年04月28日 19:13:53 +00:00Commented Apr 28, 2015 at 19:13
-
This should be the accepted answerNam G VU– Nam G VU2017年06月20日 07:57:56 +00:00Commented Jun 20, 2017 at 7:57
-
My big question is How is it so slow? Why? I don't understand... 10 seconds is way too long.Jess– Jess2021年01月19日 20:51:32 +00:00Commented Jan 19, 2021 at 20:51
Similar to Will's answer, but finds the <select>
by its element name, and clicks based on the <option>
text.
from selenium import webdriver
b = webdriver.Firefox()
b.find_element_by_xpath("//select[@name='element_name']/option[text()='option_text']").click()
-
2This worked for me using
"//select[@name='element_name']/option[@value='2']"
to select an option by it's value (in case you are concerned about option text changing). It's well worth learning about xpath, IMO. selenium-python.readthedocs.org/…Adam Starrh– Adam Starrh2015年12月26日 20:25:47 +00:00Commented Dec 26, 2015 at 20:25 -
Yes, as @AdamStarrh, this only worked with
@value
Henrique de Sousa– Henrique de Sousa2021年04月30日 21:21:48 +00:00Commented Apr 30, 2021 at 21:21
I had a similar problem and was able to resolve it by finding the elements by xpath:
from selenium import webdriver
b = webdriver.Firefox()
#...some commands here
b.find_element_by_xpath("//select/option[@value='The Options I am Looking for']").click()
easier way to manipulate the dropdowns
from selenium import webdriver
from selenium.webdriver.support.ui import Select
driver.get("link")
select = Select(driver.find_element_by_id('<given id name>'))
select.select_by_index(3)
Using the latest rewritten version (1.0.1) of facebook/php-webdriver:
$optionCssSelector = WebDriverBy::cssSelector("#order_images_row_wrapper .order-wrapper .merge-image-select option[value='2']");
$this->driver->findElements($optionCssSelector)[0]->click();
-
3That's some mighty strange looking Python you've got there.XtrmJosh– XtrmJosh2016年03月01日 13:26:35 +00:00Commented Mar 1, 2016 at 13:26
click()
on the default<option>
, which made it look like nothing had changed.option.click()
, but it does work withoption.select()
. In the latest webelement.py source,select
has been removed, andclick
must be used in it’s place. It will be interesting to see if my test works with the latest release.