GetElementsByTagName kullanımı

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Lord_Ares
Üye
Mesajlar: 1070
Kayıt: 15 Eki 2006 04:33
Konum: Çorlu

GetElementsByTagName kullanımı

Mesaj gönderen Lord_Ares »

Merhaba, aşağıdaki fonksiyon ile klas adını verdiğim divi bulup bana DivElement: IHTMLElement; olarak veriyor. Yapmak istediğim IHTMLElement olarak çıktısını aldığım bu div bloğu içinde getbydivclass fonksiyonunu kullanarak tekrar bir arama gerçekleştirip içindeki yazıyı almak.

Kod: Tümünü seç

function GetDivByClass(const Doc: IDispatch; const ClassName: string): IDispatch;
var
  Document: IHTMLDocument2;
  Body: IHTMLElement2;
  Divs: IHTMLElementCollection;
  DivElement: IHTMLElement;
  I: Integer;
begin
  Result := nil;
  if Supports(Doc, IHTMLDocument2, Document) and Supports(Document.body, IHTMLElement2, Body) then
  begin
    Divs := Body.getElementsByTagName('div');
    for I := 0 to Pred(Divs.length) do
    begin
      DivElement := Divs.item(I, EmptyParam) as IHTMLElement;
      if AnsiSameText(DivElement.className, ClassName) then
      begin
        Result := DivElement;
        Break;
      end;
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  DenemeDiv: IHTMLElement;
  DivListe: IHTMLElementCollection;
  DivElement: IHTMLElement;
  I: Integer;
begin
  DenemeDiv := GetDivByClass(WB.Document, 'deneme') as IHTMLElement;
  if Assigned(DenemeDiv) then
  begin
    DivListe := DenemeDiv.children as IHTMLElementCollection;
    DivListe := DivListe.tags('div') as IHTMLElementCollection;
    for I := 0 to Pred(DivListe.length) do
    begin
      DivElement := DivListe.item(I, EmptyParam) as IHTMLElement;
      if AnsiSameText(DivElement.className, 'iki') then
      begin
        ShowMessage(DivElement.innerHTML);
      end;
    end;
  end;
end;

Yukarıdaki kod şu şekil bir html sayfadan, deneme anadivini alıyor ve içndeki class adı iki olanları alabiliyorum.

Kod: Tümünü seç

</head>
 <body>

		<div class="deneme">
  
		     <div class="iki">   Deneme 2   </div>
           <div class="iki">   Deneme 3   </div>

		</div>

</body>
</html>
Fakat aşağıdaki gibi bir sayfada , bana Test adlı div içinde klass adı iki olanların içindekileri getir dediğimde kod çalışmıyor. illa deneme divini almam gerekiyor.

Kod: Tümünü seç

</head>
 <body>
   
    <div class="Test">

		<div class="deneme">
  
		     <div class="iki">   Deneme 2   </div>
           <div class="iki">   Deneme 3   </div>

		</div>
  </div>
</body>
</html>
Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1316
Kayıt: 07 May 2009 10:42
Konum: İstanbul
İletişim:

Re: GetElementsByTagName kullanımı

Mesaj gönderen SimaWB »

İlk aklıma gelen çözüm:
Herhangi bir DIV'in HTML içeriğini aldıktan sonra(string olarak) kendi Document'inizi oluşturabilirsiniz. Yani yapılacak işlem bir string ifadeden IHTMLDocument oluşturmak:

Kod: Tümünü seç

var
  Doc: OleVariant;
begin
  Doc := coHTMLDocument.Create as IHTMLDocument2;
  Doc.write(HTMLicerik);
  Doc.Close;
//buradan sonra Doc.Body yukarıda sizin kullandığınız Body ile aynı işlevi görür. Dolayısıyla Doc.Body.getElementsByTagName gibi bir ifadeyi kullanabilirsiniz.
end;
Buradaki 2 farklı cevap da işinize yaracaktır.
There's no place like 127.0.0.1
Lord_Ares
Üye
Mesajlar: 1070
Kayıt: 15 Eki 2006 04:33
Konum: Çorlu

