Что нового

[Данные, строки] Разбор HTML средствами AutoIT

RUVATA

лучше один раз увидеть, чем десять раз услышать...
Сообщения
132
Репутация
38
Всем доброго времени суток...
Давненько я не появлялся здесь :IL_AutoIt_1:
Передо мной встала, казалось бы тривиальная задача - разбор HTML файла с целью вытащить из него необходимые данные, содержащиеся в <table>, основная проблема в том что сервис который собирает такие html делает это крайне неуклюже, в конечном итоге из тривиальной таблицы предстоит вычленить табличку с XPath "/html/body/div/table/tbody/tr/td/div/table/tbody/tr[4]/td/div[2]/table/tbody/tr/td/div/div/table/tbody" (я сам в шоке :shok:)
ну и собственно перебирая его <tr> снимать необходимые поля...
Я был полон оптимизма найти необходимый инструмент при помощи которого можно распарить html, с целью получить в некий объект всю его структуру или опять же по XPath выдернуть тебуемый объект, основной идей в принципе является "работать с html как с объектом" вроде того как перетрясать DOM из JavaScript, или как в Qt, так же есть класс который разбирает html и представляет его в виде ассоциативного массива, где теги имена полей, а сами поля собственно данные, фактически тот же DOM получается...
И собственно у меня пока наработки хиленькие :-X удалось найти вот это здесь каким-то образом все прикручивается через
Код:
Local $hObj = ObjCreate("Shell.Explorer.2")

Google либо ловко прячет, либо действительно очень мало знает про сия зверя дивного, понятно только что это некий интерфейс доступный для OLE взаимодействия, причем сдается мне что он имеет какое-то отношение к Internet Explorer (что само по себе не радует :smile: )
ну да бог с ним... ну так я все равно не могу найти описания доступных функций, методов и т.д.
Обращаясь к коллективному разуму, хочу попросить пролить свет озарения на мои познания в отношении разбора html в AutoIT, как это делать правильнее, какие вообще методы существуют ?

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

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
RUVATA,
Может лучше показать пару Ваших HTML файлов и указать, что конкретно из них надо выдернуть?
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
OffTopic:
сори за офтоп, но таки да - в AutoIt не хватает таких мощных инструментов как BeautifulSoup или lxml в python
 
Автор
R

RUVATA

лучше один раз увидеть, чем десять раз услышать...
Сообщения
132
Репутация
38
вот пример... соответственно вытащить данные...
я пока решил регулярной, которая выдергивает <tbody>...</tbody> в котором в <tr>...</tr> раскрывается по 10 раз подряд <td>...</td> (ну как бы именно здесь это единственная таблица с 10-ю колонками, а если нет) , а потом еще одной регуляркой дергаю из нее все поля исключая содержимое любого <...>
Но это как бы обычная практика разбора текста...
А я все таки питал надежды поработать с HTML как с объектом.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
OffTopic:
madmasles
Kaster
Вам не кажется что тема в неправильном разделе? :whistle:
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR [?]
Вам не кажется что тема в неправильном разделе?
И правда, переношу. :-[

RUVATA,
Вот что у меня получилось с Вашим файлом:
Код:
#include <Array.au3>

$iCountX = 0
$iCountY = 0
$fSearch = False
$sFile = @ScriptDir & '\Detalization_for_2057867.HTML'

$sText = FileRead($sFile)

$sHead = StringRegExpReplace($sText, '(?s).*<DIV class="st4">(.*?)</DIV>.*', '$1')
If @extended <> 1 Then $sHead = ''
$aTemp = StringRegExp($sText, '<span class="st\d+.*?>(.*?)</span>', 3)
If Not @error Then
	For $i = 0 To UBound($aTemp) - 1
		$sHead &= ', ' & $aTemp[$i]
	Next
EndIf

$aTemp = StringRegExp($sText, '<TD class="st\d+.*?>(.*?)</TD>', 3)
If @error Then
	MsgBox(16, 'Error', 'StringRegExp')
	Exit
EndIf

Dim $aRes[UBound($aTemp)][9]

For $i = 0 To UBound($aTemp) - 1
	If $fSearch Then
		If Not $iCountY Then $iCountX += 1
		If $iCountX > 1 Then
			If $iCountY = 2 Then $aTemp[$i] = StringReplace($aTemp[$i], '&lt;', '<')
			Switch $iCountY
				Case 0 To 6
					$aRes[$iCountX][$iCountY] = $aTemp[$i]
				Case 8, 9
					$aRes[$iCountX][$iCountY - 1] = $aTemp[$i]
			EndSwitch
			$iCountY += 1
			If $iCountY = 10 Then $iCountY = 0
		Else
			$aRes[$iCountX][$iCountY] = $aTemp[$i]
			$iCountY += 1
			If $iCountY = 9 Then $iCountY = 0
		EndIf
	Else
		If StringInStr($aTemp[$i], 'Сведения о разговорах') Then
			$fSearch = True
		EndIf
	EndIf
Next
For $i = 0 To 8
	If Not StringIsSpace($aRes[$iCountX][$i]) Then
		$aRes[0][7] = 'Итого:'
		$aRes[0][8] = StringStripWS($aRes[$iCountX][$i], 8)
		ExitLoop
	EndIf
Next
ReDim $aRes[$iCountX][9]
$aRes[0][0] = $iCountX - 2
_ArrayDisplay($aRes, $sHead)


Можно через IE.
Код:
#include <IE.au3>
#include <Array.au3>

$sUrl = @ScriptDir & '\Detalization_for_2057867.HTML'
$oIE = _IECreate($sUrl)
$oTables = _IETableGetCollection($oIE)
ConsoleWrite(@extended & @LF)
$i = 0
For $oTable In $oTables
	ConsoleWrite(StringLeft($oTable.innertext, 200) & @LF)
	ConsoleWrite('---' & @LF)
	$aTableData = _IETableWriteToArray($oTable, True)
	_ArrayDisplay($aTableData, 'Index: ' & $i)
	$i += 1
Next
_IEQuit($oIE)
И собрать нужные данные в один массив.
 
Автор
R

RUVATA

лучше один раз увидеть, чем десять раз услышать...
Сообщения
132
Репутация
38

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

Creator сказал(а):
Вам не кажется что тема в неправильном разделе?
Ну теперь безусловно, эта тема относится к регулярным выражениям, хотя изначально я интересовался:

хочу попросить пролить свет озарения на мои познания в отношении разбора html в AutoIT, как это делать правильнее, какие вообще методы существуют ?
а в основном
А я все таки питал надежды поработать с HTML как с объектом.

Расскажите пожалуйста кто что знает про "Shell.Explorer.2", мне пока стало ясно, что это действительно модуль IE, который как раз предназначен для парсинга HTML, он показывает наружу для OLE весьма занятные объекты и методы ".document.Write($something)" / ".document.documentElement.outerHTML()" очень напоминает JavaScript.
 
Автор
R

RUVATA

лучше один раз увидеть, чем десять раз услышать...
Сообщения
132
Репутация
38
Регулярные выражения - определенно !!!
остальное (в смысле через OLE Shell.Explorer.2 или InternetExplorer.Application ) - костыли...
в основном из-за того, что работать в финале приходится с объектами имеющими неизвестную структуру, набор методов и свойств,
который как и принято в IE не бьет со стандартами обращения к DOM...
Да и собственно туган у AutoIt с типизацией, так как некоторые методы/свойства возвращают значения которые... в общем все это заканчивается autoit error:variable must be of type "object"
и с чем это связано непонятно, т.к. VBscript спокойно отрабатывает с такими-же конструкциями обращений к тому-же объекту.
Ну да это совсем не повод печалиться, т.к. Регулярные выражения в данном случае самый верный и экономичный путь...
 
Верх