![]() |
Eigener HTML-Parser/Auslesen von HTML-Tables
Hallo zusammen,
habe ein Logik-Problem und hoffe es kann mir jemand weiterhelfen: Eine Funktion soll eine HTML-Tabelle als string zurückliefern: Folgende Deklaration der Funktion:
Delphi-Quellcode:
Der Parameter ATableID ist die Tabelle, die zurückgeliefert werden soll.
function GetHTMLTable (AUrl: string; ATableID: integer): string;
Folgende Variablen:
Delphi-Quellcode:
Zunächst die Initialisierung einiger Variablen:
var
cResult: string; //Der Rükgabewert cSourceCode: string; nTableStartPos: integer; nTableEndPos: integer; nOffSet: integer; aTableCoordinatesArray: Array of TTableCoordinates; //TTableCoordinates ist ein Record mit den beiden Felden TableStartPos und TableEndPos nTableCoordinatesArraySize: integer; nI: integer; //Schleifenvariable
Delphi-Quellcode:
Dann wird das Array aTableCoordinatesArray mit allen vorkommenden Positionen von '<table' in cSourceCode gefüttert:
cSourceCode := GetSourceCode(AUrl); //GetSourceCode ist eine eigene Funktion, die mittels TIdHTTP den Sourcecode einer Website liefert. AUrl wurde als Argument an die Funktion geliefert.
nTableStartPos := Pos(tblStartIdentifier, cSourceCode); //defniert das erste Vorkommen von tblStartIdentifier (String-Konstante= '<table') nTableEndPos := Pos(tblEndIdentifier, cSourceCode); //defniert das erste Vorkommen von tblEndIdentifier (String-Konstante= '</table>') nTableCoordinatesArraySize := 0;
Delphi-Quellcode:
So weit so gut. Es fehlen die Positionen der End-Tags. Die werden folgendermaßen eingelesen:
while nTableStartPos > 0 do
begin Inc(nTableCoordinatesArraySize); //Größe des Arrays definieren SetLength(aTableCoordinatesArray, nTableCoordinatesArraySize); //Größe des Arrays definieren aTableCoordinatesArray[nTableCoordinatesArraySize-1].TableStartPos := nTableStartPos; nOffSet := nTableStartPos + Length(tblStartIdentifier); //Offset hinter die letzte gefundene Position setzen nTableStartPos := PosEx(tblStartIdentifier, cSourceCode, nOffSet); //schauen, ob's ein weiteres '<table' gibt end;
Delphi-Quellcode:
Vorweg: Der Ansatz war, alle vorkommenden Taellen im Quelltext zu kennen, um zu wissen, wo die Table anfängt und wo sie aufhört (Stichwort: Verschachtelte Tables).
for nI := 0 to High(aTableCoordinatesArray) do
begin aTableCoordinatesArray[nI].TableEndPos := nTableEndPos; nOffSet := nTableEndPos + Length(tblEndIdentifier); //Offset hinter die letzte gefundene Position setzen nTableEndPos := PosEx(tblEndIdentifier, cSourceCode, nOffSet); //nach dem nächsten '</table>' schauen. Es wird angenommen, dass cSourceCode korrekt ist und genauso viele EndTags, wie StartTags vorhanden sind. end; Genau da liegt aber mein Problem, denn der End-Tag von
Delphi-Quellcode:
ist nicht unbedingt
aTableCoordinatesArray[nI].TableStartPos
Delphi-Quellcode:
Was die Definition des Rückgabewertes betrifft: Das ist nicht das Problem an sich. aTableCoordinatesArray[nI].TableEndPos Es fällt mir lediglich schwer, zuzuordnen welcher End-Tag zu welchem Start-Tag gehört. Habe mir schon verschachtelte for-Schleifen überlegt, was allerdings alles nicht hinhaut. Habt ihr eine Idee? Würdet ihr vom Ansatz her überhaupt so wie ich beginnen? Vorab vielen Dank für euren Input! |
Re: Eigener HTML-Parser/Auslesen von HTML-Tables
Moin,
Mit deinem Ansatz, wenn ich dich richtig verstanden habe, wirst du nicht weit kommen, denn dieser funktioniert nicht mehr, wenn Tables verschachtelt vorkommen. Ich schlage daher folgendes vor: Du machst nur einen Durchlauf. Bei jedem vorkommenden "<Table" fügst du einer Liste einen Eintrag hinzu, in welchem die Startposition der (gerade gefundenen) Tabelle steht. Wenn du jetzt auf ein "</Table" stößt, dann entfernst du einfach den letzten Eintrag in der Liste und fügst die Daten des letzten Eintrags (also den Tabellen-Start) zusammen mit der Position, des gerade gefundenen End-Tags in eine weitere Liste ein. Wenn der HTML-Code korrekt ist, so wird die erste Liste nach einem Durchlauf wieder leer sein (schließlich sollte jedes Start-Tag auch ein korrespondierendes End-Tag besitzen). In der zweiten Liste befinden sich dann alle Tables zusammen mit deren (korrekten) Start- und End-Positionen. Ich hoffe ich konnte mich halbwegs klar ausdrücken ;) Grüße, Max |
Re: Eigener HTML-Parser/Auslesen von HTML-Tables
Danke! 8) :thumb:
Ging wirklich nicht wie ich ursprünglich wollte (habs auch nochmal kompliziert mit Sortierung, etc. versucht). Am einfachsten ging es dann so:
Delphi-Quellcode:
Wer möchte kann gerne Kritik an meinem Code üben! Bin immer für "Optimierungen" zu haben. :-D
function THTMLTables.GetHTMLTable(AUrl: string; ATableID: Integer): string;
var cResult: string; //Rückgabewert cSourceCode: string; //HTML-Quelltext nTablesCount: integer; //Anzahl vorhandener Tabellen im cSourceCode nStartOffSet: integer; //Da fang ich an nach '<table' zu suchen nEndOffSet: integer; //Da fang ich an nach '</table>' zu suchen nTableStartPos: integer; //Da fängt meine Table an nTableEndPos: integer; //...und da hört sie auf nNextTablePos: integer; //Start-Position der jeweils nächsten Table nResultLength: integer; //Anzahl der Zeichen, die cResult enthält. nI: integer; begin cSourceCode := GetSourceCode(AUrl); //Eigene Funktion, die mittels TIdHTTP, den Quelltext ausgibt nTablesCount := TablesCount(cSourceCode, True); //Eigene Funktion zum zählen der Tables im Quelltext - Das boolsche Argument gibt an, ob der Quelltext validiert werden soll (d.h. wenn true und genausoviele Table-Start-Tags wie End-Tags gibt's ein Ergebnis, ansonsten 0) //Weiter mit der Initialisierung von Variablen nStartOffSet := 1; nTableStartPos := 1; nTableEndPos := 1; nNextTablePos := 1; if (ATableID > 0) and (ATableID <= nTablesCount) then begin //Findet die Position von ATableID (1 = Erster Table-Tag, etc.) for nI := 0 to ATableID-1 do begin nTableStartPos := PosEx(tblStartIdentifier, cSourceCode, nStartOffSet); nStartOffSet := nTableStartPos + Length(tblStartIdentifier); end; //Findet den Table-End-Tag nEndOffSet := nStartOffSet; while (nNextTablePos <= nTableEndPos) and (nNextTablePos <> 0) do begin nNextTablePos := PosEx(tblStartIdentifier, cSourceCode, nStartOffSet); nStartOffSet := nNextTablePos + Length(tblStartIdentifier); nTableEndPos := PosEx(tblEndIdentifier, cSourceCode, nEndOffSet); nEndOffSet := nTableEndPos + Length(tblEndIdentifier); end; nResultLength := nTableEndPos - nTableStartPos + Length(tblEndIdentifier); cResult := Copy(cSourceCode, nTableStartPos, nResultLength); end; Result := cResult; end; |
Re: Eigener HTML-Parser/Auslesen von HTML-Tables
im Grunde kannst du nur ein Array anlegen
- jedesmal, wenn ein Open-Tag ( <tag ...> ) gefunden wird, dann wird dessen Anfang an das Array angehängt - und sobald ein ClosedTag ( </tag> ) entdekt wird, dann wird der letze Eintrag aus dem Array entfernt Wenn du jetzt noch je Array-Ebene/Verzeigungstiefe/Level die Aufrufe mitzählst, dann kannst du so auch erkennen, in welcher Tabelle du gerade bist. leider ist HTML eine "kranke" Sprache, in welcher die komischten Dinge grad noch so erlaubt/gedultet werden, weshalb es da garnicht so einfach ist, soeine Datei zu parsen. |
Re: Eigener HTML-Parser/Auslesen von HTML-Tables
Hmm, hab die letzte Zeit wenig mit Pascal gearbeitet. Daher sage ich nur wie es relativ leicht gehen könnte.
1. DOMDocument erstellen und HTML Code übergeben 2. normalisieren lassen(ka ob das alle libs können) 3. Abfrage nach elementen mit dem Tag Namen table und schon hat man alle HTML Tabellen. In C++ und mit QT geht das zumindest so recht fix. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:59 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