Re: GetElementsByTagName kullanımı

Mesaj gönderen Lord_Ares »

Divs := Body.getElementsByTagName('div'); burada body deki divlerde arama gerçekleşiyor. Fonskiyonun çıktısı olan DivElement: IHTMLElement;
tede aynı arama gerçekleştirebilirmiyim ona bakıyorum. Yani getbydivclass kendi içinde bir kez daha çağırabilirsem olur gibi..
örneğin şöyle

Kod: Tümünü seç

   
    begin
      DivElement := Divs.item(I, EmptyParam) as IHTMLElement;
      if AnsiSameText(DivElement.className, ClassName) then
      begin
     getbydivclass('deneme');  
   
      end;
veya şöyle

Kod: Tümünü seç


DivElement := AnaDiv.getElementsByTagName('div');
    for I := 0 to Pred(Anadiv.length) do
    begin
        if AnsiSameText(Anadiv.className, ClassName) then
      begin
    result:=DivElement.innertext  /// gibi
      end;
Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1316
Kayıt: 07 May 2009 10:42
Konum: İstanbul
İletişim:

Re: GetElementsByTagName kullanımı

Mesaj gönderen SimaWB »

Benim size gönderdiğim kou kendi kodunuzla birleştirseydiniz aslında istediğiniz olurdu(Yalnış anlamadıysam):

Kod: Tümünü seç

function GetDivByClass(HTMLicerik: string; const ClassName: string): IHTMLElement;
var
  Document: IHTMLDocument2;
  Body: IHTMLElement2;
  Divs: IHTMLElementCollection;
  DivElement: IHTMLElement;
  I: Integer;
  Doc2: OleVariant;
begin
  Result := nil;
  try
    Doc2 := coHTMLDocument.Create as IHTMLDocument2;
    Doc2.write(HTMLicerik);
    Doc2.Close;
    if Supports(Doc2.body, IHTMLElement2, Body) then
    begin
      Divs := Body.getElementsByTagName('div');
      for I := 0 to Pred(Divs.length) do
      begin
        DivElement := Divs.item(I, EmptyParam) as IHTMLElement;
        if AnsiSameText(DivElement.className, ClassName) then
        begin
          Result := DivElement;
          Break;
        end;
      end;
    end;
  finally
    Doc2 := Unassigned;
  end;
end;
Örneğin tüm sayfada arama yapmak istiyorsunuz:

Kod: Tümünü seç

var
  aDiv: IHTMLElement;
begin
  aDiv := GetDivByClass((WebBrowser1.Document as IHTMLDocument2).body.innerHTML, 'deneme');
Yada bu dönen aDiv'in içerisinde tekrar arama yapmak istiyorsunuz:

Kod: Tümünü seç

baskaDiv := GetDivByClass(aDiv.innerHTML, 'deneme');
There's no place like 127.0.0.1
Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1316
Kayıt: 07 May 2009 10:42
Konum: İstanbul
İletişim:

Re: GetElementsByTagName kullanımı

Mesaj gönderen SimaWB »

Dün bu cevabı denemeden yazmıştım, bugün deneyince çalışmadığını gördüm :)
Nedeni ise Doc2. Nedense WebBrowserdan farklı bir document kullanınca sorun oluyor.
Eğer kullandığınız webbrowser ekranda görünmüyorsa(visible:=false ise) o zaman aşağıdaki şekilde kullanım işinizi görür. Eğer Webbowser görünüyorsa o zaman 2. bir webbrowser kullanılarak da çözüme ulaşılabilir:

Kod: Tümünü seç

function GetDivByClass(WB: TWebBrowser; HTMLicerik: string; const ClassName: string): IHTMLElement;
var
  Document: IHTMLDocument2;
  Body: IHTMLElement2;
  Divs: IHTMLElementCollection;
  DivElement: IHTMLElement;
  I: Integer;
  V: OleVariant;
begin
  Result := nil;

  V := VarArrayCreate([0,0], varVariant);
  V[0] := HTMLicerik;
  Document := WB.Document as IHTMLDocument2;
  Document.designMode := 'on';
  while Document.readyState <> 'complete' do
    Application.ProcessMessages;
  Document.write(PSafeArray(TVarData(v).VArray));
  Document.designMode := 'off';
  while Document.readyState <> 'complete' do
    Application.ProcessMessages;

  if Supports(Document.body, IHTMLElement2, Body) then
  begin
    Divs := Body.getElementsByTagName('div');
    for I := 0 to Pred(Divs.length) do
    begin
      DivElement := Divs.item(I, EmptyParam) as IHTMLElement;
      if AnsiSameText(DivElement.className, ClassName) then
      begin
        Result := DivElement;
        Break;
      end;
    end;
  end;
end;

Kod: Tümünü seç

procedure TForm1.Button1Click(Sender: TObject);
var
  strHTML: string;
begin
  strHTML := (WebBrowser1.Document as IHTMLDocument2).body.innerHTML;
  aDiv := GetDivByClass(WebBrowser1, strHTML, 'test') as IHTMLElement;
  if Assigned(aDiv) then
  begin
    baskaDiv := GetDivByClass(WebBrowser1, aDiv.innerHTML, 'deneme') as IHTMLElement;
    if Assigned(baskaDiv) then
      ShowMessage(baskaDiv.innerHTML);
  end;
end;
There's no place like 127.0.0.1
Lord_Ares
Üye
Mesajlar: 1070
Kayıt: 15 Eki 2006 04:33
Konum: Çorlu

Re: GetElementsByTagName kullanımı

Mesaj gönderen Lord_Ares »

sizin gönderdiğiniz kodu birleştirmiştim. Sıkıntı tarafı button kısmına yazdığımız koddaki , Divs: IHTMLElementCollection; ile arama yapan kısımda Şöyleki :
DivListe := DivListe.tags('div') as IHTMLElementCollection; diyerek yapılan eğer iç içe iki adet ana div varsa aramada sonucu bulamıyor.
Fakat getbydivclassta yapılan arama iç içe kaç tane anadiv olursa olsun sonuc döndürüyor.

Mesela sizin vermiş olduğunuz ilk kod ile şunu denerseniz (Mesajın en başındaki getbydivclass ve button daki kod ile) aşağıdaki biçimde olan bir sayfa yapısında bana Test divi içindeki klass adı iki olanları ver dediğinizde sonuç boş döncek fakat deneme içindeki iki klass adına sahipleri ver dediğinizde sonuç olumlu dönecektir. Sanırım buradaki sıkıntı birinin DenemeDiv.children as IHTMLElementCollection; çocuk divlerinde araması, çalışanın ise Divs: IHTMLElementCollection; da araması . Bende bu yüzden getbydivclassı iç içe iki kez çağırırsam sorunun düzeleceğini düşünmüştüm.
Son gönderdiklerinizi hemen deniyorum.

Kod: Tümünü seç

</head>
 <body>
   
    <div class="Test">

      <div class="deneme">
  
           <div class="iki">   Deneme 2   </div>
           <div class="iki">   Deneme 3   </div>

      </div>
  </div>
</body>
</html>
Lord_Ares
Üye
Mesajlar: 1070
Kayıt: 15 Eki 2006 04:33
Konum: Çorlu

Re: GetElementsByTagName kullanımı

Mesaj gönderen Lord_Ares »

Merhaba ek olarak şunu sormak istiyorum getbydivclass ile class adı istediğimiz olanları buluyoruz, peki şu şekildeki bir yapıyı nasıl ayırt edebiliriz
<tr class="row" code="501">
Yani class adı row olan ve özelliği code olanları bulmak için bu fonksiyonu nasıl değiştirmeliyim.
Yardımlarınız için çok teşekkürler.
Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1316
Kayıt: 07 May 2009 10:42
Konum: İstanbul
İletişim:

Re: GetElementsByTagName kullanımı

Mesaj gönderen SimaWB »

Kod: Tümünü seç

DivElement.getAttribute('code', 0);
size 501 değerini döndürmesi lazım. (Öncesinde VarIsNull ile kontrol etmekte fayda var ;) )
There's no place like 127.0.0.1
Cevapla