- Регистрация
- 12.10.2016
- Сообщения
- 130
- Реакции
- 163
- Баллы
- 43
Всем привет.
Статья в большей степени для не совсем новичков, а тех кто уже попробовал сам писать шаблоны и начинает осваивать с#.
Будет много букв и кода.
День когда я научился пользоваться лямбда-выражениями - был одним из лучших. Радости не было предела, мне казалось - всё, теперь все мои трудности позади.
Собрать регуляркой все совпадения в тексте, проверить на какое-то дополнительное условие, привести результат к нужному мне виду... И все это в пару строк кубика С#.
=> это так называемая ЛЯБМДА. Лямбда-выражение. Слева - что передаем, справа - куда.
Начнем, как водится с простого:
Есть некоторый зено-список:

Воспользуемся методом First(принимающим функцию типа bool) проверим некоторое условие

Теперь применим лямбду к коллекции регулярок:
Практическое применение:
получим результат страницы поиска в гугле:
И выпарсим из него все ссылки:

Итого у нас в зенно-списке нужные нам ссылки.
Сделаем то же самое, только через браузер, работая о всеми элементами коллекции HemlElementCollection.
Перейдем на страницу результатов поиска:
И также выпарсим ссылки. Но будем парсить только определенные результаты и попутно собирать другие данные (тексты ссылок)
мы получили коллекцию строк формата "Текст результата поиска {tab} целевая страница"
Теперь перейдем к моей любимой коллекции:
List - список элементов некоторого типа. Типы могут быть почти любые, в том числе вложенные списки.
List<string> - список строк
List<int> - список чисел
List<HtmlElement> - список Html-элементов.
Списки я люблю за методы ForEach и IndexOf. ForEach - Аналог обычной конструкции foreach только удобнее использовать.
Почти все коллекции, наборы, массивы, можно привести к типу List методом ToList() и можно сразу проводить манипуляции с элементами.

Action отличается от функции тем, что ничего не возвращает. Просто применяет определенные команды к каждому элементу списка.
Начнем как всегда с простого:
Как это применить с пользой? Например добавим наши полученные ссылки результатов поиска в Зенно таблицу.
В зенно-таблицах к сожалению нет аналога AddRange для списков, по добавлению сразу нескольких строк. Будем это обходить:
Профит:

Вернемся теперь к нашему предыдущему списку с урлами, и будем проверять все результаты на наличие там форм, которые нам интересны:
Переходим последовательно по списку урлов из списка "test" и осуществляем проверку:
кое что пропустили...
Если мы нашли 1 форму без капчи и с емейлом еще и с текстовой областью,
А на странице есть еще другая форма с капчей, то сайт добавится в оба списка, что не есть хорошо.
Надо будет это проверять потом, или предусмотреть сейчас.
По хорошему, нужно создать новый тип со свойствами int,string и где-то его хранить... Но это не наш выбор. Мы же про работу с коллекциями и лямбды.
будем хранить в списке строки вида:
"N|url" номер формы на странице|урл страницы.
И исправим многократное добавление сайта.
Поехали!
Получили мы 4 списка:
список урлов с полем для почты.
список урлов с полем для текта.
список урлов с капчей/без капчи.
емайл+тект ария+нет капчи = очень интересно. Так и хочется заполнить и посмотреть: что же нам придет на почту... Но до этого нужно еще добраться.
Проверим полученные списки на интересные сайты. Помогут нам как всегда лямбды:
Теперь пройдемся по списку интересных сайтов с формами, и попытаемся заполнить, работая с коллекциями и списками.
Для начала получим из нашего NUrl отдельно номер и отдельно url
Делать это будем не абы как, в одну строку, а пойдем сложным - со списками и лямбдами.
поработаем со строкой как со списком символов. Наша задача - обучиться работе с коллекциями.
Чтобы приступить к заполнению форм, нужно немного подготовиться:
Теперь само заполнение формы выглядит совсем просто:
Как видно из последнего фото, даже если мы что-то не предусмотрели (поле subject) оно всеравно заполняется значением name.
Добавим пару штрихов:
Наша форма заполнена и готова для отправки.
Скрипт нажатия на кнопку отправки предлагаю написать самостоятельно (собрать коллекцию тегов button и input:submit на форме, и Форычем кликнуть по всем).
Это не идеальный скрипт по обработке всех возможных форм. Во первых, мы пропустили обработку капч, а во вторых, ищем формы только с элементом textarea.
Преимуществом данного шаблона заключается то, что для обработки новых форм с полями не предусмотренными шаблоном - достаточно добавить новое регулярное выражение и значение которое вставлять в найденный элемент.
А также поправить под себя метод Check - чтобы например при первом совпадении по регулярке - переходить к следующему инпуту. В следующей части, в заполнении регистрационных форм мы это сделаем.
Перейдем к самой сложной части - Заполнению регистрационных форм. Здесь подход "лишь бы ушло на нужный адрес с нужной ссылкой" не сработает, важна точность.
Придется подумать, или посмотреть с десяток рег форм, чтобы собрать варианты полей которые на них бывают, и подобрать к ним регулярки. Тем, кто не умеет пользоваться реулярками - придется просто больше собрать пар чтоИщем-значение.
У нас уже есть таблица со ссылками на страницы регистрации. пройдемся по ней и посмотрим. Что там есть.
Наберем с десяток пар критерий-значение
Немного изменим процедуру определения соответствия поля:
Будем работать только с видимым текстом (placeholder для input и innerText для родителей).
Процедуру ввода данных не трогаем.
Найдем форму на странице:
Отметим все чекбоксы и селекты:
Вот собственно и всё заполнение теперь:
Проверим на практике:

И наш любимый Зеннолаб:
как видим заполнено именно то что мы и указывали. Date,Year у нас нет в словаре и списке регулярок, поэтому они пустые.
Что делать с капчей?
На самом деле, до конца решить все проблемы с формами регистрации мне не удалось. В реальном шаблоне, сайты сначала группируются по типам (на некоторых сайтах сначала нужно согласиться с правилами, потом только появляются поля формы, где-то поля объединены в датасеты и для двух полей одно описание - поле и подтверждение, там алгоритм функции Check отличается).
То же самое и с капчей. В этом плане гугл-рекапча даже легче остальных будет, штатный кубик очень хорошо справляется как с поиском капчи, так и с разгадыванием. Для остальных случаев нужно или под каждый вид капчи писать отдельный обработчик, или целиком отправлять скрин элемента с капчей в сервис разгадывания. Это не является темой данной статьи.
Надеюсь теперь многие ваши задачи будут решаться быстрее, когда научитесь работать с коллекциями.
Но для заполнения большинства форм регистраций, данный способ работает. Надо только продумать достаточно вариантов типов полей и подобрать к ним регулярки.
Статья в большей степени для не совсем новичков, а тех кто уже попробовал сам писать шаблоны и начинает осваивать с#.
Будет много букв и кода.
День когда я научился пользоваться лямбда-выражениями - был одним из лучших. Радости не было предела, мне казалось - всё, теперь все мои трудности позади.
Собрать регуляркой все совпадения в тексте, проверить на какое-то дополнительное условие, привести результат к нужному мне виду... И все это в пару строк кубика С#.
=> это так называемая ЛЯБМДА. Лямбда-выражение. Слева - что передаем, справа - куда.
Начнем, как водится с простого:
Есть некоторый зено-список:

Воспользуемся методом First(принимающим функцию типа bool) проверим некоторое условие

C#:
//получим первое четное число
project.Lists["test"].First(
element //это имя для переменной обозначающей некоторый элемент данной коллекции
//тип соответствует типу елементов в коллекции
=> //это называется лямбда выражением
int.Parse(element)%2==0 //это функция условие которй мы проверяем.
//int.Parse(element) - приводим элемент к типу int
//%2==0-проверяем отстаток от деления на 2, что он равен 0.
);
//пишут обычно так:
return project.Lists["test"].First(e=>int.Parse(e)==0);
Теперь применим лямбду к коллекции регулярок:
C#:
//найдем слова c буквой о
string inp ="как однажды жан звонарь городской стащил фонарь";
string pat = @"\w*[о]\w*";
var res =
Regex.Matches(inp,pat) // мы получили коллекцию совпадений. что дальше??
.Cast<Match>() //особеность работы с регулярками - обязательно привести к типу.Match
.Select(m=>m.Value);//select - команда выборки а в скобках наша лямбда
//мы получаем как раз значение регулярки.
return string.Join("|",res);//однажды|звонарь|городской|фонарь
Практическое применение:
получим результат страницы поиска в гугле:
C#:
string url = "https://www.google.ru/search?q="+"contact-us"+"&oq="+"contact-us"+"&num=100&start="+"0"+"&lr=lang_ru";
string get =
ZennoPoster.HttpGet(url,"",@"utf-8",ZennoLab.InterfacesLibrary.Enums.Http.ResponceType.HeaderAndBody,30000,"",project.Profile.UserAgent,false,0,null,"",false);
if (get.Contains("200 OK")) return get;
И выпарсим из него все ссылки:
C#:
string html = project.Variables["codeResult"].Value; //html ответ страницы гугла
string pat = @"(?<=\!\-\-m\-\-.+?a href\="").+?(?="")";//шаблон поиска ссылок на стрнице
project.Lists["test"].AddRange(
Regex.Matches(html,pat) //все
.Cast<Match>() //тоже
.Select(m=>m.Value) //самое
);

Итого у нас в зенно-списке нужные нам ссылки.
Сделаем то же самое, только через браузер, работая о всеми элементами коллекции HemlElementCollection.
Перейдем на страницу результатов поиска:
C#:
string key = "inurl:register регистрация на форуме";
instance.ActiveTab.Navigate(
"https://www.google.ru/search?q="+key+"&oq="+key+"&num=100&start="+"0"+"&lr=lang_ru");
instance.ActiveTab.WaitDownloading();
И также выпарсим ссылки. Но будем парсить только определенные результаты и попутно собирать другие данные (тексты ссылок)
C#:
var tab = instance.ActiveTab;
//HtmlElement h;//определим вспомогательную переменную - только для вызова подсказок.
//чтобы удобней было работать с лямбдами, объявим вспомогательную переменную, которую потом удалим
//прожект мейкер не видит типы параметров в делегатах, и приходится писать "вслепую" что совсем неудобно и медленно
//в процессе написания кода, в имени нужной нам переменной, для вызова подсказок указываем эту
//а потом удалим(иначе ошибка будет)
tab.FindElementsByTags("h3") //коллекция заголовков <h3></h3>
.Where(h=>h.InnerText.Contains("егистрация"))//фильтруем ссылки по содержанию текста
.Select(h=> //формируем формат получаемых данных
h.InnerText +"{TAB}"+ h.ParentElement.GetAttribute("href")
);
Теперь перейдем к моей любимой коллекции:
List - список элементов некоторого типа. Типы могут быть почти любые, в том числе вложенные списки.
List<string> - список строк
List<int> - список чисел
List<HtmlElement> - список Html-элементов.
Списки я люблю за методы ForEach и IndexOf. ForEach - Аналог обычной конструкции foreach только удобнее использовать.
Почти все коллекции, наборы, массивы, можно привести к типу List методом ToList() и можно сразу проводить манипуляции с элементами.

Action отличается от функции тем, что ничего не возвращает. Просто применяет определенные команды к каждому элементу списка.
Начнем как всегда с простого:
C#:
int [] nums = {1,2,3,4,5,6,7,8};
//Выведем в лог четные числа:
nums.ToList() //приведем массив к списку
.ForEach(e=> //переменная для каждого элемента
{
if(e%2==0) //проверяем условие четности
project.SendInfoToLog(e.ToString());//выводим в лог
}
);
В зенно-таблицах к сожалению нет аналога AddRange для списков, по добавлению сразу нескольких строк. Будем это обходить:
C#:
var t = project.Tables["table"];//таблица ЗП
t.ColSeparator = "{TAB}"; // разделитель столбцов в строке
tab.FindElementsByTags("h3")
.Where(h=>h.InnerText.Contains("егистрация"))//фильтруем ссылки с текстом о регистрации
.Select(h=> //формируем формат получаемых данных
h.InnerText +"{TAB}"+ h.ParentElement.GetAttribute("href")
) //весь код выше - уже был.
.ToList() //приводим нашу коллекцию к списку
.ForEach(s=>t.AddRow(s));//Action для каждого элемента

Вернемся теперь к нашему предыдущему списку с урлами, и будем проверять все результаты на наличие там форм, которые нам интересны:
Переходим последовательно по списку урлов из списка "test" и осуществляем проверку:
C#:
var tab = instance.ActiveTab;
//HtmlElement f; //это помощник для вызова подсказок, потом удаляем
tab.FindElementsByTags("form")//собираем ВСЕ формы на странице
.ToList()//приводим к списку
.ForEach(f=>//в метод мы передаем переменную f (HtmlElement <form...></form>)
{
if (f.Width>0&&_f.Height>0)
{//форма видимая на странице, значит с ней можно работать
f.FindChildrenByTags("input;label").ToList().ForEach(i=>
{//берем всех потомков типа input и label
if (Regex.IsMatch(i.OuterHtml,"(mail|pochta|почта|мейл|мэйл)"))
{//еcть признаки указывающие что на форме присутствует поле для емейла
project.Lists["emailForms"].Add(project.Variables["url"].Value);//отмечаем сайт с формой на которй есть email
//простой путь понять что здесь могут быть тигры:
if (f.FindChildrenByTags("textarea").Count>0) //проверим на форме тег textarea
//отметим что сайт - с формой обратной связи или коментария
project.Lists["textAreaForms"].Add( project.Variables["url"].Value);
else if(Regex.IsMatch(f.InnerHtml,"capt(cha|ture)|robot|human"))//проверяем признаки капчи
project.Lists["captchaForms"].Add(project.Variables["url"].Value);//с капчей
else project.Lists["noCaptchaForms"].Add(project.Variables["url"].Value);//без капчи
}
}
);
}
});
кое что пропустили...
Если мы нашли 1 форму без капчи и с емейлом еще и с текстовой областью,
А на странице есть еще другая форма с капчей, то сайт добавится в оба списка, что не есть хорошо.
Надо будет это проверять потом, или предусмотреть сейчас.
По хорошему, нужно создать новый тип со свойствами int,string и где-то его хранить... Но это не наш выбор. Мы же про работу с коллекциями и лямбды.
будем хранить в списке строки вида:
"N|url" номер формы на странице|урл страницы.
И исправим многократное добавление сайта.
Поехали!
C#:
var tab = instance.ActiveTab;
//HtmlElement f; //помощник
List<HtmlElement> forms = tab.FindElementsByTags("form").ToList();
forms.ForEach(f=>//в лямбду мы передаем HtmlElement <form...></form>
{
string NUrl = project.Variables["url"].Value;
NUrl = forms.IndexOf(f).ToString()+"|"+NUrl;
if (f.Width>0&&f.Height>0)
{//форма видимая на странице
bool isMail=false;
f.FindChildrenByTags("input;label").ToList().ForEach(i=>
{//берем всех потомков типа input и label
if (Regex.IsMatch(i.OuterHtml,"(mail|pochta|почта|мейл|мэйл)"))
//еcть признаки указывающие что на форме присутствует поле для емейла
isMail=true;
});
if(isMail) project.Lists["emailForms"].Add(NUrl);//сайт с формой на которй есть email
if (f.FindChildrenByTags("textarea").Count>0) //проверитм на форме тег textarea
project.Lists["textAreaForms"].Add(NUrl); //сайт с формой обратной связи или коментария
if(Regex.IsMatch(f.InnerHtml,"capt(cha|ure)|robot|human"))//проверяем признаки капчи
project.Lists["captchaForms"].Add(NUrl);//с капчей
else project.Lists["noCaptchaForms"].Add(NUrl);//без капчи
}
});
Получили мы 4 списка:
список урлов с полем для почты.
список урлов с полем для текта.
список урлов с капчей/без капчи.
емайл+тект ария+нет капчи = очень интересно. Так и хочется заполнить и посмотреть: что же нам придет на почту... Но до этого нужно еще добраться.
Проверим полученные списки на интересные сайты. Помогут нам как всегда лямбды:
C#:
project.Lists["textAreaForms"]
.Where(t //каждый элемент списка textAreaForms
=>
!project.Lists["captchaForms"].Contains(t)//не присутствует в списке captchaForms
)
Теперь пройдемся по списку интересных сайтов с формами, и попытаемся заполнить, работая с коллекциями и списками.
Для начала получим из нашего NUrl отдельно номер и отдельно url
Делать это будем не абы как, в одну строку, а пойдем сложным - со списками и лямбдами.
поработаем со строкой как со списком символов. Наша задача - обучиться работе с коллекциями.
C#:
string NUrl = project.Lists["veryGood"].First();
List<char> nuList = NUrl.ToArray()//разбираем строку n|url по символам
.ToList(); //и приводим к списку(все как обычно)
int N = int.Parse(
nuList.Where(//выбираем только те символы в строке
c=>nuList.IndexOf(c)<nuList.IndexOf('|')//у которых номер меньше разделителя
).First(//у нас вряд ли больше 9 форм на странице, поэтому выбираем только первый элемент
).ToString()//нужно привести char к string, чтобы получить int. :) увы
);
//А для получения урла из Списка символов познакомимся с еще одним интересным методом
//Aggregate: у него два параметра на входе предыдущий элемент(точнее результат предыдущей итерации) и текущий.
string url = nuList.Where(//выбираем только те символы в строке
c=>nuList.IndexOf(c)>nuList.IndexOf('|')//все что после разделителя
) //у нас сейчас - выборка символов, это еще не строка.
// применим Агрегатную функцию:
.Aggregate("",(bef,af)=>bef.ToString()+af.ToString());
//"" - начальное значение
//(bef,af) - предыдущий элемент, и следующий.
//bef.ToString()+af.ToString() - выражение. мы просто склеиваем символы в строку.
var tab = instance.ActiveTab;
tab.Navigate(url);
tab.WaitDownloading();
Чтобы приступить к заполнению форм, нужно немного подготовиться:
C#:
//то что будем заносить в поля ввода
//чем больше вариантов опишем, тем больше сможем успешно заполнить форм
string name = project.Profile.Name;
string lname = project.Profile.Surname;
string phone = project.Profile.Phone;
string email=project.Profile.Email;
string pass = project.Profile.Password;
string message="Hallo world! http://Hallo.world";
string login = project.Profile.Login;
string company = project.Profile.NickName;
//для каждого поля определим текст по которому будем определять элемент(регулярное выражение)
//желательно предварительно изучить с десяток разных форм на разных сайтах. Но и этого нам достаточно для примера.
string isName = "Name|Имя";//первым, т.к. name присутствует в outerHtml у всех инпутов
string isLname="Last(| )name|фамилия";
string isCompany="company|компани";
string isPhone="(tel(e|)|)(ph|f)one|телефон";
string isMessage="textarea";
string isSubject="subject|t(h|)em(e|a)|тема|заголовок";
string isMail="m(a|e)il|po(4|ch)ta|почт";//это всегда последним, т.к. email может случайно заполниться, а его обязательно указать верным
//соберем всё в список:
List<string> regs = new List<string>{
isName,isLname,isCompany,isPhone,isMessage,isMail //isSubject осознанно не включаем в этот список
};
и формируем словарь:
Dictionary<string,string> regval = new Dictionary<string,string>();
regval.Add(isName,name);
regval.Add(isLname,lname);
regval.Add(isCompany,company);
regval.Add(isPhone,phone);
regval.Add(isMessage,message);
regval.Add(isSubject,subj);
regval.Add(isMail,mail);
//определим алгоритм идентификации поля ввода
Func<HtmlElement,string,bool> Check = (h,reg) =>
{
bool output = false;//не найдено соответствий
//текст где будем проверять наличие регулярки
string outer = h.OuterHtml; //сам инпут
var parent1 = h.ParentElement; //родитель
var parent2= parent1.ParentElement; //следующий родитель
if(parent1.TagName="label") //всегда проверяем ругулярку в подписи
outer+=parent1.OuterHtml;
if(parent2.TagName="label"|| //и у второго родителя тоже
parent2.FindChildrenByTags(input).Count<=1 //смотрим что не попал еще один инпут
) //что мы не ушли в область другого инпута
outer+=parent2.OuterHtml;
if(Regex.IsMatch(outer,reg,RegexOptions.IgnoreCase))
return true; //нашли соответствие
};
//и процедуру ввода данных в поле
Action<HtmlElement,string> SetValue = (h,val) =>
{
h.Focus();
h.Click();
h.SetValue("","Full",false,false);
h.SetValue(val,"Full",false,false);
};
Теперь само заполнение формы выглядит совсем просто:
C#:
HtmlElement form = tab.FindElementByTag("form",N);
//HtmlElement i; //вызыватель подсказок
regs.ForEach(reg=>//для каждого регулярного выражения
{
form.FindChildrenByTags("input;textarea").ToList().ForEach(i=>
{
if(i.GetAttribute("type") != "submit") //пропускаем кнопки
{
if(Check(i,reg)) //если совпало
SetValue(i,regval[reg]);//заполняем
}
});
});
Как видно из последнего фото, даже если мы что-то не предусмотрели (поле subject) оно всеравно заполняется значением name.
Добавим пару штрихов:
C#:
//отметим все чекбоксы
form.FindChildrenByTags("input:checkbox").ToList()
.ForEach(c=>c.SetValue("true","Full",false,false));
//отметим все селекты
form.FindChildrenByTags("select").ToList()
.ForEach(sel=>
{
sel.Click();
sel.SetValue(//выберем предполследний элемент селектов
sel.FindChildrenByTags("option").ElementAt(sel.FindChildrenByTags("option").Count-1).InnerHtml
,"Middle",true,false);
});
Наша форма заполнена и готова для отправки.
Скрипт нажатия на кнопку отправки предлагаю написать самостоятельно (собрать коллекцию тегов button и input:submit на форме, и Форычем кликнуть по всем).
Это не идеальный скрипт по обработке всех возможных форм. Во первых, мы пропустили обработку капч, а во вторых, ищем формы только с элементом textarea.
Преимуществом данного шаблона заключается то, что для обработки новых форм с полями не предусмотренными шаблоном - достаточно добавить новое регулярное выражение и значение которое вставлять в найденный элемент.
А также поправить под себя метод Check - чтобы например при первом совпадении по регулярке - переходить к следующему инпуту. В следующей части, в заполнении регистрационных форм мы это сделаем.
Перейдем к самой сложной части - Заполнению регистрационных форм. Здесь подход "лишь бы ушло на нужный адрес с нужной ссылкой" не сработает, важна точность.
Придется подумать, или посмотреть с десяток рег форм, чтобы собрать варианты полей которые на них бывают, и подобрать к ним регулярки. Тем, кто не умеет пользоваться реулярками - придется просто больше собрать пар чтоИщем-значение.
У нас уже есть таблица со ссылками на страницы регистрации. пройдемся по ней и посмотрим. Что там есть.
Наберем с десяток пар критерий-значение
C#:
string name = project.Profile.Name;
string isName = "Имя|name";
string lname = project.Profile.Surname;
string isLname="Last(| )name|фамилия";
string phone = "9991234567";//project.Profile.Phone;
string isPhone="(tel(e|)|)(ph|f)one|телефон";
string mail=project.Profile.Email;
string isMail="m(a|e)il|po(4|ch)ta|почт";
string pass = project.Profile.Password;
string isPass = "passw(or|)d|пароль";
string isConfirmPass = "confirm pass|pass confirm|подтв";
string login = project.Profile.Login;
string isLogin = "(nick|user)(|name)|login|логин";
string company = project.Profile.NickName;
string isCompany="company|компани";
string subj="Theme title";
string isSubject="subject|t(h|)em(e|a)|тема|заголовок";
//как всегда "всё в список"
List<string> regs = new List<string>{
isName,isLname,isCompany,isPhone,isMail,isPass,isConfirmPass,isLogin
};
//и в словарь:
Dictionary<string,string> regval = new Dictionary<string,string>();
regval.Add(isName,name);
regval.Add(isLname,lname);
regval.Add(isCompany,company);
regval.Add(isPhone,phone);
regval.Add(isMail,mail);
regval.Add(isPass,pass);
regval.Add(isConfirmPass,pass);
regval.Add(isLogin,login);
Немного изменим процедуру определения соответствия поля:
Будем работать только с видимым текстом (placeholder для input и innerText для родителей).
C#:
Func<HtmlElement,string,bool> Check = (h,reg) =>
{
bool output = false;//пока в начале не найдено соответствий
//текст где будем проверять наличие регулярки
string outer = h.GetAttribute("placeholder"); //сам инпут
var parent1 = h.ParentElement; //родитель
var parent2= parent1.ParentElement; //следующий родитель
if(parent1.FindChildrenByTags("input").Count==1) //проверяем что не ушли в область другого инпута
outer+=parent1.InnerText;
if(parent2.FindChildrenByTags("input").Count==1)//у второго родителя тоже
outer+=parent2.InnerText; //
if(Regex.IsMatch(outer,reg,RegexOptions.IgnoreCase))
output = true; //нашли соответствие
return output;
};
Найдем форму на странице:
C#:
HtmlElement form = instance.ActiveTab.FindElementsByTags("form")
.Where(f=>f.Width>0&&f.Height>0//только видимая форма
&&Regex.IsMatch(
f.InnerText+//ищем в тексте формы
//+в видимом тексте кнопок и сабмитов
String.Join("",f.FindChildrenByTags("button;input:submit").Select(b=>b.GetValue()))
,"registr|sign up|создать|регистр",RegexOptions.IgnoreCase)
).First();
Отметим все чекбоксы и селекты:
C#:
//отметим все чекбоксы
form.FindChildrenByTags("input:checkbox").ToList()
.ForEach(c=>c.SetValue("true","Full",false,false));
form.FindChildrenByTags("select").ToList()//отметим все селекты
.ForEach(sel=>
{
sel.Click();
sel.SetValue(//выберем предполследний элемент селектов
sel.FindChildrenByTags("option").ElementAt(sel.FindChildrenByTags("option").Count-1).InnerHtml
,"Middle",true,false);
});
Вот собственно и всё заполнение теперь:
C#:
form.FindChildrenByTags("input:text;input:password;input:email").ToList().ForEach(i=>
{
bool find = false;
if(!find&&i.GetAttribute("type") != "submit") //пропускаем кнопки
{
regs.ForEach(reg=>
{
i.Focus(); Thread.Sleep(100);
if(!find&&Check(i,reg)) //если совпало
{
SetValue(i,regval[reg]);//заполняем
find=true; //остальные пропускаем
}
});
}
});
Проверим на практике:

