- Регистрация
- 27.12.2016
- Сообщения
- 288
- Благодарностей
- 385
- Баллы
- 63
Всем добра и мира!
Из названия статьи понятно, что мы будем прикручивать к шаблону ZP NodeJS — наш шаблон будет автоматически устанавливать ноду, автоматически устанавливать npm-пакет, с которым будем работать, ну и посылать данные на обработку и получать в ответах результаты. И все это — непосредственно из кода, без всяких батников.
РАЗБОР ТЕМЫ ХОЧЕТСЯ НАЧАТЬ С БЛАГОДАРНОСТЕЙ:
NodeJS — это среда для выполнения JavaScript. Того самого js, который выполняется, пожалуй, на 99,9% страниц, загружаемых нами в браузере. А еще, того самого JS, с помощью которого владельцы сайтов и веб-сервисов получают информацию о браузере (и об ОС — fingerprint, timezone, язык системы, шрифты и т.п.), генерируют куки, определяют и отшивают ботов (тем самым нанося непоправимый вред тонкой душевной организации многих владельцев Zennoposter).
Хм... Есть JS, который мешает жить ботоводам, и есть среда для его запуска, с огромным количеством готовых к использованию инструментов, позволяющих всячески препарировать тот самый, злобный, JavaScript. Как по мне, потенциал у связки ноды с ZP огромен, и оценить его я не возьмусь, хотя бы потому, что я пока не знаю JavaScript.
Сразу напрашивается логичный вопрос — а как же пользовать такое богатство, если ключиков к нему нет?
Конечно же учить JS хотя бы на начальном уровне, учить NodeJS, чтобы понимать хотя бы примерно — что, куда и как. Но в принципе, можно обойтись — поиск пакетов по ключу cli выдает 4769 страниц. Омайнгот!!! 4769 страниц, содержащих пакеты под решение каких-то задач, с прикрученным к ним интерфейсом командной строки! Определенно, назначение многого из того, что находится на этих страницах будет пока абсолютно мутным, но, все же, я уверен, что в такой куче найдется несколько жемчужин для каждого владельца ZP.
Чтобы подтвердить утверждение о жемчужинах, я плавно перейду к шаблону, который будет прикреплен к статье. Мне понадобился функционал, который как я помнил, выкладывал @Lord_Alfred в одном из конкурсов, однако, найдя соотв. топик, оказалось, что обновилась библиотека, входящая в состав шаблона и написанная на Go, и карета превратилась в тыкву (без правок на неизвестном мне языке шаб не работал). Библиотека на C# с гитхаба с разбегу не запустилась, а нужно было срочно, и вот я нашел несколько разных вариантов библиотек под NodeJS — в том числе и та, которую интегрировал в шаблон.
Установить и запустить NodeJS вручную не сложнее чем поставить любой опенсорсный софт, еще часа-полтора проб, ошибок и чтения коротенького мануала к пакету с cli-интерфейсом и вуаля! Можно подключать к ZP.
ПАРА СЛОВ О NPM-ПЕКЕТЕ (БИБЛИОТЕКЕ) READABILITY-CLI, ИСПОЛЬЗУЕМОЙ В ПРИЛАГАЕМОМ ШАБЛОНЕ
Эта библиотека как раз и выполняет основную работу по извлечению статей из html-страниц, и делает это очень неплохо, а с учетом наработок от Lord_Alfred — отлично. Взаимодействие с пакетом происходит через командную строку (что немаловажно, с учетом нубства в js). К тому же, есть возможность получить не только очищенный текст, но и текст статьи в виде очищенного html, из которого замечательно извлекаются анкоры ссылок и информация об изображениях. Пакет не имеет никаких регалий на https://www.npmjs.com, у него совсем немного скачиваний, и к тому же, у последней версии что-то изменилось (после пары месяцев использования решил обновить либу), и часть работавшего функционала перестала работать — пришлось откатывать на предыдущий билд. Но тем не менее, я быстро получил готовое решение, которое смог интегрировать в шаблон, и после уже не спеша размышлять, оставить этот вариант или искать что-то поинтересней.
ИНФОРМАЦИЯ О ШАБЛОНЕ
Шаблон, прикрепленый к статье, представляет ценность скорее как обучающий, хотя весь заявленный функционал выполняет и работает в многопотоке. По-сути, это чуть расширенная версия «Универсального экстрактора» от Lord_Alfred, только с использованием NodeJS (и скорее всего, более медленнная версия). Итак, о функционале:
Чтобы эти либы функционировали, нужно поместить их в папку ExternalAssemblies Zennoposter.
Нелишним будет и небольшой обзор директив using:
ОБЩЕНИЕ С КОМАНДНОЙ СТРОКОЙ ИЗ КОДА C#
Класс Process из сборки System.Diagnostics, позволяет запускать и останавливать любой процесс ОС (т.е. в том числе и исполняемый файл). Используя этот класс, мы будем запускать интерфейс командной строки cmd.exe и выполнять в нем команды, а также запустим инсталятор msi с аргументамми, позволяющими установить NodeJS. Код для вызова командной строки и выполнения команды (например, опредилить битность системы), выглядит вот так:
Данный код позволяет выполнить в cmd однострочную команду, и получить в переменную результат ее выполнения. Здесь в параметр process.StartInfo.FileName мы передаем имя процесса (в нашем случае cmd.exe), а параметру process.StartInfo.Arguments команду, которую нужно выполнить - "/C wmic os get osarchitecture" (вернуть битность ОС), где ключ /C обозначет, что после выполнени команды, процесс должен быть завершен. А как быть если нужно выполнить последовательность команд? Решение имеется:
Так как общения с cmd в шабе дофига, я создал в общем коде статический класс, и запихал все это хозяйство туда, см. сборку ZHelper. Там же добавлен метод, позволяющий запустить инсталлер msi(а в принципе, любой процесс Windows), и передать ему в качестве аргумента команду установить NodeJS из указанного url:
УСТАНОВКА NODEJS ИЗ ШАБЛОНА
Что нам нужно, чтобы установить NodeJS:
В кубике мы делаем get-запрос к странице скачивания NodeJS и передаем полученный html в документ HtmlAgilityPack, создаем экземпляр класса jsHelper (в свойства которого при создании передается разрядность ОС, версия NodeJS если установлен и 0 если нет). В качестве параметра мы передаем в метод документ HtmlAgilityPack, из которого, при создании экземпляра класса, в свойство downloadUrl записывается url для скачивания последней стабильной версии NodeJS нужной разрядности. И далее, если NodeJS не установлен, или его версия ниже требуемой, происходит установка. После завершения установки мы проверяем что установка выполнена:
Вот и все, наш шаблон выполнил установку NodeJS.
УСТАНОВКА NPM-ПАКЕТА READABILITY-CLI
Тут все просто — при установке, NodeJS автоматически подтягивает необходимые для работы модули, в том числе и собственный интерфейс командной строки (доступный из cmd), и менеджер пакетов npm. Поэтому мы проверяем, установлен ли нужный нам пакет, и если нет, устанавливаем (опять же, с использованием методов статического класса ZHelperExt). Подробную справку по cli-интерфесу NodeJS можно вызвать командой node -h. Кубик установки выглядит так:
Теперь в нашем NodeJS стоит пакет, позволяющий очищать html-исходник от информационного мусора и служебных данных.
Весь процесс получения web-страницы, ее подготовки и обработки я показывать не буду, покажу лишь, кубик запроса к NodeJS, для получения очищенного html статьи:
Что происходит в кубике:
ЗАКЛЮЧЕНИЕ
Можно заметить, что мы использовали среду для выполнения js и запускали в ней вполне прикладные задачи совсем не используя JavaScript-код. До того, как остановиться на варианте с cli-интерфейсом, я пытался запустить пакеты с необходимостью написания js, но получалось небыстро и не просто, и как по-мне, cli-вариант совсем не плох, пока не хватает знаний на большее.
ССЫЛКИ
Страница скачивания NodeJS
Репозиторий с npm-пакетами для NodeJS
Страница пакета readability-cli на npmjs.com
Описание всех команд, параметров и ключей принимемых readability-cli на gitlab
Подробную справку по cli-интерфесу NodeJS можно вызвать командой node -h.
P.S. Прилагаемый шаблон написан в версии ZP 7.4.0
Из названия статьи понятно, что мы будем прикручивать к шаблону ZP NodeJS — наш шаблон будет автоматически устанавливать ноду, автоматически устанавливать npm-пакет, с которым будем работать, ну и посылать данные на обработку и получать в ответах результаты. И все это — непосредственно из кода, без всяких батников.
РАЗБОР ТЕМЫ ХОЧЕТСЯ НАЧАТЬ С БЛАГОДАРНОСТЕЙ:
- @Astraport — за появление NodeJS в моем поле зрения (прочитав именно его статью, я сделал себе заметку о необходимости потыкать палочкой этот инструмент)
- @Lord_Alfred за идею (Универсальный экстрактор контента) с использованием readability библиотеки, а так же за офигенные снипеты для очистки контента, проверки ответов на get-запросы, адские регулярки и все остальное, что присутствует в шаблоне, прикрепленном к указанной статье. Множество решений из нее не однажды использовал.
- @marsht за замечательную статью о JS
NodeJS — это среда для выполнения JavaScript. Того самого js, который выполняется, пожалуй, на 99,9% страниц, загружаемых нами в браузере. А еще, того самого JS, с помощью которого владельцы сайтов и веб-сервисов получают информацию о браузере (и об ОС — fingerprint, timezone, язык системы, шрифты и т.п.), генерируют куки, определяют и отшивают ботов (тем самым нанося непоправимый вред тонкой душевной организации многих владельцев Zennoposter).
Хм... Есть JS, который мешает жить ботоводам, и есть среда для его запуска, с огромным количеством готовых к использованию инструментов, позволяющих всячески препарировать тот самый, злобный, JavaScript. Как по мне, потенциал у связки ноды с ZP огромен, и оценить его я не возьмусь, хотя бы потому, что я пока не знаю JavaScript.
Сразу напрашивается логичный вопрос — а как же пользовать такое богатство, если ключиков к нему нет?
Конечно же учить JS хотя бы на начальном уровне, учить NodeJS, чтобы понимать хотя бы примерно — что, куда и как. Но в принципе, можно обойтись — поиск пакетов по ключу cli выдает 4769 страниц. Омайнгот!!! 4769 страниц, содержащих пакеты под решение каких-то задач, с прикрученным к ним интерфейсом командной строки! Определенно, назначение многого из того, что находится на этих страницах будет пока абсолютно мутным, но, все же, я уверен, что в такой куче найдется несколько жемчужин для каждого владельца ZP.
Чтобы подтвердить утверждение о жемчужинах, я плавно перейду к шаблону, который будет прикреплен к статье. Мне понадобился функционал, который как я помнил, выкладывал @Lord_Alfred в одном из конкурсов, однако, найдя соотв. топик, оказалось, что обновилась библиотека, входящая в состав шаблона и написанная на Go, и карета превратилась в тыкву (без правок на неизвестном мне языке шаб не работал). Библиотека на C# с гитхаба с разбегу не запустилась, а нужно было срочно, и вот я нашел несколько разных вариантов библиотек под NodeJS — в том числе и та, которую интегрировал в шаблон.
Установить и запустить NodeJS вручную не сложнее чем поставить любой опенсорсный софт, еще часа-полтора проб, ошибок и чтения коротенького мануала к пакету с cli-интерфейсом и вуаля! Можно подключать к ZP.
ПАРА СЛОВ О NPM-ПЕКЕТЕ (БИБЛИОТЕКЕ) READABILITY-CLI, ИСПОЛЬЗУЕМОЙ В ПРИЛАГАЕМОМ ШАБЛОНЕ
Эта библиотека как раз и выполняет основную работу по извлечению статей из html-страниц, и делает это очень неплохо, а с учетом наработок от Lord_Alfred — отлично. Взаимодействие с пакетом происходит через командную строку (что немаловажно, с учетом нубства в js). К тому же, есть возможность получить не только очищенный текст, но и текст статьи в виде очищенного html, из которого замечательно извлекаются анкоры ссылок и информация об изображениях. Пакет не имеет никаких регалий на https://www.npmjs.com, у него совсем немного скачиваний, и к тому же, у последней версии что-то изменилось (после пары месяцев использования решил обновить либу), и часть работавшего функционала перестала работать — пришлось откатывать на предыдущий билд. Но тем не менее, я быстро получил готовое решение, которое смог интегрировать в шаблон, и после уже не спеша размышлять, оставить этот вариант или искать что-то поинтересней.
ИНФОРМАЦИЯ О ШАБЛОНЕ
Шаблон, прикрепленый к статье, представляет ценность скорее как обучающий, хотя весь заявленный функционал выполняет и работает в многопотоке. По-сути, это чуть расширенная версия «Универсального экстрактора» от Lord_Alfred, только с использованием NodeJS (и скорее всего, более медленнная версия). Итак, о функционале:
- Автоматическая установка NodeJS и npm-пакетов
- Парсинг материалов с сайтов и их очистка от безполезной инфы — реклама, менюхи, ссылки и прочие лишние данные.
- Получение и сохранение форматированного, очищенного html статьи
- Получение и сохранение текста статьи
- Опционально — получение и сохранение анкоров и url ссылок, присутствующих в статьях
- Опционально — получение и сохранение alt, title и href картинок статей
- Опционально же — сохранение изображений, присутствующих в статье
- Сохранение в SQLite информации о полученных материалах (можно было и сами материалы туда же, но решил не заморачиваться)
- HtmlAgilityPack. Очень люблю эту либу за огромные возможности при парсинге (отдельно за отсутствие глюков при обработке всевозможных кастомных атрибутов, с которыми натерпелся при использовании штатных возможностей ZP). В принципе, она избыточна здесь, но выпиливать ее не стал.
- System.Data.SQLite - библиотека для работы с БД SQLite
- Dapper, Dapper.Contrib — либы, позволяющие пользовать ОРМ Dapper, о них я писал в прошлом конкурсе статей — MySQL, SQLite.
Чтобы эти либы функционировали, нужно поместить их в папку ExternalAssemblies Zennoposter.
Нелишним будет и небольшой обзор директив using:
- using System.Xml — для работы с HtmlAgilityPack,
- using HtmlAgilityPack — собственно сам HtmlAgilityPack
- using Dapper; using Dapper.Contrib; using Dapper.Contrib.Extensions — работа с Dapper
- using System.Data.SQLite — работа с БД SQLite
- using NodejsHelper; using Scrapping; using ZHelper — мои сборки, их внутренности подробно откомментированы в общем коде
- System.Web — не смог вспомнить, для чего он тут, выпиливать не стал
- И есть еще одно пространство имен, используя которое мы и будем автоматизировать установку ноды и общаться с ней через командную строку — using System.Diagnostics. Подробности далее.
ОБЩЕНИЕ С КОМАНДНОЙ СТРОКОЙ ИЗ КОДА C#
Класс Process из сборки System.Diagnostics, позволяет запускать и останавливать любой процесс ОС (т.е. в том числе и исполняемый файл). Используя этот класс, мы будем запускать интерфейс командной строки cmd.exe и выполнять в нем команды, а также запустим инсталятор msi с аргументамми, позволяющими установить NodeJS. Код для вызова командной строки и выполнения команды (например, опредилить битность системы), выглядит вот так:
C#:
string request = string.Empty;
using(System.Diagnostics.Process process = new System.Diagnostics.Process())
{
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/C wmic os get osarchitecture";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardInput = true;
process.Start();
while(!process.HasExited)
{
//сохранили ответ cmd
request += process.StandardOutput.ReadToEnd();
}
}
C#:
//Здесь я пишу пустой список, но в реале в нем команды для выполнения
List<string> cmd = new List<string>();
string request = string.Empty;
using(System.Diagnostics.Process process = new System.Diagnostics.Process())
{
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardInput = true;
process.Start();
using (StreamWriter sw = process.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
foreach(string str in cmd)
{
sw.WriteLine(str);
}
}
}
while(!process.HasExited)
{
//сохранили ответ cmd
request += process.StandardOutput.ReadToEnd();
}
}
C#:
/// <summary>
/// Статический класс, содержащий методы для запуска соманд в командной строке windows
/// </summary>
public static class ZHelperExt
{
/// <summary>
/// Метод запускает командную строку windows и выполняет однострочную команду, возвращает строку, в которую сохраняет результат выполнения (если команда которая выполняется имеет его)
/// </summary>
/// <param name="cmd">Команда, котороую надо выполнить в командной строке</param>
/// <returns></returns>
public static string RunSingleCmdReturnToString(string cmd)
{
string request = string.Empty;
using(System.Diagnostics.Process process = new System.Diagnostics.Process())
{
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = cmd;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardInput = true;
process.Start();
while(!process.HasExited)
{
//сохранили ответ cmd
request += process.StandardOutput.ReadToEnd(); //русский язык кракозябрами, потом надо подумать
}
return request;
}
}
/// <summary>
/// Метод запускает командную строку windows и выполняет несколько команд в той последовательности, в которой они указаны во входном списке cmd
/// </summary>
/// <param name="cmd">Список команд для выполнения в командной строке</param>
/// <returns>Строка, содержащая результаты исполнения команд</returns>
public static string RunListCmdReturnToString(List<string> cmd)
{
string request = string.Empty;
using(System.Diagnostics.Process process = new System.Diagnostics.Process())
{
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardInput = true;
process.Start();
using (StreamWriter sw = process.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
foreach(string str in cmd)
{
sw.WriteLine(str);
}
}
}
while(!process.HasExited)
{
//сохранили ответ cmd
request += process.StandardOutput.ReadToEnd(); //русский язык кракозябрами, потом надо подумать
}
return request;
}
}
/// <summary>
/// Метод позволяет запускать любые программы windows
/// </summary>
/// <param name="progName">Имя программы, которую надо запустить</param>
/// <param name="workingDir">Рабочая директория для запуска процесса (НЕ директория где находится исполняемый файл!)</param>
/// <param name="cmd">Аргументы запуска программы</param>
public static void RunSomeProgramm(string progName, string workingDir, string cmd)
{
using(System.Diagnostics.Process process = new System.Diagnostics.Process())
{
process.StartInfo.FileName = progName;
process.StartInfo.WorkingDirectory = workingDir;
process.StartInfo.Arguments = cmd;
process.StartInfo.Verb = "runas";
process.Start();
process.WaitForExit(100000);
}
}
}
УСТАНОВКА NODEJS ИЗ ШАБЛОНА
Что нам нужно, чтобы установить NodeJS:
- Разрядность ОС
- Ссылка на скачивание NodeJS
- Также, стоит проверить, не установлен ли уже в системе NodeJS, а если установлен, соответствует ли его билд требованиям npm-пакета
C#:
/// <summary>
/// Класс получает информацию о разрядности ОС, наличии в системе установленного NodeJS и его версии,
/// а так же получает ссыль на скачивание актуальной версии соотв. разрядности
/// </summary>
public class jsHelper
{
public int bitness;
public const string osBitnessReg = @"\d{2}";
public string downloadUrl{get;}
public int installedNodejsVersion;
public int minVersionNodejs = 122000;
private string installerDownluadXpath = @"//th[contains(text(), 'Windows Installer (.msi)')]/following-sibling::td/a";
private string installedNodejsVersionReg = @"(?<=v).*";
private string getOsBitnessCommand = "/C wmic os get osarchitecture";
public string getNodeVersionCommand = "/C node -v";
/// <summary>
/// Конструктор класса. При вызове, получает разрядность системы, проверяет наличие nodejs и его версию, получает сссылки на загрузку инсталлера
/// </summary>
/// <param name="hdoc"></param>
public jsHelper(HtmlAgilityPack.HtmlDocument hdoc)
{
#region Get OS bitness
string request = ZHelper.ZHelperExt.RunSingleCmdReturnToString(this.getOsBitnessCommand);
bitness = Int32.Parse(Regex.Match(request, osBitnessReg).Value); //OS bitness value — 32 or 64
#endregion
#region Get nodejs downloadUrl
var nodes = hdoc.DocumentNode.SelectNodes(installerDownluadXpath);
foreach(var node in nodes)
{
string innerhtml = node.InnerText;
int linkBit = Int32.Parse(Regex.Match(innerhtml, osBitnessReg).Value);
if(bitness == linkBit)
{
downloadUrl = node.Attributes["href"].Value;
}
}
#endregion
#region Check is NodeJS installed and get installed version
request = ZHelper.ZHelperExt.RunSingleCmdReturnToString(this.getNodeVersionCommand);
if(string.IsNullOrEmpty(request) || request.Substring(0, 1) != "v")
{
installedNodejsVersion = 0;
}
else if(!string.IsNullOrEmpty(request) || request.Substring(0, 1) == "v")
{
try
{
request = Regex.Match(request, installedNodejsVersionReg).Value.Replace(".", "").Trim();
if(request.Length == 5) request = request + "0";
installedNodejsVersion = Int32.Parse(request);
}
catch{installedNodejsVersion = 0;}
}
else installedNodejsVersion = 0;
#endregion
}
}
В кубике мы делаем get-запрос к странице скачивания NodeJS и передаем полученный html в документ HtmlAgilityPack, создаем экземпляр класса jsHelper (в свойства которого при создании передается разрядность ОС, версия NodeJS если установлен и 0 если нет). В качестве параметра мы передаем в метод документ HtmlAgilityPack, из которого, при создании экземпляра класса, в свойство downloadUrl записывается url для скачивания последней стабильной версии NodeJS нужной разрядности. И далее, если NodeJS не установлен, или его версия ниже требуемой, происходит установка. После завершения установки мы проверяем что установка выполнена:
C#:
#region get page nodejs download
string get = ZennoPoster.HTTP.Request(
method:ZennoLab.InterfacesLibrary.Enums.Http.HttpMethod.GET,
url:jsConst.nodejsPageDownloadUrl,
Encoding:@"UTF-8",
respType:ZennoLab.InterfacesLibrary.Enums.Http.ResponceType.HeaderAndBody,
Timeout:30000,
throwExceptionOnError:true
);
#endregion
//HtmlAgilityPack new document
HtmlDocument hdoc = new HtmlDocument();
hdoc.LoadHtml(get);
//Create new object JHelper
jsHelper helper = new jsHelper(hdoc);
#region check and install NodeJS
//Если установленная версия меньше минимальной или если nodejs не установлен, устанавливаем его из url
if(helper.minVersionNodejs > helper.installedNodejsVersion)
{
//setup to default folder (c:\Program Files)
string workingDir = @"C:\temp\";
string progName = "msiexec";
string cmd = string.Format(@" /quiet /i {0}", helper.downloadUrl);
//if need install nodejs to custom folder
//string cmd = string.Format(@" /quiet /i {0} INSTALLDIR=F:\Zenno_tmpl\contentor\nodejs", helper.downloadUrl);
ZHelperExt.RunSomeProgramm(progName, workingDir, cmd);
project.SendInfoToLog(helper.minVersionNodejs.ToString()+" - "+helper.installedNodejsVersion.ToString(), false);
Thread.Sleep(200);
//check that installation is complete
string res = ZHelper.ZHelperExt.RunSingleCmdReturnToString(helper.getNodeVersionCommand);
if(!string.IsNullOrEmpty(res))project.SendInfoToLog(string.Format("Install NodeJS version {0}", res.Trim()), true);
}
else
{
string res = ZHelper.ZHelperExt.RunSingleCmdReturnToString(helper.getNodeVersionCommand);
project.SendInfoToLog(string.Format("NodeJS is already installed, NodeJS version = {0}", res.Trim()), true);
}
#endregion
Вот и все, наш шаблон выполнил установку NodeJS.
УСТАНОВКА NPM-ПАКЕТА READABILITY-CLI
Тут все просто — при установке, NodeJS автоматически подтягивает необходимые для работы модули, в том числе и собственный интерфейс командной строки (доступный из cmd), и менеджер пакетов npm. Поэтому мы проверяем, установлен ли нужный нам пакет, и если нет, устанавливаем (опять же, с использованием методов статического класса ZHelperExt). Подробную справку по cli-интерфесу NodeJS можно вызвать командой node -h. Кубик установки выглядит так:
C#:
//устанавливаем пакет readability-cli
string cmd = @"/C npm install -g [email protected]";//инсталим не последнюю, а выборочную версию пакета, ключ -g задает глобальную установку пакета
string request = ZHelper.ZHelperExt.RunSingleCmdReturnToString(cmd);
Thread.Sleep(100);
//Проверяем, что установка выполнена успешно
cmd = @"/C readable -V";
request = ZHelper.ZHelperExt.RunSingleCmdReturnToString(cmd);
if(request.Trim().Contains("readability-cli v"))return true;
else throw new Exception("npm pacage is not install");
Весь процесс получения web-страницы, ее подготовки и обработки я показывать не буду, покажу лишь, кубик запроса к NodeJS, для получения очищенного html статьи:
C#:
#region Get current working folder and and the current drive
string request = ZHelper.ZHelperExt.RunSingleCmdReturnToString("/C cd");
string folderCurrent = request.Split(new string[]{@"\"}, StringSplitOptions.RemoveEmptyEntries)[0];
string folderNeeded = project.Variables["FOLDER_page"].Value.Split(new string[]{@"\"}, StringSplitOptions.RemoveEmptyEntries)[0];
#endregion
#region Create list of command to cmd
List<string> cmd = new List<string>();
//If the current and desired disks are different
if(folderCurrent != folderNeeded)
{
string mess = string.Format("Current folder disk: {0}; Needed folder disk: {1}", folderCurrent, folderNeeded);
cmd.Add("/C");
cmd.Add(string.Format("cd /d {0}", project.Variables["FOLDER_page"].Value));
cmd.Add(string.Format("readable input.html > output.html -p html-title,html-content -b {0}", project.Variables["url"].Value));
}
//if the current and desired disks are equal
else if(folderCurrent == folderNeeded)
{
cmd.Add("/C");
cmd.Add(string.Format("cd {0}", project.Variables["FOLDER_page"].Value));
cmd.Add(string.Format("readable input.html > output.html -p html-title,html-content -b {0}", project.Variables["url"].Value));
}
#endregion
Thread.Sleep(500);
#region Send command to cmd and check result
string result = ZHelper.ZHelperExt.RunListCmdReturnToString(cmd);
string[] resultArr = result.Split(new string[]{"\r\n"}, StringSplitOptions.RemoveEmptyEntries);
foreach(string str in resultArr)
{
string s = str.Trim();
project.SendInfoToLog(s, false);
}
#endregion
- Сначала мы проверяем, соответствует текущий диск диску, в котором находится целевая папка текущей страницы
- После, создаем список команд, которые будем передавать в cmd:
- Переходим в папку текущей страницы, в которой лежит html-исходник
- В строке cmd.Add(string.Format("readable input.html > output.html -p html-title,html-content -b {0}", project.Variables["url"].Value)); указываем readability-cli, что нужно обработать файл input.html и после обработки передать html-title и html-content в файл output.html. C ключом -b передается url страницы, чтобы алгоритмы readability сохранили в атрибутах href и src валидные абслоютные пути.
- Ну и собственно передаем в cmd список команд на исполнение
ЗАКЛЮЧЕНИЕ
Можно заметить, что мы использовали среду для выполнения js и запускали в ней вполне прикладные задачи совсем не используя JavaScript-код. До того, как остановиться на варианте с cli-интерфейсом, я пытался запустить пакеты с необходимостью написания js, но получалось небыстро и не просто, и как по-мне, cli-вариант совсем не плох, пока не хватает знаний на большее.
ССЫЛКИ
Страница скачивания NodeJS
Репозиторий с npm-пакетами для NodeJS
Страница пакета readability-cli на npmjs.com
Описание всех команд, параметров и ключей принимемых readability-cli на gitlab
Подробную справку по cli-интерфесу NodeJS можно вызвать командой node -h.
P.S. Прилагаемый шаблон написан в версии ZP 7.4.0
- Тема статьи
- Нестандартные хаки
- Номер конкурса статей
- Семнадцатый конкурс статей
Вложения
-
1,1 МБ Просмотры: 66
Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...
Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.
Последнее редактирование модератором: