xpath пути, срабатывает через раз

Кирилл412

Пользователь
Регистрация
21.11.2018
Сообщения
146
Благодарностей
3
Баллы
18
Не могу никак понять , есть список групп, нужно рандомно в них вступать..
http://joxi.ru/4AkjdxRCoNlap2
http://joxi.ru/ZrJv3goHw3Ddpr
Вот код, который работает через раз, мышка летит в левый верхний угол , еще раз нажать, может сработать..
var Groups = tab.FindElementsByXPath("//div[@class='groups_row search_row clear_fix']");
if (Groups.Count==0) throw new Exception("Группы!");
var Group = Groups.GetByNumber(rnd.Next(0,Groups.Count));

//Ведём мышку к этому посту
tab.FullEmulationMouseMoveToHtmlElement(Group);
tab.FullEmulationMouseSetOptions(1,5,10);

tab.FullEmulationMouseMoveAboveHtmlElement(Group, 40);

Helper.Pause(2,4);
tab.FullEmulationMouseSetOptions(1,5,10);
var more = Group.FindChildByXPath(".//button[@class='flat_button button_small button_wide']",0);
tab.FullEmulationMouseMoveToHtmlElement(more);
tab.FullEmulationMouseClick("left", "click");
 

Кирилл412

Пользователь
Регистрация
21.11.2018
Сообщения
146
Благодарностей
3
Баллы
18
Никто не подскажет??, гуру помогитеее...
 

backoff

Client
Регистрация
20.04.2015
Сообщения
5 933
Благодарностей
6 389
Баллы
113

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
гуру помогитеее...
Гуру на связи. :bc::D

Xpath не может работать через раз. Xpath это просто путь к элементу. Элемент или находится, или не находится.
А дальше уже зависит от того как составлен xpath.

var more = Group.FindChildByXPath(".//button[@class='flat_button button_small button_wide']",0);
Выведи в лог, что у тебя в more. Удостоверься что находится именно тот элемент что надо.

Попробуй так. Без точки.
.// - это путь к элементу относительно корневого узла документа. А тебе надо относительный путь от уже выбранного тобой элемента - //
var more = Group.FindChildByXPath("//button[@class='flat_button button_small button_wide']",0);

Или так, что по сути одинаково. // = descendant
var more = Group.FindChildByXPath("/descendant::button[@class='flat_button button_small button_wide']",0);
 

Кирилл412

Пользователь
Регистрация
21.11.2018
Сообщения
146
Благодарностей
3
Баллы
18
Гуру на связи. :bc::D

Xpath не может работать через раз. Xpath это просто путь к элементу. Элемент или находится, или не находится.
А дальше уже зависит от того как составлен xpath.

var more = Group.FindChildByXPath(".//button[@class='flat_button button_small button_wide']",0);
Выведи в лог, что у тебя в more. Удостоверься что находится именно тот элемент что надо.

Попробуй так. Без точки.
.// - это путь к элементу относительно корневого узла документа. А тебе надо относительный путь от уже выбранного тобой элемента - //
var more = Group.FindChildByXPath("//button[@class='flat_button button_small button_wide']",0);

Или так, что по сути одинаково. // = descendant
var more = Group.FindChildByXPath("/descendant::button[@class='flat_button button_small button_wide']",0);
Тут он просто летит с низа права, на верх лева.., more, это кнопка, которую он ищет после своих полетов непонятно куда..
 

Кирилл412

Пользователь
Регистрация
21.11.2018
Сообщения
146
Благодарностей
3
Баллы
18
Гуру на связи. :bc::D

Xpath не может работать через раз. Xpath это просто путь к элементу. Элемент или находится, или не находится.
А дальше уже зависит от того как составлен xpath.

var more = Group.FindChildByXPath(".//button[@class='flat_button button_small button_wide']",0);
Выведи в лог, что у тебя в more. Удостоверься что находится именно тот элемент что надо.

Попробуй так. Без точки.
.// - это путь к элементу относительно корневого узла документа. А тебе надо относительный путь от уже выбранного тобой элемента - //
var more = Group.FindChildByXPath("//button[@class='flat_button button_small button_wide']",0);

Или так, что по сути одинаково. // = descendant
var more = Group.FindChildByXPath("/descendant::button[@class='flat_button button_small button_wide']",0);

tab.FullEmulationMouseMoveToHtmlElement(Group);
tab.FullEmulationMouseSetOptions(1,5,10);

tab.FullEmulationMouseMoveAboveHtmlElement(Group, 40); вроде как не видит group? но через раз
 

orka13

Client
Регистрация
07.05.2015
Сообщения
2 167
Благодарностей
2 169
Баллы
113
..Вот код, который работает через раз, мышка летит в левый верхний угол , еще раз нажать, может сработать...
Это явный признак того, что на странице сайта есть элементы спрятанные в коде, но не показанные визуально. Ибо у них координаты "0,0" (верхний левый угол страницы). Иногда сайты так делают, чтобы не перегружать страницу при каких-то действиях пользователя, а просто сделать такие элементы опять видимыми.
И ваш Xpath как раз захватывает иногда видимые элементы, а иногда такие "невидимые". Чтобы подобное не происходило я сначала в коде делаю НЕвечный цикл перебора всех найденных элементов коллекции до того момента, пока на найду элемента, у которого высота\ширина больше нуля, и\или если этого иногда мало, то проверяю его координаты относительно края\начала страницы. Если элемент не подошел, то берем следующий из коллекции. Помогает обычно в конструкторе действий найти видимый и невидимый элемент и сравнить чем они отличаются, чтобы знать за что зацепится.
Вот пример такого кода с моего случая когда надо было видимую рекапчу на странице найти (а там обычно их несколько в коде спрятано), адаптируйте под себя:
C#:
//Переходим на активную вкладку:
Tab tab1 = instance.GetTabByAddress("page");
if (tab1.IsBusy)    tab1.WaitDownloading();
//используя XPath находим  елемент
HtmlElementCollection heCol = tab1.FindElementsByXPath("//div[@class='rc-anchor-content']");
if ((heCol.IsVoid) || (heCol.ErrorDetected)) return null;

HtmlElement he = null;
for (int i = 0; i < heCol.Count; i++) {
    he = heCol.Elements[i];
    int height = Int32.Parse(he.GetAttribute("height"));
    int topintab = int.Parse(he.GetAttribute("topintab"));
    int leftintab = int.Parse(he.GetAttribute("leftintab"));
    if (height>10 && topintab>50 && topintab<5600 && leftintab>50 && leftintab<700) {
        instance.ActiveTab.FullEmulationMouseMoveToHtmlElement(he);
        System.Threading.Thread.Sleep(new Random().Next(400,2000));
        instance.ActiveTab.FullEmulationMouseMoveAboveHtmlElement(he, new Random().Next(25,50));
        System.Threading.Thread.Sleep(new Random().Next(400,2000));
        return "ok13"; // выходим из цикла
    }  
}
 
Последнее редактирование:

Кирилл412

Пользователь
Регистрация
21.11.2018
Сообщения
146
Благодарностей
3
Баллы
18
Это явный признак того, что на странице сайта есть элементы спрятанные в коде, но не показанные визуально. Ибо у них координаты "0,0" (верхний левый угол страницы). Иногда сайты так делают, чтобы не перегружать страницу при каких-то действиях пользователя, а просто сделать такие элементы опять видимыми.
И ваш Xpath как раз захватывает иногда видимые элементы, а иногда такие "невидимые". Чтобы подобное не происходило я сначала в коде делаю НЕвечный цикл перебора всех найденных элементов коллекции до того момента, пока на найду элемента, у которого высота\ширина больше нуля, и\или если этого иногда мало, то проверяю его координаты относительно края\начала страницы. Если элемент не подошел, то берем следующий из коллекции. Помогает обычно в конструкторе действий найти видимый и невидимый элемент и сравнить чем они отличаются, чтобы знать за что зацепится.
Вот пример такого кода с моего случая когда надо было видимую рекапчу на странице найти (а там обычно их несколько в коде спрятано), адаптируйте под себя:
C#:
//Переходим на активную вкладку:
Tab tab1 = instance.GetTabByAddress("page");
if (tab1.IsBusy)    tab1.WaitDownloading();
//используя XPath находим  елемент
HtmlElementCollection heCol = tab1.FindElementsByXPath("//div[@class='rc-anchor-content']");
if ((heCol.IsVoid) || (heCol.ErrorDetected)) return null;

HtmlElement he = null;
for (int i = 0; i < heCol.Count; i++) {
    he = heCol.Elements[i];
    int height = Int32.Parse(he.GetAttribute("height"));
    int topintab = int.Parse(he.GetAttribute("topintab"));
    int leftintab = int.Parse(he.GetAttribute("leftintab"));
    if (height>10 && topintab>50 && topintab<5600 && leftintab>50 && leftintab<700) {
        instance.ActiveTab.FullEmulationMouseMoveToHtmlElement(he);
        System.Threading.Thread.Sleep(new Random().Next(400,2000));
        instance.ActiveTab.FullEmulationMouseMoveAboveHtmlElement(he, new Random().Next(25,50));
        System.Threading.Thread.Sleep(new Random().Next(400,2000));
        return "ok13"; // выходим из цикла
    } 
}
Вроде все как надо, но выбирает первый я так понял , из цикла, удолетворяющий условиям элемент.., c# для меня темный лес.., не могу придумать, как либо собрать все в массив, который проходит по условиям, потом от туда рандомно дергать элемент, или сразу как нить из цикла, но чтоб не первый, а какой нибудь другой )
 

orka13

Client
Регистрация
07.05.2015
Сообщения
2 167
Благодарностей
2 169
Баллы
113
Самый простой вариант (но не самый правильный) заменить:
Код:
he = heCol.Elements[i];
на:
Код:
he = heCol.Elements[new Random().Next(0,heCol.Count)];
Минус способа: может не все элементы коллекции перебрать, так как иногда на те же попадет. Для идеала надо формировать список с номерами элементов, перемешать его, и брать из него номера-строки с удалением. может еще что лучше есть, я тоже не знаток C#.

UPD: не надо ничего править как выше описано, я протупил что "HtmlElementCollection heCol" это фактически список, и его просто можно перемешать (Shuffle):
Заменить только:
Код:
HtmlElement he = null;
на:
Код:
HtmlElement he = null;
heCol.Shuffle();
 
Последнее редактирование:
  • Спасибо
Реакции: Кирилл412

Кирилл412

Пользователь
Регистрация
21.11.2018
Сообщения
146
Благодарностей
3
Баллы
18
Самый простой вариант (но не самый правильный) заменить:
Код:
he = heCol.Elements[i];
на:
Код:
he = heCol.Elements[new Random().Next(0,heCol.Count)];
Минус способа: может не все элементы коллекции перебрать, так как иногда на те же попадет. Для идеала надо формировать список с номерами элементов, перемешать его, и брать из него номера-строки с удалением. может еще что лучше есть, я тоже не знаток C#.
Спасибо, будем думать.. главное изначально идея правильна )
 

orka13

Client
Регистрация
07.05.2015
Сообщения
2 167
Благодарностей
2 169
Баллы
113

Кирилл412

Пользователь
Регистрация
21.11.2018
Сообщения
146
Благодарностей
3
Баллы
18
  • HtmlElement he = null;
  • heCol.Shuffle();
так он по идее перемешает все элементы, и которые не удовлетворяют условию видимости .... чет запутался с этим циклом... кажись надо переберать и все которые удовлетворяют условию писать в новый какойнить список, и от туда рандомом дергать..
 

Кирилл412

Пользователь
Регистрация
21.11.2018
Сообщения
146
Благодарностей
3
Баллы
18
так он по идее перемешает все элементы, и которые не удовлетворяют условию видимости .... чет запутался с этим циклом... кажись надо переберать и все которые удовлетворяют условию писать в новый какойнить список, и от туда рандомом дергать..
ааа, ну по идее,если перемешанный будет , то и дернет первый, удовлетворяющий этому условию, и он будет тож рандомный.. )))ппц
 

Кирилл412

Пользователь
Регистрация
21.11.2018
Сообщения
146
Благодарностей
3
Баллы
18
обновил предыдущий пост, оказывается есть рабочее решение попроще.
не, все равно первый по условию находит и бегает по нему... что в общемто и правильно.. вот как эти элементы собрать в кучу, а потом рандомно с кучи взять... тут токо кто C# курит
 
Последнее редактирование:

Кирилл412

Пользователь
Регистрация
21.11.2018
Сообщения
146
Благодарностей
3
Баллы
18
да вообще запутался в конец... это же делает цикл до выполнения условия, и выходит из него.. а как его прогнать по все найденным элементам..
 

orka13

Client
Регистрация
07.05.2015
Сообщения
2 167
Благодарностей
2 169
Баллы
113
Ну я думал надо только один элемент обрабатывать. А раз все, то тогда убрать выход из цикла, то есть удалить строку:
Код:
return "ok13"; // выходим из цикла
Да и если по правилам делать выход из цикла for C#, и надо еще продолжать обрабатывать строки в C# коде после самого тела цикла, то надо было там использовать строку:
Код:
break;
У меня просто там нет больше строк, вот я и не парился, и тупо сделал полностью выход их кода, а не из самого цикла.
 

Кирилл412

Пользователь
Регистрация
21.11.2018
Сообщения
146
Благодарностей
3
Баллы
18
Ну я думал надо только один элемент обрабатывать. А раз все, то тогда убрать выход из цикла, то есть удалить строку:
Код:
return "ok13"; // выходим из цикла
Да и если по правилам делать выход из цикла for C#, и надо еще продолжать обрабатывать строки в C# коде после самого тела цикла, то надо было там использовать строку:
Код:
break;
У меня просто там нет больше строк, вот я и не парился, и тупо сделал полностью выход их кода, а не из самого цикла.
Спасибо
 

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