Blog. Just Blog

Получение кода HTML-страницы и отдельных тегов

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Получение кода HTML-страницы и отдельных тегов
Получение кода HTML-страницы и отдельных тегов

Ранее мы уже познакомились с такой интересной штукой, как встроенный браузер на Ассемблере. Но его применение именно в таком виде весьма ограниченно. А вот работа с исходным текстом загруженной страницы, извлечение из нее данных, взаимодействие с элементами - это совершенно другой уровень полезности.

Начальную теорию можете почитать по приведенной ссылке, чтобы не дублировать, а тут будут материалы по теме статьи. Начнем с получения исходного кода HTML-страницы. Но сперва чуть-чуть теории. После выполнения запроса на открытие ссылки при помощи метода Navigate2, надо определить момент, когда страница будет полностью загружена, чтобы можно было получить ее исходный код. Для этого удобнее всего использовать таймер с коротким интервалом, по которому проверяется статус выполняемого запроса. Когда статус будет иметь значение READYSTATE_COMPLETE или READYSTATE_LOADED, то можно приступать к основной части задачи.

Получить код страницы можно разными способами. Но в любом случае нам понадобится несколько объемных структур.
  1. ; GUID {8856F961-340A-11D0-A96B-00C04FD705A2}
  2. CLSID_WebBrowser dd 08856F961h
  3.                  dw 0340Ah
  4.                  dw 011D0h
  5.                  db 0A9h, 06Bh, 000h, 0C0h, 04Fh, 0D7h, 005h, 0A2h
  6.  
  7. ; GUID {D30C1661-CDAF-11D0-8A3E-00C04FC9E26E}
  8. IID_IWebBrowser2 dd 0D30C1661h
  9.                  dw 0CDAFh
  10.                  dw 011D0h
  11.                  db 08Ah, 03Eh, 000h, 0C0h, 04Fh, 0C9h, 0E2h, 06Eh
  12.  
  13. ; GUID {332C4425-26CB-11D0-B483-00C04FD90119}
  14. IID_IHTMLDocument2 dd 0332C4425h
  15.                    dw 026CBh
  16.                    dw 011D0h
  17.                    db 0B4h, 083h, 000h, 0C0h, 04Fh, 0D9h, 001h, 019h
  18.  
  19. ; GUID {3050F1FF-98B5-11CF-BB82-00AA00BDCE0B}
  20. IID_IHTMLElement dd 03050F1FFh
  21.                  dw 098B5h
  22.                  dw 011CFh
  23.                  db 0BBh, 082h, 000h, 0AAh, 000h, 0BDh, 0CEh, 00Bh
  24.  
  25. ; IID_IWebBrowser2 Interface
  26. struct IWebBrowser2
  27.     ; IUnknown
  28.     QueryInterface           dd ?   ; 000h
  29.     AddRef                   dd ?   ; 004h
  30.     Release                  dd ?   ; 008h
  31.     ; IWebBrowser2
  32.     GetTypeInfoCount         dd ?   ; 00Ch
  33.     GetTypeInfo              dd ?   ; 010h
  34.     GetIDsOfNames            dd ?   ; 014h
  35.     _Invoke                  dd ?   ; 018h
  36.     GoBack                   dd ?   ; 01Ch
  37.     GoForward                dd ?   ; 020h
  38.     GoHome                   dd ?   ; 024h
  39.     GoSearch                 dd ?   ; 028h
  40.     Navigate                 dd ?   ; 02Ch
  41.     Refresh                  dd ?   ; 030h
  42.     Refresh2                 dd ?   ; 034h
  43.     Stop                     dd ?   ; 038h
  44.     get_Application          dd ?   ; 03Ch
  45.     get_Parent               dd ?   ; 040h
  46.     get_Container            dd ?   ; 044h
  47.     get_Document             dd ?   ; 048h
  48.     get_TopLevelContainer    dd ?   ; 04Ch
  49.     get_Type                 dd ?   ; 050h
  50.     get_Left                 dd ?   ; 054h
  51.     put_Left                 dd ?   ; 058h
  52.     get_Top                  dd ?   ; 05Ch
  53.     put_Top                  dd ?   ; 060h
  54.     get_Width                dd ?   ; 064h
  55.     put_Width                dd ?   ; 068h
  56.     get_Height               dd ?   ; 06Ch
  57.     put_Height               dd ?   ; 070h
  58.     get_LocationName         dd ?   ; 074h
  59.     get_LocationURL          dd ?   ; 078h
  60.     get_Busy                 dd ?   ; 07Ch
  61.     Quit                     dd ?   ; 080h
  62.     ClientToWindow           dd ?   ; 084h
  63.     PutProperty              dd ?   ; 088h
  64.     GetProperty              dd ?   ; 08Ch
  65.     get_Name                 dd ?   ; 090h
  66.     get_HWND                 dd ?   ; 094h
  67.     get_FullName             dd ?   ; 098h
  68.     get_Path                 dd ?   ; 09Ch
  69.     get_Visible              dd ?   ; 0A0h
  70.     put_Visible              dd ?   ; 0A4h
  71.     get_StatusBar            dd ?   ; 0A8h
  72.     put_StatusBar            dd ?   ; 0ACh
  73.     get_StatusText           dd ?   ; 0B0h
  74.     put_StatusText           dd ?   ; 0B4h
  75.     get_ToolBar              dd ?   ; 0B8h
  76.     put_ToolBar              dd ?   ; 0BCh
  77.     get_MenuBar              dd ?   ; 0C0h
  78.     put_MenuBar              dd ?   ; 0C4h
  79.     get_FullScreen           dd ?   ; 0C8h
  80.     put_FullScreen           dd ?   ; 0CCh
  81.     Navigate2                dd ?   ; 0D0h
  82.     QueryStatusWB            dd ?   ; 0D4h
  83.     ExecWB                   dd ?   ; 0D8h
  84.     ShowBrowserBar           dd ?   ; 0DCh
  85.     get_ReadyState           dd ?   ; 0E0h
  86.     get_Offline              dd ?   ; 0E4h
  87.     put_Offline              dd ?   ; 0E8h
  88.     get_Silent               dd ?   ; 0ECh
  89.     put_Silent               dd ?   ; 0F0h
  90.     get_RegisterAsBrowser    dd ?   ; 0F4h
  91.     put_RegisterAsBrowser    dd ?   ; 0F8h
  92.     get_RegisterAsDropTarget dd ?   ; 0FCh
  93.     put_RegisterAsDropTarget dd ?   ; 100h
  94.     get_TheaterMode          dd ?   ; 104h
  95.     put_TheaterMode          dd ?   ; 108h
  96.     get_AddressBar           dd ?   ; 10Ch
  97.     put_AddressBar           dd ?   ; 110h
  98.     get_Resizable            dd ?   ; 114h
  99.     put_Resizable            dd ?   ; 118h
  100. ends
  101.  
  102. ; IID_IHTMLDocument2 Interface
  103. struct IHTMLDocument2
  104.     ; IUnknown
  105.     QueryInterface         dd ?   ; 000h
  106.     AddRef                 dd ?   ; 004h
  107.     Release                dd ?   ; 008h
  108.     ; IHTMLDocument2
  109.     GetTypeInfoCount       dd ?   ; 00Ch
  110.     GetTypeInfo            dd ?   ; 010h
  111.     GetIDsOfNames          dd ?   ; 014h
  112.     _Invoke                dd ?   ; 018h
  113.     get_Script             dd ?   ; 01Ch
  114.     get_all                dd ?   ; 020h
  115.     get_body               dd ?   ; 024h
  116.     get_activeElement      dd ?   ; 028h
  117.     get_images             dd ?   ; 02Ch
  118.     get_applets            dd ?   ; 030h
  119.     get_links              dd ?   ; 034h
  120.     get_forms              dd ?   ; 038h
  121.     get_anchors            dd ?   ; 03Ch
  122.     put_title              dd ?   ; 040h
  123.     get_title              dd ?   ; 044h
  124.     get_scripts            dd ?   ; 048h
  125.     put_designMode         dd ?   ; 04Ch
  126.     get_designMode         dd ?   ; 050h
  127.     get_selection          dd ?   ; 054h
  128.     get_readyState         dd ?   ; 058h
  129.     get_frames             dd ?   ; 05Ch
  130.     get_embeds             dd ?   ; 060h
  131.     get_plugins            dd ?   ; 064h
  132.     put_alinkColor         dd ?   ; 068h
  133.     get_alinkColor         dd ?   ; 06Ch
  134.     put_bgColor            dd ?   ; 070h
  135.     get_bgColor            dd ?   ; 074h
  136.     put_fgColor            dd ?   ; 078h
  137.     get_fgColor            dd ?   ; 07Ch
  138.     put_linkColor          dd ?   ; 080h
  139.     get_linkColor          dd ?   ; 084h
  140.     put_vlinkColor         dd ?   ; 088h
  141.     get_vlinkColor         dd ?   ; 08Ch
  142.     get_referrer           dd ?   ; 090h
  143.     get_location           dd ?   ; 094h
  144.     get_lastModified       dd ?   ; 098h
  145.     put_URL                dd ?   ; 09Ch
  146.     get_URL                dd ?   ; 0A0h
  147.     put_domain             dd ?   ; 0A4h
  148.     get_domain             dd ?   ; 0A8h
  149.     put_cookie             dd ?   ; 0ACh
  150.     get_cookie             dd ?   ; 0B0h
  151.     put_expando            dd ?   ; 0B4h
  152.     get_expando            dd ?   ; 0B8h
  153.     put_charset            dd ?   ; 0BCh
  154.     get_charset            dd ?   ; 0C0h
  155.     put_defaultCharset     dd ?   ; 0C4h
  156.     get_defaultCharset     dd ?   ; 0C8h
  157.     get_mimeType           dd ?   ; 0CCh
  158.     get_fileSize           dd ?   ; 0D0h
  159.     get_fileCreatedDate    dd ?   ; 0D4h
  160.     get_fileModifiedDate   dd ?   ; 0D8h
  161.     get_fileUpdatedDate    dd ?   ; 0DCh
  162.     get_security           dd ?   ; 0E0h
  163.     get_protocol           dd ?   ; 0E4h
  164.     get_nameProp           dd ?   ; 0E8h
  165.     write                  dd ?   ; 0ECh
  166.     writeln                dd ?   ; 0F0h
  167.     open                   dd ?   ; 0F4h
  168.     close                  dd ?   ; 0F8h
  169.     clear                  dd ?   ; 0FCh
  170.     queryCommandSupported  dd ?   ; 100h
  171.     queryCommandEnabled    dd ?   ; 104h
  172.     queryCommandState      dd ?   ; 108h
  173.     queryCommandIndeterm   dd ?   ; 10Ch
  174.     queryCommandText       dd ?   ; 110h
  175.     queryCommandValue      dd ?   ; 114h
  176.     execCommand            dd ?   ; 118h
  177.     execCommandShowHelp    dd ?   ; 11Ch
  178.     createElement          dd ?   ; 120h
  179.     put_onhelp             dd ?   ; 124h
  180.     get_onhelp             dd ?   ; 128h
  181.     put_onclick            dd ?   ; 12Ch
  182.     get_onclick            dd ?   ; 130h
  183.     put_ondblclick         dd ?   ; 134h
  184.     get_ondblclick         dd ?   ; 138h
  185.     put_onkeyup            dd ?   ; 13Ch
  186.     get_onkeyup            dd ?   ; 140h
  187.     put_onkeydown          dd ?   ; 144h
  188.     get_onkeydown          dd ?   ; 148h
  189.     put_onkeypress         dd ?   ; 14Ch
  190.     get_onkeypress         dd ?   ; 150h
  191.     put_onmouseup          dd ?   ; 154h
  192.     get_onmouseup          dd ?   ; 158h
  193.     put_onmousedown        dd ?   ; 15Ch
  194.     get_onmousedown        dd ?   ; 160h
  195.     put_onmousemove        dd ?   ; 164h
  196.     get_onmousemove        dd ?   ; 168h
  197.     put_onmouseout         dd ?   ; 16Ch
  198.     get_onmouseout         dd ?   ; 170h
  199.     put_onmouseover        dd ?   ; 174h
  200.     get_onmouseover        dd ?   ; 178h
  201.     put_onreadystatechange dd ?   ; 17Ch
  202.     get_onreadystatechange dd ?   ; 180h
  203.     put_onafterupdate      dd ?   ; 184h
  204.     get_onafterupdate      dd ?   ; 188h
  205.     put_onrowexit          dd ?   ; 18Ch
  206.     get_onrowexit          dd ?   ; 190h
  207.     put_onrowenter         dd ?   ; 194h
  208.     get_onrowenter         dd ?   ; 198h
  209.     put_ondragstart        dd ?   ; 19Ch
  210.     get_ondragstart        dd ?   ; 1A0h
  211.     put_onselectstart      dd ?   ; 1A4h
  212.     get_onselectstart      dd ?   ; 1A8h
  213.     elementFromPoint       dd ?   ; 1ACh
  214.     get_parentWindow       dd ?   ; 1B0h
  215.     get_styleSheets        dd ?   ; 1B4h
  216.     put_onbeforeupdate     dd ?   ; 1B8h
  217.     get_onbeforeupdate     dd ?   ; 1BCh
  218.     put_onerrorupdate      dd ?   ; 1C0h
  219.     get_onerrorupdate      dd ?   ; 1C4h
  220.     toString               dd ?   ; 1C8h
  221.     createStyleSheet       dd ?   ; 1CCh
  222. ends
  223.  
  224. ; IHTMLElement Interface
  225. struct IHTMLElement
  226.     ; IUnknown
  227.     QueryInterface        dd ?   ; 000h
  228.     AddRef                dd ?   ; 004h
  229.     Release               dd ?   ; 008h
  230.     ; IHTMLElement
  231.     GetTypeInfoCount      dd ?   ; 00Ch
  232.     GetTypeInfo           dd ?   ; 010h
  233.     GetIDsOfNames         dd ?   ; 014h
  234.     _Invoke               dd ?   ; 018h
  235.     setAttribute          dd ?   ; 01Ch
  236.     getAttribute          dd ?   ; 020h
  237.     removeAttribute       dd ?   ; 024h
  238.     put_className         dd ?   ; 028h
  239.     get_className         dd ?   ; 02Ch
  240.     put_id                dd ?   ; 030h
  241.     get_id                dd ?   ; 034h
  242.     get_tagName           dd ?   ; 038h
  243.     get_parentElement     dd ?   ; 03Ch
  244.     get_style             dd ?   ; 040h
  245.     put_onhelp            dd ?   ; 044h
  246.     get_onhelp            dd ?   ; 048h
  247.     put_onclick           dd ?   ; 04Ch
  248.     get_onclick           dd ?   ; 050h
  249.     put_ondblclick        dd ?   ; 054h
  250.     get_ondblclick        dd ?   ; 058h
  251.     put_onkeydown         dd ?   ; 05Ch
  252.     get_onkeydown         dd ?   ; 060h
  253.     put_onkeyup           dd ?   ; 064h
  254.     get_onkeyup           dd ?   ; 068h
  255.     put_onkeypress        dd ?   ; 06Ch
  256.     get_onkeypress        dd ?   ; 070h
  257.     put_onmouseout        dd ?   ; 074h
  258.     get_onmouseout        dd ?   ; 078h
  259.     put_onmouseover       dd ?   ; 07Ch
  260.     get_onmouseover       dd ?   ; 080h
  261.     put_onmousemove       dd ?   ; 084h
  262.     get_onmousemove       dd ?   ; 088h
  263.     put_onmousedown       dd ?   ; 08Ch
  264.     get_onmousedown       dd ?   ; 090h
  265.     put_onmouseup         dd ?   ; 094h
  266.     get_onmouseup         dd ?   ; 098h
  267.     get_document          dd ?   ; 09Ch
  268.     put_title             dd ?   ; 0A0h
  269.     get_title             dd ?   ; 0A4h
  270.     put_language          dd ?   ; 0A8h
  271.     get_language          dd ?   ; 0ACh
  272.     put_onselectstart     dd ?   ; 0B0h
  273.     get_onselectstart     dd ?   ; 0B4h
  274.     scrollIntoView        dd ?   ; 0B8h
  275.     contains              dd ?   ; 0BCh
  276.     get_sourceIndex       dd ?   ; 0C0h
  277.     get_recordNumber      dd ?   ; 0C4h
  278.     put_lang              dd ?   ; 0C8h
  279.     get_lang              dd ?   ; 0CCh
  280.     get_offsetLeft        dd ?   ; 0D0h
  281.     get_offsetTop         dd ?   ; 0D4h
  282.     get_offsetWidth       dd ?   ; 0D8h
  283.     get_offsetHeight      dd ?   ; 0DCh
  284.     get_offsetParent      dd ?   ; 0E0h
  285.     put_innerHTML         dd ?   ; 0E4h
  286.     get_innerHTML         dd ?   ; 0E8h
  287.     put_innerText         dd ?   ; 0ECh
  288.     get_innerText         dd ?   ; 0F0h
  289.     put_outerHTML         dd ?   ; 0F4h
  290.     get_outerHTML         dd ?   ; 0F8h
  291.     put_outerText         dd ?   ; 0FCh
  292.     get_outerText         dd ?   ; 100h
  293.     insertAdjacentHTML    dd ?   ; 104h
  294.     insertAdjacentText    dd ?   ; 108h
  295.     get_parentTextEdit    dd ?   ; 10Ch
  296.     get_isTextEdit        dd ?   ; 110h
  297.     click                 dd ?   ; 114h
  298.     get_filters           dd ?   ; 118h
  299.     put_ondragstart       dd ?   ; 11Ch
  300.     get_ondragstart       dd ?   ; 120h
  301.     toString              dd ?   ; 124h
  302.     put_onbeforeupdate    dd ?   ; 128h
  303.     get_onbeforeupdate    dd ?   ; 12Ch
  304.     put_onafterupdate     dd ?   ; 130h
  305.     get_onafterupdate     dd ?   ; 134h
  306.     put_onerrorupdate     dd ?   ; 138h
  307.     get_onerrorupdate     dd ?   ; 13Ch
  308.     put_onrowexit         dd ?   ; 140h
  309.     get_onrowexit         dd ?   ; 144h
  310.     put_onrowenter        dd ?   ; 148h
  311.     get_onrowenter        dd ?   ; 14Ch
  312.     put_ondatasetchanged  dd ?   ; 150h
  313.     get_ondatasetchanged  dd ?   ; 154h
  314.     put_ondataavailable   dd ?   ; 158h
  315.     get_ondataavailable   dd ?   ; 15Ch
  316.     put_ondatasetcomplete dd ?   ; 160h
  317.     get_ondatasetcomplete dd ?   ; 164h
  318.     put_onfilterchange    dd ?   ; 168h
  319.     get_onfilterchange    dd ?   ; 16Ch
  320.     get_children          dd ?   ; 170h
  321.     get_all               dd ?   ; 174h
  322. ends
Первый вариант. Начиная с объекта бразуера, последовательно извлекаем объект загруженной страницы, затем через метод get_body интерфейса IHTMLDocument2 из него получаем объект элемента BODY. Вызывает недоумение, почему при столь богатом арсенале методов для работы с объектом страницы, в нем напрочь отсутствует такой очевидный инструмент, как получение ее исходного кода. Приходится применять танцы с бубнами, а именно тот факт, что для тега BODY родительским тегом является HTML, содержимое которого с обрамляющими элементами по сути и есть нужный нам исходник. При помощи метода get_parentElement через интерфейс IHTMLElement получаем родительский элемент у тега BODY и затем методом get_outerHTML извлекаем его содержимое.
  1.         ; Получить объект загруженной страницы
  2.         mov     eax,[pBrowser]
  3.         mov     eax,[eax]
  4.         stdcall dword [eax+IWebBrowser2.get_Document],[pBrowser],\
  5.                 pDocument
  6.  
  7.         mov     eax,[pDocument]
  8.         mov     eax,[eax]
  9.         stdcall dword [eax+IWebBrowser2.QueryInterface],[pDocument],\
  10.                 IID_IHTMLDocument2,pHtmlDocument
  11.  
  12.         ; Получить объект тега BODY
  13.         mov     eax,[pHtmlDocument]
  14.         mov     eax,[eax]
  15.         stdcall dword [eax+IHTMLDocument2.get_body],[pHtmlDocument],\
  16.                 pBodyElement
  17.  
  18.         ; Получить объект корневого тега
  19.         mov     eax,[pBodyElement]
  20.         mov     eax,[eax]
  21.         stdcall dword [eax+IHTMLElement.get_parentElement],\
  22.                 [pBodyElement],pRootElement
  23.  
  24.         ; Получить содержимое корневого тега страницы
  25.         mov     eax,[pRootElement]
  26.         mov     eax,[eax]
  27.         stdcall dword [eax+IHTMLElement.get_outerHTML],[pRootElement],\
  28.                 bStr
  29.  
  30.         ; [bStr] -> указатель на строку с исходным кодом страницы
  31.  
  32.         ; Прибраться за собой
  33.         mov     eax,[pRootElement]
  34.         mov     eax,[eax]
  35.         stdcall dword [eax+IHTMLElement.Release],[pRootElement]
  36.  
  37.         mov     eax,[pBodyElement]
  38.         mov     eax,[eax]
  39.         stdcall dword [eax+IHTMLElement.Release],[pBodyElement]
  40.  
  41.         mov     eax,[pHtmlDocument]
  42.         mov     eax,[eax]
  43.         stdcall dword [eax+IHTMLDocument2.Release],[pHtmlDocument]
  44.  
  45.         mov     eax,[pDocument]
  46.         mov     eax,[eax]
  47.         stdcall dword [eax+IWebBrowser2.Release],[pDocument]
Очень удобно, что при этом не требуется резервировать память для получаемых данных, об этом позаботится система. От вас требуется только очистить выделенную память, когда она больше не нужна. Также есть еще одно полезное свойство подобной обработки данных. При обычном статическом скачивании ссылок, там будет только их исходный код, который в дальнейшем при отображении в браузере может модифицироваться скриптами JavaScript. Тут же будет получен сиюсекундный снимок исходника после всех модификаций, если таковые были.

При получении исходного кода HTML-страницы вторым способом, используется метод get_documentElement интерфейса IHTMLDocument3. Работая с COM-объектами в Windows я уже немного привык, что интерфейсы с номерами на конце являются развитием своих более ранних версий, отличаются только GUID'ами и тем, что в них добавлены новые методы, причем строго в конец списка. В итоге можно просто взять интерфейс с самой старшей цифрой на конце и использовать его. Тут же интерфейс IHTMLDocument3 целиком и полностью отличается от IHTMLDocument2. То есть из-за нескольких методов, которые описаны в разных интерфейсах, вам придется создавать два объекта страницы и потом не запутаться в них. Браво, Microsoft!
  1. ; GUID {3050F485-98B5-11CF-BB82-00AA00BDCE0B}
  2. IID_IHTMLDocument3 dd 03050F485h
  3.                    dw 098B5h
  4.                    dw 011CFh
  5.                    db 0BBh, 082h, 000h, 0AAh, 000h, 0BDh, 0CEh, 00Bh
  6.  
  7. ; IID_IHTMLDocument3 Interface
  8. struct IHTMLDocument3
  9.     ; IUnknown
  10.     QueryInterface         dd ?   ; 000h
  11.     AddRef                 dd ?   ; 004h
  12.     Release                dd ?   ; 008h
  13.     ; IHTMLDocument3
  14.     GetTypeInfoCount       dd ?   ; 00Ch
  15.     GetTypeInfo            dd ?   ; 010h
  16.     GetIDsOfNames          dd ?   ; 014h
  17.     _Invoke                dd ?   ; 018h
  18.     releaseCapture         dd ?   ; 01Ch
  19.     recalc                 dd ?   ; 020h
  20.     createTextNode         dd ?   ; 024h
  21.     get_documentElement    dd ?   ; 028h
  22.     get_uniqueID           dd ?   ; 02Ch
  23.     attachEvent            dd ?   ; 030h
  24.     detachEvent            dd ?   ; 034h
  25.     put_onrowsdelete       dd ?   ; 038h
  26.     get_onrowsdelete       dd ?   ; 03Ch
  27.     put_onrowsinserted     dd ?   ; 040h
  28.     get_onrowsinserted     dd ?   ; 044h
  29.     put_oncellchange       dd ?   ; 048h
  30.     get_oncellchange       dd ?   ; 04Ch
  31.     put_ondatasetchanged   dd ?   ; 050h
  32.     get_ondatasetchanged   dd ?   ; 054h
  33.     put_ondataavailable    dd ?   ; 058h
  34.     get_ondataavailable    dd ?   ; 05Ch
  35.     put_ondatasetcomplete  dd ?   ; 060h
  36.     get_ondatasetcomplete  dd ?   ; 064h
  37.     put_onpropertychange   dd ?   ; 068h
  38.     get_onpropertychange   dd ?   ; 06Ch
  39.     put_dir                dd ?   ; 070h
  40.     get_dir                dd ?   ; 074h
  41.     put_oncontextmenu      dd ?   ; 078h
  42.     get_oncontextmenu      dd ?   ; 07Ch
  43.     put_onstop             dd ?   ; 080h
  44.     get_onstop             dd ?   ; 084h
  45.     createDocumentFragment dd ?   ; 088h
  46.     get_parentDocument     dd ?   ; 08Ch
  47.     put_enableDownload     dd ?   ; 090h
  48.     get_enableDownload     dd ?   ; 094h
  49.     put_baseUrl            dd ?   ; 098h
  50.     get_baseUrl            dd ?   ; 09Ch
  51.     get_childNodes         dd ?   ; 0A0h
  52.     put_inheritStyleSheets dd ?   ; 0A4h
  53.     get_inheritStyleSheets dd ?   ; 0A8h
  54.     put_onbeforeeditfocus  dd ?   ; 0ACh
  55.     get_onbeforeeditfocus  dd ?   ; 0B0h
  56.     getElementsByName      dd ?   ; 0B4h
  57.     getElementById         dd ?   ; 0B8h
  58.     getElementsByTagName   dd ?   ; 0BCh
  59. ends
Но тут хотя бы писанины получается на несколько строчек меньше. При помощи метода get_documentElement получаем объект корневого тега, то есть HTML. Дальше, как и в первом способе, извлекаем из него содержимое.
  1.         ; Получить объект загруженной страницы
  2.         mov     eax,[pBrowser]
  3.         mov     eax,[eax]
  4.         stdcall dword [eax+IWebBrowser2.get_Document],[pBrowser],\
  5.                 pDocument
  6.  
  7.         mov     eax,[pDocument]
  8.         mov     eax,[eax]
  9.         stdcall dword [eax+IWebBrowser2.QueryInterface],[pDocument],\
  10.                 IID_IHTMLDocument3,pHtmlDocument
  11.  
  12.         ; Получить объект корневого тега
  13.         mov     eax,[pHtmlDocument]
  14.         mov     eax,[eax]
  15.         stdcall dword [eax+IHTMLDocument3.get_documentElement],\
  16.                 [pHtmlDocument],pRootElement
  17.  
  18.         ; Получить содержимое корневого тега страницы
  19.         mov     eax,[pRootElement]
  20.         mov     eax,[eax]
  21.         stdcall dword [eax+IHTMLElement.get_outerHTML],[pRootElement],\
  22.                 bStr
  23.  
  24.         ; [bStr] -> указатель на строку с исходным кодом страницы
  25.  
  26.         ; Прибраться за собой
  27.         mov     eax,[pRootElement]
  28.         mov     eax,[eax]
  29.         stdcall dword [eax+IHTMLElement.Release],[pRootElement]
  30.  
  31.         mov     eax,[pHtmlDocument]
  32.         mov     eax,[eax]
  33.         stdcall dword [eax+IHTMLDocument3.Release],[pHtmlDocument]
  34.  
  35.         mov     eax,[pDocument]
  36.         mov     eax,[eax]
  37.         stdcall dword [eax+IWebBrowser2.Release],[pDocument]
С полным текстом страницы разобрались, теперь будем извлекать из нее отдельные элементы. Самое время вспомнить язык JavaScript, а точнее его функции для работы с DOM. Они очень похожи на методы, которые мы сейчас будем использовать. Сперва надо извлечь так называемую коллекцию элементов. В зависимости от задачи это делается, например, при помощи интерфейса IHTMLDocument2 и его метода get_all или интерфейса IHTMLDocument3 и методов getElementsByName, getElementById, getElementsByTagName, а также некоторых других. С полученной коллекцией элементов можно работать через методы интерфейса IHTMLElementCollection. Их не так много, обычно хватает get_length для получения количества элементов в коллекции и item для получения нужного элемента по его индексу. Сам процесс получения и перебора коллекции выглядит примерно так:
  1.         ; Получить объект загруженной страницы
  2.         mov     eax,[pBrowser]
  3.         mov     eax,[eax]
  4.         stdcall dword [eax+IWebBrowser2.get_Document],[pBrowser],\
  5.                 pDocument
  6.  
  7.         mov     eax,[pDocument]
  8.         mov     eax,[eax]
  9.         stdcall dword [eax+IWebBrowser2.QueryInterface],[pDocument],\
  10.                 IID_IHTMLDocument3,pHtmlDocument
  11.  
  12.         ; Прибраться за собой
  13.         mov     eax,[pDocument]
  14.         mov     eax,[eax]
  15.         stdcall dword [eax+IWebBrowser2.Release],[pDocument]
  16.  
  17.         ; Получить коллекцию тегов <H1>
  18.         mov     eax,[pHtmlDocument]
  19.         mov     eax,[eax]
  20.         stdcall dword [eax+IHTMLDocument3.getElementsByTagName],\
  21.                 [pHtmlDocument],szTag,pTags
  22.  
  23.         ; Получить количество тегов
  24.         mov     eax,[pTags]
  25.         mov     eax,[eax]
  26.         stdcall dword [eax+IHTMLElementCollection.get_length],\
  27.                 [pTags],dLen
  28.  
  29.         ; Коллекция не пустая?
  30.         cmp     [dLen],0
  31.         je      loc_skip
  32.  
  33.         xor     ebx,ebx
  34. loc_next_element:
  35.         mov     [dummy.vt],VT_I4
  36.         mov     [dummy.lVal],ebx
  37.  
  38.         ; Получить очередной элемент из коллекции
  39.         mov     eax,[pTags]
  40.         mov     eax,[eax]
  41.         ; Структуры передаются целиком на стек, а не по указателю
  42.         stdcall dword [eax+IHTMLElementCollection.item],[pTags],\
  43.                 dword[dummy],dword[dummy+4],\
  44.                 dword[dummy+8],dword[dummy+12],\
  45.                 dword[dummy],dword[dummy+4],\
  46.                 dword[dummy+8],dword[dummy+12],\
  47.                 pTag
  48.  
  49.         ; Получить его интерфейс IHTMLElement
  50.         mov     eax,[pTag]
  51.         mov     eax,[eax]
  52.         stdcall dword [eax+IDispatch.QueryInterface],[pTag],\
  53.                 IID_IHTMLElement,pElement
  54.  
  55.         ; Получить содержимое тега
  56.         mov     eax,[pElement]
  57.         mov     eax,[eax]
  58.         stdcall dword [eax+IHTMLElement.get_innerHTML],[pElement],bStr
  59.  
  60.         ; [bStr] -> указатель на строку с содержимым тега
  61.  
  62.         invoke  SysFreeString,[bStr]
  63.  
  64.         ; Прибраться за собой
  65.         mov     eax,[pElement]
  66.         mov     eax,[eax]
  67.         stdcall dword [eax+IHTMLElement.Release],[pElement]
  68.  
  69.         ; Следующий элемент в коллекции
  70.         inc     ebx
  71.         cmp     ebx,[dLen]
  72.         jb      loc_next_element
  73.  
  74.         ; Прибраться за собой
  75.         mov     eax,[pTags]
  76.         mov     eax,[eax]
  77.         stdcall dword [eax+IHTMLElementCollection.Release],[pTags]
  78.  
  79. loc_skip:
  80.         ; Прибраться за собой
  81.         mov     eax,[pHtmlDocument]
  82.         mov     eax,[eax]
  83.         stdcall dword [eax+IHTMLDocument3.Release],[pHtmlDocument]
Самая жесть тут в том, что при вызове метода item в параметрах передаются две структуры типа VARIANT. Но на стек кладутся не указатели на них, как в других методах, а именно сами структуры целиком. Разработчики Microsoft не перестают радовать программистов и держать их в тонусе подобными закидонами.

Когда нужный элемент будет найден, при помощи различных методов интерфейса IHTMLElement можно извлечь из него необходимую информацию, например, идентификатор тега, название тега, содержимое, атрибуты и все прочее, что обычно извлекается со страницы средствами JavaScript. Также часть атрибутов элемента можно изменить и даже передать ему некоторые команды. Как видите, полноценный парсинг HTML-страниц на чистом Ассемблере - это не такая уж и фантастика.

Для взаимодействия со страницей, как это делает обычный браузер, используется интерфейс IOleCommandTarget. Придется дополнить список GUID'ов, констант и интерфейсов.
  1. ; GUID {ED016940-BD5B-11CF-BA4E-00C04FD70816}
  2. CGID_IWebBrowser \
  3.     dd 0ED016940h
  4.     dw 0BD5Bh
  5.     dw 011CFh
  6.     db 0BAh, 04Eh, 000h, 0C0h, 04Fh, 0D7h, 008h, 016h
  7.  
  8. ; GUID {B722BCCB-4E68-101B-A2BC-00AA00404770}
  9. IID_IOleCommandTarget \
  10.     dd 0B722BCCBh
  11.     dw 04E68h
  12.     dw 0101Bh
  13.     db 0A2h, 0BCh, 000h, 0AAh, 000h, 040h, 047h, 070h
  14.  
  15. ; IID_IOleCommandTarget Interface
  16. struct IOleCommandTarget
  17.     ; IUnknown
  18.     QueryInterface dd ?   ; 000h
  19.     AddRef         dd ?   ; 004h
  20.     Release        dd ?   ; 008h
  21.     ; IOleCommandTarget
  22.     QueryStatus    dd ?   ; 00Ch
  23.     Exec           dd ?   ; 010h
  24. ends
  25.  
  26. OLECMDEXECOPT_DODEFAULT      = 0
  27. OLECMDEXECOPT_PROMPTUSER     = 1
  28. OLECMDEXECOPT_DONTPROMPTUSER = 2
  29.  
  30. HTMLID_FIND       = 1
  31. HTMLID_VIEWSOURCE = 2
  32. HTMLID_OPTIONS    = 3
Интерфейс IOleCommandTarget можно получить через метод QueryInterface объекта документа, который мы научились получать ранее. После загрузки страницы можно будет выполнять команды с помощью метода Exec. Первым параметром определяется GUID группы команд, в нашем случае это будет CGID_IWebBrowser. Затем идет тип команды, для CGID_IWebBrowser это может быть просмотр исходного кода, поиск и вызов стандартного окна настроект подключения. Для стандартной группы список доступных команд еще более обширный. Следующий параметр интересный, он позволяет программно определять поведение браузера при выполнении команды: запрашивать пользователя, выполнить без уведомления или действовать по умолчанию для данной команды.
  1.         ; Получить интерфейс IOleCommandTarget
  2.         mov     eax,[pDocument]
  3.         mov     eax,[eax]
  4.         stdcall dword [eax+IWebBrowser2.QueryInterface],[pDocument],\
  5.                 IID_IOleCommandTarget,pCmd
  6.  
  7.         ; Выполнить команду "Исходный код страницы"
  8.         mov     eax,[pCmd]
  9.         mov     eax,[eax]
  10.         stdcall dword [eax+IOleCommandTarget.Exec],[pCmd],\
  11.                 CGID_IWebBrowser,\
  12.                 HTMLID_VIEWSOURCE,\
  13.                 OLECMDEXECOPT_DODEFAULT,\
  14.                 NULL,NULL
  15.  
  16.         ; Прибраться за собой
  17.         mov     eax,[pCmd]
  18.         mov     eax,[eax]
  19.         stdcall dword [eax+IOleCommandTarget.Release],[pCmd]
Последние два параметра метода определяют входные и выходные данные для исполняемой команды, если она их поддерживает.

В приложении примеры программ с исходными текстами, которые реализуют способы получения информации из HTML-страниц, описанные в статье.

Примеры программ с исходными текстами (FASM)Примеры программ с исходными текстами (FASM)

Embedded.Browser.Parsing.Demo.zip (17,138 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 808 | Комментариев: 3

Метки: Assembler, сеть, COM
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (26.05.2023 в 16:13):
Добавил в статью информацию о выполнении команд.
ManHunter (01.03.2023 в 13:51):
Grey, абсолютно ничем, просто дело привычки.
Grey (01.03.2023 в 13:24):
Расскажи, чем плохи interface и comcall ?

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.08 сек. / MySQL: 2 (0.0067 сек.) / Память: 4.5 Mb
Наверх