Не понимаю логику работы FindChildByXPath()

Dmitriy Ka

Client
Регистрация
03.05.2016
Сообщения
541
Благодарностей
291
Баллы
63
Каждый раз когда использую метод FindChildByXPath(), каждый раз у меня ломается мозг.

Есть коллекция HtmlElement из которой мне нужно дернуть другую коллекцию HtmlElement.
Для примера возьмем блоки поисковой выдачи (блок1, блок2, блок3 ...)
Из этих блоков я хочу забрать HtmlElement: Заголовок, Ссылка, Описание.

Я собираю коллекцию этих блоков
tab.FindElementsByXPath();

Потом форичем получаю уже нужные HtmlElement: Заголовок, Ссылка, Описание.
C#:
foreach (var item in SearchResultCollection)
{
    var title = item.FindChildByXPath(RESULT_TITLE, 0);
    var link = item.FindChildByXPath(RESULT_LINK, 0);
    var description = item.FindChildByXPath(RESULT_DESCRIPTION, 0);

    Title.Add(title);
    Link.Add(link);
    Description.Add(description);
}
Весь мозг ломает индекс в FindChildByXPath("xPath", 0), почему для корректного сбора я должен изменять индекс на +1?
То есть у нас меняется item и мы из этого item под индексом 0 выдергиваем нужные данные по xPath, но нет так не работает, выдергивается только первый результат из выдачи, даже если у нас item от 10 элемента.

Чтобы все заработало и собрать все HtmlElement заголовков должны прописать так
C#:
var i = 0; //Костыль для работы FindChildByXPath
foreach (var item in SearchResultCollection)
{
    var title = item.FindChildByXPath(RESULT_TITLE, i);
    var link = item.FindChildByXPath(RESULT_LINK, i);
    var description = item.FindChildByXPath(RESULT_DESCRIPTION, i);

    Title.Add(title);
    Link.Add(link);
    Description.Add(description);
    i++;
}
Я не понимаю, почему чтобы все корректно работало мы должны менять индекс у нас ведь и так меняется item?!
 

Yuriy Zymlex

Moderator
Команда форума
Регистрация
24.10.2016
Сообщения
6 369
Благодарностей
3 294
Баллы
113

Dmitriy Ka

Client
Регистрация
03.05.2016
Сообщения
541
Благодарностей
291
Баллы
63
Напишите сами XPath'ы.
Собрать коллекцию
C#:
var SearchResultCollection = tab.FindElementsByXPath("//li[contains(@class,'item_card')][contains(@data-fast,'1')]");
Работа с коллекцией
C#:
List<HtmlElement> Title = new List<HtmlElement>();
List<HtmlElement> Link = new List<HtmlElement>();
List<HtmlElement> Description = new List<HtmlElement>();

foreach (var item in SearchResultCollection)
{
    var title = item.FindChildByXPath("//span[contains(@class,'organic__title')]", 0);
    var link = item.FindChildByXPath("//div[contains(@class,'organic__path')]", 0);
    var description = item.FindChildByXPath("//span[contains(@class,'TextContent')]", 0);

    Title.Add(title);
    Link.Add(link);
    Description.Add(description);
}
 

Sherminator

Client
Регистрация
10.09.2021
Сообщения
996
Благодарностей
535
Баллы
93
Собрать коллекцию
C#:
var SearchResultCollection = tab.FindElementsByXPath("//li[contains(@class,'item_card')][contains(@data-fast,'1')]");
Работа с коллекцией
C#:
List<HtmlElement> Title = new List<HtmlElement>();
List<HtmlElement> Link = new List<HtmlElement>();
List<HtmlElement> Description = new List<HtmlElement>();

foreach (var item in SearchResultCollection)
{
    var title = item.FindChildByXPath("//span[contains(@class,'organic__title')]", 0);
    var link = item.FindChildByXPath("//div[contains(@class,'organic__path')]", 0);
    var description = item.FindChildByXPath("//span[contains(@class,'TextContent')]", 0);

    Title.Add(title);
    Link.Add(link);
    Description.Add(description);
}
У дочерних вроде как точку надо ставить перед первыми двумя слешами
 
  • Спасибо
Реакции: sydoow и Dmitriy Ka

Dmitriy Ka

Client
Регистрация
03.05.2016
Сообщения
541
Благодарностей
291
Баллы
63
У дочерних вроде как точку надо ставить перед первыми двумя слешами
Спасибо, действительно помогло! Я об этом даже и не знал, такая мелочь, а так важна :-)

Получаю нужный результат.
C#:
foreach (var item in SearchResultCollection)
{
    var title = item.FindChildByXPath(".//span[contains(@class,'organic__title')]", 0);
    var link = item.FindChildByXPath(".//div[contains(@class,'organic__path')]", 0);
    var description = item.FindChildByXPath(".//span[contains(@class,'TextContent')]", 0);

    Title.Add(title);
    Link.Add(link);
    Description.Add(description);
}
 

Yuriy Zymlex

Moderator
Команда форума
Регистрация
24.10.2016
Сообщения
6 369
Благодарностей
3 294
Баллы
113
Без точки (означающей текущий элемент), вы нивелируете весь смысл поиска на основе дочернего.
Так же м.б. не лишне избавиться от поиска во всех подэлементах.
 

heks

Client
Регистрация
01.10.2013
Сообщения
1 076
Благодарностей
256
Баллы
83
Regex рулит с хпачем вообще не пойму что делать надо и как его составлять
 

backoff

Client
Регистрация
20.04.2015
Сообщения
5 926
Благодарностей
6 389
Баллы
113
с хпачем вообще не пойму что делать надо и как его составлять
тоже так раньше думал, потом потратил день на изучение, посмотрел видосы на ютубчике, почитал примеры, и теперь пользуюсь только им ... всего лишь день
 

sydoow

Client
Регистрация
22.06.2011
Сообщения
273
Благодарностей
141
Баллы
43
Ах вот оно что, нужно было точку ставить
А я несколько лет думал это глюк ZP: когда перебираешь коллекцию и пытаешься достать из неё элемент через FindChildByXPath -ZP выдавала всегда не то
 

Sherminator

Client
Регистрация
10.09.2021
Сообщения
996
Благодарностей
535
Баллы
93

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113
Ах вот оно что, нужно было точку ставить
А я несколько лет думал это глюк ZP: когда перебираешь коллекцию и пытаешься достать из неё элемент через FindChildByXPath -ZP выдавала всегда не то
в каком-то смысле это и есть глюк зп
 
  • Спасибо
Реакции: sydoow

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)