В связи с тем, что из-за проблем с кодировкой (это другой вопрос, меня не касается), видимый текст “Фамилия1 Имя1” бывает показывается так: “Ф?м?лия1 Им?1”.
Поэтому мне нужно выбрать по value.
Но как передать в value значение со обратным слэшэм “domain\00031477”?
select.select_by_value(value)
Пробовал и двойным слэшем.
Дает ошибку.
Это значение “domain\00031477” - мне известно.
Как вариант - можно дебагом поймать момент появления нужного Select, посмотреть его значения и скопировать ровно то. что там есть, со спец. символами и т.д.
Можно проще.
Я Python плохо знаю (моя стихия — это Ruby), так что за корявость кода сильно не бейте.
Итак, у нас есть файл /index.html
<!-- I am /index.html -->
<select>
<option value="domain\00031477">Alex Foo</option>
<option value="domain\00031478">Kevin Bar</option>
</select>
Нам нужно выбрать второй элемент Kevin Bar по атрибуту value.
Создадим файл ‘/webdriver.py’
# I am /webdriver.py
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('file:///index.html')
select = driver.find_element_by_css_selector('select')
options = select.find_elements_by_css_selector('option')
for option in options:
if option.get_attribute('value') == u'domain\\00031478':
option.click()
break
Сначала мы находим искомый элемент select.
Потом в нём находим все элементы option.
Проходим в цикле все option, и если его атрибут value равен нужному нам, то кликаем по нему.
Самое интересно, как выглядит мой stacktrace (внутри сделано как вы написали):
self = <selenium.webdriver.support.select.Select instance at 0x03120468>
value = 'domain\\00031478'
def select_by_value(self, value):
"""Select all options that have a value matching the argument. That is, when given "foo" this
would select an option like:
<option value="foo">Bar</option>
:Args:
- value - The value to match against
throws NoSuchElementException If there is no option with specisied value in SELECT
"""
css = "option[value =%s]" % self._escapeString(value)
opts = self._el.find_elements(By.CSS_SELECTOR, css)
matched = False
for opt in opts:
self._setSelected(opt)
if not self.is_multiple:
return
matched = True
if not matched:
> raise NoSuchElementException("Cannot locate option with value: %s" % value)
E NoSuchElementException: Message: Cannot locate option with value: domain\00031478
На css действительно не работает даже с экранированием, я бы завел багу на webdriver.
Xpath работает
>>> d.find_element(‘xpath’, “//option[@value=’%s’]” % value)
<selenium.webdriver.remote.webelement.WebElement (session=“ef9a7d95a0e4187fd82c8d7e45af49da”, element=“0.9059672434567432-1”)>
>>> value
‘domain\00031477’
>>> r'domain\\00031477'
'domain\\\\00031477'
>>> [i.get_attribute('value') for i in d.find_elements('css selector', 'option')]
['domain\\00031477', 'domain\\00031478']
Но "r" это же дополнительное экранирование, мне кажется это все таки бага, возможно даже только python версии
Если посмотреть в исходники модуля Select, то там можно увидеть дополнительно деэкранирование.
def select_by_value(self, value):
"""Select all options that have a value matching the argument. That is, when given "foo" this
would select an option like:
<option value="foo">Bar</option>
:Args:
- value - The value to match against
"""
css = "option[value =%s]" % self._escapeString(value)
opts = self._el.find_elements(By.CSS_SELECTOR, css)
matched = False
for opt in opts:
self._setSelected(opt)
if not self.is_multiple:
return
matched = True
if not matched:
raise NoSuchElementException("Cannot locate option with value: %s" % value)
def _escapeString(self, value):
if '"' in value and "'" in value:
substrings = value.split("\"")
result = ["concat("]
for substring in substrings:
result.append("\"%s\"" % substring)
result.append(", '\"', ")
result = result[0:-1]
if value.endswith('"'):
result.append(", '\"'")
return "".join(result) + ")"