C# клик по случайному элементу в пределах видимой области

orka13

Client
Joined
May 7, 2015
Messages
2,184
Reaction score
2,197
Points
113
Часто это постоянно поднимают на форуме. Вроде задание на 1 сниппет, но есть свои подводные камни. Здесь в коде максимально напичкано выводов в лог и комментирования чтобы можно было понять как в зенке формируется «видимая область». К конкурсам тема не относится, просто в раздел "Внеконкурсные статьи" вроде подобные мини-мануалы сбрасывают.

Я не гуру C#, и часть костылей в коде может надо по-другому делать. За основу бралась полноценная конкурсная статья от LaGir:
Сниппеты эмуляции мыши: FullEmulationMouse
Если накосячил, то указывайте что исправить.
JS-кубики надо обязательно отдельно выполнять перед каждым запуском рабочих C#-кубиков, интегрировать их в C# не рекомендую. А то будет беда.
Если элемент хоть немного выходить краями за пределы задаваемой области, то по нему не кликнет, так как в расчётах учитывается вся площадь элемента, а не его одна точка. Наглядно это видно на видео и скрине (сопоставьте из лога список подходящих элементов с теми, что на странице). В лог выводятся подходящие элементы, чтобы потом не было вопросов почему по этому кликает, а по этому нет…
Вот код основных кубиков (весь шаблон прикреплен в конце топика):
#4 JS window.innerWidth - обязательно перед C# выполнять!:
JavaScript:
return window.innerWidth;
#5 JS window.innerHeight - обязательно перед C# выполнять!:
JavaScript:
return window.innerHeight;
#6 Задаем свои параметры:
C#:
//Делаем отступы в пикселях от краёв видимой части страницы чтобы не кликать по элементам, близко расположенным к краю:
project.Variables["margin_left"].Value = "50"; // отступ от левого края
project.Variables["margin_top"].Value = "50"; // отступ сверху
project.Variables["margin_right"].Value = "150"; // отступ от правого края
project.Variables["margin_bottom"].Value = "220"; // отступ снизу
//Задаем минимальную ширину и высоту интересующего нас элемента в пикселях (у невидимых элементов это обычно "0", значит пропишем хотя бы "1"):
project.Variables["Width_Min"].Value = "1";
project.Variables["Height_Min"].Value = "1";
//Задаем максимальную ширину и высоту элемента в пикселях (ну, вдруг вы не захотите кликать по крупным баннерам и т.д., а пока "9999" равносильно "игнорированию" этой опции):
project.Variables["Width_Max"].Value = "9999";
project.Variables["Height_Max"].Value = "9999";
#7 просто в лог выводим что нашли (можно убрать):
C#:
// получаем документ из вкладки:
var tab = instance.ActiveTab;

//Высота и ширина главного документа страницы (https://zennolab.com/discussion/threads/navigacija-bota-na-web-stranicax.48679/#post-364240)
//Они, как правило - нижняя и правая конечные точки инстанса
int MainDocument_Width = tab.MainDocument.Width;
int MainDocument_Height = tab.MainDocument.Height;

int window_Width = Convert.ToInt32(project.Variables["windowinnerWidth"].Value); //парсим высоту видимого окна браузера из переменой JS.
int window_Height = Convert.ToInt32(project.Variables["windowinnerHeigth"].Value); //парсим ширину видимого окна браузера из переменой JS.

project.SendInfoToLog("Ширина и высота всего окна браузера в пикселях = " + MainDocument_Width.ToString() + "x" + MainDocument_Height.ToString(), true); // выводим в лог
project.SendInfoToLog("Ширина и высота видимого окна браузера из переменных JS = " + window_Width.ToString() + "x" + window_Height.ToString(), true); // выводим в лог

//Делаем отступы в пикселях от краёв видимой части страницы чтобы не кликать по элементам, близко расположенным к краю:
int margin_left = Int32.Parse(project.Variables["margin_left"].Value); // отступ от левого края
int margin_top = Int32.Parse(project.Variables["margin_top"].Value); // отступ сверху
int margin_right = Int32.Parse(project.Variables["margin_right"].Value); // отступ от правого края
int margin_bottom = Int32.Parse(project.Variables["margin_bottom"].Value); // отступ снизу

//Задаем минимальную ширину и высоту элемента в пикселях (у невидимых элементов это обычно "0", значит пропишем хотя бы "1"):
int Width_Min = Int32.Parse(project.Variables["Width_Min"].Value);
int Height_Min = Int32.Parse(project.Variables["Height_Min"].Value);
//Задаем максимальную ширину и высоту элемента в пикселях (ну, вдруг вы не захотите кликать по крупным баннерам и т.д., а пока "9999" равносильно "игнорированию" этой опции):
int Width_Max = Int32.Parse(project.Variables["Width_Max"].Value);
int Height_Max = Int32.Parse(project.Variables["Height_Max"].Value);

//Находим элементы (банально все ссылки по xPath):
HtmlElementCollection heCol  = tab.FindElementsByXPath("//a"); // все ссылки
project.SendInfoToLog("Столько элементов нашли по Xpath на всей странице: " + heCol.Count.ToString(), true); // выводим в лог
project.SendInfoToLog("Вот такой элемент полностью в зоне видимости окна с учетом полей:", true); // выводим в лог
project.SendInfoToLog("(Номер, Координаты начала элемента в видимом окне (x,y), конца, ширина, высота, текст, тег)", true); // выводим в лог
for (int i = 0; i < heCol.Count; i++) {  
    HtmlElement el = heCol.GetByNumber(i);  
    //Координаты начала элемента (его верхний левый угол) в видимом окне:
    int elX_1 = el.DisplacementInTabWindow.X;
    int elY_1 = el.DisplacementInTabWindow.Y;
    //Ширина и высота элемента:
    int elWidth = el.Width;
    int elHeight = el.Height;
    //Координаты конца элемента (его нижний правый угол) в видимом окне:
    int elX_2 = elX_1 + elWidth;
    int elY_2 = elY_1 + elHeight;
//Проверяем проходит ли наш элемент сразу по всем условиям:  
    if (
        elX_1 >= margin_left && // отступ слева
        elY_1 >= margin_top && // отступ сверху
        elX_2 <= window_Width-margin_right &&  // отступ справа
        elY_2 <= window_Height-margin_bottom && // отступ снизу
        elWidth >= Width_Min && // минимальная ширина
        elHeight >= Height_Min && // минимальная высота
        elWidth <= Width_Max && // максимальная ширина
        elHeight <= Height_Max // максимальная высота
        ) {
            string InnerText = el.InnerText;
            string FullTagName = el.FullTagName;
            project.SendInfoToLog("#"+ i.ToString() + ", " + elX_1.ToString() + ":" + elY_1.ToString() + ", " + elX_2.ToString() + ":" + elY_2.ToString() + ", " + elWidth.ToString() + ", " + elHeight.ToString() + ", " + InnerText + ", " + FullTagName, true); // выводим в лог
        }
}
project.SendInfoToLog("Для наглядности рисуем курсором границы зоны поиска, учитывая наши поля-отступы:", true); // выводим в лог
HtmlElement el_0  = tab.FindElementByXPath("//*", 0); //ищем нулевой тег вверху слева страницы
int el_0X_1 = el_0.DisplacementInTabWindow.X;
int el_0Y_1 = el_0.DisplacementInTabWindow.Y;
project.SendInfoToLog("На столько пикселей мы видимой областью отдалились от начала страница (x,y от нулевого тега вверху слева страницы): " + el_0X_1.ToString() + ", " +el_0Y_1.ToString(), true); // выводим в лог
project.SendInfoToLog("учитываем это при составлении координат нашей зоны", true); // выводим в лог

//Ведем к 1 точке прямоугольника:
instance.ActiveTab.FullEmulationMouseMove(-el_0X_1 + margin_left, -el_0Y_1 + margin_top);
System.Threading.Thread.Sleep(2 * 1000); // пауза 2 сек.
//Ведем к 2 точке прямоугольника:
instance.ActiveTab.FullEmulationMouseMove(-el_0X_1 + window_Width - margin_right, -el_0Y_1 + margin_top);
System.Threading.Thread.Sleep(2 * 1000); // пауза 2 сек.
//Ведем к 3 точке прямоугольника:
instance.ActiveTab.FullEmulationMouseMove(-el_0X_1 + window_Width - margin_right, -el_0Y_1 + window_Height - margin_bottom);
System.Threading.Thread.Sleep(2 * 1000); // пауза 2 сек.
//Ведем к 4 точке прямоугольника:
instance.ActiveTab.FullEmulationMouseMove(-el_0X_1 + margin_left, -el_0Y_1 + window_Height - margin_bottom);
System.Threading.Thread.Sleep(2 * 1000); // пауза 2 сек.
//Ведем к 1 точке прямоугольника обратно:
instance.ActiveTab.FullEmulationMouseMove(-el_0X_1 + margin_left, -el_0Y_1 + margin_top);
System.Threading.Thread.Sleep(2 * 1000); // пауза 2 сек.
#8 кликаем на рандомный элемент:
C#:
// получаем документ из вкладки:
var tab = instance.ActiveTab;

int window_Width = Convert.ToInt32(project.Variables["windowinnerWidth"].Value); //парсим высоту видимого окна браузера из переменой JS.
int window_Height = Convert.ToInt32(project.Variables["windowinnerHeigth"].Value); //парсим ширину видимого окна браузера из переменой JS.

//Делаем отступы в пикселях от краёв видимой части страницы чтобы не кликать по элементам, близко расположенным к краю:
int margin_left = Int32.Parse(project.Variables["margin_left"].Value); // отступ от левого края
int margin_top = Int32.Parse(project.Variables["margin_top"].Value); // отступ сверху
int margin_right = Int32.Parse(project.Variables["margin_right"].Value); // отступ от правого края
int margin_bottom = Int32.Parse(project.Variables["margin_bottom"].Value); // отступ снизу

//Задаем минимальную ширину и высоту элемента в пикселях (у невидимых элементов это обычно "0", значит пропишем хотя бы "1"):
int Width_Min = Int32.Parse(project.Variables["Width_Min"].Value);
int Height_Min = Int32.Parse(project.Variables["Height_Min"].Value);
//Задаем максимальную ширину и высоту элемента в пикселях (ну, вдруг вы не захотите кликать по крупным баннерам и т.д., а пока "9999" равносильно "игнорированию" этой опции):
int Width_Max = Int32.Parse(project.Variables["Width_Max"].Value);
int Height_Max = Int32.Parse(project.Variables["Height_Max"].Value);

//Находим элементы (банально все ссылки по xPath):
HtmlElementCollection heCol  = tab.FindElementsByXPath("//a"); // все ссылки
project.SendInfoToLog("Столько элементов нашли по Xpath на всей странице: " + heCol.Count.ToString(), true); // выводим в лог

//heCol.Shuffle(); // обычное перемешивание не проканало, будем городить костылями:
List <string> Indexes = new List <string>();
for (int i = heCol.Count-1; i >= 0 ; i--) {  
    int c = Global.Classes.rnd.Next(0, heCol.Count());
    HtmlElement el = heCol.ElementAt(c);
    //Координаты начала элемента (его верхний левый угол) в видимом окне:
    int elX_1 = el.DisplacementInTabWindow.X;
    int elY_1 = el.DisplacementInTabWindow.Y;
    //Ширина и высота элемента:
    int elWidth = el.Width;
    int elHeight = el.Height;
    //Координаты конца элемента (его нижний правый угол) в видимом окне:
    int elX_2 = elX_1 + elWidth;
    int elY_2 = elY_1 + elHeight;
//Проверяем проходит ли наш элемент сразу по всем условиям:  
    if (
        elX_1 >= margin_left && // отступ слева
        elY_1 >= margin_top && // отступ сверху
        elX_2 <= window_Width-margin_right &&  // отступ справа
        elY_2 <= window_Height-margin_bottom && // отступ снизу
        elWidth >= Width_Min && // минимальная ширина
        elHeight >= Height_Min && // минимальная высота
        elWidth <= Width_Max && // максимальная ширина
        elHeight <= Height_Max // максимальная высота
        ) {
            project.SendInfoToLog("Вот такой случайный элемент полностью в зоне видимости окна с учетом полей, его и кликаем:", true); // выводим в лог
            project.SendInfoToLog("(Координаты начала элемента в видимом окне (x,y), конца, ширина, высота, текст, тег)", true); // выводим в лог
            string InnerText = el.InnerText;
            string FullTagName = el.FullTagName;
            project.SendInfoToLog(elX_1.ToString() + ":" + elY_1.ToString() + ", " + elX_2.ToString() + ":" + elY_2.ToString() + ", " + elWidth.ToString() + ", " + elHeight.ToString() + ", " + InnerText + ", " + FullTagName, true); // выводим в лог
            instance.ActiveTab.FullEmulationMouseMoveToHtmlElement(el);
            System.Threading.Thread.Sleep(new Random().Next(1000,2000)); // пауза 1 - 2 сек.
            instance.ActiveTab.FullEmulationMouseClick("left", "click");
            return "успешно кликнули, и пофиг что страница потом стала 404";
        }
        heCol.Remove(c);
}
return "НЕ кликнули (видать нет видимых элементов в указанной зоне)";
//или вместо строки выше раскомментируйте и вставьте "выход по красной":
//throw new Exception("НЕ кликнули (видать нет видимых элементов в указанной зоне)");
Видео на 40 секунд с быстрой демонстрацией рисования границ видимой области:

