Что нового

Простой парсер HTML кода HTMLFILE

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Простой парсер HTML кода

madmasles [?]
И Name, и Value вроде могут быть с пробелами, типа
А как тогда разделяются атрибуты? если я не ошибаюсь, только значение может иметь пробелы, и это при том, что оно обрамлено кавычками.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Re: Простой парсер HTML кода

CreatoR [?]
если я не ошибаюсь, только значение может иметь пробелы, и это при том, что оно обрамлено кавычками.
Вы правы, Name с пробелами не определяется, значит, должен быть одним словом.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Простой парсер HTML кода

Поправил свой пример выше, теперь корректно обрабатывает атрибуты без значении.
Если значение атрибута имеет пробелы, то оно должно обрамляться кавычками, иначе всё что после пробела, будет интерпретироваться как другой атрибут (так оно работает в Html).
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Re: Простой парсер HTML кода

CreatoR,
Пол ночи искал, как проверить через какое-нибудь свойство, отображается ли атрибут в теге или использует значение по умолчанию и не отображается, но не нашел такого свойства. Похоже, Ваш способ решает этот вопрос.
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Re: Простой парсер HTML кода

Вот так аттрибуты можно получить:
Код:
$tag = '<img src="http://autoit-script.ru/Themes/default/images/icons/modify_inline.gif" alt="Редактировать сообщение" title="Редактировать сообщение" class="modifybutton" id="modify_button_71833" style="cursor: pointer;" onclick="oQuickModify.modifyMsg(''71833'')">';
$document = ObjCreate('HtmlFile')
$document.write($tag)
$attributes = $document.GetElementById('modify_button_71833').Attributes
For $item = 0 To $attributes.length - 1
	ConsoleWrite($attributes.item($item).name  & '=' & $attributes.item($item).Value & @CRLF)
Next

Код:
title=Редактировать сообщение
class=modifybutton
id=modify_button_71833
style=cursor: pointer;
onclick=oQuickModify.modifyMsg('71833')
alt=Редактировать сообщение
src=http://autoit-script.ru/Themes/default/images/icons/modify_inline.gif
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Re: Простой парсер HTML кода

inververs,
У меня с Вашим кодом (IE8) вот такая простыня:
Код:
onresizeend=null
onrowenter=null
aria-haspopup=
ondragleave=null
onbeforepaste=null
ondragover=null
onbeforecopy=null
aria-disabled=
onpage=null
onbeforeactivate=null
accessKey=
onbeforeeditfocus=null
oncontrolselect=null
aria-hidden=
onblur=null
hideFocus=false
style=null
onbeforedeactivate=null
dir=
aria-expanded=
onkeydown=null
ondragstart=null
onscroll=null
onpropertychange=null
ondragenter=null
id=modify_button_71833
aria-level=0
onrowsinserted=null
lang=
onmouseup=null
aria-busy=
oncontextmenu=null
language=
dataSrc=
implementation=null
onbeforeupdate=null
onreadystatechange=null
onmouseenter=null
onresize=null
aria-checked=
aria-readonly=
oncopy=null
onselectstart=null
onmove=null
ondragend=null
onrowexit=null
aria-secret=
onactivate=null
class=modifybutton
onfocus=null
onfocusin=null
onmouseover=null
oncut=null
onmousemove=null
title=Редактировать сообщение
role=
dataFld=
onfocusout=null
onfilterchange=null
disabled=false
aria-posinset=0
ondrop=null
ondblclick=null
onrowsdelete=null
tabIndex=0
onkeypress=null
aria-relevant=
onlosecapture=null
aria-live=
ondeactivate=null
aria-labelledby=
aria-pressed=
ondatasetchanged=null
ondataavailable=null
aria-invalid=
onafterupdate=null
onmousewheel=null
onkeyup=null
onmovestart=null
aria-valuenow=
aria-selected=
onmouseout=null
aria-owns=
aria-valuemax=
onmoveend=null
contentEditable=inherit
dataFormatAs=
oncellchange=null
aria-valuemin=
onlayoutcomplete=null
onhelp=null
onerrorupdate=null
onmousedown=null
aria-setsize=0
onpaste=null
onmouseleave=null
onclick=oQuickModify.modifyMsg('71833')
ondrag=null
aria-controls=
onresizestart=null
aria-flowto=
ondatasetcomplete=null
aria-required=
aria-describedby=
onbeforecut=null
aria-activedescendant=
aria-multiselectable=
border=
lowsrc=
name=
hspace=0
alt=Редактировать сообщение
vspace=0
onerror=null
align=
loop=1
onabort=null
src=http://autoit-script.ru/Themes/default/images/icons/modify_inline.gif
isMap=false
width=0
start=fileopen
vrml=
dynsrc=
longDesc=
onload=null
height=0
useMap=
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Re: Простой парсер HTML кода

CreatoR [?]
но как мне получить только те что относятся к найденному (по id) элементу?
Код:
$sHTML = _
    '<body>' & @CRLF & _
    '   <span id="users">' & @CRLF & _
    '       <div id="user">User1</div>' & @CRLF & _
    '       <div id="user">User2</div>' & @CRLF & _
    '       <div id="user">User3</div>' & @CRLF & _
    '   </span>' & @CRLF & _
    '   <span id="logins" class="logins">' & @CRLF & _
    '       <div id="login">login1</div>' & @CRLF & _
    '       <div id="login">login2</div>' & @CRLF & _
    '       <div id="login">login3</div>' & @CRLF & _
    '   </span>' & @CRLF & _
    '</body>'

$oHTML = ObjCreate('HtmlFile')
$oHTML.Open
$oHTML.Write($sHTML)
$oHTML.Close

$oAllCollection = $oHTML.all
$oUsersCollection = $oAllCollection.users.children
ConsoleWrite(StringFormat('--> users: [%d]\n', $oUsersCollection.length))

For $oUser In $oUsersCollection
	ConsoleWrite(StringFormat('> id: %s --> %s\n', $oUser.id, $oUser.innerText))
Next

$oLoginsCollection = $oAllCollection.logins.children
ConsoleWrite(StringFormat('--> logins: [%d]\n', $oLoginsCollection.length))

For $oLogin In $oLoginsCollection
	ConsoleWrite(StringFormat('> id: %s --> %s\n', $oLogin.id, $oLogin.innerText))
Next



Добавлено:
Сообщение автоматически объединено:

CreatoR
Кстати, id индивидуален для каждого элемента.
В вашем примере, лучше использовать class="user" и class="login".


Добавлено:
Сообщение автоматически объединено:

Как пример:
Код:
$sHTML = _
    '<body>' & @CRLF & _
    '   <span id="class_1a" class="reinforced_english">' & @CRLF & _
    '       <div class="children">User1</div>' & @CRLF & _
    '       <div class="children">User2</div>' & @CRLF & _
    '       <div class="children">User3</div>' & @CRLF & _
    '   </span>' & @CRLF & _
    '   <span id="class_1b" class="reinforced_french">' & @CRLF & _
    '       <div class="children">User1</div>' & @CRLF & _
    '       <div class="children">User2</div>' & @CRLF & _
    '       <div class="children">User3</div>' & @CRLF & _
    '   </span>' & @CRLF & _
    '   <span id="class_1c" class="reinforced_french">' & @CRLF & _
    '       <div class="children">User1</div>' & @CRLF & _
    '       <div class="children">User2</div>' & @CRLF & _
    '       <div class="children">User3</div>' & @CRLF & _
    '   </span>' & @CRLF & _
    '</body>'
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Простой парсер HTML кода

Сделал некую библиотеку псевдо XPath :laugh: (см. вложение).
 

Вложения

  • HtmlXPath.zip
    2.4 КБ · Просмотры: 24

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Простой парсер HTML кода

И потом понял, что зря...

Код:
$sHTML = _
	'<body>' & @CRLF & _
	'	<span id="users" class="users">' & @CRLF & _
	'		<div id="user">User1</div>' & @CRLF & _
	'		<div id="user" class="user">User2</div>' & @CRLF & _
	'		<div id="user" class="user">User3</div>' & @CRLF & _
	'	</span>' & @CRLF & _
	'	<span id="logins" class="logins">' & @CRLF & _
	'		<div id="login">login1</div>' & @CRLF & _
	'		<div id="login">login2</div>' & @CRLF & _
	'		<div id="login">login3</div>' & @CRLF & _
	'	</span>' & @CRLF & _
	'</body>'


$sXPath = '*/span[(@id="users" or @class="users")]/div[@id="user"][1]'
$oNode = _XHtmlXPath_SelectNode($sHTML, $sXPath)

ConsoleWrite(_XHtmlXPath_GetNodeValue($oNode) & @LF)

Func _XHtmlXPath_SelectNode($sXHTML, $sXPath)
	Local $oXMLDOM = ObjCreate('Msxml2.DOMDocument.3.0')
	
	If Not IsObj($oXMLDOM) Then
		Return SetError(1, 0, 0)
	EndIf
	
	$oXMLDOM.loadXML($sXHTML)
	Return $oXMLDOM.selectSingleNode($sXPath)
EndFunc

Func _XHtmlXPath_GetNodeValue($oNode, $sValue = 'Text')
	If Not IsObj($oNode) Then
		Return SetError(1, 0, 0)
	EndIf
	
	If $sValue = 'Text' Then
		Return $oNode.Text
	EndIf
	
	Return $oNode.Xml
EndFunc


Мораль - не изобретайте велосипед!!!
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Простой парсер HTML кода

А нет, не зря.
Msxml2.DOMDocument не работает с реальным Html полученным с интернета (к примеру тот же autoitscript.com).
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Простой парсер HTML кода

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

Код:
$oHTML = ObjCreate('HTMLFILE')
If Not IsObj($oHTML) Then Exit

$sHTML = BinaryToString(InetRead('http://devid.info/en/search?text=dell'))

$oHTML.Write($sHTML)

$oList = $oHTML.GetElementById('os-list-6.1')
$oItems = $oList.childNodes

ConsoleWrite($oItems.length & @LF)

For $oItem In $oItems
	If $oItem.Attributes('class').Value == 'item-box' Then
		ConsoleWrite($oItem.innertext & @LF)
	EndIf
Next


Система Win7 X64 Rus (AutoIt 3.3.6.1 -> 3.3.12.0 x86, хотя и под x64 тоже самое).
IE8.
Кто то может проверить у себя? запускать по несколько раз, у меня раза со второго-третьего скрипт намертво повисает.
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Re: Простой парсер HTML кода

CreatoR
Виной тому InetRead. Меняйте на альтернативные методы.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Простой парсер HTML кода

firex [?]
Виной тому InetRead
Я записал в файл то что получил с инета, далее читаю с файла, но результат тот же.
В чём проблематичность InetRead?

Да и ещё, когда зависает, система иногда выдаёт вот такое сообщение:

 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Простой парсер HTML кода

Попробовал со всеми мне известными методами получения Html, вывод однозначный - дело не в этом.

Дело в размере получаемой информации, нужно проверить есть ли ограничения у этого объекта...

Обновление
Для инициализации Html, нужно использовать не .Write($sHtml), а .Body.InnerHtml = $sHtml!
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Re: Простой парсер HTML кода

CreatoR
Почему вы избегаете методов open и close?
Код:
$oHTML.Open
$oHTML.Write($sHTML)
$oHTML.Close

Кто то может проверить у себя?
У меня скрипт отрабатывает без проблем. Win7 X64, WinXP SP2
Код:
$oHTML = ObjCreate('HTMLFILE')
If Not IsObj($oHTML) Then Exit

$sHTML = BinaryToString(InetRead('http://devid.info/en/search?text=dell'))

$oHTML.Open
$oHTML.Write($sHTML)
$oHTML.Close

$oList = $oHTML.GetElementById('os-list-6.1')
$oItems = $oList.childNodes

ConsoleWrite($oItems.length & @LF)

For $oItem In $oItems
    If $oItem.Attributes('class').Value == 'item-box' Then
        ConsoleWrite($oItem.innertext & @LF)
    EndIf
Next
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Простой парсер HTML кода

Garrett [?]
Почему вы избегаете методов open и close?
Я это использовал, просто в примере забыл указать.
У меня с этим скрипт зависает (не всегда).
А с .Body.InnerHtml = $sHtml - нет.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Re: Простой парсер HTML кода

CreatoR [?]
А с .Body.InnerHtml = $sHtml - нет.
Код:
$oHTML = ObjCreate('HTMLFILE')
If Not IsObj($oHTML) Then Exit

$oHTML.Open

#Region Пример 1
;~ $oHTML.Write("<div>Hi!</div>")
#EndRegionПример 1

#Region Пример 2
$oHTML.Body.InnerHtml = "<p>Hi!</p>" ; НЕ правильно! (поэтому и не виснет)
#EndRegionПример 2

#Region Пример 3
;~ $oHTML.Body
;~ $oHTML.Write("<div>Hi!</div>")
#EndRegionПример 3

$oHTML.Close

ConsoleWrite(StringFormat("> Body Outer Html: --> %s\n", (Not StringStripWS($oHTML.Body.OuterHtml, 3)) ? "не правильно" : StringStripWS($oHTML.Body.OuterHtml, 3)))
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Простой парсер HTML кода

Ну а как оно работает если неправильно?

Код:
$oHTML = ObjCreate('HTMLFILE')
If Not IsObj($oHTML) Then Exit

$oHTML.body.InnerHtml = "<p id='test'>Hi!</p><p id='0'>buy</p>"

ConsoleWrite($oHTML.GetElementById('test').innertext & @LF)


Просто Open/Close не нужно в этом случае.
 
Верх