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

Кирилл412

Пользователь
Joined
Nov 21, 2018
Messages
146
Reaction score
3
Points
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

Пользователь
Joined
Nov 21, 2018
Messages
146
Reaction score
3
Points
18
Никто не подскажет??, гуру помогитеее...
 

backoff

Client
Joined
Apr 20, 2015
Messages
6,341
Reaction score
6,624
Points
113

Moadip

Client
Joined
Sep 26, 2015
Messages
509
Reaction score
825
Points
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

Пользователь
Joined
Nov 21, 2018
Messages
146
Reaction score
3
Points
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

Пользователь
Joined
Nov 21, 2018
Messages
146
Reaction score
3
Points
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
Joined
May 6, 2015
Messages
2,190
Reaction score
2,209
Points
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"; // выходим из цикла
    }  
}
 
Last edited:

Кирилл412

Пользователь
Joined
Nov 21, 2018
Messages
146
Reaction score
3
Points
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
Joined
May 6, 2015
Messages
2,190
Reaction score
2,209
Points
113
Самый простой вариант (но не самый правильный) заменить:
Code:
he = heCol.Elements[i];
на:
Code:
he = heCol.Elements[new Random().Next(0,heCol.Count)];
Минус способа: может не все элементы коллекции перебрать, так как иногда на те же попадет. Для идеала надо формировать список с номерами элементов, перемешать его, и брать из него номера-строки с удалением. может еще что лучше есть, я тоже не знаток C#.

UPD: не надо ничего править как выше описано, я протупил что "HtmlElementCollection heCol" это фактически список, и его просто можно перемешать (Shuffle):
Заменить только:
Code:
HtmlElement he = null;
на:
Code:
HtmlElement he = null;
heCol.Shuffle();
 
Last edited:
  • Thank you
Reactions: Кирилл412

Кирилл412

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

orka13

Client
Joined
May 6, 2015
Messages
2,190
Reaction score
2,209
Points
113
Спасибо, будем думать.. главное изначально идея правильна )
обновил предыдущий пост, оказывается есть рабочее решение попроще.
 

Кирилл412

Пользователь
Joined
Nov 21, 2018
Messages
146
Reaction score
3
Points
18
  • HtmlElement he = null;
  • heCol.Shuffle();
так он по идее перемешает все элементы, и которые не удовлетворяют условию видимости .... чет запутался с этим циклом... кажись надо переберать и все которые удовлетворяют условию писать в новый какойнить список, и от туда рандомом дергать..
 

Кирилл412

Пользователь
Joined
Nov 21, 2018
Messages
146
Reaction score
3
Points
18
так он по идее перемешает все элементы, и которые не удовлетворяют условию видимости .... чет запутался с этим циклом... кажись надо переберать и все которые удовлетворяют условию писать в новый какойнить список, и от туда рандомом дергать..
ааа, ну по идее,если перемешанный будет , то и дернет первый, удовлетворяющий этому условию, и он будет тож рандомный.. )))ппц
 

Кирилл412

Пользователь
Joined
Nov 21, 2018
Messages
146
Reaction score
3
Points
18
обновил предыдущий пост, оказывается есть рабочее решение попроще.
не, все равно первый по условию находит и бегает по нему... что в общемто и правильно.. вот как эти элементы собрать в кучу, а потом рандомно с кучи взять... тут токо кто C# курит
 
Last edited:

Кирилл412

Пользователь
Joined
Nov 21, 2018
Messages
146
Reaction score
3
Points
18
да вообще запутался в конец... это же делает цикл до выполнения условия, и выходит из него.. а как его прогнать по все найденным элементам..
 

orka13

Client
Joined
May 6, 2015
Messages
2,190
Reaction score
2,209
Points
113
Ну я думал надо только один элемент обрабатывать. А раз все, то тогда убрать выход из цикла, то есть удалить строку:
Code:
return "ok13"; // выходим из цикла
Да и если по правилам делать выход из цикла for C#, и надо еще продолжать обрабатывать строки в C# коде после самого тела цикла, то надо было там использовать строку:
Code:
break;
У меня просто там нет больше строк, вот я и не парился, и тупо сделал полностью выход их кода, а не из самого цикла.
 

Кирилл412

Пользователь
Joined
Nov 21, 2018
Messages
146
Reaction score
3
Points
18
Ну я думал надо только один элемент обрабатывать. А раз все, то тогда убрать выход из цикла, то есть удалить строку:
Code:
return "ok13"; // выходим из цикла
Да и если по правилам делать выход из цикла for C#, и надо еще продолжать обрабатывать строки в C# коде после самого тела цикла, то надо было там использовать строку:
Code:
break;
У меня просто там нет больше строк, вот я и не парился, и тупо сделал полностью выход их кода, а не из самого цикла.
Спасибо
 

Users Who Are Viewing This Thread (Total: 1, Members: 0, Guests: 1)