Спойлер

воскресенье, 19 октября 2014 г.

Сниппеты от А до Я

 http://zennolab.com/discussion/threads/snipety-ot-a-do-ja.13515/

Intro

Эта статья о снипетах на языке С# (Си шарп). Статья ориентирована на тех пользователей, которые слышали о его поддержке в ZennoPoster, но их пугало слово программирование и им казалось что это сложно. В этой статье не будет акцента на углубление в изучении языка C#. В этой статье акцент на тех базовых возможностях языка которые собственно и достаточно знать для решения большинства задач с которыми Вы сталкиваетесь при каждом новом проекте для ZennoPoster. Только в первом блоке мы затронем немного теории и понятий которые нельзя не затронуть. Только самое используемое из личного опыта.



Типы данных

Язык C# - язык со строгой типизацией. Любые данные имеют некий тип, и этот тип нужно указывать.
На схеме мы видим множество типов, но только с несколькими из них Вы будете сталкиваться в 90% случаев при написании проектов.


[​IMG]
Синтаксис оформления переменных:

тип имя = значение;

Основные типы которых будет достаточно знать.

Code (csharp):
//Логический тип. Принимает true или false
bool flag = false;
//Тип char. Символы
char symbol = 'Z';
//Тип string. Строки/Текст
string str = "Zenno";
//Тип int. Число от -2147483648 до 2147483647
int x = 0;
//Тип var. Универсальный /Динамический тип. Может включать любой тип.
var dyn = SomeType;
Тип string - имеет свойство Length которое вернет число знаков в строке.

Code (csharp):
string str = "некоторая строка";
//В переменной strLenght будет число знаков  строке
int strLenght = str.Length;
Массивы

Массивы - коллекция (данных)переменных одного типа с общим именем, и доступом к ним по их числовому индексу. Массивы бывают одномерные, многомерные и ступенчатые. Достаточно знать одномерных массивов.





Синтаксис оформления одномерных массивов:

тип[] имя;
тип[] имя = new тип[кол-во элементов];
тип[] имя = new тип [] {элемент0, элемент1, элемент2}

В первом случае у нас массив с отложенной инициализацией.
Достаточно знать первую конструкцию.



Code (csharp):
// Объявляем массив типа int
int[] myArr;
// Инициализируем каждый элемент массива вручную
myArr[0] = 8;
myArr[1] = 6;
myArr[2] = 2;
myArr[3] = -1;
myArr[4] = -13;




Списки

Синтаксис объявления списков

List<тип> имя = new List<тип>();
Code (csharp):
//Список myList с элементами типа string
 List<string> myList= new List<string>();
//Добавим в конец списка элемент
myList.Add("Строка1");
//Кол-во строк в списке
int listSize = myList.Count;


Условные операторы

Оператор if (если)

Синтаксис:


if (условие)
{
действия;
}
else
{

действия;
}


Code (csharp):
//Объявим переменные и установим им значения
int x =1;
int y= 5;
//Если x меньше чем y
if(x<y)
{
//Увеличим значение в переменной х на 1
x = x+1;
}
//Иначе
else
{
//Уменьшим значение в переменной х на 1
x = x-1;
}
else - необязательный оператор.

Циклы for, while и foreach

Цикл for (счетчик)

Синтаксис:

for (начальное значение; условие; шаг)
{
//действия
}

Code (csharp):
//обьявим массив типа string который содержит дни недели
string[] days = new string [] {"Понедельник","Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"};
//Переберм все элементы массива
for(int =0; i<days.Length; i++)
{
//если это Среда  
if(days[i]=="Среда")
{
//вернем индекс этого элемента
return i;
}
}
Цикл while

while
(true)
{
//Действия
}


Как и for можно использовать как счетчик.

Цикл foreach

foreach (тип имя_переменной_цикла in коллекция)
{
//действия;
}

Счетчик без условия. Когда нужно перебрать все элементы некой коллекции без необходимости получения индекса элемента.


Для понимания дальнейшей практической части к которой мы перейдем после этого теоретического блока, стоит обозначить такие понятия как Класс и Метод.

Класс - структура, позволяющая нам описать некий обьект.
Включает в себя методы и свойства для взаимодействия с нашим обьектом и придает ему физическую сущность.

Метод(Функция) - "Черный ящик" выполняющий некие действия над обьектом. Главной особенностью которого является многократное его использование. Все методы принадлежат классам. Передаем в метод аргументы, он выполняет на ними действия и возвращает нам результат. Но методы могут и не принимать аргументов, такие методы называются статическими.

Когда мы создавали список выше, мы создавали обьект принадлежащий к классу List со свойством Count, которое и придавало ему физическу сущность - размерность.

Code (csharp):
//myList - обьект типа string (строка) принадлежащий к классу List
 List<string> myList= new List<string>();
//Add() - метод добавляющий к обьекту строку
myList.Add("Строка1");
//Count - свойство обьекта. Его размерность.
int listSize = myList.Count;
Теперь перейдем от нудной но необходимой теории к практической части :-)
Где собственно и будет практическое применение тех базовых, но достаточных знаний для решения повседневных задач при написании проектов для ZennoPoster.



Тип string - работа со строками


String.Format - метод (String, Object, Object)
Составная строка в некотором формате.
[​IMG] [​IMG] [​IMG]

String.Split - метод (Char[])

Разбиваем строку на массив по разделителю
[​IMG]

String.Trim - метод
Удалить пробелы в начале и конце строки


Code (csharp):
string str = " Some string ";
str = str.Trim();

String.Replace - метод (String, String)
Заменить часть строки


Code (csharp):
string str = "Some string";
//Replace(старое значение, новое значение);
str = str.Replace("Some","My Some");
String.ToLower - метод
String.ToUpper - метод

Перевод строки в нижний и верхний регистр

Code (csharp):
string str = "text";
//ToLower -  в нижний регистр
str = str.ToLower();
//ToUpper - в верхний
str = str.ToUpper();



Массивы на примере одной капчи
В качестве примера решил привести практическую реализацию распознавания одной капчи.
Основа всего алгоритма распознавания полностью завязана на возможностях одномерных массивов.
Этот пример может служить базой при написании распознавалок для подобного вида капч.
Есть сайт http://radiostationawards.ru На нем такая капча.

[​IMG]
Смотря на эту капчу можно увидеть массив. Массив состоящий из 7 элементов = 7 картинок.
Помнить что нумерация в массивах идет от нуля. Первый элемент массива имеет индекс = 0!

Когда в Зенно вы выбираете капчу(обьект картинка) за это отвечает метод DrawToBitmap
который входит в библиотеку классов ZennoLab.CommandCenter. Метод передает эту картинку модулю распознавания, который передает ее уже на сервис распознавания в виде картинки.
Мы воспользуемся этим методом для своих целей. Целей идентификации картинки.

Синтаксис метода:

Code (csharp):
//Метод вернет base64 представление нашей картинки в виде строки
public string DrawToBitmap(
   bool isImage
)
Вот так выглядит base64 строка одной картинки из этой капчи. Такую строку вернет нам метод DrawToBitmap.

Как видим, длина такой строки имеет неудобный вид для работы.
Воспользуемся Снипетом получения MD5 для строки

Code (csharp):
string input = "base64 строка";
// Создаем объект этого класса.
System.Security.Cryptography.MD5 md5Hasher = System.Security.Cryptography.MD5.Create();
// Преобразуем входную строку в массив байт и вычисляем хэш
byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
// Создаем новый Stringbuilder (Изменяемую строку) для набора байт
StringBuilder md5hash = new StringBuilder();
// Преобразуем каждый байт хэша в шестнадцатеричную строку
for (int i = 0; i < data.Length; i++)
{
    //преобразуем элемент в шестнадцатиричную строку длиной в два символа
    md5hash.Append(data[i].ToString("x2"));
}
//Возвращаем MD5 хеш для строки
return md5hash.ToString();
В результате получим md5 хеш нашей строки.

Шаг #1 - Создание базы

Алгоритм действий


[​IMG]



После этого нам нужно сохранить в базу текст вопроса и соответствующий хеш.
Для этого на форму для ручного ввода капчи выведем весь блок капчи с текстом вопроса.
В качестве ответа вбиваем индекс картинки которую просят выбрать.(Нумерация от нуля!!)
[​IMG]

Парсим сам текст картинки которую просят найти.
Передаем индекс в следующий код.
Для работы кода нужно добавить using:
using System.Security.Cryptography;

Code (csharp):
//Индекс нужной картинки
int index  = Convert.ToInt32(project.Variables["index"].Value);
//Массив хешей картинок на странице
string[] md5source = new string[7];
//Результат. Будет содержать нужный хеш по индексу
string md5 = String.Empty;
//Заполняем массив md5source
for(int i=0; i<md5source.Length; i++)
{
    //Пауза 2с
    System.Threading.Thread.Sleep(2000);
    //Находим капчи
    Tab tab = instance.ActiveTab;
    Document doc = tab.MainDocument;
    HtmlElement he = doc.FindElementByAttribute("img", "src", "http://radiostationawards.ru/image.php\\?show=.*", "regexp", i);
    //Получаем BASE64 представление каптчи. Стат.метод DrawToBitmap(); возвращает тип string
    string base64 = he.DrawToBitmap(true);
    //Получаем md5 от строки base64
    MD5 md5Hasher = MD5.Create();
    byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(base64));
    StringBuilder md5hash = new StringBuilder();
    for (int j=0; j < data.Length; j++)
    {
        md5hash.Append(data[j].ToString("x2"));
    }
    //Заполняем массив md5 хешами каптч
    md5source[i] = md5hash.ToString();
}
//Хеш нужной картинки каптчи по ее индексу
md5 = md5source[index].ToString();
//Вернем результат
return md5;
После этого у нас в переменной {-Variable.text-} будет текст вопроса, а в переменной {-Variable.md5-} буде md5 хеш соответствующей картинки.
Сохраняем все это в список в формате text;md5
Запустим проект в 5 потоков. Вбиваем индексы нужных нам картинок.Через 30-60 минут получим базу в таком виде

[​IMG]






Шаг #2 - Использование базы

Создаем рабочий проект.
Подключаем базу как список.
Используем следующий снипет.

Code (csharp):
//База признаков text;md5
var baselist = project.Lists["base"];
//Текст на странице
string text  = project.Variables["text"].Value;
//Массив хешей картинок на странице
string[] md5source = new string[7];
//Будет содержать md5 найденный из базы признаков
string  md5 = String.Empty;
//Будет содержать найденный индекс нужной нам капчи
string index = String.Empty;
//Заполняем массив md5source
for(int i=0; i<md5source.Length; i++)
{
    //Находим капчи
    Tab tab = instance.ActiveTab;
    Document doc = tab.MainDocument;
    HtmlElement he = doc.FindElementByAttribute("img", "src", "http://radiostationawards.ru/image.php\\?show=.*", "regexp", i);
 
    //Получаем BASE64 представление каптчи
    string base64 = he.DrawToBitmap(true);
    //Получаем md5 от строки base64
    MD5 md5Hasher = MD5.Create();
    byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(base64));
    StringBuilder md5hash = new StringBuilder();
    for (int j=0; j < data.Length; j++)
    {
        md5hash.Append(data[j].ToString("x2"));
    }
    //Заполняем массив md5 хешами капч
    md5source[i] = md5hash.ToString();
}
//Перебираем все строки из базы признаков
foreach(string str in baselist)
{
    //Если строка содержит text
    if(str.Contains(text))
    {
        //Отделим text от md5 и поместим в массив
        string [] split = str.Split(';');
        //split[0] - text
        //split[1] - md5
        md5 = split[1];  
    }
}
//Сравниваем массив хешей капч со страницы с хешем из базы
for(int i=0; i<md5source.Length; i++)
{
    if(md5source[i] == md5)
    {
        //получим его индекс
        index = i.ToString();
    }
}
//вернем индекс нужной нам капчи :)
return index;
Делаем клик по соответствующей картинке :-)


Комментариев нет:

Отправить комментарий