Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: ActiveX/СОМ/CORBA > парсинг IE с фреймами


Автор: simsmann 4.12.2006, 19:26
Как осуществить парсинг в IE и найти нужные теги, если страница состоит из фреймов

Автор: December 4.12.2006, 21:55
Код

function GetFrameDoc(gDoc:IHTMLDocument2;ind:integer):IHTMLDocument2;
var
  Container : IOleContainer;
  Browser : IWebBrowser2;
  Unknown : IUnknown;
  Enumerator : ActiveX.IEnumUnknown;
  Fetched: Longint;
begin
result:=nil;
if not (Supports(gdoc, IOleContainer, Container)) then exit;
if Container.EnumObjects(OLECONTF_EMBEDDINGS, Enumerator) <> S_OK then exit;
Enumerator.Skip(ind);
if Enumerator.Next(1, Unknown, @Fetched) <> S_OK then exit;
try
if Supports(Unknown, IWebBrowser2, browser) then result:=Browser.Document as IHTMLDocument2;
except
end;//except silencer
end;//GetFrameDoc

Автор: simsmann 5.12.2006, 23:10
Спасибо ! December
Но немного непонятно. Нелзя ли поподробней описать.
Что я должен передать функции? Подключится к IE привязать к IWebBrowser2 тогда что такое ind (порядковый номер фрейма), что получу result IWebBrowser2 фрейма ind.
Вообще в идеале следующее. Подключаемся определяем имеет ли загруженная страница в IE фреймы, если Да то находим определенный тег во всех фреймах.

Автор: December 6.12.2006, 13:29
При итерации по веб-странице, обычно запращивается интерфейс IHTMLDocument2, от которого получаются разнообразные коллекции, от коллекций берутся item'ы (которые репрезентуют HTML тэги) и идёт обработка собственно тэгов. В процессе итерации может попасться тэг FRAME (IFRAME). В этом случае надо определить, какой по счёту этот frame в документе, и передать функции этот порядковый номер вторым аргументом.
Я экспериментально доказал, что фреймы всегда следуют в том порядке, в котором они объявлены в коде.

Автор: simsmann 7.12.2006, 00:17
К December! Пока ни чего не получилось еще больше запутался. Нельзя ли подкинуть мини готовый примерчик. При парсинге страницы не получается передать IHTMLDocument2 и ind и еще коечто. За ранее спасибо!

Автор: December 7.12.2006, 04:15
функция GetHTMLElementUnderneath возвращает HTML тэг, который находится в заданных координатах. При необходимости функция анализирует фреймы.
Код

function GetFrameIndex(gFrame:IHTMLElement):integer;
var
  i:integer;
  iColl:IHTMLElementCollection;
  tEl:IHTMLElement;
  doc:IHTMLDocument2;
begin
result:=-1;
doc:=gFrame.document as IHTMLDocument2;
iColl:=doc.all.tags('FRAME') as IHTMLElementCollection;
for i:=0 to iColl.length-1 do
  begin
  inc(result);
  tEl:=IDispatch(iColl.item(i,0)) as IHTMLElement;
  if gFrame.sourceIndex=tEl.sourceIndex then exit;
  end;//for
iColl:=doc.all.tags('IFRAME') as IHTMLElementCollection;
for i:=0 to iColl.length-1 do
  begin
  inc(result);
  tEl:=IDispatch(iColl.item(i,0)) as IHTMLElement;
  if gFrame.sourceIndex=tEl.sourceIndex then exit;
  end;//while
result:=-1;
end;//GetFrameIndex


function GetFrameDoc(gDoc:IHTMLDocument2;ind:integer):IHTMLDocument2;overload;
var
  Container : IOleContainer;
  Browser : IWebBrowser2;
  Unknown : IUnknown;
  Enumerator : ActiveX.IEnumUnknown;
  Fetched: Longint;
begin
result:=nil;
if not (Supports(gdoc, IOleContainer, Container)) then exit;
if Container.EnumObjects(OLECONTF_EMBEDDINGS, Enumerator) <> S_OK then exit;
Enumerator.Skip(ind);
if Enumerator.Next(1, Unknown, @Fetched) <> S_OK then exit;
try
if Supports(Unknown, IWebBrowser2, browser) then result:=Browser.Document as IHTMLDocument2;
except
end;//except silencer
end;//GetFrameDoc


function GetFrameDoc(gFrame:IHTMLElement):IHTMLDocument2;overload;
var
  ind:integer;
begin
result:=nil;
ind:=GetFrameIndex(gFrame);
if ind=-1 then exit;
result:=GetFrameDoc(gFrame.document as IHTMLDocument2,ind);
end;//GetFrameDoc

function GetHTMLElementUnderneath(gX,gY:integer;gWB:TWebBrowser):IHTMLElement;
var
  TheDoc:IHTMLDocument2;
  cP:TPoint;
begin
result:=nil;
if not IsHTMLContent(gWB) then exit;
cP:=gWB.ScreenToClient(Point(gX,gY));
if Assigned(gWB.ControlInterface) then
  TheDoc:=gWB.ControlInterface.Document as IHTMLDocument2;
if not Assigned(TheDoc) then exit;
result:=TheDoc.ElementFromPoint(cP.X,cP.Y);
while Assigned(result) and
      ((result.tagName='FRAME') or  (result.tagName='IFRAME')) do
  begin
  TheDoc:=GetFrameDoc(result);
  if not Assigned(TheDoc) then exit;
  cP.X:=cP.X-GetElementLeft(result);
  cP.Y:=cP.Y-GetElementTop(result);
  result:=TheDoc.ElementFromPoint(cP.X,cP.Y);
  end;//while
end;//GetHTMLElementUnderneath

Автор: simsmann 7.12.2006, 14:38
Спасибо!
Попробую разобраться

Автор: simsmann 9.12.2006, 17:25
Докумекал! Возможно пока коряво, кто может упростите. Буду естесственно пробовать сам.
Код


uses ...  ActiveX, SHDocVw, Mshtml;

procedure TForm1.Button1Click(Sender: TObject);
var
shellwindow: ishellwindows;
wb: iwebbrowser2;
spdisp: idispatch;
idoc1: ihtmldocument2;

idocNew: ihtmldocument2;
col: IHTMLElementCollection;
el : IHTMLElement;

document: variant;
k, m: integer;
ovelements: olevariant;
i: integer;
begin
shellwindow := coshellwindows.create;
//ищем окна и далее опр. явл. они webbrouser
for k := 0 to shellwindow.count do
begin
spdisp := shellwindow.item(k);
  if spdisp = nil then continue;
spdisp.queryinterface(iwebbrowser2, wb);
  if wb <> nil then
  begin
  wb.document.queryinterface(ihtmldocument2, idoc1);
    if idoc1 <> nil then
    begin
    wb := shellwindow.item(k) as iwebbrowser2;
    begin
    document := wb.document;
      for m := 0 to document.frames.length - 1 do
      begin
      //опр. номер фрейма
      ovelements := document.frames.item(m);
      //ShowMessage(IntToStr(m)); Посмотреть номер фрейма
      //вызываем функцию предложенную December
      //и получаем ihtmldocument2 фрейма m
      idocNew := GetFrameDoc(iDoc1, m);
      //далее парсинг фрейма нахадим нужный тег
      //поставьте в '' какой тег собираетесь искать 
      col := idocNew.all.tags('') as IHTMLElementCollection;
        for i := 0 to col.length-1 do
        begin
            //ищем нужный вам тег
            //и делаете , что вам надо
        end;
      end;
    end;
    end;
  end;
end;
end;

Следует отметить как делать парсинг есть на форуме.
Так же следует отметить, что поиск фреймов в данном коде будет по всем запущенным окнам IE/
Можно привязать к последнему или первому или определенному тогда определить все УРЛЫ в IE.

Но здесь тогда еще вопрос как связать определенный урл с wb: iwebbrowser2 в данном коде. С последним или первым окном можно по счетчику переменной, а если в середине только по УРЛ КАК?

Код работает. Пишем кто модернизирует-упростит.

Автор: December 9.12.2006, 23:57
хотелось бы заметить, что этот код не будет работать со вложенными фреймами smile

Автор: simsmann 10.12.2006, 13:18
Самое интересное проверил и со вложенными РАБОТАЕТ! Хотя возможно более правильно организовать рукурсию для прповерки каждого фрейма на наличие фреймов и.т.д. Но это уже дело техники.

Спасибо ! December

Все отлажено. Так же решен вопрос по привязке определенного УРЛ. Считаю тему закрытой!

Автор: Cleric57 10.2.2011, 19:06
Специально зарегистрировался только лишь ради того, чтобы поблагодарить господина December-а за его функцию (во втором посте), принцип ее работы не понимаю вообще, но интерфейс ясен, все пашет, с объектами страницы во фреймах удается делать теперь что угодно.. СПАСИБО!

Автор: December 13.2.2011, 15:09
Cleric57, спасибо за отзыв! Очень приятно, что удалось помочь smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)