Как найти элемент, содержащий определенный текст в Selenium Webdriver (Python)?

Я пытаюсь проверить сложный интерфейс 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) без включения текста дочернего элемента?

Ответ 1

Попробуйте следующее:

driver.find_elements_by_xpath("//*[contains(text(), 'My Button')]")

Ответ 2

вы можете попробовать xpath вроде:

'//div[contains(text(), "{0}") and @class="inner"]'.format(text)

Ответ 3

Вы также можете использовать его с шаблоном объекта страницы, например:

Попробуйте этот код:

@FindBy(xpath = "//*[contains(text(), 'Best Choice')]")
WebElement buttonBestChoice;

Ответ 4

//* будет искать любой тег HTML. Где, если какой-то текст является общим для кнопки и тега div и если //* - категории, он не будет работать должным образом. Если вам нужно выбрать какой-то конкретный объект, вы можете получить его, объявив тег HTML-элемента. Подобно:

driver.find_element_by_xpath("//div[contains(text(),'Add User')]")
driver.find_element_by_xpath("//button[contains(text(),'Add User')]")

Ответ 5

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"));

Ответ 6

Интересно, что практически все ответы вращаются вокруг функции 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') флагом).

Ответ 7

Используйте driver.find_elements_by_xpath и соответствует функции совпадения регулярных выражений для случая нечувствительного поиска элемента по его тексту.

driver.find_elements_by_xpath("//*[matches(.,'My Button', 'i')]")

Ответ 8

Аналогичная проблема: найдите <button>Advanced...</button>

Возможно, это даст вам некоторые идеи (пожалуйста, перенесите концепцию с Java на Python):

wait.until(ExpectedConditions.elementToBeClickable(//
    driver.findElements(By.tagName("button")).stream().filter(i -> i.getText().equals("Advanced...")).findFirst().get())).click();

Ответ 9

Попробуйте это. Его очень легко:

driver.getPageSource().contains("text to search");

Это действительно сработало для меня в веб-драйвере селена.