Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - HTML Parser


RuSsAk - Mo 12.10.09 20:45
Titel: HTML Parser
hi leute

ich habe da mal ein problem und hoffe ihr könnt mir helfen

ich weiss hier gibts schon tausende threads dazu habe auch die ganzen codes ausprobiert aber mich hat nichts weiter gebracht gegoogelt und bei DP hab ich auch shcon geguckt aber nichts nur welche die die ganzen text auslesen aber da bleibt zu viel übrig und string replace würde da auch nichts bringen:(

ich suche eine funktion die ein quelltext parst

und zwar ich brauceh den text der zwischen "href="" und "</a>" steht aber auch wirklich nur den der dazwischen steht weil sonst sonst wäre das ja so wie bei den anderen die ich aussprobiert habe


wäre für eure hilfe sehr dankbar

ps. den quelltext habe ich in ein memo

mfg


Moderiert von user profile iconNarses: Topic aus Internet / Netzwerk verschoben am Mo 12.10.2009 um 23:05


Dude566 - Mo 12.10.09 20:49

Dann geh den Quelltext doch Zeile für Zeile mit einer Schleife durch und schaue nach ob dort diese Anfangs und Enddaten gefunden werden.
Wenn ja soll der Anfangspunkt fürs Kopieren hinter dem ersten Tag und der Endpunkt fürs Kopieren vor dem letzteren Tag stehen. :wink:


RuSsAk - Mo 12.10.09 20:50

user profile iconDude566 hat folgendes geschrieben Zum zitierten Posting springen:
Dann geh den Quelltext doch Zeile für Zeile mit einer Schleife durch und schaue nach ob dort diese Anfangs und Enddaten gefunden werden.
Wenn ja soll der Anfangspunkt fürs Kopieren hinter dem ersten Tag und der Endpunkt fürs Kopieren vor dem letzteren Tag stehen. :wink:



hättest du vllt ein beispiel code zur seite?

bin noch frischling


Dude566 - Mo 12.10.09 21:05

Bei Gelegenheit kann ich da mal ein kleines Beispiel schreiben, habe leider gerade keins an der Hand. Vielleicht hat ja jemand eins.


RuSsAk - Mo 12.10.09 21:08

user profile iconDude566 hat folgendes geschrieben Zum zitierten Posting springen:
Bei Gelegenheit kann ich da mal ein kleines Beispiel schreiben, habe leider gerade keins an der Hand. Vielleicht hat ja jemand eins.


wäre dir sehr dankbar:)

ja wäre auch schön :D


Apuch - Mo 12.10.09 21:08

HTML parsen wird übel (vor allem für deinen Webcrawler, der es sicher werden soll ;) ). Echte HTML-Daten sind nicht zwangsläufig wohlgeformt, damit wirds schwieriger...

Das einfachste ist wirklich Ueilenweise durchzugehen... für jede Zeile dann folgende Schritte:
1) suche 'href="'
2) gehe von der Position rückwärts bis zum letzten '<'
3) War der Buchstabe davor ein 'a'? Dann haben wir fast einen Eintrag
4) von der gefundenen 'href="'-Position aus alles einlesen bis zum nächsten '"'. das ist das Ergebniss

Das ganze natürlich mit der restlichen Zeile wiederhohlen...

@user profile iconRuSsAk: blind aus dem HTML-Code dieser Seite rausgegriffen:

XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
<div id="sidebar_quicklinks" class="sidebarbox">

<div class="sidebarheader">
<b>Quicklinks</b>
</div>
<div class="sidebarcontent" style="line-height: 14px">
<a href="search.php?search_id=newposts" class="gensmall">Beiträge seit letztem Besuch</a>
<a href="search.php?search_id=unread" class="gensmall">Ungelesene Themen</a>
<div class="gensmall" style="margin-top: 2px">
<form action="search.php?search_id=sincex" method="POST" name="sincex_sb_searchform" style="margin-top: 0px; margin-bottom: 0px">
Seit <select class="post" style="font-size: 9px; width: 43px; " name="sincex_time"><option>1</option>
          <option>2</option>

          <option>3</option>
          <option>4</option>
          <option>5</option>
          <option>8</option>
          <option>12</option>
          <option>15</option>

          <option>20</option>
          <option>24</option>
          <option>36</option>
          <option>48</option></select> Stunden
 <input class="liteoption" style="font-size: 9px; width: 30px;" type="submit" value="Go!" /></form></div>
<a href="search.php?search_id=unanswered" class="gensmall">Unbeantwortete Beiträge</a>
<a href="search.php?search_id=open" class="gensmall">Offene Fragen</a>

<a href="vc.php?mode=new&ref_type=0" class="gensmall">Kontakt zum Team</a>
</div>
</div>

alles was mit '<a' anfängt, ist ein potentielles Ergebniss...

MfG


RuSsAk - Mo 12.10.09 21:19

Moderiert von user profile iconNarses: Komplett-Zitat des letzten Beitrags entfernt.

das hilft mir leider auch nich weiter :(


Apuch - Mo 12.10.09 22:08

Sorry, hatte da was durcheinander gehauen...

Hier eine Quick&Dirty-Variante. Ich arbeite mich selbst gerade in Delphi ein (Quereinsteiger, komme von C). Das sollte man also nicht als Beispiel für guten Code nehmen ;) Für produktiven Code solltest du noch etwas aufräumen und es sind sicher nicht alle Sonderfälle sauber abgefangen...


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
procedure ScanLine(line : stringvar urls : TStringList);
var
  p,p2 : integer;
  i : integer;
  url : string;
begin
  // kommt ein href=" vor?
  p := pos('href="', line);
  if p = 0 then
    Exit;

  // jetzt suchen wir nach <a
  i := p;
  while not (ord(line[i]) = ord('<')) do
  begin
    dec(i);
    if i = 0 then
    begin
      // am Anfang der Zeile angekommen .. Fehler
      line := copy(line, p + 6, length(line) - p - 6);
      // Vielleicht im restlichen String?
      ScanLine(line, urls);
      Exit;
    end;
  end;
  // i zeigt nicht auf '<' -> i+1 == a ? Fehler
  if not ord(line[p+1]) = ord('a'then
  begin
    line := copy(line, p + 6, length(line) - p - 6);
    // Vielleicht im restlichen String?
    ScanLine(line, urls);
    Exit;
  end;

  // Wo kommt das " ?
  p2 := PosEx('"', line, p + 6);
  if p2 = 0 then
    // kommt keins mehr.. dann auch kein href="
    Exit;


  // Jubel.. haben was gefunden
  url := copy(line, p + 6, p2 - p - 6);
  urls.Add(url);

  // mal sehen ob noch was kommt
  line := copy(line, p2, length(line) - p2);
  ScanLine(line, urls);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  line : string;
  urls : TStringList;
begin
  line := copy(Memo1.Text,1,length(Memo1.Text));
  urls := TStringList.Create;
  ScanLine(line, urls);
  Memo2.Lines := urls;
end;


Zwei Memos und den entsprechenden Button noch schnell anlegen und testen...
Memo1-Text : Der HTML-Code von oben
Memo2-Text :
search.php?search_id=newposts
search.php?search_id=unread
search.php?search_id=unanswered
search.php?search_id=open
vc.php?mode=new&amp;ref_type=0

so besser? ;)


RuSsAk - Mo 12.10.09 23:14

Moderiert von user profile iconNarses: Komplett-Zitat des letzten Beitrags entfernt.
danke dir erstmal :)

aber guck mal: Moderiert von user profile iconNarses: Bild als Anhang hochgeladen.


elundril - Di 13.10.09 03:07

Hast du oben bei uses die Unit "StrUtils" stehen?

lg elundril


RuSsAk - Di 13.10.09 03:19

user profile iconelundril hat folgendes geschrieben Zum zitierten Posting springen:
Hast du oben bei uses die Unit "StrUtils" stehen?

lg elundril


ahh misst das hatte ich vergessen :oops:


ich danke euch vielmals für eure hilfe :)


[EDIT]misst habe noch ein kleines problemchen hätte vllt noch jmd ein code zur seite der doppelte wörter löscht? wenn nicht denn auch nich schlimm denn google ich mal wieder :lol:


und nochmal danke :D [/EDIT]


martin300 - Di 13.10.09 09:52

Hallo,
eine Möglichkeit ist eine TStringList und dort alle Wörter speichern. Wird das Property Duplicates auf dupIgnore gesetzt sind keine Duplikate in der Liste.


RuSsAk - Di 13.10.09 14:20

user profile iconmartin300 hat folgendes geschrieben Zum zitierten Posting springen:
Hallo,
eine Möglichkeit ist eine TStringList und dort alle Wörter speichern. Wird das Property Duplicates auf dupIgnore gesetzt sind keine Duplikate in der Liste.


kennst du vllt eine leichtere methode?

mfg,


martin300 - Di 13.10.09 15:22

sieh dir das an:

http://delphi.about.com/od/delphitips2009/qt/remove-duplicat.htm

oder du prüfst beim Einfügen ob der Eintrag schon vorhanden ist. Dafür eignet sich

Delphi-Quelltext
1:
IndexOf(....)                    

bei der TStringList.

Das Ergebnis vom Code weiter oben ist übrigens schon in einer TStringList gespeichert. :wink: