AutoIt — Клёвый код https://coolcode.ru Скриптописание и кодинг Fri, 22 Jul 2016 08:47:56 +0000 ru-RU hourly 1 https://wordpress.org/?v=5.8.13 https://coolcode.ru/wp-content/uploads/2015/10/YO1-150x150.png AutoIt — Клёвый код https://coolcode.ru 32 32 Autoit. Взаимодействие с сайтом. https://coolcode.ru/autoit-vzaimodeystvie-s-saytom/ https://coolcode.ru/autoit-vzaimodeystvie-s-saytom/#comments Tue, 29 Dec 2015 08:59:39 +0000 http://coolcode.ru/?p=5442

В предыдущей статье мы узнали, как находить нужное значение.

Здесь, рассмотрим, как взаимодействовать с сайтом, с помощью Autoit.

Задача следующая, ввести в поле поиска сайта coolcode.ru число 12 и нажать кнопку поиска.

У меня получился вот такой код:

#include <IE.au3>
#include <StringConstants.au3>
Global $Num="12"

Local $oIE = _IECreate("http://www.coolcode.ru",0,1,0,1)
Sleep(2000)
Local $oDiv = _IEGetObjById($oIE, "search")

Local $oInput = _IEGetObjById($oDiv, "s")
_IEAction($oInput, "focus")
Sleep(1000)
_IEFormElementSetValue($oInput,$Num)

Local $oInput = _IEGetObjById($oDiv, "s")
Sleep(1000)
Local $oButton=_IEGetObjById($oDiv, "searchsubmit")
_IEAction($oButton, "focus")
Sleep(1000)
_IEAction($oButton, "click")


;_IEQuit($oIE)

Воспользуемся модулем:

#include <IE.au3>

В предыдущей статье у нас появилась переменная

Global $Num="12"

Уже знакомыми командами открываем IE с сайтом coolcode.ru

Local $oIE = _IECreate("http://www.coolcode.ru",0,1,0,1)
Sleep(2000)

Теперь ищем <div> с id «search»

Local $oDiv = _IEGetObjById($oIE, "search")

 

После выполнения команды в переменной $oDiv Будет находится следующий элемент:

<div id="search">
						<form method="get" id="searchform" action="http://coolcode.ru/">
	<label for="s" class="assistive-text hidden">Поиск</label>
	<input id="s" type="text" name="s" placeholder="Поиск">
	<button id="$Num" name="submit" type="submit">Поиск</button>
</form>					</div>

В этом dive у нас находятся, как поле ввода в которое мы должны ввести 12, так и кнопка, по которой мы должны нажать.

 

Найдём поле ввода

Local $oInput = _IEGetObjById($oDiv, "s")

и кнопку

Local $oButton=_IEGetObjById($oDiv, "searchsubmit")

 

устанавливаем значение поля ввода такое же как и содержание переменной $Num

_IEAction($oInput, "focus")
Sleep(1000)
_IEFormElementSetValue($oInput,$Num)

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

Это всё сделано, для того что бы это хоть как то было похоже на взаимодействие человека. Многие сайты не любят роботов, а особенно когда те с ними общаются.

 

И последнее нажимаем на кнопку

_IEAction($oButton, "focus")
Sleep(1000)
_IEAction($oButton, "click")

Тоже самое сначала фокус, потом задержка, потом нажимаем на кнопку.

И вуаля… сайт послушно ищет 12.

]]>
https://coolcode.ru/autoit-vzaimodeystvie-s-saytom/feed/ 19
Autoit. Парсинг сайта или забрать значение с сайта. https://coolcode.ru/autoit-parsing-sayta-ili-zabrat-znachenies-sayta/ https://coolcode.ru/autoit-parsing-sayta-ili-zabrat-znachenies-sayta/#comments Tue, 29 Dec 2015 07:50:47 +0000 http://coolcode.ru/?p=5416

 

Парсить чужие сайты — это нудный и не благодарный труд. Обычно для этого продвинутые спамеры и ботоводы используют специальный софт. Например, когда это понадобилось мне я пользовался программой ZennoPoster. Для профессионального использования придётся покупать лицензию. Но для небольших задач, доступна демо версия которая позволяет в процессе тестирования делать небольшие проекты и запускать их, и доступно какой-то период штука для автоматического запуска проектов. Очень много визуального программирования и доступны вставки на языке например C#.

Но если парсить сайты — это лишь небольшая часть скрипта, то можно попытаться обойтись AutoIt.

Обратите внимание, что если появляются ошибки, то надо проверить следующие моменты:

— Скрипт должен выполнятся с правами администратора.

— В зависимости от политик безопасности, возможно сайт придётся занести в доверенную зону.

— Работе скрипта так же может мешать UAC (отключение может помочь)

!!!В 9 строчке (Local $aArray = StringRegExp($oLiHtml,‘( (.*?))’,1)),  в конструкции ‘ \ ((.*?) \ )’ убираем пробелы !!!!

#include <IE.au3>
Local $oIE = _IECreate("http://www.coolcode.ru",0,1,0,1)
Sleep(2000)
Local $oDiv = _IEGetObjById($oIE, "categories-3")
Local $oLis = _IETagNameGetCollection($oDiv, "li")
For $oLi In $oLis
 If StringInStr ($oLi.innerhtml,"Администрирование")>0 Then
  Local $oLiHtml=_IEPropertyGet($oLi,"innerhtml")
  Local $aArray = StringRegExp($oLiHtml,' \ ((.*?) \ )',1)
  Global $Num=$aArray[0]
 EndIf
next
MsgBox(0,"",$Num);
_IEQuit($oIE)

И так рассмотрим проект который на сайте CoolCode.Ru пытается посмотреть сколько статей в разделе  Администрирование.

Воспользуемся модулем:

#include <IE.au3>

 

Запускаем IE с нашим сайтом:

Local $oIE = _IECreate("http://www.coolcode.ru",0,1,0,1)

Параметры по порядку:

«http://www.coolcode.ru» — соответственно url страницы

0 — мы не пытаемся открыть новую вкладку.

1- окно видимо

0 — мы не ожидаем конца загрузки страницы(реклама и социальные кнопки… да ну их)

1 — с делать это окно в фокусе

 

Ждём 2 секунды

Sleep(2000)

это скользкий путь если не важно время выполнения скрипта, то лучше на предыдущей строчке в ожидании конца загрузки поставить 1. Так же для ускорения можно сделать небольшой тюнинг самого IE установить там ADBlock(не забываем выключать на моём сайте, что бы кликать рекламу :)), отключить картинки, убрать CSV, и прочее.

 

Дальше мы из объекта $oIE выцыпляем объект с id = «categories-3»

Local $oDiv = _IEGetObjById($oIE, "categories-3")

Для того, что бы посмотреть код объекта смотрим html страницы, а лучше самого объекта, для этого рекомендую Firefox. Хотя мне хватило Chrome.

Вообще в Autoit нету выцыпления по классу в базовом наборе … прям беда. 🙁

 

И того у нас в объекте $oDiv содержиться примерно такая беда:

Если бы у нас была такая команда

ConsoleWrite($oDiv.Outerhtml)

, то в консоли выдался бы такой текст:

<div class="widget clearfix widget_categories" id="categories-3"><h3 class="heading">Рубрики</h3>		<ul>
	<li class="cat-item cat-item-9"><a href="http://coolcode.ru/admin/">Администрирование</a> (12)
<ul class="children">
	<li class="cat-item cat-item-6"><a href="http://coolcode.ru/admin/scripts/">Скрипты</a> (9)
</li>
</ul>
</li>
	<li class="cat-item cat-item-1"><a href="http://coolcode.ru/bez-rubriki/">Без рубрики</a> (2)
</li>
	<li class="cat-item cat-item-27"><a href="http://coolcode.ru/novosti/">Новости</a> (2)
</li>
	<li class="cat-item cat-item-31"><a href="http://coolcode.ru/reshenie-zadach/">Проверка знаний</a> (862)
</li>
	<li class="cat-item cat-item-24"><a href="http://coolcode.ru/proektyi/">Проекты</a> (1)
</li>
	<li class="cat-item cat-item-21"><a href="http://coolcode.ru/tsiklyi-statey/">Циклы статей.</a> (1)
</li>
	<li class="cat-item cat-item-11"><a href="http://coolcode.ru/programming_languages/">Языки программирования</a> (21)
<ul class="children">
	<li class="cat-item cat-item-12"><a href="http://coolcode.ru/programming_languages/training/">Обучение</a> (17)
	<ul class="children">
	<li class="cat-item cat-item-19"><a href="http://coolcode.ru/programming_languages/training/spravochnaya-informatsiya/">Справочная информация</a> (15)
</li>
	</ul>
</li>
</ul>
</li>
		</ul>
</div>

 

Здесь мы видим список <li> объектов, делаем коллекцию $oLis.

Local $oLis = _IETagNameGetCollection($oDiv, "li")

Бежим по получившейся коллекции:

For $oLi In $oLis
...
next

 

Здесь мы скатились к простому анализу строк, через регулярные выражения:

!!!В 3 строчке (Local $aArray = StringRegExp($oLiHtml,‘( (.*?))’,1)),  в конструкции ‘ \ ((.*?) \ )’ убираем пробелы !!!!

If StringInStr ($oLi.innerhtml,"Администрирование")>0 Then
  Local $oLiHtml=_IEPropertyGet($oLi,"innerhtml")
  Local $aArray = StringRegExp($oLiHtml,' \ ((.*?) \ )',2)
 EndIf

В принципе, если вы профессионал в регулярных выражениях, вы бы могли сразу воспользоваться функцией: _INetGetSource из модуля  Inet.au3 и просто парсить код страницы. Предыдущие манипуляции просто упрощают задачу.

Итак, я немного отвлёкся. В коде мы бежим по li объектам если мы видим что в этом объекте содержится текст Администрирование, то объект правильный.

If StringInStr ($oLi.innerhtml,"Администрирование")>0 Then

Сохраняем его в переменную $oLiHtml значение свойства innerhtml:

Local $oLiHtml=_IEPropertyGet($oLi,"innerhtml")

То-есть код внутри тега.

 

Дальше используем поиск всех значений в скобачках и помещаем их в массив $aArray

!!!Строчка (Local $aArray = StringRegExp($oLiHtml,‘( (.*?))’,1)), пишется без пробелов в конструкции ‘ \ ((.*?) \ )’!!!!

Local $aArray = StringRegExp($oLiHtml,' \ ((.*?) \ )',2)

Дальше запихиваем нужное значение в переменную $Num

Global $Num=$aArray[0]

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

 

Далее мы выводим результат на экран и закрываем окно.

MsgBox(0,"",$Num);
_IEQuit($oIE)

На этом парсинг сайта закончен.

Ну и немного модефицировав код, мы можем получить индекс Доу-Джонса с сайта yahoo

#include <IE.au3>
Local $oIE = _IECreate("https://beta.finance.yahoo.com/quote/%5EDJI/news",0,0,1,1)
;Sleep(10000)
Local $oLis = _IETagNameGetCollection($oIE, "span")
For $oLi In $oLis
 If StringInStr ($oLi.outerhtml,'class="quote-price"')>0 Then
   Local $oLiHtml=_IEPropertyGet($oLi,"innerhtml")
  Global $Num=$oLiHtml
 EndIf
next
_IEQuit($oIE)
MsgBox(0,"",$Num);

Статья про взаимодействием сайта и AutoIt

Спасибо Юрию за комментарий, о устранении возможных ошибок.

]]>
https://coolcode.ru/autoit-parsing-sayta-ili-zabrat-znachenies-sayta/feed/ 11
Вставки скриптов в AutoIT https://coolcode.ru/vstavki-skriptov-v-autoit/ https://coolcode.ru/vstavki-skriptov-v-autoit/#comments Thu, 03 Apr 2014 03:27:06 +0000 http://coolcode.ru/?p=54

В Autoit бывают ситуации, когда какое нибудь действие легче сделать с помощью других скриптов, например общение с АД, да мало ли бывает ситуций. При этом так же важно иметь отклик от данного скрипта, что бы можно было среагировать на поступающие ошибки или мы просто хотим получить данные.

Предлагаю несколько вариантов вставок.

 

Запуск VBS из AutoIt:

Рассмотрим следующий код:

Local $Code = ""
$Code &= 'On Error Resume Next' & @LF

$Code &= 'Function up(i2)' & @LF
$Code &= 'UP=i2+1' & @LF
$Code &= 'End Function' & @LF

$Code &= 'Function Test(i)' & @LF
$Code &= '  Dim k' & @LF
$Code &= '  Dim Res' & @LF
$Code &= '  Res=1' & @LF
$Code &= '  For k = 1 To i' & @LF
$Code &= '   Res=up(Res)' & @LF
$Code &= '  Next' & @LF
$Code &= ' Test=Res' & @LF
$Code &= 'End Function' & @LF

 Local $VbsObj = ObjCreate("ScriptControl")
    If @error Then Return SetError(1, 0, -1)
    $VbsObj.Language = "vbscript"
    $VbsObj.AddCode($Code)
$Res =$VbsObj.Run("Test", 20)

 

 

Local $Code = ""

Объявляем переменную $Code, в эту переменную мы будем записывать код на VBS

Не буду подробно описывать код который я использую на VBS, так как функции и реализация надуманны
Обращу ваше внимание на следующие моменты:

$Code &= 'Function up(i2)' & @LF

Здесь мы объявляем функцию UP которая возвращает значение параметра i2 увеличенное на 1

$Code &= 'Function Test(i)' & @LF

Здесь мы бъявляем вторую функцию Test с параметром i

 

$Code &= '   Res=up(Res)' & @LF

В ней мы можем использовать объявленные в этом коде функции, в нашем примере функция up

 

$Code &= 'End Function' & @LF

На этой строчке мы закончили наполнять переменную $Code.

 

Local $VbsObj = ObjCreate("ScriptControl")

$VbsObj становится ссылкой на COM объект  «ScriptControl»

 

If @error Then Return SetError(1, 0, -1)

Проверяем удачность предыдущего события

 

$VbsObj.Language = "vbscript"

Указываем язык нашего кода в переменной  $Code — «vbscript»

 

$VbsObj.AddCode($Code)

Добавляем наш код в этот ком объект

 

$Res =$VbsObj.Run("Test", 20)

$VbsObj.Run(«Test», 20)- Запускаем функцию Test где 20 это параметр i, результатом функции $VbsObj.Run будет результат возвращённый функцией «Test». И соответственно он присвоится переменной $Res

 

Запуск PowerShell из AutoIt или обратный отклик от EXE :

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

Разберём следующий скрипт:

Func _OEM2ANSI($what)
    $ret = DllCall('user32.dll', 'Int', 'OemToChar', 'str', $what, 'str','')
    Return $ret[2]
 EndFunc   ;==>_OEM2ANSI

$Cmd = 'Get-Process'
$PowerShell = Run('PowerShell.exe '&$Cmd, "", @SW_HIDE , $STDERR_CHILD + $STDOUT_CHILD + $STDIN_CHILD)
StdinWrite($PowerShell)

$line=""
$lineData=""
$lineError=""
While 1
    $line = StdoutRead($PowerShell)
    If @error Then ExitLoop
    $lineData &=_OEM2ANSI($line)
Wend
While 1
    $line = StderrRead($PowerShell)
    If @error Then ExitLoop
    $lineError &=_OEM2ANSI($line)
Wend

 

Func _OEM2ANSI($what)

Из за того, что в консоли виндовс нам выдаются надписи в кодировке OEM2, а AutoIt работает с ANSI, то без перекодировки не обойтись если нам нужен отклик от программы.

$ret = DllCall('user32.dll', 'Int', 'OemToChar', 'str', $what, 'str','')
    Return $ret[2]

Для перекодировки используем библиотеку user32.dll  c помощью функции DllCall.

Её первый параметр используемая библиотека(user32.dll),

второй тип результата функции(Int),

третий сама функция из библиотеки (OemToChar),

четвёртый тип первого параметра(str),

пятый непосредственно сам параметр(параметр нашей функции $watch),

шестая тип втого параметра(str),

седьмая значение второго параметра(»)

 

$Cmd = 'Get-Process'

Здесь пишем команды на PowerShell не забываем, что это будет папаметр к PowerShell.exe, так что всё в одну строчку ипользуем ‘;’ если надо разделить команды.

 

$PowerShell = Run('PowerShell.exe '&$Cmd, "", @SW_HIDE , $STDERR_CHILD +$STDOUT_CHILD + $STDIN_CHILD)

Запускаем  PowerShell.exe с параметром $Cmd, при этом запуск будет не заметным для пользователя (@SW_HIDE)
$STDIN_CHILD заставляет использовать указатель дочернего потока STDIN
$STDOUT_CHILD заставляет использовать указатель дочернего потока STDOUT
$STDERR_CHILD заставляет использовать указатель дочернего потока STDERR

 

StdinWrite($PowerShell)

Забираем потоки вывода которые были сформированны при запуске нашего приложения

 

$line=""
$lineData=""
$lineError=""

Эти переменные понадобятся нам, для того что бы забрать данные из потоков вывода

 

While 1
$line = StdoutRead($PowerShell)
If @error Then ExitLoop
$lineData &=_OEM2ANSI($line)
Wend

Здесь мы забираем данные из потока STDOUT по строчно($line = StdoutRead($PowerShell)).

И записываем в переменную, не забыв их преобразовать в нужную кодировку из OEM2 в ANSI  ($lineData &=_OEM2ANSI($line))

Так как этих данных может быть больше одной строчки, то забираем в цикле пока не появится какая либо ошибка, например кончились данные.

 

While 1
$line = StderrRead($PowerShell)
If @error Then ExitLoop
$lineError &=_OEM2ANSI($line)
Wend

Тоже самое делаем с данными попавшими в поток ошибок StderrRead.

]]>
https://coolcode.ru/vstavki-skriptov-v-autoit/feed/ 8