Автор: ZennoPoster  
 Название: Швейцарский нож разработчика  
  
  
     Проблемы при создании шаблонов    
 В каждом шаблоне ZennoPoster приходится использовать однотипные действия будь то проверка или конвертация данных, которые пользователь указал во входных настройках, или же загрузка страниц и поиск элементов с последующей проверкой были ли они найдены.    
 В больших шаблонах все это превращается в нагромождение экшенов или же в простыни однообразного кода, а порой и в комбинацию этих факторов.      
 Самые распространенные проблемы  
 —————————————————————————————————    
   - Большой объем однотипного кода
    - Плохочитаемый код
    - Трудности с поиском и исправлением багов
   
     Рассмотрим небольшой кусок кода, который загружает страницу Яндекса, вводит поисковой запрос и нажимает кнопку поиска.  
 Примечание: здесь и далее приведенный код написан на языке C#.  
 Блоки кода PHP используются только для подсветки синтаксиса ввиду отсутствия блоков C#.    
 Как это выглядит в коде:    
 PHP:  
 instance.ClearCache();  
 instance.ClearCookie();    
 var tab = instance.ActiveTab;  
 tab.Navigate('ya.ru');    
 if(tab.IsBusy)  
 {  
 tab.WaitDownloading();  
 }    
 var searchInput = tab.FindElementByXPath('//input', 0);  
 if(searchInput.IsVoid)  
 {  
 throw new Exception('Поле ввода запроса не найдено.');  
 }    
 searchInput.SetValue('test request', 'full', false);    
 var findButton = tab.FindElementByXPath('//button' , 0);  
 if(findButton.IsVoid)  
 {  
 throw new Exception('Кнопка 'Найти' не найдена');  
 }    
 findButton.Click();    
 Наверняка подобный код вам знаком. Проверка загрузки страницы, проверка найденных элементов на странице. Все эти рутинные действия есть в каждом шаблоне, работающем с браузером.    
 Так почему бы не сделать эту рутину менее утомительной?  
 Взгляните на этот код, который делает то же самое, что и код выше:    
 PHP:  
 instance.ClearCacheAndCookie();    
 var tab = instance.ActiveTab;  
 tab.Go('ya.ru').WaitLoading();    
 tab.GetElementByXpath('//input').ThrowIfNull('Поле ввода запроса не найдено.').SetVal('test request');  
 tab.GetElementByXpath('//button').ThrowIfNull('Кнопка 'Найти' не найдена').Click();    
 Такой код гораздо компактнее, быстрее пишется и проще читается.  
 Вы сможете конструировать подобный код с помощью библиотеки ZennoExtensions.        
 Продукт складчины состоит из следующего  
 —————————————————————————————————    
   - DLL файл библиотеки ZennoExtensions
    - Файлы проекта с исходным кодом для самостоятельного изучения и доработки
    - Документация и инструкции по использованию
    - Демо шаблоны с примерами использования, открытые для просмотра
   
     Что представляет из себя библиотека ZennoExtensions?  
 ZennoExtensions - DLL библиотека, расширяющая стандартный набор методов классов ZennoPoster. С ее помощью вы сможете разрабатывать шаблоны быстрее, повысить удобство разработки и качество продуктов, улучшить отладку и исправление багов.    
 Содержимое  
 —————————————————————————————————    
   - Методы расширения для работы с типами ZennoPoster:
    - Instance, Project, Tab, HtmlElement, LocalVariable
    - Модуль для работы с аккаунтами
    - Модуль для работы с настройками браузера
    - Модуль логирования
    - Дополнительные классы-помощники
   
Ниже будут рассмотрены примеры использования разных частей библиотеки.  
     Значительный функционал библиотеки представляет из себя набор методов расширения, благодаря чему можно напрямую работать с объектами стандартных классов ZennoPoster'а, не прибегая к созданию экземпляров сторонних классов.    
 Большинство из методов расширений в библиотеке реализованы в стиле Fluent Interface.    
 Fluent interface или текучий интерфейс — способ реализации объектно-ориентированного API, нацеленный на повышение читабельности исходного кода программы.    
 Те, кто работал с LINQ уже знакомы с этим понятием. Методы LINQ возвращают результирующую коллекцию, на которой мы вновь можем использовать методы LINQ:     
list.Select(…).Where(…).Select(…).Where(…) и т.д.     То есть вызовы методов объединяются в цепочки вызовов. Это и есть Fluent Interface.    
 Методы расширения библиотеки    
 В библиотеке представлены методы расширения для следующих классов:      
   - Instance (ZennoLab.CommandCenter.Instance)
    - Project (ZennoLab.InterfacesLibrary.ProjectModel.IZennoPosterProjectModel)
    - LocalVariable (ZennoLab.InterfacesLibrary.ProjectModel.ILocalVariable)
    - Tab (ZennoLab.CommandCenter.Tab)
    - HtmlElement (ZennoLab.CommandCenter.HtmlElement)
    - Некоторые системные типы
   
   Проверка входных настроек    
 Рассмотрим использование методов расширения на примере проверки входных настроек шаблона.  
 Проверка входных настроек при запуске является хорошей практикой разработки шаблона.  
 Она несет следующие преимущества:      
   - Быстрая настройка и запуск шаблона за счет подробных уведомлений в логе
    - Устранение багов из-за некорректно введенных данных
    - Пользователи смогут понять и исправить свою ошибку во входных настройках не прибегая к вашей помощи
   
   Принцип проверки состоит в том, чтобы проверять корректность всех введенных в настройках данных. Если какие-то данные введены не правильно, нужно оповестить об этом в логе и прекратить дальнейшее выполнение шаблона.    
 Для этого в библиотеке есть набор методов расширения для локальных переменных.  
 Методы можно соединять в цепочки вызовов для проверки переменной на соответствие нескольким условиям.    
 PHP:  
 // Указываем чтобы сообщения выводились в лог с восклицательным знаком (Warning)  
 Throw.InvokeBeforeExceptionThrowing = args =>  
 project.SendWarningToLog(args.Message, true);    
 project.Variables['AccountsPath']  
 .ThrowIfEmpty('Не указан путь к файлу с аккаунтами.')  
 .ThrowIfFileNotExists('Файл с аккаунтами не найден.')  
 .ThrowIfTextFileIsEmpty('Файл с аккаунтами пуст.');    
 Здесь проверяются сразу 3 различных ситуации:    
   - Задал ли вообще пользователь файл с аккаунтами. Если файл задан, переходим ко второму шагу.
    - Существует ли такой файл. Если файл существует, переходим к третьему шагу.
    - Есть ли в файле содержимое.
   
В случае если какое-то условие не выполнено, будет выведено Warning сообщение в лог и выкинуто исключение (экшн завершится по ветви BadEnd). Сообщение можно не указывать, тогда будет выдано исключение с сообщение по умолчанию. Но ваши сообщения помогут пользователю лучше понять в чем именно проблема.    
 А вот как выглядит логика проверки без использования библиотеки.    
 PHP:  
 var path = project.Variables['AccountsPath'].Value;    
 if (string.IsNullOrWhiteSpace(path))  
 {  
 project.SendWarningToLog('Не указан путь к файлу с аккаунтами.', true);  
 throw new Exception('Не указан путь к файлу с аккаунтами.');  
 }    
 if (!File.Exists(path))  
 {  
 project.SendWarningToLog('Файл с аккаунтами не найден.', true);  
 throw new Exception('Файл с аккаунтами не найден.');  
 }    
 bool fileIsEmpty = new FileInfo(path).Length == 0;  
 if (fileIsEmpty)  
 {  
 project.SendWarningToLog('Файл с аккаунтами пуст.', true);  
 throw new Exception('Файл с аккаунтами пуст.');  
 }    
 Как видите, код получился 2 раза больше, читаемость кода хуже, а если понадобится проверить еще несколько переменных, то проверка и вовсе станет огромной. К тому же поддерживать такой код будет сложнее - если вы захотите изменить логирование, придется менять его во всех местах.      
 Мультилогер    
 В библиотеке представлен класс MultiLogger который позволяет удобно логировать в несколько мест одновременно. Одной строчкой кода вы можете записать сообщение в файл, вывести его пользователю в виде MessageBox и в лог ZennoPoster. Также можно добавить в мультилогер свой вариант логирования, например, в БД.    
 PHP:  
 var logger = project.GetLogger();    
 // Указываем чтобы логировалось одновременно в ZennoPoster и в файл  
 logger.LogTo = Logger.ZennoPoster | Logger.File;  
 logger.FileLogPath = @'C:mylog.txt';    
 logger.MultiLog('Тестовая запись в лог 1');  
 logger.MultiLog('Тестовая запись в лог 2', MessageType.Warning);    
 Класс мультилогера предоставляет возможность логирования в режиме разработки, логи будут писаться только при откладке из ProjectMaker или CodeCreator.  
 PHP:  
 // Сообщение будет выведено только если исполняемой средой является ProjectMaker или CodeCreator  
 logger.MultiLogDebug('Тестовая запись в лог');      
 Менеджер аккаунтов    
 Практически каждый шаблон выполняет работу с аккаунтами, который предоставляет пользователь. Менеджер аккаунтов призван решить проблемы многопоточной работы со списком аккаунтов, а также позволить закреплять ваши данные за аккаунтами, например, прокси.  
 Особенности  
 —————————————————————————————————    
   - Файл аккаунтов не подвергается изменениям
    - Для файла аккаунтов создается свой файл конфигурации, в котором содержатся все необходимые данные для последовательного выполнения аккаунтов как при работе в одном, так и в нескольких потоках
    - Аккаунты для работы распределяются равномерно - не возникнет такой ситуации, что один аккаунт отработает 10 раз, а другой 1
    - Для каждого аккаунта можно сохранять дополнительную информацию
   
   Менеджер браузера    
 Менеджер браузера позволяет генерировать и применять различные параметры браузера, а также сохранять их для последующего использования с аккаунтом.    
 Генерируемые параметры  
 —————————————————————————————————      
   - Использование JavaScript
    - Блокировка рекламяяяяя
    - Использование веб хранилищ (LocalStorage, SessionStorage, Global Storage, Database Storage)
    - Использование IndexedDB
    - Использование WebGL
    - Использование плагинов
    - DoNotTrack
    - Подмена часового пояса
    - Эмуляция WebRTC
    - Эмуляция Canvas
    - Свойства навигатора и HTTP заголовки
    - UserAgent
    - Language
   
   PHP:  
 var profile = BrowserManager.Generate();    
 // Применение настроек  
 BrowserManager.Setup(profile, instance, project);    
 // Сохранение в файл  
 string path = 'C:\1.xml';  
 BrowserManager.Save(profile, instance, path);    
 // Загрузка  
 profile = BrowserManager.Load(path);      
 Парсер строк    
 Данный класс-помощник позволяет в удобном формате работать с элементами строк. С помощью него можно дать возможность пользователям самостоятельно указывать формат используемых ресурсов. Это добавит гибкости в настройке и избавит от подстраивания используемых файлов под ваш шаблон.    
 Например, можно вынести задание формата файла аккаунтов во входные настройки. Тогда пользователю нужно будет указать шаблон, содержащий ключевые слова и используемые разделители:  
 login
;password
:proxy  
 Вот так выглядит разбор строки в коде:      
 Библиотека активно используется и дорабатывается. Участники складчины будут получать обновления бесплатно и смогут вносить предложения по доработке. Помимо самой библиотеки всем участникам будет также доступен проект Visual Studio с исходным кодом, что даст возможность изучать и дорабатывать функционал самостоятельно.      
   - Инструкция по разработке шаблонов через Visual Studio
    - Способы подключения библиотек к шаблону без использования ExternalAssemblies
    - Список полезных сервисов и инструментов для разработки
    - Подборка ссылок на обучающие материалы для самостоятельного изучения
    - Способы дополнительного заработка на шаблонах
   
       Подробнее:           Для просмотра содержимого вам необходимо .   
        Скачать: