Как на странице сайта определить ссылку по фрагменту текста и без учёта регистра текста?

csharp
webdriver
selenium
Теги: #<Tag:0x00007fedb8733658> #<Tag:0x00007fedb87333b0> #<Tag:0x00007fedb8733248>

(It Ot) #1

Имеется код со следующим сценарием:

  1. Поиск ссылок на странице
  2. Если текст содержит “программа на C#”, то код нажимает на ссылку.
private void button4_Click(object sender, EventArgs e)
        {
            List<IWebElement> Element = Browser.FindElements( By.CssSelector("#tabnews_newsc a") ).ToList();
 
            for (int i = 0; i < Element.Count; i++ )
            {
                String s = Element[i].Text;                
 
                if (s.Contains("программа на C#")) // если текст СОДЕРЖИТ
                {
                    Element[i].Click(); // КЛИК по новости, которая СОДЕРЖИТ искомый текст
                    break;
                }
            }
        }

ВОПРОС
Как сделать, чтобы поиск осуществлялся без учёта регистра текста для поиска?
Т.е. если текст содержит “программа на C#”, то переход осуществляется, а если текст содержит “Программа на C#” (слово “Программа” с большой буквы “П” ), то перехода по ссылке не происходит.


(rmerkushin) #2

Перед сравнением текста переведите его в верхний или нижний регистр а потом сравнивайте с текстом соответствующим:

s.ToLower().Contains("программа на c#")

На счёт правильности кода не уверен. Но по идее должно работать)

P.S.: вообще проще через #xpath наверное вытаскивать только нужные элементы и уже кликать по ним

//h3//a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ', 'abcdefghijklmnopqrstuvwxyzабвгдеёжзиклмнопрстуфхцчшщьыъэюя'), 'программа на c#')]

(It Ot) #3

При использовании предложенной вами строчки появляется ошибка.

ОШИБКА
‘string’ does not contain a definition for ‘contains’ and no extension method ‘contains’ accepting a first argument of type ‘string’ could be found (are you missing a using directive or an assembly reference?)

Скрин

ВОПРОС
Не могли бы вы подсказать как её исправить?

PS
Только осваиваю WebDriver Selenium заранее прошу извинить, если вопрос элементарный


(It Ot) #4

Ошибку устранил.
Всё работает…

Вы бы не могли подсказать как сделать с помощью xpath на примере моего кода?

Пробовал вставить вашу строку, что-то не срабатывает.


(rmerkushin) #5
//h3//a[contains(lower-case(.), "программа на c#")]

Не уверен на счет #xpath сделал его на основе вашего #css-selectors . Делаете поиск элементов по этому xpath. У вас будет в итоге список элементов которые только содержат такой текст, соответственно обходите этот список и кликаете по каждому элементу или что там у вас делает тест)


(It Ot) #6

не могу нигде найти описание это части кода.
Что это такое?
В частности "lower-case(.)"


(James Howlett) #7

На java:

List<WebElement> elements = driver.findElements(By.cssSelector("#tabnews_newsc a"));
        for (WebElement ls : elements)
        {
            if (ls.getText().equalsIgnoreCase("программа на C#")) // если текст СОДЕРЖИТ
            {
                ls.click(); // КЛИК по новости, которая СОДЕРЖИТ искомый текст
            }
        }

(Yury) #8

By XPath:

List<WebElement> elements = driver.findElements(By.xpath("//a[contains(text(), 'программа на c#')]"));

(It Ot) #9

Данный код будет выбирать текст, если слово "программа… " будет с большой буквы “П”, т.е. “Программа”?

PS
Всем спасибо за ответы


(Yury) #10

Да, будет собирать только ссылки, которые буквально содержат текст “программа на c#”
В принципе с помощью XPath можно задать любые критерии отбора.


(rmerkushin) #11

Lower-case приводит текст к нижнему регистру. А точка это короткая запись text()


(Сергей Кузьмин) #12

насколько хорошо xpath поддерживает кодировки ?

может проще сделать на с# - передать ignorecase несколькими способами оставить необходимые

 e = d.FindElements(By.CssSelector("#tabnews_newsc a"));
  String matcher = "(?i:" + "программа на c#" + ")";
 if (Regex.IsMatch(e.Text, matcher, RegexOptions.IgnoreCase)) {
 }

(vmaximv) #13

Так же добавлю, что lower-case это XPath 2.0 - который в данный момент не поддерживается браузерами.
А точка это не text(), а текущая нода относительно предиката…


(Yury) #14

Настолько хорошо, насколько их поддерживает веб-браузер.

В принципе, уже видно, что существует несколько путей решений задачи топикстартера. Лично мне вариант с прямым поиском по XPath видится самым производительным, так как сразу формируется массив из нужных элементов. В вашем же случае сперва сформируется массив из всех ссылок, а потом он еще должен перебираться, сравнивая каждый элемент с шаблоном регулярного выражения.


(rmerkushin) #15

Ну в конкретном случае . будет равносильна использованию text(). В других случаях это будет текущая нода.
P.S.: вот страшный вариант для xpath 1.0:

//h3//a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ', 'abcdefghijklmnopqrstuvwxyzабвгдеёжзиклмнопрстуфхцчшщьыъэюя'), 'программа на c#')]

(vmaximv) #16

Нет. Читайте спеку.


(rmerkushin) #17

Я про то что оно работает.


(vmaximv) #18

А я про то, что вы утверждаете, что в данной конструкции

Что неверно:

https://jsfiddle.net/a5n2o3L9/


(rmerkushin) #19

Ясен пень оно будет работать по разному ) Я не утверждал что . == text(), я имел в виду что в некоторых случаях замена text() на . будет давать тот же результат. Мне так удобнее было записать пример и все. Главное что он работает.


(vmaximv) #20

Ну если для вас все ясно, расскажите топик-стартеру, что же просиходит к конструкции вида contains(.,'some text'), и чем оно отличается от contains(text(),'some text').