Random.png

Варианты применения этих кубиков: нагуливание кук по сайтам, только измените xPath в коде на более сложный, чтобы по рекламе не кликать.
 

Attachments

Для запуска проектов требуется программа ZennoPoster.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...

Для того чтобы запустить шаблон, откройте программу ZennoPoster. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.

Last edited:

Iv1

Client
Joined
Feb 21, 2016
Messages
1,957
Reaction score
784
Points
113
Хорошая тема
Для себя что-то подобное реализовал сам и тоже мучался.
 

Fedor5588

Client
Joined
Jun 4, 2017
Messages
343
Reaction score
85
Points
28
Подскажите как правильно будет изменить код

C#:
HtmlElement he;
for(int i=0;i<20;i++)
{
    if(instance.ActiveTab.FindElementsByAttribute("a", "tagname", "a", "regexp").Count>0)
    {
        Random rnd = new Random();
        int x=rnd.Next(0,instance.ActiveTab.FindElementsByAttribute("a", "tagname", "a", "regexp").Count-1);

    he = instance.ActiveTab.FindElementByAttribute("a", "tagname", "a", "regexp",x);
    if(!he.IsVoid)
    {
        instance.ActiveTab.FullEmulationMouseMoveToHtmlElement(he);
        //he.RiseEvent("onclick","full");
        break;
    }

    }
    System.Threading.Thread.Sleep(2000);
}

return "";
на поиск по xpatch вот с такими параметрами

C#:
FindElementsByXPath("//a[@href][not(contains(@href, 'google')) and not(contains(@href, 'ad')) and not(contains(@href, 'yandex'))]")
 

Phoenix78

Client
Read only
Joined
Nov 6, 2018
Messages
11,789
Reaction score
5,729
Points
113

Fedor5588

Client
Joined
Jun 4, 2017
Messages
343
Reaction score
85
Points
28
FindElementsByAttribute менять на FindElementsByXPath
FindElementByAttribute менять на FindElementByXPath
это я понял, можете пожалуйста эту часть показать, у меня ошибка постоянно

C#:
    if(instance.ActiveTab.FindElementsByAttribute("a", "tagname", "a", "regexp").Count>0)
    {
        Random rnd = new Random();
        int x=rnd.Next(0,instance.ActiveTab.FindElementsByAttribute("a", "tagname", "a", "regexp").Count-1);

    he = instance.ActiveTab.FindElementByAttribute("a", "tagname", "a", "regexp",x);
 

Phoenix78

Client
Read only
Joined
Nov 6, 2018
Messages
11,789
Reaction score
5,729
Points
113
это я понял, можете пожалуйста эту часть показать, у меня ошибка постоянно
погонял приведенный код , ошибок не выдает.
заменил на xpath, тоже не выдает ошибок.
так то работает, но xpath наверно надо немного другой, так как постоянно пытается уехать к невидимым элементам.

блин, почему то сайт не дает код разместить. вот тогда скриншот.
65429
 

Fedor5588

Client
Joined
Jun 4, 2017
Messages
343
Reaction score
85
Points
28
погонял приведенный код , ошибок не выдает.
заменил на xpath, тоже не выдает ошибок.
так то работает, но xpath наверно надо немного другой, так как постоянно пытается уехать к невидимым элементам.

блин, почему то сайт не дает код разместить. вот тогда скриншот.
View attachment 65429
блин/
ровно так же сделал, вываливается вот така ошибка
Компиляция кода Ошибка в действии "CS1501" "No overload for method 'FindElementsByXPath' takes 2 arguments". [Строка: 9; Cтолбец: 29]
 

Phoenix78

Client
Read only
Joined
Nov 6, 2018
Messages
11,789
Reaction score
5,729
Points
113
блин/
ровно так же сделал, вываливается вот така ошибка
Компиляция кода Ошибка в действии "CS1501" "No overload for method 'FindElementsByXPath' takes 2 arguments". [Строка: 9; Cтолбец: 29]
FindElementsByXPath имеет 1 аргумент
FindElementByXPath имеет 2 аргумента
 
  • Thank you
Reactions: Fedor5588

Fedor5588

Client
Joined
Jun 4, 2017
Messages
343
Reaction score
85
Points
28
погонял приведенный код , ошибок не выдает.
заменил на xpath, тоже не выдает ошибок.
так то работает, но xpath наверно надо немного другой, так как постоянно пытается уехать к невидимым элементам.

блин, почему то сайт не дает код разместить. вот тогда скриншот.
View attachment 65429
Заработал, не знал что есть два вида поиска по xpatch, обычный и с приставкой s. а По какому лучше элементу искать чтобы был случайный клик но при этом без клика по рекламе?
 

Phoenix78

Client
Read only
Joined
Nov 6, 2018
Messages
11,789
Reaction score
5,729
Points
113
Заработал, не знал что есть два вида поиска по xpatch, обычный и с приставкой s. а По какому лучше элементу искать чтобы был случайный клик но при этом без клика по рекламе?
они одинаковые. FindElementsByXPath возвращает коллекцию найденных элементов
FindElementByXPath возвращает один найденный элемент.
за поиск отвечает сам путь xpath, вот в нем и надо прописывать все условия и исключения в виде рекламы.
 
  • Thank you
Reactions: smelka

Rus74

Client
Joined
Jan 9, 2019
Messages
112
Reaction score
43
Points
28
Спасибо большое за шаблон, прямо очень помог для имитации случайных кликов мышью по видимой области.
Подскажите, пожалуйста, как правильно исправить код, чтоб в логах вообще ничего не выводилось?
А то такую красоту в логах видеть нет необходимости.
https://prnt.sc/xg32ir
 

orka13

Client
Joined
May 7, 2015
Messages
2,184
Reaction score
2,197
Points
113
Спасибо большое за шаблон, прямо очень помог для имитации случайных кликов мышью по видимой области.
Подскажите, пожалуйста, как правильно исправить код, чтоб в логах вообще ничего не выводилось?
А то такую красоту в логах видеть нет необходимости.
https://prnt.sc/xg32ir
Заменить в строках с project.SendInfoToLog в конце параметр true на false. Типа сделать вот так, и они только в ProjectMaker будут видны:
C#:
project.SendInfoToLog("Для наглядности рисуем курсором границы зоны поиска, учитывая наши поля-отступы:", false);
Либо убрать их вообще.
UPD: подправил ошибку в слове false.
 
Last edited:
  • Thank you
Reactions: userx and Rus74

daymos

Client
Joined
Nov 11, 2009
Messages
807
Reaction score
241
Points
43
Если работать с профиль папками, шаблон запускается без браузера и JS не отдает области, даже после запуска инстанса.
 

TheBoss

Client
Joined
Mar 30, 2015
Messages
601
Reaction score
236
Points
43
Если работать с профиль папками, шаблон запускается без браузера и JS не отдает области, даже после запуска инстанса.
Как решать, подскажешь?

Часто бывает, что скрипт, как бы тупить начинает и кликать хер знает куда по несколько минут... Есть у кого вариант подправленный, ребят?
 

Smms

Новичок
Joined
Jan 20, 2024
Messages
24
Reaction score
3
Points
3
Если работать с профиль папками, шаблон запускается без браузера и JS не отдает области, даже после запуска инстанса.
Удалось решить проблему? У меня тоже JavaScript не получает данные для переменных.
 

Smms

Новичок
Joined
Jan 20, 2024
Messages
24
Reaction score
3
Points
3
Удалось решить проблему? У меня тоже JavaScript не получает данные для переменных.
Помогли найти решение. У меня в кубике было выбрано "выполнять локально". Изменил и JS заработал.
 
  • Thank you
Reactions: orka13

poludivan41k

Client
Joined
May 24, 2018
Messages
104
Reaction score
8
Points
18
Шаблон на пароле. Подскажите пароль пожалуйста
 

Sergodjan

Administrator
Staff member
Joined
Sep 5, 2012
Messages
21,493
Reaction score
9,550
Points
113
Шаблон на пароле. Подскажите пароль пожалуйста
Пароля нет, открывайте файл в ПроджектМейкере или Зеннопостере.
 

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