AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Eigener HTML-Parser/Auslesen von HTML-Tables

Eigener HTML-Parser/Auslesen von HTML-Tables

Ein Thema von NiceWeather · begonnen am 12. Aug 2009 · letzter Beitrag vom 13. Aug 2009
Antwort Antwort
NiceWeather

Registriert seit: 12. Aug 2009
2 Beiträge
 
#1

Eigener HTML-Parser/Auslesen von HTML-Tables

  Alt 12. Aug 2009, 16:18
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:
function GetHTMLTable (AUrl: string; ATableID: integer): string; Der Parameter ATableID ist die Tabelle, die zurückgeliefert werden soll.

Folgende Variablen:
Delphi-Quellcode:
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
Zunächst die Initialisierung einiger Variablen:

Delphi-Quellcode:
  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;
Dann wird das Array aTableCoordinatesArray mit allen vorkommenden Positionen von '<table' in cSourceCode gefüttert:

Delphi-Quellcode:
  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;
So weit so gut. Es fehlen die Positionen der End-Tags. Die werden folgendermaßen eingelesen:

Delphi-Quellcode:
  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;
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).

Genau da liegt aber mein Problem, denn der End-Tag von
aTableCoordinatesArray[nI].TableStartPos ist nicht unbedingt
Delphi-Quellcode:
 
aTableCoordinatesArray[nI].TableEndPos
Was die Definition des Rückgabewertes betrifft: Das ist nicht das Problem an sich.
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!
  Mit Zitat antworten Zitat
Prototypjack

Registriert seit: 2. Feb 2003
611 Beiträge
 
Delphi 2009 Professional
 
#2

Re: Eigener HTML-Parser/Auslesen von HTML-Tables

  Alt 12. Aug 2009, 17:21
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
Max
„If you have any great suggestions, feel free to mail me, and I'll probably feel free to ignore you.“ . Linus Torvalds
  Mit Zitat antworten Zitat
NiceWeather

Registriert seit: 12. Aug 2009
2 Beiträge
 
#3

Re: Eigener HTML-Parser/Auslesen von HTML-Tables

  Alt 13. Aug 2009, 16:46
Danke! 8)

Ging wirklich nicht wie ich ursprünglich wollte (habs auch nochmal kompliziert mit Sortierung, etc. versucht).

Am einfachsten ging es dann so:

Delphi-Quellcode:
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;
Wer möchte kann gerne Kritik an meinem Code üben! Bin immer für "Optimierungen" zu haben.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.017 Beiträge
 
Delphi 12 Athens
 
#4

Re: Eigener HTML-Parser/Auslesen von HTML-Tables

  Alt 13. Aug 2009, 17:09
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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Hisoka

Registriert seit: 2. Jan 2008
Ort: im Norden
53 Beiträge
 
FreePascal / Lazarus
 
#5

Re: Eigener HTML-Parser/Auslesen von HTML-Tables

  Alt 13. Aug 2009, 18:35
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.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:26 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz