Сниппеты эмуляции мыши: FullEmulationMouse

LaGir

Client
Регистрация
01.10.2015
Сообщения
211
Благодарностей
849
Баллы
93
Приветствую всех!

Не так давно ZennoLab порадовали нас обновой с виртуальной мышью. Хотя лично у меня пока не было нужды использовать мышь в своих проектах, из интереса посидел вечерок за тестами новой эмуляции. В результате родились на свет пара сниппетов и чутка размышлений, кои и представлены ниже - возможно кому пригодятся.

Итак, появилось несколько методов работы с виртуальной мышью, доступных из C#-кода.
Самый интересный, несомненно, FullEmulationMouseMoveAboveHtmlElement, предназначенный для эмуляции чтения. Метод принимает в качестве параметров элемент страницы, который нужно "прочесть", и некий sizeOfType в виде некоего числа. На момент создания темы до сих пор непонятно, что это за sizeOfType такой - в документации объяснения нет, от разработчиков конкретного ответа тоже не было. Много тестил поведение метода с различными значениями, но так и не пришёл к понятному объяснению, как и на что влияет этот параметр. Если кто-то понял его назначение, или хотя бы есть однозначные предположения - большая просьба отписаться.
Также добавлю, что в ходе тестов не получилось найти и оптимального значения sizeOfType, при котором эмуляция чтения смотрелась бы более-менее реалистично. Моё мнение - над реализацией этой виртуальной мыши разработчикам ещё работать и работать.

Но довольно о проблемах. Так как виртуальная мышь сейчас доступна только из кода, с которым немало пользователей ZennoPoster "на Вы", разберём пару простых задач с применением виртуальной мыши. Для примера возьмём главную страницу известного портала 4pda.

Задача 1: "прочитать" рандомный пост с главной страницы и перейти к его полной версии.
C#:
var rnd = new Random();

//Переходим на целевую страничку
Tab tab1 = instance.ActiveTab;
tab1.Navigate("http://4pda.ru/");
if (tab1.IsBusy)    tab1.WaitDownloading();

//Находим коллекцию элементов-постов (на главной нашего сайта их 30 штук)
//Эти элементы будем использовать как родительские, для поиска заголовка и контента каждого из постов
var posts = tab1.FindElementsByXPath("//article[@class='post']");
//Я обычно использую XPath, но можно искать и просто по атрибутам:
//posts = tab1.FindElementsByAttribute("article", "class", "post", "text");

//Если ни одного поста не найдено, выходим из сниппета по красной ветке
if (posts.Count==0)    throw new Exception("Посты не найдены!");

//Получаем рандомный пост на странице
var post = posts.GetByNumber(rnd.Next(0,posts.Count));

//Ведём мышку к этому посту
tab1.FullEmulationMouseMoveToHtmlElement(post);

//Ищем заголовок поста
var h2 = post.FindChildByXPath(".//h2",0);
//Проводим мышкой по заголовку
tab1.FullEmulationMouseMoveAboveHtmlElement(h2, 30);

//Ищем текст поста
var p = post.FindChildByXPath(".//p",0);
//Проводим мышкой по тексту
tab1.FullEmulationMouseMoveAboveHtmlElement(p, 40);

Thread.Sleep(2000);    //Пауза 2 с

//Ведём мышку к кнопке "далее" и кликаем по ней
var more = post.FindChildByXPath(".//a[text()='далее']",0);
tab1.FullEmulationMouseMoveToHtmlElement(more);
tab1.FullEmulationMouseClick("left", "click");

Задача 2: "прочитать" все посты на главной странице.
C#:
var rnd = new Random();

//Переходим на целевую страничку
Tab tab1 = instance.ActiveTab;
tab1.Navigate("http://4pda.ru/");
if (tab1.IsBusy)    tab1.WaitDownloading();

//Находим коллекцию элементов-постов
var posts = tab1.FindElementsByXPath("//article[@class='post']");

//Проходим в цикле по каждому посту
foreach (var post in posts.Elements){
  
    //Ищем заголовок поста
    var h2 = post.FindChildByXPath(".//h2",0);
    //Проводим мышкой по заголовку, для второго параметра используем рандом (например, от 30 до 50)
    tab1.FullEmulationMouseMoveAboveHtmlElement(h2, rnd.Next(30,50));
    //Делаем случайную паузу от 0,1 до 1 секунды
    Thread.Sleep(rnd.Next(1,10) * 100);
  
    //Ищем текст поста
    var p = post.FindChildByXPath(".//p",0);
    //Проводим мышкой по тексту
    tab1.FullEmulationMouseMoveAboveHtmlElement(p, rnd.Next(30,50));
    //Делаем случайную паузу от 0,5 до 3 секунд
    Thread.Sleep(rnd.Next(4,30) * 100);
  
    //Для доп рандомизации (или просто опытов), можно также после "прочтения" каждого поста менять настройки движения мышки (метод доступен с версии 5.10.4.1)
    //По умолчанию каждый параметр равен 5. Для их изменения также можно применять рандом:
    //t1.FullEmulationMouseSetOptions(rnd.Next(3,20), 5, rnd.Next(5,10));
}
Перед использованием методов FullEmulationMouseMoveAboveHtmlElement и FullEmulationMouseSetOptions рекомендую потестить разные значения их целочисленных параметров, возможно вам удастся получить более адекватные движения мышки.

Если у вас вопросы, идеи сниппетов, или же есть самим что написать по теме виртуальной мыши - жду ваших сообщений в топике. :-)
 

LaGir

Client
Регистрация
01.10.2015
Сообщения
211
Благодарностей
849
Баллы
93
Рассмотрим подробнее метод FullEmulationMouseSetOptions, доступный с версии 5.10.4.1.
Предназначен он для установки параметров эмуляции мыши, причём после каждого вызова метода Navigate параметры сбрасываются на значения по умолчанию.

Параметры.
1. pause

Описание. Пауза в миллисекундах при генерации следующей точки для движения мыши.
Значение по умолчанию: 5.
Стоит ли менять? В принципе, на мой взгляд значение по умолчанию вполне себе оптимальное. Если его уменьшить - мышка будет двигаться быстрее, и наоборот. Причём увеличить скорость передвижения мышки таким способом получится сравнительно немного (опускаем значение с 5 до 0), а вот замедлить можно очень сильно (поднимаем значение с 5 до скольки угодно).

2. pauseVariance
Описание. Отклонение для паузы (1-й параметр). Пример работы: если пауза стоит 50 мс, а отклонение 10 мс - пауза будет случайной в диапазоне от 40 до 60 мс.
Значение по умолчанию: 5.
Стоит ли менять? Тоже вполне можно считать оптимальным значением. Но, конечно, поиграться с паузами лично - хорошая идея, возможно найдёте для себя значения получше.

3. pointDistanse
Описание. Длина шага по прямой линии между генерируемыми точками.
Значение по умолчанию: 5.
Стоит ли менять? Вот этот параметр, на мой взгляд, стоит активно использовать для изменения скорости движения мыши. Изменять это значение нужно осторожно, ибо увеличение даже до 20 сильно ускоряет движение мыши.

Выводы.
По умолчанию скорость мыши в методах FullEmulationMouse неизменна, в результате чего эмуляция легко палится, мягко говоря. Скорость движения мышки реального человека как правило постоянно меняется, нередко встречаются быстрые рывки.
Следовательно, для лучшей эмуляции, после каждого применения методов движения FullEmulationMouse в идеале чутка менять параметры метода FullEmulationMouseSetOptions, как минимум для изменения скорости движения мыши.
Конечно, вряд ли можно сказать, что эти действия существенно "очеловечат" движения, но по крайней мере некоторые действия (а именно - движение мыши на большое расстояние и "чтение" большого количества текста) будут выглядеть на порядок правдоподобнее.

Разберём регулярное изменение скорости мыши с помощью этого метода, на примере первого сниппета из прошлого поста.
C#:
var rnd = new Random();
//Переходим на целевую страничку
Tab tab1 = instance.ActiveTab;
tab1.Navigate("http://4pda.ru/");
if (tab1.IsBusy)    tab1.WaitDownloading();
//Находим коллекцию элементов-постов
var posts = tab1.FindElementsByXPath("//article[@class='post']");
//Если ни одного поста не найдено, выходим из сниппета по красной ветке
if (posts.Count==0)    throw new Exception("Посты не найдены!");

//Находим 1-й пост на странице
var post = posts.GetByNumber(1);

//Меняем скорость и ведём мышкой к посту
tab1.FullEmulationMouseSetOptions(5,5,14);
tab1.FullEmulationMouseMoveToHtmlElement(post);
Thread.Sleep(1000);    //Пауза 1 с

//Снова меняем скорость (чуть медленнее) и проводим мышкой по заголовку
tab1.FullEmulationMouseSetOptions(5,5,8);
var h2 = post.FindChildByXPath(".//h2",0);    //Поиск заголовка поста
tab1.FullEmulationMouseMoveAboveHtmlElement(h2, 30);
Thread.Sleep(1000);    //Пауза 1 с

//Снова меняем скорость (ещё медленнее, а-ля более внимательное чтение) и проводим мышкой по тексту поста
tab1.FullEmulationMouseSetOptions(5,5,3);
var p = post.FindChildByXPath(".//p",0);    //Поиск текста поста
tab1.FullEmulationMouseMoveAboveHtmlElement(p, 40);

//Также напоминаю, что настройки мыши можно задавать рандомно
//Например, так случайным образом будет задаваться 3-й параметр в диапазане от 4 до 10:
tab1.FullEmulationMouseSetOptions(5,5,rnd.Next(4,11));
Запустив сниппет, можно наглядно увидеть, что скорость движения мыши в этих 3-х действиях ощутимо различалась, и была уже более похожа на человеческие (нежели в первых сниппетах, по крайней мере). 1 движение - резкое движени курсора к посту, 2 движение - быстрое чтение заголовка, 3 движение - медленное чтение текста поста.

Ещё важный момент. Если запустить этот сниппет, но указать не 1 пост, а например 10, то можно заметить ещё одну проблему текущей реализации виртуальной мыши: при передвижении мышки далеко вниз или далеко вверх по странице (скролл по сути) - настройки мыши нифига не работают, мышка тащится медленно и с одинаковой скоростью, что очень не по-человечески. Возможно, именно этот момент разберём в следующей "серии" более подробно. :-)
 

LaGir

Client
Регистрация
01.10.2015
Сообщения
211
Благодарностей
849
Баллы
93
За работой немного позабыл об этой темке хотя давно пора было ответить на вопрос, который задавал в первом посте темы. VladZen в этом сообщении объяснил, что sizeOfType, второй параметр метода FullEmulationMouseMoveAboveHtmlElement относится к отступам/примерному размеру шрифта "читаемого" текста. Спасибо пользователю @Серёжа за напоминание в личку об этом параметре.

Также, упоминал о проблеме прокрутки в предыдущем посте - с этим реальные проблемы, тестил разные варианты, любой способ скролла не может корректно работать вместе с методами FullEmulationMouse. Также, об этом уже написали в этой теме, но походу разработчики считали имеющийся скролл правдоподобным и что его достаточно. Однако, надежда есть.


Ну и, раз уж пишу пост, можно ещё и по теме примеров что-нибудь написать.
Рано или поздно новой виртуальной мышью можно будет рулить из кубиков, и примеры в этой темке потеряют часть своей актуальности. Однако, многие вещи по теме именно увеличения качества эмуляции проще и легче делать в коде.
Поэтому, предлагаю сегодня рассмотреть рандомное "чтение" каких-либо текстов виртуальной мышью, на примере заголовков из примеров первого поста темки.

Суть - если заголовок достаточно короткий, то пользователь вполне может его пропустить курсором, быстро прочитав только глазами.
Можно это эмулировать, вытащив текст заголовка, псчитав количество его символов, и - если их меньше, скажем, 30 - пропускать. Берём за основу этот кусок кода из сниппета первого поста:
C#:
//Ищем заголовок поста
var h2 = post.FindChildByXPath(".//h2",0);
//Проводим мышкой по заголовку, для второго параметра используем рандом (например, от 30 до 50)
tab1.FullEmulationMouseMoveAboveHtmlElement(h2, rnd.Next(30,50));
Переделываем согласно вышеизложенному:
C#:
var h2 = post.FindChildByXPath(".//h2",0);
int h2min = 30;        //Задаём минимальную длину заголовка для прочтения
int h2dlina = post.InnerText.Length;    //Определяем длину заголовка в символах
if (h2dlina > h2min){        //Если длина заголовка больше мин. значения - читаем заголовок
    tab1.FullEmulationMouseMoveAboveHtmlElement(h2, rnd.Next(30,50));
}
Итог: мышка проведёт по заголовку, если он длиннее или равен 30 символам, иначе - просто пропустит.

Можно ещё модернизировать. Скажем, если длина заголовка меньше 30 символов, то одно из двух: с вероятностью 33% "читаем" заголовок, с вероятностью 67% - пропускаем. Вероятность задаём в третьей строчке.

C#:
var h2 = post.FindChildByXPath(".//h2",0);
int h2min = 30;        //Задаём минимальную длину заголовка для прочтения
int ver = 33;        //Задаём вероятность прочтения заголовка меньше 'h2min' символов, в процентах
int h2dlina = post.InnerText.Length;    //Определяем длину заголовка в символах
int prsnt = rnd.Next(100);
if ((h2dlina < h2min && prsnt >= ver) || h2dlina >= h2min){
    //Заголовки
    tab1.FullEmulationMouseMoveAboveHtmlElement(h2, 30);
}
Полный вариант сниппета из первого поста с обновлённым "чтением" заголовков под спойлером.
C#:
var rnd = new Random();

//Переходим на целевую страничку
Tab tab1 = instance.ActiveTab;
tab1.Navigate("http://4pda.ru/");
if (tab1.IsBusy)    tab1.WaitDownloading();

//Находим коллекцию элементов-постов
var posts = tab1.FindElementsByXPath("//article[@class='post']");

//Проходим в цикле по каждому посту
foreach (var post in posts.Elements){

    //Ищем заголовок поста
    var h2 = post.FindChildByXPath(".//h2",0);
    int h2min = 30;        //Задаём минимальную длину заголовка для прочтения
    int ver = 33;        //Задаём вероятность прочтения заголовка меньше 'h2min' символов, в процентах
    int h2dlina = post.InnerText.Length;    //Определяем длину заголовка в символах
    int prsnt = rnd.Next(100);
    if ((h2dlina < h2min && prsnt >= ver) || h2dlina >= h2min){
        //Заголовки
        tab1.FullEmulationMouseMoveAboveHtmlElement(h2, 30);
    }
    //Делаем случайную паузу от 0,1 до 1 секунды
    Thread.Sleep(rnd.Next(1,10) * 100);

    //Ищем текст поста
    var p = post.FindChildByXPath(".//p",0);
    //Проводим мышкой по тексту
    tab1.FullEmulationMouseMoveAboveHtmlElement(p, rnd.Next(30,50));
    //Делаем случайную паузу от 0,5 до 3 секунд
    Thread.Sleep(rnd.Next(4,30) * 100);

    //Для доп рандомизации (или просто опытов), можно также после "прочтения" каждого поста менять настройки движения мышки (метод доступен с версии 5.10.4.1)
    //По умолчанию каждый параметр равен 5. Для их изменения также можно применять рандом:
    //t1.FullEmulationMouseSetOptions(rnd.Next(3,20), 5, rnd.Next(5,10));
}

Не знаю, какую конструкцию придётся соорудить из кубиков для реализации этого простого "баффа" эмуляции, но полагаю что немаленькую - так что думаю кому-то эти несколько строк будут полезными. :-)
 

deopl

Client
Регистрация
06.12.2011
Сообщения
656
Благодарностей
125
Баллы
43
Заметил что одинаковые элементы, только с разным left, кликает по одним и тем же координатам каждого элемента
К примеру горизонтальное меню
 

Juniorcpa

Client
Регистрация
27.05.2014
Сообщения
2 031
Благодарностей
1 285
Баллы
113
Спасибо за статьи. Очень круто и подробно расписано.
 
  • Спасибо
Реакции: leha52rus и LaGir

zenfreak

Client
Регистрация
21.08.2013
Сообщения
249
Благодарностей
11
Баллы
18
Описание. Отклонение для паузы (1-й параметр). Пример работы: если пауза стоит 50 мс, а отклонение 10 мс - пауза будет случайной в диапазоне от 40 до 60 мс.
Значение по умолчанию: 5.
Если значение по умолчанию для паузы составляет 5 миллисекунд, а дисперсия паузы также составляет 5 миллисекунд, значит ли это, что пауза будет случайным значением от 0 до 10 миллисекунд?
 

LaGir

Client
Регистрация
01.10.2015
Сообщения
211
Благодарностей
849
Баллы
93
Если значение по умолчанию для паузы составляет 5 миллисекунд, а дисперсия паузы также составляет 5 миллисекунд, значит ли это, что пауза будет случайным значением от 0 до 10 миллисекунд?
Верно.
 
  • Спасибо
Реакции: zenfreak

socrobotic

Client
Регистрация
14.02.2016
Сообщения
203
Благодарностей
85
Баллы
28
блин надо было сразу же до конца дочитать и взять эти строчки))) а так пришлось сначала 1 код поставить по себя сделать, потом дальше и в итоге просто всю ветку перечитала и добавила последний варинат, реально крутое решеие, пасибо!
 
  • Спасибо
Реакции: leha52rus и LaGir

chutev

Client
Регистрация
23.01.2016
Сообщения
111
Благодарностей
15
Баллы
18
Делаю для одного сайта эмуляцию движения мыши, появилась проблема. В определенный момент, когда курсор движется к найденному элементу, он как будто залипает и не переставая двигаться в этом направлении упирается в край экрана. Прервать, в этом случает, можно только закрыв окно. Элемент на странице присутствует. Может у кого была такая проблема, как лечить? Или может есть какой то способ, что бы прервать выполнение кубика с#?
 

esouldy

Client
Регистрация
28.02.2016
Сообщения
185
Благодарностей
92
Баллы
28
Делаю для одного сайта эмуляцию движения мыши, появилась проблема. В определенный момент, когда курсор движется к найденному элементу, он как будто залипает и не переставая двигаться в этом направлении упирается в край экрана. Прервать, в этом случает, можно только закрыв окно. Элемент на странице присутствует. Может у кого была такая проблема, как лечить? Или может есть какой то способ, что бы прервать выполнение кубика с#?
возможно элемент не один, и курсор хватается за другой, с координатой меньше или равной нулю, либо же скрытый. собирай элементы в массив и проверяй координаты
 
  • Спасибо
Реакции: chutev

Redsmokky

Client
Регистрация
06.10.2015
Сообщения
311
Благодарностей
195
Баллы
43
Делаешь в ПМ норм отрабатывает, а ЗП бывает что вылетает за край экрана почему-то элемент и виснет инстанс, со скролом та же фигня, поток потом жрет ЦП и память пока не сдохнет и ЗП его не закроет. Хз как убрать эту штуку
 

LaGir

Client
Регистрация
01.10.2015
Сообщения
211
Благодарностей
849
Баллы
93
С момента моих последних постов в этой теме появилось ещё несколько методов виртуальной мыши: FullEmulationMouseWheel (5.10.7.0), FullEmulationMouseDragAndDrop и FullEmulationMouseSetScrollBorder (5.11.6.0).
Давайте кратко рассмотрим эти методы.

1. FullEmulationMouseWheel
Данный метод предназначен для эмуляции прокрутки колёсиком мыши.
Метод принимает 2 параметра типа int:
  • deltaX - величина в пикселях, на которую прокрутится страница по горизонтали (ось x)
  • deltaY - величина в пикселях, на которую прокрутится страница по вертикали (ось y)

Если нужно крутить вниз, то указываем положительное значени, если вверх - отрицательное.
C#:
//Делаем прокрутку на 500 пикселей ВНИЗ (по y)
instance.ActiveTab.FullEmulationMouseWheel(0, 500);
//Делаем прокрутку на 500 пикселей ВВЕРХ (по y)
instance.ActiveTab.FullEmulationMouseWheel(0, -500);
Пример использования. Допустим, есть кнопка далеко внизу страницы, нужно проскролить и кликнуть по ней.
C#:
//Находим элемент кнопки
var elButton = instance.ActiveTab.FindElementByXPath("//button", 0);
//Определяем, на каком расстоянии от верха страницы находится кнопка
int topInBrowser = int.Parse(elButton.GetAttribute("topInBrowser"));
//Делаем прокрутку на это расстояние
instance.ActiveTab.FullEmulationMouseWheel(0, topInBrowser);
//Ведём курсор мышки к кнопке
instance.ActiveTab.FullEmulationMouseMoveToHtmlElement(elButton);
//Кликаем
instance.ActiveTab.FullEmulationMouseClick("left", "click");

2. FullEmulationMouseDragAndDrop
Данный метод предназначен для эмуляции перетаскивания элементов мышкой по принципу DragAndDrop.
У него есть 2 перегрузки - перетаскивание по координатам, перетаскивание одного элемента на другой.

Перетаскивание по координатам:
C#:
//Координата по X, от которой начинаем перетаскивание
int fromX = 400;
//Координата по Y, от которой начинаем перетаскивание
int fromY = 100;
//Координата по X, на которую тащим
int toX = 500;
//Координата по Y, на которую тащим
int toY = 300;

//Перетаскиваем по координатам
instance.ActiveTab.FullEmulationMouseDragAndDrop(fromX, fromY, toX, toY);
Перетаскивание элементов:
C#:
//Находим 1-й элемент
var el1 = instance.ActiveTab.FindElementByXPath("//img[@class='logo']", 0);
//Находим 2-й элемент
var el2 = instance.ActiveTab.FindElementByXPath("//textarea[@id='field']", 0);
//Перетаскивание 1-го элемента на 2-ой
instance.ActiveTab.FullEmulationMouseDragAndDrop(el1, el2);

3. FullEmulationMouseSetScrollBorder
Данный метод предназначен для установки положения курсора мыши относительно края страницы во время прокрутки. Например, по умолчанию при прокрутке страницы курсор останавливается в 20 пикселях от края страницы, в сторону которого производится прокрутка.
Метод принимает 2 параметра типа int:
  • scrollX - расстояния курсора мыши от края страницы при горизонтальном скролле
  • scrollY - расстояния курсора мыши от края страницы при вертикальном скролле
ScrollY.jpg

C#:
//Меняем значения границ скролла на 0 для горизонтальной прокрутки и 10 для вертикальной
instance.ActiveTab.FullEmulationMouseSetScrollBorder(0, 10);
 

Juniorcpa

Client
Регистрация
27.05.2014
Сообщения
2 031
Благодарностей
1 285
Баллы
113
А давай рассмотрим эти методы на основе актуального сайта?)
 
  • Спасибо
Реакции: LaGir

LaGir

Client
Регистрация
01.10.2015
Сообщения
211
Благодарностей
849
Баллы
93

Juniorcpa

Client
Регистрация
27.05.2014
Сообщения
2 031
Благодарностей
1 285
Баллы
113

chutev

Client
Регистрация
23.01.2016
Сообщения
111
Благодарностей
15
Баллы
18
возможно элемент не один, и курсор хватается за другой, с координатой меньше или равной нулю, либо же скрытый. собирай элементы в массив и проверяй координаты
Элемент на странице есть. Мышка тупо пробегает мимо.
 

LaGir

Client
Регистрация
01.10.2015
Сообщения
211
Благодарностей
849
Баллы
93
Zennolab.com, авторизация, поиск этой темы, написать сюда что-нибудь :-)
Конкретно для демонстрации методов мыши необычный вариант, но почему бы и нет. :-) Добавил ещё поиск последнего поста в теме и его "чтение".
Только сорре, что к мыши не относится - тоже в коде, на кубиках разучился писать (зато почти всё закомменчено).

Прикрепляю шаблон к сообщению. Для ленивых - содержимое сниппетов под спойлерами.
C#:
//Получаем логин и пароль из переменных проекта
string login = project.Variables["login"].Value;
string pass = project.Variables["pass"].Value;

//Заходим на ZennoLab
var tab = instance.ActiveTab;
tab.Navigate("http://zennolab.com/discussion/");
if (tab.IsBusy)    tab.WaitDownloading();
Helper.Pause();


//Логинимся

//Поиск кнопки по XPath
var elLogIn = tab.FindElementByXPath("//a[contains(@href,'login')]", 0);
//Поиск кнопки по атрибутам
//var elLogIn = tab.FindElementByAttribute("a", "href", "login/", "text", 0);

//Ведём мышку к кнопке
tab.FullEmulationMouseMoveToHtmlElement(elLogIn);
//Задержка совсем чуть-чуть (от 200 до 400 мс)
Helper.Pause(2,5);
//Клакием по кнопке
tab.FullEmulationMouseClick("left", "click");

//Задержка на выезд панельки (от 1 до 2 с)
Helper.Pause(10,21);

//Ищем поля логина и пароля, кнопку входа
var elMail = tab.FindElementByXPath("//input[@name='login']", 0);
var elPass = tab.FindElementByXPath("//input[@name='password']", 0);
var elLogInBtn = tab.FindElementByXPath("//input[@class='button primary']", 0);

//Проверяем, выдвинулась ли панелька с формой входа
if (int.Parse(elMail.GetAttribute("topInTab"))<0)
    throw new Exception("Фигня какая-то, брат, форма с авторизацией не выдвигается!");

//Изменяем настройки мыши (теперь двигается чутка быстрее)
tab.FullEmulationMouseSetOptions(5,5,10);
//Ведём её к полю ввода email/логина
tab.FullEmulationMouseMoveToHtmlElement(elMail);
//Кликаем по полю
tab.FullEmulationMouseClick("left", "click");
//Вводим логин
elMail.SetValue(login, "Middle");
//Микропауза (300-700 мс)
Helper.Pause(3,8);

//Возвращаем настройки мыши к стандартным
tab.FullEmulationMouseSetOptions();
//Ведём её к полю ввода пароля
tab.FullEmulationMouseMoveToHtmlElement(elPass);
//Кликаем по полю
tab.FullEmulationMouseClick("left", "click");
//Вводим пароль
elPass.SetValue(pass, "Middle");
//Микропауза (300-700 мс)
Helper.Pause(3,8);

//Ведём мышь к кнопке входа
tab.FullEmulationMouseMoveToHtmlElement(elLogInBtn);
//Микропауза (200-500 мс)
Helper.Pause(2,6);
//Кликаем по кнопке
tab.FullEmulationMouseClick("left", "click");
//Ждём прогрузку
if (tab.IsBusy)    tab.WaitDownloading();
Helper.Pause();
C#:
//Название темки
string searchText = project.Variables["searchText"].Value;

var tab = instance.ActiveTab;

//Ищем поле поиска по форуму
var elSearchField = tab.FindElementByXPath("//input[@id='QuickSearchQuery']", 0);
//Подведём к нему мышь. Для разнообразия, по координатам
//Находим координату середины поля по x
int toX = int.Parse(elSearchField.GetAttribute("leftInBrowser")) + elSearchField.Width/2;
//Находим координату середины поля по y
int toY = int.Parse(elSearchField.GetAttribute("topInBrowser")) + elSearchField.Height/2;
//Ведём мышь к найденным координатам
tab.FullEmulationMouseMove(toX, toY);
//Микропауза (200-500 мс)
Helper.Pause(2,6);
//Клик
tab.FullEmulationMouseClick("left", "click");
//Микропауза (200-500 мс)
Helper.Pause(2,6);
//Вводим строку поиска
elSearchField.SetValue(searchText, "Middle");

//Ищем кнопку поиска
var elSearchButton = tab.FindElementByXPath("//input[contains(@class,'button primar')]", 0);
//Ведём к ней мышь
tab.FullEmulationMouseMoveToHtmlElement(elSearchButton);
//Микропауза (200-500 мс)
Helper.Pause(2,6);
//Кликаем по кнопке
tab.FullEmulationMouseClick("left", "click");

//Ждём прогрузку страницы
if (tab.IsBusy)    tab.WaitDownloading();
Helper.Pause();

//Ищем ссылку на тему
var elTopicLink = tab.FindElementByXPath("//a[string()='" + searchText + "']", 1);
//Ведём к ней мышку
tab.FullEmulationMouseMoveToHtmlElement(elTopicLink);
//Микропауза (200-500 мс)
Helper.Pause(2,6);
//Кликаем по ссылке
tab.FullEmulationMouseClick("left", "click");

//Ждём прогрузку страницы
if (tab.IsBusy)    tab.WaitDownloading();
Helper.Pause();
C#:
//Текст поста
string text = project.Variables["postText"].Value;

var tab = instance.ActiveTab;

//Находим на странице последний пост
var elLastPost = tab.FindElementByXPath("//li[contains(@id,'post-')][last()]", 0);
//Ищем, где на странице расположен пост
//Находим координату начала поста по y
int toY = int.Parse(elLastPost.GetAttribute("topInBrowser"));
//Если от текущего положения мыши на странице до последнего поста далеко (свыше 2000 пикселей)
if ((toY-tab.FullEmulationMouseCurrentPosition.Y) > 2000){
    //То крутим колесико мышки на это расстояние
    tab.FullEmulationMouseWheel(0, toY-tab.FullEmulationMouseCurrentPosition.Y);
}

//Микропауза (400-900 мс)
Helper.Pause(4,10);

//Находим текст поста
var elLastPostText = elLastPost.FindChildByXPath(".//article",0);
//"Читаем" его мышкой
tab.FullEmulationMouseMoveAboveHtmlElement(elLastPostText, 35);

//Находим поле для ответа
var replyField = tab.FindElementByXPath("//body[@dir='LTR']", 0);
//Ведём к полю мышку
tab.FullEmulationMouseMoveToHtmlElement(replyField);
//Микропауза (200-500 мс)
Helper.Pause(2,6);
//Кликаем по полю
tab.FullEmulationMouseClick("left", "click");
//Вводим текст ответа
replyField.SetValue(text, "Middle");
//Микропауза (800-1100 мс)
Helper.Pause(8,12);

//Находим кнопку отправки ответа
var replySubmit = tab.FindElementByXPath("//div[@class='draftUpdate']/following-sibling::input[contains(@class,'button primar')]", 0);
//Ведём к ней мышку
tab.FullEmulationMouseMoveToHtmlElement(replySubmit);
//Микропауза (800-1100 мс)
Helper.Pause(8,12);
//Кликаем по кнопке
//tab.FullEmulationMouseClick("left", "click");

//Ждём прогрузку страницы
if (tab.IsBusy)    tab.WaitDownloading();
Helper.Pause();
 

Вложения

Juniorcpa

Client
Регистрация
27.05.2014
Сообщения
2 031
Благодарностей
1 285
Баллы
113
Конкретно для демонстрации методов мыши необычный вариант, но почему бы и нет. :-) Добавил ещё поиск последнего поста в теме и его "чтение".
Только сорре, что к мыши не относится - тоже в коде, на кубиках разучился писать (зато почти всё закомменчено).

Прикрепляю шаблон к сообщению. Для ленивых - содержимое сниппетов под спойлерами.
C#:
//Получаем логин и пароль из переменных проекта
string login = project.Variables["login"].Value;
string pass = project.Variables["pass"].Value;

//Заходим на ZennoLab
var tab = instance.ActiveTab;
tab.Navigate("http://zennolab.com/discussion/");
if (tab.IsBusy)    tab.WaitDownloading();
Helper.Pause();


//Логинимся

//Поиск кнопки по XPath
var elLogIn = tab.FindElementByXPath("//a[contains(@href,'login')]", 0);
//Поиск кнопки по атрибутам
//var elLogIn = tab.FindElementByAttribute("a", "href", "login/", "text", 0);

//Ведём мышку к кнопке
tab.FullEmulationMouseMoveToHtmlElement(elLogIn);
//Задержка совсем чуть-чуть (от 200 до 400 мс)
Helper.Pause(2,5);
//Клакием по кнопке
tab.FullEmulationMouseClick("left", "click");

//Задержка на выезд панельки (от 1 до 2 с)
Helper.Pause(10,21);

//Ищем поля логина и пароля, кнопку входа
var elMail = tab.FindElementByXPath("//input[@name='login']", 0);
var elPass = tab.FindElementByXPath("//input[@name='password']", 0);
var elLogInBtn = tab.FindElementByXPath("//input[@class='button primary']", 0);

//Проверяем, выдвинулась ли панелька с формой входа
if (int.Parse(elMail.GetAttribute("topInTab"))<0)
    throw new Exception("Фигня какая-то, брат, форма с авторизацией не выдвигается!");

//Изменяем настройки мыши (теперь двигается чутка быстрее)
tab.FullEmulationMouseSetOptions(5,5,10);
//Ведём её к полю ввода email/логина
tab.FullEmulationMouseMoveToHtmlElement(elMail);
//Кликаем по полю
tab.FullEmulationMouseClick("left", "click");
//Вводим логин
elMail.SetValue(login, "Middle");
//Микропауза (300-700 мс)
Helper.Pause(3,8);

//Возвращаем настройки мыши к стандартным
tab.FullEmulationMouseSetOptions();
//Ведём её к полю ввода пароля
tab.FullEmulationMouseMoveToHtmlElement(elPass);
//Кликаем по полю
tab.FullEmulationMouseClick("left", "click");
//Вводим пароль
elPass.SetValue(pass, "Middle");
//Микропауза (300-700 мс)
Helper.Pause(3,8);

//Ведём мышь к кнопке входа
tab.FullEmulationMouseMoveToHtmlElement(elLogInBtn);
//Микропауза (200-500 мс)
Helper.Pause(2,6);
//Кликаем по кнопке
tab.FullEmulationMouseClick("left", "click");
//Ждём прогрузку
if (tab.IsBusy)    tab.WaitDownloading();
Helper.Pause();
C#:
//Название темки
string searchText = project.Variables["searchText"].Value;

var tab = instance.ActiveTab;

//Ищем поле поиска по форуму
var elSearchField = tab.FindElementByXPath("//input[@id='QuickSearchQuery']", 0);
//Подведём к нему мышь. Для разнообразия, по координатам
//Находим координату середины поля по x
int toX = int.Parse(elSearchField.GetAttribute("leftInBrowser")) + elSearchField.Width/2;
//Находим координату середины поля по y
int toY = int.Parse(elSearchField.GetAttribute("topInBrowser")) + elSearchField.Height/2;
//Ведём мышь к найденным координатам
tab.FullEmulationMouseMove(toX, toY);
//Микропауза (200-500 мс)
Helper.Pause(2,6);
//Клик
tab.FullEmulationMouseClick("left", "click");
//Микропауза (200-500 мс)
Helper.Pause(2,6);
//Вводим строку поиска
elSearchField.SetValue(searchText, "Middle");

//Ищем кнопку поиска
var elSearchButton = tab.FindElementByXPath("//input[contains(@class,'button primar')]", 0);
//Ведём к ней мышь
tab.FullEmulationMouseMoveToHtmlElement(elSearchButton);
//Микропауза (200-500 мс)
Helper.Pause(2,6);
//Кликаем по кнопке
tab.FullEmulationMouseClick("left", "click");

//Ждём прогрузку страницы
if (tab.IsBusy)    tab.WaitDownloading();
Helper.Pause();

//Ищем ссылку на тему
var elTopicLink = tab.FindElementByXPath("//a[string()='" + searchText + "']", 1);
//Ведём к ней мышку
tab.FullEmulationMouseMoveToHtmlElement(elTopicLink);
//Микропауза (200-500 мс)
Helper.Pause(2,6);
//Кликаем по ссылке
tab.FullEmulationMouseClick("left", "click");

//Ждём прогрузку страницы
if (tab.IsBusy)    tab.WaitDownloading();
Helper.Pause();
C#:
//Текст поста
string text = project.Variables["postText"].Value;

var tab = instance.ActiveTab;

//Находим на странице последний пост
var elLastPost = tab.FindElementByXPath("//li[contains(@id,'post-')][last()]", 0);
//Ищем, где на странице расположен пост
//Находим координату начала поста по y
int toY = int.Parse(elLastPost.GetAttribute("topInBrowser"));
//Если от текущего положения мыши на странице до последнего поста далеко (свыше 2000 пикселей)
if ((toY-tab.FullEmulationMouseCurrentPosition.Y) > 2000){
    //То крутим колесико мышки на это расстояние
    tab.FullEmulationMouseWheel(0, toY-tab.FullEmulationMouseCurrentPosition.Y);
}

//Микропауза (400-900 мс)
Helper.Pause(4,10);

//Находим текст поста
var elLastPostText = elLastPost.FindChildByXPath(".//article",0);
//"Читаем" его мышкой
tab.FullEmulationMouseMoveAboveHtmlElement(elLastPostText, 35);

//Находим поле для ответа
var replyField = tab.FindElementByXPath("//body[@dir='LTR']", 0);
//Ведём к полю мышку
tab.FullEmulationMouseMoveToHtmlElement(replyField);
//Микропауза (200-500 мс)
Helper.Pause(2,6);
//Кликаем по полю
tab.FullEmulationMouseClick("left", "click");
//Вводим текст ответа
replyField.SetValue(text, "Middle");
//Микропауза (800-1100 мс)
Helper.Pause(8,12);

//Находим кнопку отправки ответа
var replySubmit = tab.FindElementByXPath("//div[@class='draftUpdate']/following-sibling::input[contains(@class,'button primar')]", 0);
//Ведём к ней мышку
tab.FullEmulationMouseMoveToHtmlElement(replySubmit);
//Микропауза (800-1100 мс)
Helper.Pause(8,12);
//Кликаем по кнопке
//tab.FullEmulationMouseClick("left", "click");

//Ждём прогрузку страницы
if (tab.IsBusy)    tab.WaitDownloading();
Helper.Pause();
Спасибо за то, что делаешь :-)
 
Последнее редактирование:
  • Спасибо
Реакции: LaGir

Gizmond

Client
Регистрация
18.02.2017
Сообщения
263
Благодарностей
51
Баллы
28
Добрый день! Подскажите пожалуйста. Как вставить значение из переменной в этот кусок кода.

Код:
var posts = tab1.FindElementsByAttribute("a", "href", "Сюда значение из меременной", "regexp");
пробывал так :

var TestVar = project.Variables["b"].Value;

и потом TestVar подставлять туда - не катит. Я просто не особо разбираюсь в сшарп, поэтому пробовал разные варианты )
 

Gizmond

Client
Регистрация
18.02.2017
Сообщения
263
Благодарностей
51
Баллы
28
Добрый день! Подскажите пожалуйста. Как вставить значение из переменной в этот кусок кода.

Код:
var posts = tab1.FindElementsByAttribute("a", "href", "Сюда значение из меременной", "regexp");
пробывал так :

var TestVar = project.Variables["b"].Value;

и потом TestVar подставлять туда - не катит. Я просто не особо разбираюсь в сшарп, поэтому пробовал разные варианты )
Разобрался) Все правильно делал. Завернул переменку в TestVar и нужно было вставить ее в код без " "

получилось вот так

var TestVar = project.Variables["b"].Value;
var posts = tab1.FindElementsByAttribute("a", "href", TestVar, "regexp");
 
  • Спасибо
Реакции: LaGir

ezotonal

Client
Регистрация
13.01.2014
Сообщения
808
Благодарностей
227
Баллы
43
Разобрался) Все правильно делал. Завернул переменку в TestVar и нужно было вставить ее в код без " "

получилось вот так

var TestVar = project.Variables["b"].Value;
var posts = tab1.FindElementsByAttribute("a", "href", TestVar, "regexp");
Можно просто переменную вставить

Код:
var posts = tab1.FindElementsByAttribute("a", "href", project.Variables["b"].Value, "regexp");
 

Gizmond

Client
Регистрация
18.02.2017
Сообщения
263
Благодарностей
51
Баллы
28

Juniorcpa

Client
Регистрация
27.05.2014
Сообщения
2 031
Благодарностей
1 285
Баллы
113
Компиляция кода Ошибка в действии "CS0103" "Имя "Helper" отсутствует в текущем контексте". [Строка: 4; Cтолбец: 1]
- такие дела :-)
 

LaGir

Client
Регистрация
01.10.2015
Сообщения
211
Благодарностей
849
Баллы
93
Компиляция кода Ошибка в действии "CS0103" "Имя "Helper" отсутствует в текущем контексте". [Строка: 4; Cтолбец: 1]
- такие дела :-)
Либо скопируй из того шаблона к себе блок директив и общего кода, либо замени в сниппетах все строчки вида:
C#:
Helper.Pause(2,5);
На подобные:
C#:
Thread.Sleep(Global.Classes.rnd.Next(2,5)*100);
В общем, в тех сниппетах используется кастомный метод паузы из общего кода, на него и ругается компилятор, если тот отсутствует. :-)
 
  • Спасибо
Реакции: Mikhail B.

Juniorcpa

Client
Регистрация
27.05.2014
Сообщения
2 031
Благодарностей
1 285
Баллы
113
Либо скопируй из того шаблона к себе блок директив и общего кода, либо замени в сниппетах все строчки вида:
C#:
Helper.Pause(2,5);
На подобные:
C#:
Thread.Sleep(Global.Classes.rnd.Next(2,5)*100);
В общем, в тех сниппетах используется кастомный метод паузы из общего кода, на него и ругается компилятор, если тот отсутствует. :-)
Логика в целом понятна, жаль что без знаний адаптировать под свой будущий проект пока не выходит.
 

Juniorcpa

Client
Регистрация
27.05.2014
Сообщения
2 031
Благодарностей
1 285
Баллы
113
  • Спасибо
Реакции: LaGir

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
741
Баллы
113
Как вставить переменную
  1. //Делаем прокрутку на 500 пикселей ВНИЗ (по y)
  2. instance.ActiveTab.FullEmulationMouseWheel(project.Variables["test"].Value);
  3. //Делаем прокрутку на 500 пикселей ВВЕРХ (по y)
  4. instance.ActiveTab.FullEmulationMouseWheel(0, -500)
  5. Так вставляю не работает
 

esouldy

Client
Регистрация
28.02.2016
Сообщения
185
Благодарностей
92
Баллы
28
Как вставить переменную
  1. //Делаем прокрутку на 500 пикселей ВНИЗ (по y)
  2. instance.ActiveTab.FullEmulationMouseWheel(int.Parse(project.Variables["test"].Value));
  3. //Делаем прокрутку на 500 пикселей ВВЕРХ (по y)
  4. instance.ActiveTab.FullEmulationMouseWheel(0, -500)
 

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
741
Баллы
113
НЕ работает так.
 
Последнее редактирование:
  • Спасибо
Реакции: Viking01

Viking01

Client
Регистрация
19.08.2017
Сообщения
228
Благодарностей
151
Баллы
43
о, как раз начал разбираться с эмуляцией) с новой версией ничего не изменилось по "очеловечиванию" движения мышки?
 

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