Ответ 1
Попробуйте следующее:
driver.find_elements_by_xpath("//*[contains(text(), 'My Button')]")
Я пытаюсь проверить сложный интерфейс javascript с Selenium (используя интерфейс Python и через несколько браузеров). У меня есть несколько кнопок формы:
<div>My Button</div>
Я хотел бы иметь возможность искать кнопки на основе "Моя кнопка" (или не учитывающие регистр, частичные совпадения, такие как "моя кнопка" или "button")
Я нахожу это удивительно трудным, насколько мне кажется, что я пропускаю что-то очевидное. Самое лучшее, что у меня есть до сих пор:
driver.find_elements_by_xpath('//div[contains(text(), "' + text + '")]')
Это зависит от регистра. Другая вещь, которую я пробовал, - это повторение всех разделов на странице и проверка свойства element.text. Однако каждый раз, когда вы получаете ситуацию в форме:
<div class="outer"><div class="inner">My Button</div></div>
div.outer также имеет "Моя кнопка" в качестве текста. Чтобы исправить THAT, я попытался посмотреть, является ли div.outer родителем div.inner, но не мог понять, как это сделать (element.get_element_by_xpath ('..') возвращает родительский элемент, но он тесты не равны div.outer). Кроме того, повторение всех элементов на странице кажется очень медленным, по крайней мере, с помощью веб-браузера Chrome.
Идеи?
Изменить: этот вопрос вышел немного расплывчато. Спросил (и ответил) более конкретную версию здесь: Как получить текст элемента в Selenium WebDriver (через Python api) без включения текста дочернего элемента?
Попробуйте следующее:
driver.find_elements_by_xpath("//*[contains(text(), 'My Button')]")
вы можете попробовать xpath вроде:
'//div[contains(text(), "{0}") and @class="inner"]'.format(text)
Вы также можете использовать его с шаблоном объекта страницы, например:
Попробуйте этот код:
@FindBy(xpath = "//*[contains(text(), 'Best Choice')]")
WebElement buttonBestChoice;
//* будет искать любой тег HTML. Где, если какой-то текст является общим для кнопки и тега div и если //* - категории, он не будет работать должным образом. Если вам нужно выбрать какой-то конкретный объект, вы можете получить его, объявив тег HTML-элемента. Подобно:
driver.find_element_by_xpath("//div[contains(text(),'Add User')]")
driver.find_element_by_xpath("//button[contains(text(),'Add User')]")
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(), 'YourTextHere')]")));
assertNotNull(driver.findElement(By.xpath("//*[contains(text(), 'YourTextHere')]")));
String yourButtonName=driver.findElement(By.xpath("//*[contains(text(), 'YourTextHere')]")).getAttribute("innerText");
assertTrue(yourButtonName.equalsIgnoreCase("YourTextHere"));
Интересно, что практически все ответы вращаются вокруг функции xpath contains()
, игнорируя тот факт, что она чувствительна к регистру - вопреки OP ask.
Если вам нужна нечувствительность к регистру, это достижимо в xpath 1.0 (версия, поддерживаемая современными браузерами), хотя это не очень приятно - с помощью функции translate()
. Он заменяет исходный символ в желаемой форме с помощью таблицы перевода.
Построение таблицы всех символов в верхнем регистре эффективно преобразует текст узла в его нижнюю() форму, позволяя сопоставление без учета регистра (здесь только прерогатива):
[
contains(
translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),
'my button'
)
]
# will match a source text like "mY bUTTon"
Полный вызов Python:
driver.find_elements_by_xpath("//*[contains(translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZЙ', 'abcdefghijklmnopqrstuvwxyzй'), 'my button')]")
Естественно, у этого подхода есть свои недостатки - как дано, он будет работать только для латинского текста; если вы хотите охватить символы юникода - вам придется добавить их в таблицу перевода. Я сделал это в приведенном выше примере - последний символ - это кириллица "Й"
.
И если бы мы жили в мире, где браузеры поддерживали xpath 2.0 и выше (🤞, но скоро это не произойдет ☹️), мы могли бы использовать функции в lower-case()
(пока не полностью ориентированные на локали) и matches
(для поиска по регулярному выражению, с регистронезависимым ('i'
) флагом).
Используйте driver.find_elements_by_xpath и соответствует функции совпадения регулярных выражений для случая нечувствительного поиска элемента по его тексту.
driver.find_elements_by_xpath("//*[matches(.,'My Button', 'i')]")
Аналогичная проблема: найдите <button>Advanced...</button>
Возможно, это даст вам некоторые идеи (пожалуйста, перенесите концепцию с Java на Python):
wait.until(ExpectedConditions.elementToBeClickable(//
driver.findElements(By.tagName("button")).stream().filter(i -> i.getText().equals("Advanced...")).findFirst().get())).click();
Попробуйте это. Его очень легко:
driver.getPageSource().contains("text to search");
Это действительно сработало для меня в веб-драйвере селена.