Все началось с того, что я учился парсингу из Delphi. Хотелось понять возможности Delphi в этом направлении. В сети очень, очень много разнообразной информации, тема давным давно изучена многими людьми, но для меня это новая информация. В данном посте я попытался более-менее структурировать то, что нашел. В основном этот пост посвящен различным способам загрузки.
Как загрузить страницу?
Способ №1
На мой взгляд – самый простой способ – загрузить через idHTTP.get(‘url’) . Страницу мы получаем в виде строки и далее можно искать (парсить) в ней различные теги, email и др. информацию при помощи регулярных выражений. Способ хорош своей простотой и универсальностью, но если вдруг со страницей произойдут какие-то изменения – регулярки, возможно придется переписывать.
Способ №2
Через интерфейс IHTMLDocument2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// uses activex,mshtml,ComObj ... var idoc:IHTMLDocument2; ... procedure TForm2.Button1Click(Sender: TObject); var V: OleVariant; HTML: String; begin try //Сначала просто загружаем в html как строку idhttp1.HandleRedirects:=true; html:=idhttp1.Get('http://www.e1.ru/'); //Создаем вариантный массив v:=VarArrayCreate([0,0],VarVariant); v[0]:= HTML; // присваиваем 0 элементу массива строку с html // Создаем интерфейс {Можно загружать через CreateComObject либо через coHTMLDocument.Create} //iDoc:=CreateComObject(Class_HTMLDOcument) as IHTMLDocument2; idoc:=coHTMLDocument.Create as IHTMLDocument2; //пишем в интерфейс idoc.write(PSafeArray(System.TVarData(v).VArray)); {все, теперь страницу можно обрабатывать при помощи MSHTML} finally end; end; |
Если использовать этот код, то постоянно выплывает это окошко…
Как бороться с этим окном?
Самый “железный” способ – снизить безопасность в Internet Explorer до нуля! Как это сделать? Заходим в свойства браузера и выставляем ползунок в нулевое положение.
Программный способ избавиться от окна. Если допустим мы пишем софт для машины клиента, а не для своей, и чтобы потом ему 33 раза не объяснять где что нажать, чтобы заработало, то программный способ просто необходим!!!
Чуть позже я напишу отдельный пост на эту тему, но суть в том, что нужно поменять в реестре windows
1 |
HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3\1A10 |
значение переменной 1A10 на 0, то есть так…
Только не ручками, а программно.Эта переменная как раз отвечает за cookie, значение 0 – соответствует разрешению принимать куки со всех сайтов.
В отдельном посте сделаю программную реализацию этого метода, чтобы здесь не выходить за рамки.
По поводу программного способа – долго искал сам.
Воспользовался программой Process Monitor от Microsoft и отследил какие изменения в реестре происходят при изменении настроек IE.
Очень помог пост EricLaw, в особенности его фраза
One notable factor is that the slider applies only to cookies for sites in the Internet Zone. Internally,URLACTION_COOKIES_ENABLED (0x01a10) setting has no UI but controls the behavior of Cookies on a per-zone basis. When set to 0, all cookies are Allowed. When set to 1, the P3P Policy is Evaluated to determine if the cookie should be accepted according to the user’s preference. When set to 3, all cookies are blocked. By default, cookies set for the Intranet Zone are always permitted, cookies for the Internet Zone are evaluated against the user’s P3P preferences, and cookies by sites in the Restricted Zone are always blocked.
Продолжаем тему про загрузку страницы…
Маленькое отступление. Что такое интерфейс?
Согласно книге В.В Фаронова “Delphi. Программирование на языке высокого уровня” основное назначение интерфейсов – описать свойства, методы и события удаленного объекта в терминах машины клиента, то есть на используемом при разработке клиентского приложения языке программирования.
Интерфейс это частный случай описания классов. Описание интерфейса аналогично объявлению абстрактного класса (без реализации методов). В отличие от классов – интерфейс не может содержать поля. Read and Write могут ссылаться только на методы.
Проверим эту информацию, залезем в IHTMLDocument2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
IHTMLDocument2 = interface(IHTMLDocument) ['{332C4425-26CB-11D0-B483-00C04FD90119}'] function Get_all: IHTMLElementCollection; safecall; function Get_body: IHTMLElement; safecall; function Get_activeElement: IHTMLElement; safecall; function Get_images: IHTMLElementCollection; safecall; function Get_applets: IHTMLElementCollection; safecall; function Get_links: IHTMLElementCollection; safecall; function Get_forms: IHTMLElementCollection; safecall; function Get_anchors: IHTMLElementCollection; safecall; procedure Set_title(const p: WideString); safecall; function Get_title: WideString; safecall; function Get_scripts: IHTMLElementCollection; safecall; procedure Set_designMode(const p: WideString); safecall; function Get_designMode: WideString; safecall; function Get_selection: IHTMLSelectionObject; safecall; function Get_readyState: WideString; safecall; function Get_frames: IHTMLFramesCollection2; safecall; function Get_embeds: IHTMLElementCollection; safecall; function Get_plugins: IHTMLElementCollection; safecall; procedure Set_alinkColor(p: OleVariant); safecall; function Get_alinkColor: OleVariant; safecall; procedure Set_bgColor(p: OleVariant); safecall; function Get_bgColor: OleVariant; safecall; procedure Set_fgColor(p: OleVariant); safecall; function Get_fgColor: OleVariant; safecall; procedure Set_linkColor(p: OleVariant); safecall; function Get_linkColor: OleVariant; safecall; procedure Set_vlinkColor(p: OleVariant); safecall; function Get_vlinkColor: OleVariant; safecall; function Get_referrer: WideString; safecall; function Get_location: IHTMLLocation; safecall; function Get_lastModified: WideString; safecall; procedure Set_url(const p: WideString); safecall; function Get_url: WideString; safecall; procedure Set_domain(const p: WideString); safecall; function Get_domain: WideString; safecall; procedure Set_cookie(const p: WideString); safecall; function Get_cookie: WideString; safecall; procedure Set_expando(p: WordBool); safecall; function Get_expando: WordBool; safecall; procedure Set_charset(const p: WideString); safecall; function Get_charset: WideString; safecall; procedure Set_defaultCharset(const p: WideString); safecall; function Get_defaultCharset: WideString; safecall; function Get_mimeType: WideString; safecall; function Get_fileSize: WideString; safecall; function Get_fileCreatedDate: WideString; safecall; function Get_fileModifiedDate: WideString; safecall; function Get_fileUpdatedDate: WideString; safecall; function Get_security: WideString; safecall; function Get_protocol: WideString; safecall; function Get_nameProp: WideString; safecall; procedure write(psarray: PSafeArray); safecall; procedure writeln(psarray: PSafeArray); safecall; function open(const url: WideString; name: OleVariant; features: OleVariant; replace: OleVariant): IDispatch; safecall; procedure close; safecall; procedure clear; safecall; function queryCommandSupported(const cmdID: WideString): WordBool; safecall; function queryCommandEnabled(const cmdID: WideString): WordBool; safecall; function queryCommandState(const cmdID: WideString): WordBool; safecall; function queryCommandIndeterm(const cmdID: WideString): WordBool; safecall; function queryCommandText(const cmdID: WideString): WideString; safecall; function queryCommandValue(const cmdID: WideString): OleVariant; safecall; function execCommand(const cmdID: WideString; showUI: WordBool; value: OleVariant): WordBool; safecall; function execCommandShowHelp(const cmdID: WideString): WordBool; safecall; function createElement(const eTag: WideString): IHTMLElement; safecall; procedure Set_onhelp(p: OleVariant); safecall; function Get_onhelp: OleVariant; safecall; procedure Set_onclick(p: OleVariant); safecall; function Get_onclick: OleVariant; safecall; procedure Set_ondblclick(p: OleVariant); safecall; function Get_ondblclick: OleVariant; safecall; procedure Set_onkeyup(p: OleVariant); safecall; function Get_onkeyup: OleVariant; safecall; procedure Set_onkeydown(p: OleVariant); safecall; function Get_onkeydown: OleVariant; safecall; procedure Set_onkeypress(p: OleVariant); safecall; function Get_onkeypress: OleVariant; safecall; procedure Set_onmouseup(p: OleVariant); safecall; function Get_onmouseup: OleVariant; safecall; procedure Set_onmousedown(p: OleVariant); safecall; function Get_onmousedown: OleVariant; safecall; procedure Set_onmousemove(p: OleVariant); safecall; function Get_onmousemove: OleVariant; safecall; procedure Set_onmouseout(p: OleVariant); safecall; function Get_onmouseout: OleVariant; safecall; procedure Set_onmouseover(p: OleVariant); safecall; function Get_onmouseover: OleVariant; safecall; procedure Set_onreadystatechange(p: OleVariant); safecall; function Get_onreadystatechange: OleVariant; safecall; procedure Set_onafterupdate(p: OleVariant); safecall; function Get_onafterupdate: OleVariant; safecall; procedure Set_onrowexit(p: OleVariant); safecall; function Get_onrowexit: OleVariant; safecall; procedure Set_onrowenter(p: OleVariant); safecall; function Get_onrowenter: OleVariant; safecall; procedure Set_ondragstart(p: OleVariant); safecall; function Get_ondragstart: OleVariant; safecall; procedure Set_onselectstart(p: OleVariant); safecall; function Get_onselectstart: OleVariant; safecall; function elementFromPoint(x: Integer; y: Integer): IHTMLElement; safecall; function Get_parentWindow: IHTMLWindow2; safecall; function Get_styleSheets: IHTMLStyleSheetsCollection; safecall; procedure Set_onbeforeupdate(p: OleVariant); safecall; function Get_onbeforeupdate: OleVariant; safecall; procedure Set_onerrorupdate(p: OleVariant); safecall; function Get_onerrorupdate: OleVariant; safecall; function toString: WideString; safecall; function createStyleSheet(const bstrHref: WideString; lIndex: Integer): IHTMLStyleSheet; safecall; property all: IHTMLElementCollection read Get_all; property body: IHTMLElement read Get_body; property activeElement: IHTMLElement read Get_activeElement; property images: IHTMLElementCollection read Get_images; property applets: IHTMLElementCollection read Get_applets; property links: IHTMLElementCollection read Get_links; property forms: IHTMLElementCollection read Get_forms; property anchors: IHTMLElementCollection read Get_anchors; property title: WideString read Get_title write Set_title; property scripts: IHTMLElementCollection read Get_scripts; property designMode: WideString read Get_designMode write Set_designMode; property selection: IHTMLSelectionObject read Get_selection; property readyState: WideString read Get_readyState; property frames: IHTMLFramesCollection2 read Get_frames; property embeds: IHTMLElementCollection read Get_embeds; property plugins: IHTMLElementCollection read Get_plugins; property alinkColor: OleVariant read Get_alinkColor write Set_alinkColor; property bgColor: OleVariant read Get_bgColor write Set_bgColor; property fgColor: OleVariant read Get_fgColor write Set_fgColor; property linkColor: OleVariant read Get_linkColor write Set_linkColor; property vlinkColor: OleVariant read Get_vlinkColor write Set_vlinkColor; property referrer: WideString read Get_referrer; property location: IHTMLLocation read Get_location; property lastModified: WideString read Get_lastModified; property url: WideString read Get_url write Set_url; property domain: WideString read Get_domain write Set_domain; property cookie: WideString read Get_cookie write Set_cookie; property expando: WordBool read Get_expando write Set_expando; property charset: WideString read Get_charset write Set_charset; property defaultCharset: WideString read Get_defaultCharset write Set_defaultCharset; property mimeType: WideString read Get_mimeType; property fileSize: WideString read Get_fileSize; property fileCreatedDate: WideString read Get_fileCreatedDate; property fileModifiedDate: WideString read Get_fileModifiedDate; property fileUpdatedDate: WideString read Get_fileUpdatedDate; property security: WideString read Get_security; property protocol: WideString read Get_protocol; property nameProp: WideString read Get_nameProp; property onhelp: OleVariant read Get_onhelp write Set_onhelp; property onclick: OleVariant read Get_onclick write Set_onclick; property ondblclick: OleVariant read Get_ondblclick write Set_ondblclick; property onkeyup: OleVariant read Get_onkeyup write Set_onkeyup; property onkeydown: OleVariant read Get_onkeydown write Set_onkeydown; property onkeypress: OleVariant read Get_onkeypress write Set_onkeypress; property onmouseup: OleVariant read Get_onmouseup write Set_onmouseup; property onmousedown: OleVariant read Get_onmousedown write Set_onmousedown; property onmousemove: OleVariant read Get_onmousemove write Set_onmousemove; property onmouseout: OleVariant read Get_onmouseout write Set_onmouseout; property onmouseover: OleVariant read Get_onmouseover write Set_onmouseover; property onreadystatechange: OleVariant read Get_onreadystatechange write Set_onreadystatechange; property onafterupdate: OleVariant read Get_onafterupdate write Set_onafterupdate; property onrowexit: OleVariant read Get_onrowexit write Set_onrowexit; property onrowenter: OleVariant read Get_onrowenter write Set_onrowenter; property ondragstart: OleVariant read Get_ondragstart write Set_ondragstart; property onselectstart: OleVariant read Get_onselectstart write Set_onselectstart; property parentWindow: IHTMLWindow2 read Get_parentWindow; property styleSheets: IHTMLStyleSheetsCollection read Get_styleSheets; property onbeforeupdate: OleVariant read Get_onbeforeupdate write Set_onbeforeupdate; property onerrorupdate: OleVariant read Get_onerrorupdate write Set_onerrorupdate; end; |
И что мы видим? Функции разных типов, процедуры и ни одного свойства! Не обманул Валерий Фаронов!!! В основном типажи функций – OleVariant, WideString, и различные интерфейсы.
И действительно! Свойства описаны при помощи функций, а не напрямую и ни одной реализации. Не обманул Валерий!!!
Ещё одно небольшое отступление
Также, когда мы загружали страницу, то пользовались такой конструкцией
1 |
idoc:=coHTMLDocument.Create as IHTMLDocument2; |
На сайте delphikingdom я обнаружил такую информацию
Далее мы увидим как QueryInterface использовать явно.
Попробуем поработать с idoc, который мы получили выше. Как видно из кода, это интерфейс IHTMLDocument2, из которого можно вытащить что-нибудь полезное. Для начала вытащим просто список тегов.
Пробуем парсить. Вытаскиваем список тегов
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
procedure TForm2.Button2Click(Sender: TObject); var i:integer; s:string; idisp:IDispatch; iElement : IHTMLElement; begin for i := 1 to idoc.all.length do begin idisp:=idoc.all.item(pred(i),0); idisp.QueryInterface(IHTMLElement,iElement);// <<Тот самый <b>QueryInterface</b> str(pred(i),s); s:=s+' '; if assigned(ielement) then begin S:=S+' tag '+iElement.tagName+' '; end; memo1.Lines.Add(s); end; end; |
Что такое IHTMLElement? Это опять же интерфейс из библиотеки MSHTML, если в неё заглянуть, то там большая портянка функций и процедур. Приведу здесь только выдержки из неё – то, что мы использовали в коде выше.
1 |
property tagName: WideString read Get_tagName; |
1 |
function Get_tagName: WideString; safecall; |
Причем если кликнуть на Get_tagName, то мы никуда не попадем, реализации-то нет! Прав был Валерий Фаронов!!!
Собственно, результат наших трудов…
Способ №3 (только в VCL)
Вот код, который можно встретить в различных уголках Интернета. Для этого способа нужно визуально или динамически создать Webbrowser.
1 2 3 4 5 6 7 |
... begin iDoc := WebBrowser1.Document as IHTMLDocument2; WebBrowser1.OleObject.document.getElementById('shform').ClassName := ''; S := Doc.body.innerHTML; end; ... |
Я так и этак пытался запустить этот способ в FireMonkey но прочитав форум Embarcadero понял, что эта затея бессмысленна в FireMonkey;
Думаю это самый удобный способ, если работать в VCL, так как усилий минимум, результата максимум. Можно почти напрямую обращаться к элементам по их id и что-то с ними делать.
В следующем посте займусь непосредственно парсингом.
Список литературы
Основополагающая статья на DelphiKingdom “Использование функциональности IE или заметки о WebBrowser”
Получение содержимого web-страниц – вариант первый самый простой
Ответ на вопрос № (дан способ загрузки страницы через IHTMLDocument2)
Ответ на вопрос (человек пытается создать свои функции для парсинга, например getElementsByAttr и др. )
Пост EricLaw (решение проблемы всплывающего окна проблемы безопасности)