Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Обучение от Mail.Ru Group.
Онлайн-университет
для программистов с
гарантией трудоустройства.
Набор открыт!

2004 г.

NQL: твои агенты в Сети

Арсений Чеботарев,
«Издательский Дом «КОМИЗДАТ»

Сеть разбухает с каждым днем, и наш усталый мозг давно уже не в состоянии обрабатывать входящий трафик. Но лень на то и добродетель программиста, чтобы побудить его к автоматизации собственной жизни… Интернет, скажем, автоматизировать можно по-всякому - к примеру, так...

Идея автоматизации работы в Сети не нова. Если условно считать сеть состоящей из серверов и клиентов, то код, работающий на стороне сервера, изначально создавался для работы в автоматическом режиме. В последнее время, например, большинство контента веб-страниц генерируется динамически. Так что для того, чтобы действительно "вкалывали" роботы, а не человек, осталось автоматизировать клиентскую часть. Идея проста: пускай компьютеры общаются друг с другом - а человеку останется обналичивать кэш. (Программы, работающие на стороне и/или от имени клиента, будем называть сетевыми агентами, роботами или ботами.)

Исторически сложилось два подхода к программированию сетевых агентов. Первый заключается в реализации сетевых протоколов, таких как http и ftp. Обычно это уже не нужно делать вручную, поскольку современные языки, как правило, содержат необходимые библиотеки. К наиболее известным можно отнести сетевые библиотеки perl, Delphi, Java, а теперь еще и этот новомодный.NET.

Другой подход, специфичный для нескольких протоколов, связан с автоматизацией Internet Explorer'a и реализуется обычно на Бейсике. Хотя многие программисты могут посмеяться над этой техникой, но на самом деле использовать чужой код всегда выгодно. Internet Explorer реализует массу высокоуровневых вещей, которые тот же perl не сделает никогда - или, по крайней мере, это будет лишняя и ненужная работа. К таким вещам относится поддержка куков вообще и сессий в частности, выполнение скриптов, динамическая генерация контента, обработка встроенных объектов и так далее. То есть проблема сводится к одному: некоторый контент генерируется автоматически, и не всегда легко вычислить, что там в конце концов получится.

Расскажу вам о языке программирования NQL, сочетающем в себе лучшее из обоих миров,- это значит, что он может как работать на уровне GET-POST, так и автоматизировать IE. И дело не столько в том, что NQL может это делать (при определенной сноровке такие вещи можно проделать на любом языке) - суть в том, что для NQL это основное занятие: синтаксис доступа к Сети крайне прост, встроен в язык, хорошо документирован и доступен для понимания на уровне продвинутого пользователя (бывалый кодировщик может при случае вспомнить dbase2).

Встроенные возможности языка

Минималистический стиль этого описания я позаимствую из инструкции к трояну Donald Dick. Итак, в язык встроено всё: сокеты, http, ftp, почта (писать, получать, разбирать), работа с локальными файлами, базами данных через ADO/OLEDB/ODBC SQL, автоматизация браузера (полнейшая), базовая обработка графики (включая управление TWAIN-устройствами), OLE-автоматизация, разбор XML, работа под CGI, управление мобильными устройствами, финансовые и e-commerce функции (OFX), Fuzzy logic, нейронные сети, функции принятия решения, приложения теории вероятностей, воспроизведение голосовых сообщений, масса функций и возможности расширения языка.

Хотя этот перечень и выглядит как набор "все на свете", но реализация сделана очень прямолинейно и поэтому изящно, в духе языков "эпохи до ООП". Поскольку NQL не предназначен для создания масштабных и, тем более, универсальных приложений, то здесь не применяются классы и объекты. Это можно рассматривать и как недостаток, и как достоинство - поскольку объекты и классы часто применяются в тех случаях, где без них было бы лучше.

Документация

Опыт доказывает: недокументированная возможность равнозначна ее отсутствию - поэтому от документации зависит очень многое. Документация к NQL может служить примером "как это нужно делать". Есть два основных текста: обзоры по всем темам - NQL Language Manual, и отдельно - NQL Statement Reference Guide. Единственный недостаток последнего - модальное окно. То есть во время чтения справки вы не можете править программу. Кроме названных двух help'ов, во время набора текста вы получаете внизу экрана справку по введенной команде и ее параметрам - очень удобно.

Сбоку экрана (изначально справа) располагается Toolbar. В отличие от современных пиктографических палитр инструментов (вероятно, рассчитанных на неграмотных), в этом Toolbar'e перечисляются команды по функциональным группам, предоставляя тем самым способ быстрого построения кода.

Особенности NQL-синтаксиса

Что общего у синтаксиса C и Basic? Этим общим знаменателем как раз и является синтаксис NQL. Некоторые элементы позаимствованы у Basic (например, разделение команд в одной строке двоеточиями). С другой стороны - фигурные скобки и комментарии явно указывают на родство с C. Обработка ошибок поддерживается в двух формах - можно обрабатывать прерывания по ошибке в духе On Error, а можно анализировать значения возвращаемой функции.

В язык встроены две уникальные по своему удобству возможности, в других языках не встречающиеся. Первая - это встроенное состояние, оставляемое после последней команды. Это состояние сигнализирует о том, успешно ли была выполнена команда (или был ли получен положительный результат), и принимает значения true или false. Впоследствии это значение может быть предметом исследования - так, как бы вы выполнили if:

get URL
then {
...
}

Такая манера выполнения может оказаться более удобной, чем постоянный опрос функций. Второй уникальной конструкцией является стек. Собственно в самом стеке ничего уникального нет. А вот то, что он встроен на уровне языка, это, конечно, сильно. Со стеком по умолчанию работают многие функции и команды, так что код становится "интуитивным". Например:

get URL: show

показывает в окне содержимое только что получtнного htpp-документа (или что уж там было получено). Стек адресуется встроенными переменными. (точка) и.. (две точки) - для указания на первый и второй сверху элементы. Встроенные функции push и pop позволяют, соответственно, получить и вставить в стек элемент - так что стеком можно управлять как явно, так и неявно, в процессе выполнения команд.

Способы запуска программ

NQL не является универсальным языком программирования, на нем нельзя написать полноценную программу с графическим интерфейсом пользователя. Поэтому фрагменты NQL-кода часто должны выполняться в каком-то другом приложении. Поговорим о том, как выполняются NQL-программы, то есть, как вы используете готовые скрипты на SQL - как из OS, так и из других программ.

Выполнение всегда происходит по одному и тому же сценарию: ваша программа в текстовом виде находится в файле или в переменной в памяти. Дополнительно есть две области для входных и выходных данных и, возможно, еще несколько параметров. Иными словами, вы имеете текст программы и передаете его интерпретатору. Такой "полностью динамический" механизм позволяет не только загружать файлы во время выполнения, но и конструировать программы прямо во время выполнения - точно так же, как это делается с командами SQL. Обратная сторона, быстродействие, в сети вряд ли будет критическим местом - запросы к сети, как правило, будут раз в 100-1000 медленнее интерпретации.

Первый способ выполнения - в среде разработки IDE. Фактически вы можете выполнять программу в трех режимах: выделенном (не рекомендую - подвешивает систему), фоновом и отладочном. В последнем случае код выполняется по одной строке, и вы по ходу дела имеете доступ к переменным, стеку данных и прочим подробностям рантайма. Как вариант - с помощью IDE создать файл бота с расширением .BOT. Это бинарная форма программы после синтаксического разбора, созданная для поставки ваших программ в "нечитабельном" виде.

Способ номер два - создать независимой приложение, выбрав в IDE Create EXE. Само приложение располагается на рабочем столе (несколько нетипичное поведение, обычно на стол выкладывается ярлык). У независимых модулей есть дополнительные возможности - выводить данные о текущем состоянии программы в специальных областях нотификации. При выполнении таких программ вы можете прикрепить к своей программе скин - bmp-образ, и таким образом сделать вашего бота ни на что не похожим. К сожалению, эта возможность еще требует доработки.

Способ № 3 - выполнять программы NLQ из командных файлов или из командной строки с помощью программы nqlexec. Этот метод имеет ограничение - ваша программа не сможет получать или выдавать входной и выходной потоки данных.

Способ № 4 - выполнять скрипт в заданное время с помощью программы NQL Agent. Это оконная программа, доступная через меню Пуск.

Остальные способы - программные, то есть вы вызываете интерпретатор NQL из другого языка программирования, такого как C или Basic.

Для вызова из таких языков, как Basic, проще всего использовать ActiveX-компонент. Расскажу об этом подробнее, поскольку такое применение является самым вероятным, например в VBA. В вашем распоряжении только три метода: Run, RunScript и RunScriptFile - что, в общем-то, одно и то же, за исключением того, где лежит текст вашей программы. Из событий в наличии тоже три наименования: End, Notify, Show - соответствующие активным действиям вашего приложения. Несколько больше полей данных - в частности, для входных и выходных потоков, флаги обработки ошибок и нотификации.

Метод № 6, облегченный ActiveX - ATL-класс для встраивания в "легкие" контейнеры. Обычно для создания экземпляров класса в ASP-приложениях с помощью CreateObject.

Метод номер следующий - вызов скриптов через классы Java и C++, для чего нужно подключить к вашему приложению соответствующие файлы class, java, h - и так далее.

И, наконец, если вам не подходит ни один из перечисленных способов (что само по себе странно), то вы можете вызывать интерпретатор непосредственно из DLL через соответствующий API. Для этого, опять-таки, понадобится nql.h, и придется продумать еще пару трюков - то есть это не то, к чему вы должны стремиться, поскольку для интерпретатора не существует разницы между ATL/DLL.

Если вы заинтересованы в подробностях - читайте раздел Working with NQL в NQL language manual.

Теперь приведу несколько примеров в подтверждение своих слов. Скажу сразу - не всё из перечисленного будет работать :-). В частности, ftp-сервер narod.ru больше не отвечает на запросы. Так что, хотя сайт tooeasy.narod.ru и существует, реально обновить его не удастся - и, уж конечно, не с приведенным паролем. Естественно, что в реальных приложениях все окна автоматизированного браузера можно скрыть - здесь они отображаются только в целях наглядности.

Пример № 1: использование http

Часто нужно посмотреть, как сделана та или иная страничка - то есть не просто HTML-содержание, а, например, тип возвращаемого контента (некоторые мастера любят периодически толкать html, а то и exe с расширением jpeg). Кроме того, часто бывает полезным "выцепить сессию" - то есть отследить, какие куки устанавливаются в момент авторизации, чтобы потом передвигаться по сайту под своей сессией. Получить хедер ресурса не просто, а очень просто:

head 'http://easypic.com/main.html?bypass'
show httpHeader

После каждой HTTP-операции четыре переменные: httpAction, httpHeader, httpURL и httpData - устанавливаются в последнее полученное значение. Если нет уверенности в том, что ресурс существует, можно сделать отображение условным:

head 'http://yahoo.com'
then {
show httpHeader
}

Отобразить собственно содержимое страницы еще проще, поскольку после загрузки по get контент находится в стеке:

get 'aaa.com'
show

Если требуется передать данные по POST, то нужные параметры следует затолкать в стек и после этого вызвать команду post:

push 'Login=melkosoft&Password=guess&level=1&Domain=ukr.net'
post 'http://www2.ukr.net/cgi-bin/auth'
show

Последний пример может оказаться полезным для пересылки почты с ukr.net на какой-то POP3-аккаунт, поскольку POP3 на ukr.net может как работать, так и не работать. Более сложная программа может делать анонсы полученной почты за последнюю неделю, выбирать только интересные сообщения и посылать сообщение об этом на другой аккаунт. Если последний еще и связан с пейджером, то можно создать систему фильтрации входящих сообщений от спама с параллельным уведомлением на SMS. Другое применение - брутальные форсеры для онлайн-почты.

При входе в систему с паролем вам придется отслеживать сессии, записываемые в куки - возможно, вы предпочтете автоматизировать браузер в случаях, подобных показанных в следующем примере.

Пример № 2: автоматизация IE, match, upload по ftp

Следующий пример показывает автоматизацию браузера. Происходящее можно назвать "похищением контента": из Сети закачивается веб-страничка, содержание анализируется на предмет наличия полезных линков, после чего формируется новая страничка, содержащая только интересующую нас информацию. Опционально полученная страничка "поднимается" по ftp на наш сайт.

Хочу подчеркнуть, что это только демонстрация работающей технологии, а не дискуссия по правовым и/или моральным вопросам, таким как порно в Сети, использование "Ad Killers" и чужого контента.

// следующий фрагмент - калька с get
 'http://easypic.com/main.html?bypass'
// здесь get не работает -
 из-за перегрузки сервера страница часто
// не успевает загрузиться и сеанс обрывается.
for j=1,10
{
openbrowser 'http://easypic.com/main.html?bypass',
 '', '', '', '', true
every 10	// с периодичностью 10 сек
{
i=1
getbrowserdata
if (contains (., 'EasyPic<sup>TM</sup>'))
 // первый параметр - вершина стека
{
break 4
}
else {
pop
i=i+1
if (i>60) // если за 10 мин. не закачалось
 - начинаем сначала
{
closebrowser
break 3
}
}
}
}
closebrowser

// прошу прощения у всех Василиев Пупкиных за
 использование их несгибаемого трейдмарка
create 'C:\index.htm'
write '<html><title>Too Easy Pics</title>
<body><FONT face=verdana size=1 color=navy>'
write '<center><h3>Vasiliy Pupkin presents:
 great EasyPic now easier than ever!</h3>'
write '<br> To see original EasyPic with counters,
 banners, links to links, popups '
write 'and other useless stuff click 
<a href=http://easypic.com>herom</a> <center><br>'
match ('<FONT face=verdana color=red size=4>
<B>Webcams</B></FONT>')
while (match ('size=4><B>{Title}</B></FONT>'))
{
write '<center><FONT face=verdana color=red size=3>
<B>{Title}</B></FONT></center><BR>'
write '<FONT face=verdana size=1 color=navy>'

// смысл следующих строк - сделать копию контента 
(остатка), отрезать спереди один раздел, копию
// выбросить а сам раздел положить в стек,
 не факт что все оптимально, главное, что работает
push.
match '{once} size=4><B>'
pop
push once

while (match ('<A href={Link}>'))
{
if (!contains (Link,'traffic.cgi')&&!contains
 (Link,'cout.cgi')&&!contains (Link,'spotbrokers'))
{
write "<a href={Link}>XXX</a> "
}
}
pop
write '</FONT><BR><BR>'
if (Title=='Shemale')
{
break 2
}
}
write '</body></html>'
close

end // закомментируйте, если хотите выложить результат
 в Сеть,- только не пишите, что это ваше:\

ftpidentity 'tooeasy','guess'
ftpopen 'ftp.narod.ru'
ftpput 'C:\index.htm'
ftpclose
Пример № 3: закачка контента в БД

Это самый типичный случай для делового приложения - закачка контента в БД. Ситуация может быть самая разбанальная - вы ищете варианты квартир или еще что-то в газетах типа "Авизо". Можно сканировать саму газету, можно листать сайт бесконечным образом, но все-таки более экономичный вариант - выкачать контент в базу данных и после программно обеспечить условия для поиска, печати или анализа информации.

NQL может получать доступ к БД тремя способами, или, как говорят, "методами": ODBC, ADO и OLEDB. По умолчанию стоит ODBC, и поскольку это работает нормально, нет никаких причин изменять это умолчание. Для Java-версии, соответственно, предусмотрено несколько методов с участием JDBC.

Для операций можно использовать SQL-конструкции и дополнительно - nextrecord для выбора следующей записи. Поля результирующего набора при выборе по SELECT отображаются в переменные автоматически. Nextrecod тоже автоматически, в духе NQL, устанавливает код ошибки, так что код, выполняющий запрос и обрабатывающий результат, выглядит тривиально:

opendb "phonebook"
select "SELECT Contacts WHERE State='NY'";
while
{
show Name, Street, City, State, Zip, Phone
nextrecord
}

Рассмотрим практический пример - пусть наша программа получает данные из газеты объявлений и складывает их в таблицу БД. Как всегда, можно "пойти другим путем" - выкачать весь раздел или даже газету и потом в комфортной обстановке разбирать ее на молекулы. Либо же прямо в момент выкачки анализировать и выбирать нужные строки. Мы продемонстрируем второй вариант - то есть выкачаем один раздел с фильтрацией строк. Допустим, мы ищем б/у Hi-Fi технику.

Наша программа может выглядеть так:

record #avizorec=issue, rubric, rubname, pline

get 'http://www.aviso.com.ua/aviso/browse.asp'
match "ads/kiv/{codename}.asp"
pop

push codename
match '{prefix}/'
pop

get "http://www.aviso.com.ua/aviso/ads/kiv/"
&codename&".asp"
match "HRef=\"{pagename}.asp\">Rubric #620"
pop
push pagename
match "{dbsec}/"
pop

openbrowser 
"http://www.aviso.com.ua/aviso/ads/kiv/"
&prefix&"/"&pagename&".asp",'','','','',True
getbrowserdata

opendb 'avizo'
table 'ads'

while true
{
match "<font size=+1>Aviso newspaper {issue}.
 Rubric {rubric}.{rubname}</font>"
match "<br><br>"
push.
match "{lines}<BR><BR><BR><BR>"
pop
push lines
while (match ("{pline}<br><br>"))
{
if contains (pline,'б/у')&&contains (pline,'удио')
{
addrecord #avizorec
}
}
pop

match "<A HRef=\"{lnextp}.asp\">- NEXT -
 </A><BR>"
else {
break 2
}
browse "http://www.aviso.com.ua/aviso/ads/kiv/"
&prefix&"/"&dbsec&"/"&lnextp&".asp"
getbrowserdata
}
closedb
closebrowser

Как видно, здесь применяется комбинированный подход - сначала осуществляется поиск нужной страницы с помощью get (URL имеет прихотливый и непредсказуемый вид, так что приходится исследовать ссылки), а после, во избежание работы к куками, закачивается собственно информация - можете переделать этот фрагмент с использованием get и посмотреть, что получится. Результат в данном случае сохраняется в базе данных - предполагается, что вы предварительно создали ODBC-источник с именем avizo и что эта БД содержит таблицу adv. В дальнейшем нам ничего не мешает снова использовать NQL для работы с этими данными.

Пример реализации этой технологии: периодическое выкачивание предложений работы по заданному критерию (допустим, с такого мегапортала, как dice.com) и массовая рассылка резюме по найденным адресам (это вовсе не спам - там оставляют свои адреса как раз затем, чтобы им присылали резюме; да и как же иначе должен рассылать программист, если не автоматически?). Поскольку данные изменяются сравнительно медленно (скажем, раз в сутки-двое), а рассылки (гипотетически) производятся по несколько раз в день, то окажется выгодным закачивать данные один раз и хранить их в БД для последующего использования.

* * *

Всё, о чем тут шла речь, это только верхушка айсберга. Каждый из вас придумает (если уже не придумал) десятки применений своим агентам - от закачки бизнес-котировок до системы управления контентом, поиска квартирных вариантов или активной раскрутки веб-проектов. Только имейте в виду: вы в ответе за сетевых агентов, которых приручили,- и потом не говорите, что я вас не предупреждал!

Новости мира IT:

Архив новостей

Последние комментарии:

Релиз ядра Linux 4.14  (6)
Пятница 17.11, 16:12
Apple запустила Pay Cash (2)
Четверг 09.11, 21:15
Loading

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 985 1945361
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2015 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...