![]() |
DIV classes mit getElementByID auslesen
Hi DP !
Ich möchte folgende, immer gleich aufgebaute HTML Struktur auslesen:
Code:
Das sind 2 Einträge von über 300. Ich möchte pro div-Block die 4 fett markierten Informationen auslesen:
<div class="FFT_header">[B]29Apr14 15:30[/B]<span class="FFT_header_for_name">[B]Tom Jerry[/B]</span>
<br> <span class="FFT_header_group">[B]Delphi Praxis Team[/B]</span> </div> <div class="fftText"> <pre>[B]Lorem Ipsum[/B]<br></pre> </div> <div class="FFT_header">[B]29Apr14 15:32[/B]<span class="FFT_header_for_name">[B]Eduard Junge[/B]</span> <br> <span class="FFT_header_group">[B]Torry Pages[/B]</span> </div> <div class="fftText"> <pre>[B]Lorem Ipsum 2[/B]<br></pre> </div> das Datum, den Namen, die Gruppe und den Text Ein ähnliches Problem habe ich mit String-Funktionen gelöst, aber himitsu erwähnte den Einsatz von HTML-DOM. Ich habe einige Gehversuche damit gestartet, komme aber nicht zurecht:
Delphi-Quellcode:
Wie spreche ich denn eine div class richtig an ?
var
divbody, div_class1, div_class2, Inputs : OleVariant; i,j,k: Integer; begin divBody := Webbrowser1.OleObject.document.getElementById('div class="FFT_header"'); div_class1 := divBody.getElementsByTagName('div class="FFT_header"'); for i := 1 to div_class1.length - 1 do begin div_class2 := div_class2.item(i, null).getElementsByTagName('class="FFT_header_group"'); for j := 0 to div_class2.length - 1 do begin Inputs := div_class2.item(j, null).getElementsByTagName('input'); for k := 0 to Inputs.length - 1 do memo1.Lines.add(Inputs.item(k, null).value); end; end; end; |
AW: DIV classes mit getElementByID auslesen
Ich denke, Du suchst getElementsByClassName, aber das wird nicht von allen Browsern unterstützt, siehe
![]() |
AW: DIV classes mit getElementByID auslesen
Kannst ja auch alternativ versuchen mit dieser Klasse
![]() zu arbeiten. Evtl. geht das leichter von der Hand. |
AW: DIV classes mit getElementByID auslesen
Hallo,
Zitat:
Delphi-Quellcode:
uses
MSHTML; function DOMNodeClassNameIs (const Node : IHTMLDOMNode; const Name : string) : Boolean; var e : IHTMLElement; begin e := Node as IHTMLElement; if not Assigned (e) then Exception.Create ('Fehlermeldung'); Result := e.className = Name end; function DOMNodeIsTextNode (const Node : IHTMLDOMNode) : Boolean; begin if Assigned (Node) then Result := Node.nodeType = 3 else Result := False end; function DOMNodeTagNameIs (const Node : IHTMLDOMNode; const Name : string) : Boolean; begin if Assigned (Node) then Result := LowerCase (Node.nodeName) = LowerCase (Name) else Result := False end; function FindSpanByClassName (Node : IHTMLDOMNode; const Name : string) : IHTMLDOMNode; begin Result := nil; while Assigned (Node) do begin if (LowerCase (Node.nodeName) = 'span') and DOMNodeClassNameIs (Node, Name) then begin Result := Node.firstChild; Break end; Node := Node.nextSibling end end; procedure TForm1.Button1Click(Sender: TObject); var d : IHTMLDocument3; c : IHTMLElementCollection; i : Integer; n : IHTMLDOMNode; s : string; procedure AddNodeValue (const Node : IHTMLDOMNode; var S : string); begin if not Assigned (Node) then Exception.Create ('Fehlermeldung'); if S <> '' then S := S + ' '; S := S + Node.nodeValue end; procedure AddFFTHeader (const Node : IHTMLDOMNode; var S : string); var n : IHTMLDOMNode; procedure AddFFTDateTime (var Node : IHTMLDOMNode; var S : string); begin if not DOMNodeIsTextNode (Node) then Exception.Create ('Fehlermeldung'); AddNodeValue (Node, S); Node := Node.nextSibling end; procedure AddFFTSpanByClassName (var Node : IHTMLDOMNode; var S : string; const Name : string); var n : IHTMLDOMNode; begin n := FindSpanByClassName (Node, Name); if not Assigned (n) then Exception.Create ('Fehlermeldung'); AddNodeValue (n, S); Node := Node.nextSibling end; begin n := Node.firstChild; AddFFTDateTime (n, S); AddFFTSpanByClassName (n, S, 'FFT_header_for_name'); AddFFTSpanByClassName (n, S, 'FFT_header_group') end; procedure AddFFTText (Node : IHTMLDOMNode; var S : string); begin if not (DOMNodeTagNameIs (Node, 'div') and DOMNodeClassNameIs (Node, 'fftText')) then Exception.Create ('Fehlermeldung'); Node := Node.firstChild; if not DOMNodeTagNameIs (Node, 'pre') then Exception.Create ('Fehlermeldung'); Node := Node.firstChild; if DOMNodeIsTextNode (Node) then AddNodeValue (Node, S) end; begin d := WebBrowser1.Document as IHTMLDocument3; if not Assigned (d) then Exit; c := d.getElementsByTagName ('div'); for i := 0 to c.length - 1 do begin n := c.item (i, EmptyParam) as IHTMLDOMNode; if not Assigned (n) then Exception.Create ('Fehlermeldung'); if DOMNodeClassNameIs (n, 'FFT_header') then begin s := ''; AddFFTHeader (n, s); AddFFTText (n.nextSibling, s); Memo1.Lines.Add (s) end end end; Gruß |
AW: DIV classes mit getElementByID auslesen
Hallo Volker !
Ich habe mich gerade mit deinem Code beschäftigt und etwas damit experimentiert. Abgesehen von einer klitzekleinen Änderung (siehe unten) funktioniert der Code bis an folgender Stelle
Delphi-Quellcode:
sehr gut ! Da gibt es eine Access violation welche ich derzeit näher auf den Grund gehe. Aber vielen Dank schon mal für deine Hilfe, ich werde mich weiter mit diesem Thema beschäftigen ! :dp:
AddFFTText (n.nextSibling, s);
Zitat:
|
AW: DIV classes mit getElementByID auslesen
Okay eine Frage habe ich noch:
Delphi-Quellcode:
Die obige Prozedur speichert den Text zwischen <pre> </pre> nur bis zum 1. Vorkommen eines <br>, der Rest wird nicht mehr mitgenommen.procedure AddNodeValue (const Node : IHTMLDOMNode; var S : string); begin if not Assigned (Node) then Exception.Create ('Fehlermeldung'); if S <> '' then S := S + ' '; S := S + Node.nodeValue end; procedure AddFFTText (Node : IHTMLDOMNode; var S : string); begin if not (DOMNodeTagNameIs (Node, 'div') and DOMNodeClassNameIs (Node, 'fftText')) then Exception.Create ('Fehlermeldung'); Node := Node.firstChild; if not DOMNodeTagNameIs (Node, 'pre') then Exception.Create ('Fehlermeldung'); Node := Node.firstChild; if DOMNodeIsTextNode (Node) then AddNodeValue (Node, S) end;
Code:
Muss ich da noch eine Schleife über die <br> Knoten hinzufügen ?
<div class="fftText">
<pre>Das ist der 1. Satz<br>Und dies ist der 2. Satz. In diesem Falle mit X<br>Ich mag auch mit !</pre> </div> |
AW: DIV classes mit getElementByID auslesen
Zitat:
![]() |
AW: DIV classes mit getElementByID auslesen
Hallo,
Zitat:
Dein
Code:
Kann man sich als DOM-Baumstruktur so vorstellen ([-] heißt es existieren Kindknoten, eingerückt heißt Knoten auf derselben Ebene):
<div class="fftText">
<pre>Das ist der 1. Satz<br>Und dies ist der 2. Satz. In diesem Falle mit X<br>Ich mag auch mit !</pre> </div>
Code:
Wenn Dich die Kinder eines gegeben DOM-Knotens interessieren, dann gibt Dir
[-]<div class="fftText">
[-]<pre> Das ist der 1. Satz <br> Und dies ist der 2. Satz. In diesem Falle mit X <br> Ich mag auch mit !
Delphi-Quellcode:
die Referenz auf den ersten Kindknoten - oder nil, falls kein Kindknoten existiert. Wenn Du den DIV-Knoten an
Node := Node.firstChild;
Delphi-Quellcode:
übergibst, dann liefert die erste Zuweisung den PRE-Knoten und die zweite Zuweisung den Textknoten "Das ist der 1. Satz".
procedure AddFFTText (Node : IHTMLDOMNode; var S : string);
Möchtest Du DOM-Knoten auf derselben Ebene untersuchen, dann sind die Zuweisungen:
Delphi-Quellcode:
bzw.
Node := Node.nextSibling;
Delphi-Quellcode:
hilfreich; erstere liefert eine Referenz auf den nächsten Kindknoten, letztere eine Referenz auf den vorherigen Kindknoten derselben Ebene.
Node := Node.previousSibling;
Wenn Du nur die Kinder der ersten Ebene des PRE-Knotens und dann auch nur Textknoten berücksichtigen möchtest: das erste Kind holen, solange diese Knoteneben durchlaufen bis kein weiterer Knoten mehr vorhanden ist, dabei jeden Knoten prüfen, ob es ein Textknoten ist - alles andere links liegen lassen. In Code gegossen:
Delphi-Quellcode:
Dann ist auch "Ich mag auch mit !" mit von der Partie.
procedure AddFFTText (Node : IHTMLDOMNode; var S : string);
begin if not (DOMNodeTagNameIs (Node, 'div') and DOMNodeClassNameIs (Node, 'fftText')) then Exception.Create ('Fehlermeldung'); Node := Node.firstChild; if not DOMNodeTagNameIs (Node, 'pre') then Exception.Create ('Fehlermeldung'); Node := Node.firstChild; while Assigned (Node) do begin if DOMNodeIsTextNode (Node) then AddNodeValue (Node, S); Node := Node.nextSibling end end; Ich hoffe ich konnte Deine Frage beantworten. Zu Deiner Anmerkung:
Delphi-Quellcode:
kann gut sein, dass es ab XE5 oder XE6 mit Unterstrich sein muss.
Result := e.className = Name //richtig ist: e._className
Und was war da mit der Access violation. Kannst Du dazu mehr sagen? Gruß |
AW: DIV classes mit getElementByID auslesen
Hallo nochmal,
Ich hatte heute wieder die Gelegenheit am Code zu arbeiten. Zunächst sei gesagt, dass mir die Sichtweise eines TreeViews im Bezug auf die Arbeit mit DOM nicht nur geholfen, sondern auch inspiriert hat die Elemente als TreeView Knoten darzustellen:
Delphi-Quellcode:
Ich fühle mich dank euren Erklärungen schon etwas sicherer mit dem Umgang von DOM. Ich habe auch die Access Violation gefunden: es klingt seltsam, aber sobald die Webseite einen meta-tag enthält, ist die Node in:
procedure TForm1.Button1Click(Sender: TObject);
var d : IHTMLDocument3; c : IHTMLElementCollection; i,entries : Integer; n : IHTMLDOMNode; s, datum, logger, group, text: string; tn: TTreeNode; procedure AddFFTHeader (const Node : IHTMLDOMNode; var S : string); var n : IHTMLDOMNode; //-------------------Timestamp-------------------------------------------------- procedure AddFFTDateTime (var Node : IHTMLDOMNode; var S : string); begin if not DOMNodeIsTextNode (Node) then Exception.Create ('AddFFTHeader Error!'); datum := Node.nodeValue; Node := Node.nextSibling end; //-------------------logger------------------------------------------------- procedure AddFFTName (var Node : IHTMLDOMNode; var S : string; const Name : string); var n : IHTMLDOMNode; begin n := FindSpanByClassName (Node, Name); if not Assigned (n) then Exception.Create ('AddFFTName Error'); logger := n.nodeValue; Node := Node.nextSibling end; //-------------------Group------------------------------------------------- procedure AddFFTgroup (var Node : IHTMLDOMNode; var S : string; const Name : string); var n : IHTMLDOMNode; begin n := FindSpanByClassName (Node, Name); if not Assigned (n) then Exception.Create ('AddFFTgroup Error'); group := n.nodeValue; Node := Node.nextSibling end; begin n := Node.firstChild; AddFFTDateTime (n, S);//Datum adden AddFFTName (n, S, 'FFT_header_for_name'); AddFFTGroup (n, S, 'FFT_header_group'); end; //-------------------TEXT ------------------------------------------------- procedure AddFFTText (Node : IHTMLDOMNode; var S : string); begin if not (DOMNodeTagNameIs (Node, 'div') and DOMNodeClassNameIs (Node, 'fftText')) then Exception.Create ('DOMNodeTagNameIs error: Weder div noch fftText gefunden'); Node := Node.firstChild; if not DOMNodeTagNameIs (Node, 'pre') then Exception.Create ('DOMNodeTagNameIs error: pre Tag nicht gefunden'); if assigned(node) then begin Node := Node.firstChild; text := ''; while Assigned (Node) do begin if DOMNodeIsTextNode (Node) then text := text + ' ' + Node.nodeValue; Node := Node.nextSibling end; end; end; begin d := WebBrowser1.Document as IHTMLDocument3; if not Assigned (d) then Exit; c := d.getElementsByTagName ('div'); for i := 0 to c.length - 1 do begin n := c.item (i, EmptyParam) as IHTMLDOMNode; if not Assigned (n) then Exception.Create ('Fehlermeldung'); if DOMNodeClassNameIs (n, 'FFT_header') then begin s := ''; AddFFTHeader (n, s); AddFFTText (n.nextSibling, s); inc(entries); label1.Caption := IntToStr(entries)+' Einträge gefunden'; //Add Treenode tn := Treeview.Items.Add(TreeView.Items.GetFirstNode, datum); TreeView.Items.AddChild(tn, logger); TreeView.Items.AddChild(tn, group); TreeView.Items.AddChild(tn, text); end end end;
Delphi-Quellcode:
immer NIL und deshalb NOT ASSIGNED. Deshalb hab ich ein
procedure AddFFTText (Node : IHTMLDOMNode; var S : string);
begin if not (DOMNodeTagNameIs (Node, 'div') and DOMNodeClassNameIs (Node, 'fftText')) then Exception.Create ('DOMNodeTagNameIs error: Weder div noch fftText gefunden'); Node := Node.firstChild; if not DOMNodeTagNameIs (Node, 'pre') then Exception.Create ('DOMNodeTagNameIs error: pre Tag nicht gefunden'); if assigned(node) then begin Node := Node.firstChild; text := ''; while Assigned (Node) do begin if DOMNodeIsTextNode (Node) then text := text + ' ' + Node.nodeValue; Node := Node.nextSibling end; end; end;
Delphi-Quellcode:
eingebaut um den Fehler zu umgehen. Dabei ist es egal was im meta tag steht, die Node ist dann immer NIL...:gruebel:
if assigned(node)
Ich habe auch einen kleinen Demonstrator gebaut, welchen ich euch gerne zum Testen zur Verfügung stellen kann. Den Code von Christian werde ich mir jetzt mal anschauen ! |
AW: DIV classes mit getElementByID auslesen
Guten Abend !
Ich habe mein Problem selbst behoben aufgrund Christian's Code:
Delphi-Quellcode:
Damit muss ich nicht mit dem original HTML Dokument leben und kann mich auf die Bereiche konzentrieren, welche ich auswerten möchte. Vielen, vielen Dank für dein Beispiel, jetzt hab ich 2 sehr geniale Ansätze um mich mit den HTML Elementen vertrauter zu machen :thumb:
LDOC := TcsHTMLDocument.Create;
LDOC.Content := Memo1.Text; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:16 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz