Автор Тема: Простой парсер HTML кода HTMLFILE  (Прочитано 40451 раз)

0 Пользователей и 2 Гостей просматривают эту тему.

Оффлайн inververs [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 2135
  • Репутация: 460
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.12.0
Простой парсер HTML кода HTMLFILE
« Создано: Декабрь 23, 2013, 18:19:27 »
В замен парсеру на регулярных выражениях html кода есть более удобный инструмент как объект HTMLDocument.
Создается так:
Код: AutoIt [Выделить]
$oHTML = ObjCreate("HTMLFILE")

Позволяет загрузить html код и получать доступ к свойствам и методам.
Все свойства можно найти здесь:
http://msdn.microsoft.com/en-us/library/ms535862
или здесь
http://www.w3schools.com/jsref/dom_obj_document.asp
или же пользоваться функциями из библиотеки IE.au3

Основной метод это write - который загружает html код.

Вот например, получение расположения всех картинок нашего форума:
Код: AutoIt [Выделить]
Local $oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
$oHTTP.Open("GET", "http://autoit-script.ru/")
$oHTTP.Send()
Local $HTMLSource = $oHTTP.Responsetext

Local $oHTML = ObjCreate("HTMLFILE")
$oHTML.Write($HTMLSource)
Local $imgs = $oHTML.images
For $img in $imgs
    ConsoleWrite($img.src & @LF)
Next




Добавлено: Декабрь 23, 2013, 18:43:58

Функции из библиотеки Ie.au3


Код: AutoIt [Выделить]
#include <IE.au3>
$imgs = _IETagNameGetCollection ( $oHTML, 'img')
For $img in $imgs
    ConsoleWrite($img.src & @LF)
Next


Получим объект Window, для передачи его в функцию _IEGetObjByName
Код: AutoIt [Выделить]
Local $oWindow = $oHTML.parentWindow


Получим приветствие:
Код: AutoIt [Выделить]
Local $oLi = _IEGetObjByName($oWindow,'name')
ConsoleWrite($oLi.InnerText & @LF)


Если весь текст форума без тэгов
Код: AutoIt [Выделить]

Русское сообщество AutoIt

Простой парсер HTML кода HTMLFILE
« Отправлен: Декабрь 23, 2013, 18:19:27 »

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7809
  • Репутация: 2281
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Re: Простой парсер HTML кода
« Ответ #1, Отправлен: Февраль 06, 2015, 23:40:03 »
Можно с помощью этой штуки получить типа дерево тегов, или получать данные как то так:

Код: AutoIt [Выделить]
$oHTML.getElementById("some_id").Div.P.A.Href


 :think:?


Правила, Поиск, Супер тема


AutoIt is simple, subtle, elegant.


«Не оказываю тех. поддержку через ПМ/ICQ, и по электронной почте - для этого есть форум. (C)»
«Законы Мэрфи неоспоримы!»


Мои работы

Оффлайн firex [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 940
  • Репутация: 202
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: Простой парсер HTML кода
« Ответ #2, Отправлен: Февраль 06, 2015, 23:57:01 »
Код: AutoIt [Выделить]
$oHTML.getElementById("some_id").GetElementsByTagName("div") ;Это уже потенциальная коллекция


В любом случае вы не обойдетесь без вложенных циклов с вашей задачей.

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7809
  • Репутация: 2281
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Re: Простой парсер HTML кода
« Ответ #3, Отправлен: Февраль 07, 2015, 01:06:16 »
А как можно получить объект по его классу?
я знаю что есть getElementsByClassName, но оно работает только в IE 9+, у меня же стоит 8.


Нашёл, это classname.
« Последнее редактирование: Февраль 07, 2015, 01:14:48 от CreatoR »

Русское сообщество AutoIt

Re: Простой парсер HTML кода
« Ответ #3 Отправлен: Февраль 07, 2015, 01:06:16 »

Оффлайн madmasles [?]

  • Глобальный модератор
  • *
  • Сообщений: 7790
  • Репутация: 2314
  • Пол: Мужской
  • Награды За модерирование форума
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: Простой парсер HTML кода
« Ответ #4, Отправлен: Февраль 07, 2015, 01:12:38 »
CreatoR  [?]
Цитировать
как можно получить объект по его классу?
Можно примерно так, у меня тоже 8:
(нажмите для показа/скрытия)
« Последнее редактирование: Февраль 07, 2015, 01:20:04 от madmasles »

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7809
  • Репутация: 2281
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Re: Простой парсер HTML кода
« Ответ #5, Отправлен: Февраль 07, 2015, 02:46:56 »
Пытаюсь построить на основе этой штуки некую функцию, чтобы легче обрабатывать Html, вот пример:

Код: AutoIt [Выделить]
$sHtml = _
    '<body>' & @CRLF & _
    '   <span id="links">' & @CRLF & _
    '       <a id="some" name="123">test1</a>' & @CRLF & _
    '       <a id="link" class="link" href="http://test.com">test2</a>' & @CRLF & _
    '   </span>' & @CRLF & _
    '   <span id="links">' & @CRLF & _
    '       <a id="some" name="123">test3</a>' & @CRLF & _
    '       <a id="link" class="link" href="http://test.com">test4</a>' & @CRLF & _
    '   </span>' & @CRLF & _
    '</body>'

$oHTML = _HtmlDOM_Init($sHtml)
$oTree = _HtmlDOM_GetElementByTree($oHTML, 'body//span{links}(0)//a{link}')
$sResult = _HtmlDOM_GetProperty($oTree, 'Html')

ConsoleWrite($sResult & @LF)

Func _HtmlDOM_Init($sHtml)
    Local $oHTML = ObjCreate('HTMLFILE')
   
    If Not IsObj($oHTML) Then
        Return SetError(1, 0, 0)
    EndIf
   
    $oHTML.Write($sHtml)
    Return $oHTML
EndFunc

Func _HtmlDOM_GetElementByTree($oHTML, $sTree)
    If Not IsObj($oHTML) Then
        Return SetError(1, 0, 0)
    EndIf
   
    Local $aTree, $sTag, $sAttrib, $iNode
    Local $oTree_Tmp = 0
    Local $oTree = $oHTML
   
    $aTree = StringSplit($sTree, '//', 1)
   
    For $i = 1 To $aTree[0]
        $sTag = StringRegExpReplace($aTree[$i], '^([^{(]+).*', '\1')
        If @extended = 0 Then ContinueLoop
       
        $sAttrib = StringRegExpReplace($aTree[$i], '^[^{(]+{([^}]+)}.*', '\1')
        If @extended = 0 Then $sAttrib = ''
       
        $iNode = Number(StringRegExpReplace($aTree[$i], '^[^{(]+(?:{[^}]+})?\((\d+)\)', '\1'))
       
        ;Current node have no tags attributes
        If $sAttrib = '' Then
            $oTree_Tmp = $oTree.getElementsByTagName($sTag)
           
            If IsObj($oTree_Tmp) Then
                $oTree = $oTree_Tmp($iNode)
            EndIf
           
            ContinueLoop
        EndIf
       
        $oTree_Tmp = $oTree.getElementById($sAttrib)
       
        ConsoleWrite($oTree.NodeName & @TAB & $sAttrib & @TAB & ' Attrib found = ' & (IsObj($oTree_Tmp) = 1) & @LF)
       
        ;If current element found with specified attrib (id/class/name), the assign it and continue with next node
        If IsObj($oTree_Tmp) Then
            $oTree = $oTree_Tmp
            ContinueLoop
        EndIf
       
        ;Search by tag name
        $oTree_Tmp = $oTree.getElementsByTagName($sTag)
       
        If IsObj($oTree_Tmp) Then
            For $oTag In $oTree_Tmp
                If $oTag.ID = $sAttrib Or $oTag.ClassName = $sAttrib Or $oTag.Name = $sAttrib Then
                    $oTree = $oTag
                    ContinueLoop 2
                EndIf
            Next
           
            $oTree = $oTree_Tmp($iNode)
        EndIf
    Next
   
    Return $oTree
EndFunc

Func _HtmlDOM_GetProperty($oHTML, $sProperty, $sInnerOuter = 'Inner')
    If Not IsObj($oHTML) Then
        Return SetError(1, 0, 0)
    EndIf
   
    Switch $sProperty
        Case 'Html'
            Return ($sInnerOuter = 'Inner' ? $oHTML.InnerHtml : $oHTML.OuterHtml)
        Case 'Text'
            Return ($sInnerOuter = 'Inner' ? $oHTML.InnerText : $oHTML.OuterText)
    EndSwitch
EndFunc


Здесь я ожидаю на выходе test2, но почему то получаю test1 :think:.
Идея в том, чтобы одним вызовом получить объект указанного элемента используя древовидную структуру.

body//span{links}(0)//a{link}тут дерево разделено //, каждый элемент это тег, далее его атрибуты (id/class/name), и в конце номер элемента (если найдено несколько одинаковых).

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7809
  • Репутация: 2281
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Re: Простой парсер HTML кода
« Ответ #6, Отправлен: Февраль 07, 2015, 03:33:57 »
Вот оно! :laugh:

Код: AutoIt [Выделить]
$sHTML = _
    '<body>' & @CRLF & _
    '   <span id="links">' & @CRLF & _
    '       <a id="some" name="123">test1</a>' & @CRLF & _
    '       <a id="link" class="link" href="http://test.com">test2</a>' & @CRLF & _
    '   </span>' & @CRLF & _
    '   <span id="links">' & @CRLF & _
    '       <a id="some" name="123">test3</a>' & @CRLF & _
    '       <a id="link" class="link" href="http://test.com">test4</a>' & @CRLF & _
    '   </span>' & @CRLF & _
    '</body>'

$oHTML = _HtmlDOM_Init($sHTML)

$oTree = _HtmlDOM_GetElementByTree($oHTML, 'span{links}(0)//a{link}')
$sResult = _HtmlDOM_GetProperty($oTree, 'Html') ;test2
ConsoleWrite($sResult & @LF)

$oTree = _HtmlDOM_GetElementByTree($oHTML, 'span{links}(1)//a{link}')
$sResult = _HtmlDOM_GetProperty($oTree, 'Html') ;test4
ConsoleWrite($sResult & @LF)

_HtmlDOM_UnInit($oHTML)

Func _HtmlDOM_Init($sHTML)
    Local $oHTML = ObjCreate('HTMLFILE')
   
    If Not IsObj($oHTML) Then
        Return SetError(1, 0, 0)
    EndIf
   
    $oHTML.Write($sHTML)
    Return $oHTML
EndFunc

Func _HtmlDOM_UnInit($oHTML)
    If Not IsObj($oHTML) Then
        Return SetError(1, 0, 0)
    EndIf
   
    $oHTML.Close
EndFunc

Func _HtmlDOM_GetElementByTree($oHTML, $sTree)
    If Not IsObj($oHTML) Then
        Return SetError(1, 0, 0)
    EndIf
   
    Local $aTree, $sTag, $sAttrib, $iNode
    Local $oTree_Tmp = 0, $oTag = 0
    Local $oTree = $oHTML
   
    $aTree = StringSplit($sTree, '//', 1)
   
    For $i = 1 To $aTree[0]
        $sTag = StringRegExpReplace($aTree[$i], '^([^{(]+).*', '\1')
        If @extended = 0 Then ContinueLoop
       
        $sAttrib = StringRegExpReplace($aTree[$i], '^[^{(]+{([^}]+)}.*', '\1')
        If @extended = 0 Then $sAttrib = ''
       
        $iNode = StringRegExpReplace($aTree[$i], '^[^{(]+(?:{[^}]+})?\((\d+)\)', '\1')
       
        If @extended = 0 Then
            $iNode = ''
        Else
            $iNode = Number($iNode)
        EndIf
       
        ;Current node have no tags attributes
        If $sAttrib = '' Then
            $oTree_Tmp = $oTree.GetElementsByTagName($sTag)
           
            If IsObj($oTree_Tmp) Then
                If $iNode == '' Then $iNode = 0
                $oTree = $oTree_Tmp($iNode)
            EndIf
           
            ContinueLoop
        EndIf
       
        ;Search by tag name
        $oTree_Tmp = $oTree.GetElementsByTagName($sTag)
       
        If IsObj($oTree_Tmp) Then
            If $iNode == '' Then
                For $oTag In $oTree_Tmp
                    If ($oTag.ID And $oTag.ID = $sAttrib) Or ($oTag.ClassName And $oTag.ClassName = $sAttrib) Or ($oTag.Name And $oTag.Name = $sAttrib) Then
                        $oTree = $oTag
                        ExitLoop
                    EndIf
                Next
            Else
                $oTag = $oTree_Tmp($iNode)
               
                If ($oTag.ID And $oTag.ID = $sAttrib) Or ($oTag.ClassName And $oTag.ClassName = $sAttrib) Or ($oTag.Name And $oTag.Name = $sAttrib) Then
                    $oTree = $oTag
                EndIf
            EndIf
        EndIf
    Next
   
    Return $oTree
EndFunc

Func _HtmlDOM_GetProperty($oHTML, $sProperty, $sInnerOuter = 'Inner')
    If Not IsObj($oHTML) Then
        Return SetError(1, 0, 0)
    EndIf
   
    Switch $sProperty
        Case 'Html'
            Return ($sInnerOuter = 'Inner' ? $oHTML.InnerHtml : $oHTML.OuterHtml)
        Case 'Text'
            Return ($sInnerOuter = 'Inner' ? $oHTML.InnerText : $oHTML.OuterText)
    EndSwitch
EndFunc


Оффлайн inververs [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 2135

  • Автор темы
  • Репутация: 460
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.12.0
Re: Простой парсер HTML кода
« Ответ #7, Отправлен: Февраль 07, 2015, 10:56:54 »
Такая функция вряд ли будет нужна, т.к есть более мощный  queryselector который позволяет найти практически любой элемент. А если уже и делать, то это функцию получающую элементы по XPath.

Русское сообщество AutoIt

Re: Простой парсер HTML кода
« Ответ #7 Отправлен: Февраль 07, 2015, 10:56:54 »

Оффлайн madmasles [?]

  • Глобальный модератор
  • *
  • Сообщений: 7790
  • Репутация: 2314
  • Пол: Мужской
  • Награды За модерирование форума
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: Простой парсер HTML кода
« Ответ #8, Отправлен: Февраль 07, 2015, 11:11:03 »
inververs  [?]
Цитировать
Такая функция вряд ли будет нужна, т.к есть более мощный  queryselector который позволяет найти практически любой элемент. А если уже и делать, то это функцию получающую элементы по XPath.
А можно пример для IE8?

Оффлайн inververs [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 2135

  • Автор темы
  • Репутация: 460
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.12.0
Re: Простой парсер HTML кода
« Ответ #9, Отправлен: Февраль 07, 2015, 11:15:33 »
madmasles  [?]
Цитировать
А можно пример для IE8?
Откройте консоль браузера и напишите  к примеру document.querySelector('p') сработает? если нет, то в IE8 не поддерживает. Нужно обновляться хотя бы до 9, а в идеале до 11 версии

Оффлайн madmasles [?]

  • Глобальный модератор
  • *
  • Сообщений: 7790
  • Репутация: 2314
  • Пол: Мужской
  • Награды За модерирование форума
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: Простой парсер HTML кода
« Ответ #10, Отправлен: Февраль 07, 2015, 11:34:12 »
inververs,
Проверил, в IE8 не работает, увы...

Оффлайн inververs [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 2135

  • Автор темы
  • Репутация: 460
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.12.0
Re: Простой парсер HTML кода
« Ответ #11, Отправлен: Февраль 07, 2015, 11:36:36 »
madmasles  [?]
Цитировать
Проверил, в IE8 не работает, увы...
Ясно, ну ничего. Всегда можно обойтись другими средствами. Но хочу сказать, что IE8, 9, 10 нужно забыть и не использовать.

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7809
  • Репутация: 2281
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Re: Простой парсер HTML кода
« Ответ #12, Отправлен: Февраль 07, 2015, 13:51:04 »
inververs  [?]
Цитировать
IE8, 9, 10 нужно забыть и не использовать.
А если я пишу не для себя, не могу же принудить народ обновлять IE только для того, чтобы мой софт работал.

И вообще, нужен такой инструмент который бы не работал вообще с IE, а с собственным движком.

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7809
  • Репутация: 2281
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Re: Простой парсер HTML кода
« Ответ #13, Отправлен: Февраль 07, 2015, 14:12:11 »
inververs  [?]
Цитировать
если уже и делать, то это функцию получающую элементы по XPath.
Во, это я и хотел сделать, забыл как эта штука называется  :).

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7809
  • Репутация: 2281
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Re: Простой парсер HTML кода
« Ответ #14, Отправлен: Февраль 07, 2015, 22:12:02 »
Не могу понять, как тут получить все атрибуты определённого узла?

Код: AutoIt [Выделить]
$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.Write($sHTML)

$oAttribs = $oHTML.GetElementById('user').Attributes()

For $oAttrib In $oAttribs
    ConsoleWrite($oAttrib.Name & '=' & $oAttrib.Value & @LF)
Next


У меня это выдаёт кучу атрибутов, я так понял всевозможные, но как мне получить только те что относятся к найденному (по id) элементу?

Русское сообщество AutoIt

Re: Простой парсер HTML кода
« Ответ #14 Отправлен: Февраль 07, 2015, 22:12:02 »

 

Похожие темы

  Тема / Автор Ответов Последний ответ
4 Ответов
6616 Просмотров
Последний ответ Апрель 23, 2012, 19:14:27
от ggzgamer
5 Ответов
2911 Просмотров
Последний ответ Октябрь 31, 2014, 14:07:45
от denispuh
1 Ответов
2302 Просмотров
Последний ответ Апрель 20, 2013, 21:12:41
от sngr
3 Ответов
1967 Просмотров
Последний ответ Сентябрь 28, 2013, 13:38:52
от bdkitty
0 Ответов
714 Просмотров
Последний ответ Июль 24, 2014, 19:17:23
от e.belykh
6 Ответов
1791 Просмотров
Последний ответ Февраль 05, 2015, 11:44:42
от darkwhite
8 Ответов
2795 Просмотров
Последний ответ Март 06, 2015, 21:17:45
от Nosfer_x
30 Ответов
14140 Просмотров
Последний ответ Апрель 26, 2015, 11:54:58
от Garrett
0 Ответов
895 Просмотров
Последний ответ Апрель 22, 2015, 17:49:49
от madmasles
1 Ответов
3073 Просмотров
Последний ответ Июнь 22, 2015, 13:17:44
от madmasles