И наш любимый Зеннолаб:
как видим заполнено именно то что мы и указывали. Date,Year у нас нет в словаре и списке регулярок, поэтому они пустые.
Что делать с капчей?
На самом деле, до конца решить все проблемы с формами регистрации мне не удалось. В реальном шаблоне, сайты сначала группируются по типам (на некоторых сайтах сначала нужно согласиться с правилами, потом только появляются поля формы, где-то поля объединены в датасеты и для двух полей одно описание - поле и подтверждение, там алгоритм функции Check отличается).
То же самое и с капчей. В этом плане гугл-рекапча даже легче остальных будет, штатный кубик очень хорошо справляется как с поиском капчи, так и с разгадыванием. Для остальных случаев нужно или под каждый вид капчи писать отдельный обработчик, или целиком отправлять скрин элемента с капчей в сервис разгадывания. Это не является темой данной статьи.
Надеюсь теперь многие ваши задачи будут решаться быстрее, когда научитесь работать с коллекциями.
Но для заполнения большинства форм регистраций, данный способ работает. Надо только продумать достаточно вариантов типов полей и подобрать к ним регулярки.
- Номер конкурса статей
- Одиннадцатый конкурс статей
- Тема статьи
- Парсинг
Вложения
Последнее редактирование модератором:






Не кладёт данные в список. Может у меня в Regex ошибка? Хотя вроде всё норм....