Рубрика: Без рубрики

Описание работы ViKing.ApplicationFramework

Описание работы ViKing.ApplicationFramework

Давайте теперь разберемся в работе ViKing.ApplicationFramework более детально. В этой статья я попытался подробно описать работу фреймворка, поэтому статье получилось скучной и похожей на документацию. Тем не менее рекомендую ее прочитать, чтобы понять как все работает.

Основные функции

Основной класс Job состоит из нескольких функций (для использования их нужно перегрузить):

  • StartWork
  • DoWork
  • FinishWork

Вот что происходит при нажатии кнопки старт:

  • Создается новый инстанс класса Job
  • Инициализируются все поля
  • Выполняется конструктор класса (нам он не понадобится)
  • Выполняется функция StartJob
  • Запускается цикл, который бесконечно создает потоки (сколько задано пользователем) и выполняет на них функцию DoWork, до тех пор, пока не будет вызвана функция StopJob или юзер нажмет на стоп. Кнопка HardStop в интерфейсе вызывает Thread.Abort на всех потоках
  • После этого новые потоки не запускаются и фреймворк ждет, когда старые закончат выполняться
  • После этого вызывается функция FinishWork, в которой можно обработать и сохранить результат работы. Она будет вызвана даже если пользователь отменил выполнение задания

Также есть функции ApplicationStartup и ApplicationShutdown, которые выполняются при запуске и закрытии приложения.

Настройки

Для задания пользовательских данных используются публичные статические свойства. Для всех таких свойств будут сгенерированы элементы интерфейса. Их значения автоматически сохраняются в реестре, а отображение в интерфейсе можно контролировать с помощью атрибута PropertyDescription. Например

[PropertyDescription(Caption="Enter text", DefaultValue="example")]
public static string Prop { get; set; }

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

private ResourceManager<string> links = new ResourceManager<string>("links");

Во фреймворке есть свойства GlobalCookies и ThreadCookies. Эти куки подставляются в каждый запрос, сделанный функцией Request, если в ней явно не указан другой контейнер с куками. GlobalCookies общие для всех потоков, а ThreadCookies для каждого потока свои. То же самое и с проксями GlobalProxy и ThreadProxy.

Дополнительные инструменты

При работе с прокси рекомендую пользоваться встроенным менеджером. Для его включения нужно повесить атрибут [GuiSettings(UseProxies=true)] к классу Job. Он автоматически создаст необходимые элементы интерфейса, инициализирует ProxyManager, и будет выдавать каждому потоку в DoWork новый ThreadProxy. Если на потоке возникает ошибка, то она приписывается к текущему прокси. Если у сервера много ошибок, то он выкидывается из менеджера.

Аналогичным образом включается antigate. Добавляем [GuiSettings(UseAntigate=true)], если нужно включить антигейт и прокси, все записывается в одном атрибуте. Разгадывать капчу нужно с помощью функции PostCaptcha, при выключенном антигейте она просто будет выдавать окно с капчей пользователю.

Пример их использования есть в статье регер почты Rambler в 15 строк кода.

Списки и статистика

При выполнении задания юзеру показывается статистика. Показывать ее можно с помощью объекта Stats, например Stats[“accounts”]++, инициализировать ничего не надо.

Для записи файлов удобно использовать FileWriter. Он сам следит за статсами и удобен в работе:

FileWriter w = new FileWriter("file");
w.AppendLine("test");

При указании имени файла автоматически добавляется расширение .txt (если его нет). В статистике будет отображаться количество записанных строк.

Для чтения используется ResourceManager<T>. Остановимся на нем подробнее. Этот класс представляет из себя потокобезопасную очередь. Для инициализации используется конструктор, в который передается список объектов либо имя файла, имя статсов (если не указано будет совпадать с именем файла) и следует ли останавливать задание если список пуст. Для удобства у всех коллекций IEnumerable есть метод ToResourceManager(). Вытаскиваются из списка объекты с помощью метода Pop, а с помощью метода Push можно запихать их обратно.

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

ResourceManager<ProxyWithStats> m = new ResourceManager<ProxyWithStats>();
m.InsertTakenToEnd = true;
m.ItemPopping += (o, e) =>
{
    e.Take = e.Item.ErrorsCount < ProxyWithStats.MaxErrors;
    e.Remove = !e.Take;
};

При вызове m.Pop хэндлер либо вернет первый прокси, либо удалит его из списка и попробует вернуть следующий (либо коллекция окажется пустой). Что если вы не возвращаете элемент, то удалять его необязательно и наоборот, можно удалять возвращенные элементы.

На этом пока все, рекомендую посмотреть пару более практических статей по фреймворку и попробовать что-то сделать самому.

ViKing.ApplicationFramework

ViKing.ApplicationFramework

Наконец-то нашел время написать эту статью. Давно уже пользуюсь, пора бы и поделиться. Итак, речь пойдет о ViKing.ApplicationFramework

Основная цель этой библиотеки — сделать процесс написания всевозможных парсеров и накрутчиков максимально быстрым при минимальном объеме кода. Фреймворк сам генерирует интерфейс и занимается потоками, остается только написать код, обрабатывающий запросы. На практике для большинства задач достаточно создать проект и написать всего пару десятков строк кода.

Давайте рассмотрим процесс работы с фреймворком на примере создания парсера подписчиков публичных страниц вконтакте. Здесь я хочу в общих чертах показать, как выглядит процесс создания простого приложения, более подробное описание функционала библиотеки будет в следующем посте.

Сначала библиотеку нужно скачать и установить. Подробнее здесь.

Далее создаем новый проект:

new viking framework project

Проект состоит из основного файла с кодом Job.cs, папки lib с движком и фреймворком и нескольких стандартных файлов. На данном этапе при запуске мы получаем следующее окно: framework_vk_parser1

Содержимое файла Job.cs для нового проекта:

using ...

namespace Viking_Application1
{
    public class Job : JobBase
    {
        public override void DoWork()
        {

        }
    }
}

Давайте теперь напишем основную логику. Для начала нам понадобятся данные от пользователя: аккаунт вконтакте и номер сообщества. Для создания полей ввода нужно всего лишь задать статичное свойство. Значения свойств сами сохраняются в реестр и подгружаются при следующем запуске программы. Все делается автоматически

public static string Login { get; set; }
public static string Password { get; set; }
public static string Public { get; set; }

Парсинг будет состоять из 2 шагов: нужно один раз залогиниться, и затем в несколько потоков качать и разбирать страницы. Для однопоточной инициализации перегружаем функцию StartWork() и делаем запрос на логин с глобальными куками (они потом автоматически будут подставляться в каждый поток). Обратите внимание, что для выполнения запроса тут используется локальная функция, позже я расскажу, чем она отличается от функции из Viking.Engine.

public override void StartWork()
{
    Request(String.Format("https://login.vk.com/?act=login&role=al_frame&email={0}&pass={1}", Login, Password), FollowRedirects: true, cookies: GlobalCookies);
}

Теперь пишем код для парсинга в многопоточной функции DoWork(). Качаем список участников сообщества:

var content = Request(String.Format("http://vk.com/al_page.php?act=box&al=1&offset={0}&oid=-{1}&tab=members", offset, Public)).Content;

Вытаскиваем из него ссылки на аккаунты:

var akks = content.Matches(@"fans_fan_lnk"" href=""/([^""]+)").GetGroup(1).ToList();

Если найдено 0 акков – пора останавливать задание:

if (akks.Count == 0) StopJop("No more members");

И в конце записываем полученые аккаунты:

File.AppendAllLines("members.txt", akks);

Все, софт готов, можно пользоваться. Вот что получилось в результате: framework_vk_parser2

using ...;

namespace Viking_Application1
{
    public class Job : JobBase
    {
        public static string Login { get; set; }
        public static string Password { get; set; }
        public static string Public { get; set; }

        int page = 0;

        public override void StartWork()
        {
            Request(String.Format("https://login.vk.com/?act=login&role=al_frame&email={0}&pass={1}", Login, Password), FollowRedirects: true, cookies: GlobalCookies);
            File.Delete("members.txt");
        }

        public override void DoWork()
        {
            int offset = page++ * 60;
            var content = Request(String.Format("http://vk.com/al_page.php?act=box&al=1&offset={0}&oid=-{1}&tab=members", offset, Public)).Content;
            var akks = content.Matches(@"fans_fan_lnk"" href=""/([^""]+)").GetGroup(1).ToList();
            Log("Found {0} members", akks.Count);
            Stats["Members"] += akks.Count;
            if (akks.Count == 0) StopJop("No more members");
            File.AppendAllLines("members.txt", akks);
        }
    }
}

Я понимаю, что к концу прочтения поста могло возникнуть много вопросов. Этот пост в большей степени является рекламой фреймворка. В следующей статье я более подробно расскажу как все работает.

Исходник с комментариями можно скачать тут, сам фреймворк находится здесь.

upd: Обновил совместимость с .NET 4.0 и 4.5

Устали каждый раз писать куки и прокси в запросе?

Устали каждый раз писать куки и прокси в запросе?

Специально для этого в движке есть функция VkRequest.StaticRequest(). Она делает то же самое, что и обычная функция Request, но при этом не нужно указывать прокси и куки. Они берутся из специальных свойств, которые подразделяются на 2 набора. Первый:

  • GlobalProxy
  • GlobalCookies
  • GlobalHeaders

Значения этих свойств будут использоваться во всех вызовах функции StaticRequest. То есть достаточно один раз установить свойства

VkRequest.GlobalProxy = ...;
VkRequest.GlobalCookies = new CookieCollection();

И просто пользоваться функцией StaticRequest, указанный прокси будет использоваться автоматически и куки будут передаваться между всеми запросами.

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

  • ThreadProxy
  • ThreadCookies
  • ThreadHeaders

Это особые ThreadStatic cвойства. Это означает, что для каждого потока это свойство имеет разное значение. В остальном они работают так же как и предыдущий набор свойств. ThreadProxy и ThreadCookies имеют больший приоритет, чем свойства из предыдущего набора. То есть если указать GlobalProxy и ThreadProxy, то движок будет использовать ThreadProxy. Заголовки GlobalHeaders и ThreadHeaders работают немного по другому, движок объединяет оба эти набора в один. При этом если встречается 2 заголовка с одинаковым именем, то используется заголовок из набора ThreadHeaders.

Smile

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

Движок теперь поддерживает HTTPS!

Движок теперь поддерживает HTTPS!

Вышла новая версия Viking.Engine, теперь можно делать https запросы! Для того чтобы этим воспользоваться достаточно просто сделать запрос к https странице, все работает само. При этом только следует учесть, что далеко не все HTTP проски могут работать с HTTPS, так что советую для этого использовать соксы.

Еще появилась возможность жаловаться на неправильно разгаданную капчу. Делается это вот так:

string captchaId;
VkRequest.PostCaptcha("http://website.com/captcha?sid=234fre", out captchaId);
// Узнаем что капча неправильная
VkRequest.ReportBadCaptcha(captchaId);

И последнее, что хочу отметить – новый параметр запроса: FollowRedirects, который позволяет автоматически переходить по редиректам.

VkRequest.Request("http://vkontakte.ru/", FollowRedirects: true);

Все подробности про новую версию можно узнать на странице движка.

Вышла новая версия движка и help!

Вышла новая версия движка и help!

На самом деле новые версии выходили вместе с каждым уроком, и из-за этого могла возникать некоторая путанница. Теперь все будет подругому – появилась страница с историей версий, на которой будут публиковаться все новые версии с указанием изменений. А еще теперь к движку можно скачать помощь и XML-документацию. К сожалению, я пока что описал далеко не все классы, но помощь тоже будет обновляться и современем станет полной. Для тех кто не знает: XML-документация нужна для того, чтобы Visual Studio могла выводить всплывающие подсказки к функциям движка. Чтобы она работала просто киньте .xml файл в папку к .dll