Einzelnen Beitrag anzeigen

Novo

Registriert seit: 27. Mai 2007
122 Beiträge
 
Delphi 7 Enterprise
 
#1

PosExUltra - Ultimative Stringsuche/Parser

  Alt 21. Feb 2010, 15:19
Wenn ihr schon immer mal eine Funktion gebraucht habt, die euch Webseiten und große Texte parsen/filtern/auslesen kann,
OHNE dass ihr ewig euch mit Pos und PosEx rumärgern müsst, dann hat eure Suche ein Ende!

PS:
Für Verbesserungen, optimierungen wären wir sehr Dankbar!

Delphi-Quellcode:
{
* --------------------------------------------------------------------------------------
* "THE BEER-WARE LICENSE"
* YaNNiC und Novo schrieben diese Datei. Solange Sie diesen Vermerk nicht entfernen,
* können Sie mit der Datei machen, was Sie möchten. Wenn wir uns eines Tages treffen
* und Sie denken, die Datei ist es wert, können Sie mir dafür ein Bier ausgeben.
* Wir hatten auf jeden Fall genug davon, als wir diese Funktion geschrieben haben :D
* --------------------------------------------------------------------------------------
}


procedure PosExUltra(source, searchwordbefore, searchwordafter, addbefore, addafter: string; continuesearch, reversesearch: boolean; liste: Tstringlist);
var
  Anfang, Ende, Posi: Integer;
  Ergebnis: string;
begin
  if reversesearch then
  begin //if reversesearch = true:
    if continuesearch then
    begin //if continuesearch = true:
      Ende := 0;
      while PosEx(searchwordafter, source, ende) > 0 do
      begin
        Anfang := PosEX(searchwordafter, source, Ende);
        Posi := Anfang;
        if Anfang > 0 then
        begin
          while (PosEX(searchwordbefore, source, Posi) = 0) or (PosEX(searchwordbefore, source, Posi) > Posi) do
          begin
            Dec(Posi);
          end;
          Ergebnis := Copy(source, Posi + length(searchwordbefore), Anfang - (Posi + length(searchwordbefore)));
          if (Ergebnis <> '') or (Ergebnis <> ' ') then liste.Add(addbefore + Ergebnis + addafter);
          Ende := Posi + length(searchwordbefore) + Length(Ergebnis) + Length(searchwordafter);
        end;
      end;
    end
    else //if continuesearch = false:
    begin
      Ende := 0;
      Anfang := PosEX(searchwordafter, source, Ende);
      Posi := Anfang;
      if Anfang > 0 then
      begin
        while (PosEX(searchwordbefore, source, Posi) = 0) or (PosEX(searchwordbefore, source, Posi) > Posi) do
        begin
          Dec(Posi);
        end;
        Ergebnis := Copy(source, Posi + length(searchwordbefore), Anfang - (Posi + length(searchwordbefore)));
        if (Ergebnis <> '') or (Ergebnis <> ' ') then liste.Add(addbefore + Ergebnis + addafter);
      end;
    end;
  end
  else //if reversesearch = false:
  begin
    if continuesearch then
    begin //if continuesearch = true:
      Ende := 0;
      Anfang := PosEX(searchwordbefore, source, Ende);
      while Anfang > 0 do
      begin
        Anfang := PosEX(searchwordbefore, source, Ende);
        if Anfang > 0 then
        begin
          Ende := PosEX(searchwordafter, source, Anfang);
          Ergebnis := Copy(source, Anfang + length(searchwordbefore), (Ende - Anfang) - length(searchwordbefore));
          if (Ergebnis <> '') or (Ergebnis <> ' ') then liste.Add(addbefore + Ergebnis + addafter);
          Anfang := Anfang + length(Ergebnis);
        end;
      end;
    end
    else //if continuesearch = false:
    begin
      Ende := 0;
      Anfang := PosEX(searchwordbefore, source, Ende);
      if Anfang > 0 then
      begin
        Ende := PosEX(searchwordafter, source, Anfang);
        Ergebnis := Copy(source, Anfang + length(searchwordbefore), (Ende - Anfang) - length(searchwordbefore));
        if (Ergebnis <> '') or (Ergebnis <> ' ') then liste.Add(addbefore + Ergebnis + addafter);
      end;
    end;
  end;
end;
Erklärung:
Code:
procedure PosExUltra(source, searchwordbefore, searchwordafter, addbefore, addafter: string; continuesearch, reversesearch: boolean; liste: Tstringlist);

In "source" befindet sich der große Text, den man Filtern möchte.
"searchwordbefore" ist der Text, der sich VOR dem Wort was man will befindet.
"searchwordafter" ist der Text, der sich NACH dem Wort was man will befindet.
"addbefore" ist der Text, den man alternativ VOR dem GEFUNDENEN Wort anhängt.
"addafter" ist der Text, den man alternativ NACH dem GEFUNDENEN Wort anhängt.
"continuesearch": Es durchsucht den gesamten Text, wenn es MEHRERE Ergebnisse gibt (z.B. ALLE URLS),
bei False bricht es nach dem 1. Fund ab.
"reversesearch": Wenn "searchwordbefore" zu klein oder zu allgemein (zu oft vorkommend, oder gar variabel ist),
dann sucht es erst nach "searchwordafter" und geht dann rückwärts, bis er "searchwordbefore" gefunden hat.
Bsp: <ID=20>TEXT1<hierimmergleich> <ID=25>TEXT2<hierimmergleich> <ID=30>TEXT3<hierimmergleich> und man möchte alle!
How To Use:
Delphi-Quellcode:
  uses ... StrUtils;

  public
    stringlist: TStringList;

---

  stringlist := TStringList.Create;
  source := 'groooßer Text mit Inhalt was ich will';

  // wahlweise Absätze und Leerzeichen entfernen, um ein Besseres Ergenbis zu bekommen oder
  // weiteren Text zur Filterung zu erhalten:
  //source := StringReplace(source, ''#$A'', '', [rfReplaceAll]);
  //source := StringReplace(source, ''#13'', '', [rfReplaceAll]);
  //source := StringReplace(source, ' ', '', [rfReplaceAll]);

                                          //continue, reverse
  PosExUltra(source, 'VORDEMTEXT', 'NACHDEMTEXT', '', '', true, false, stringlist);
  
  stringlist.free;
Beispiele:

Einfache Vorwärtssuche bei eindeutigen Worten:
Delphi-Quellcode:
source := '<text>DASWILLICH</text>';
PosExUltra(source, '<text>', '</text>', '', '', true, false, stringlist);
//Suchwörter für Anfang und Ende sind leicht Filterbar, man kann vorwärts suchen.
Man möchte alle URL Links, die mit .com aufhören haben:
Delphi-Quellcode:
source := 'blatext xD [url]http://imagexxx.com[/url] und weiter text';
PosExUltra(source, 'http://', '.com', 'http://', '.com', true, false, stringlist);
//Suchwörter für Anfang und Ende sind leicht Filterbar, man kann vorwärts suchen.
//Da "http://" und ".com" abgeschnitten werden, fügen wir das dem gefundenen Wort nacher wieder an.
Schwierige Stelle zum Suchen: Die Rückwärtssuche!

Nehmen wir an, der Text wäre:
Code:
source :=
<td>[url="?content=dictionary&amp;task=term&amp;dir=bla&amp;ID=456"]DASWILLICH[/url]</td>
      <td style="line-height: 6pt;">
Der Anfangs und End Suchwert wäre:
Anfang: '">'
Ende: '</a></td>'
Das würde nicht funktionieren, da Anfang SEHR häufig vorkommt.
Also geht man zuerst so vor:

Delphi-Quellcode:
source := StringReplace(source, ''#$A'', '', [rfReplaceAll]);
source := StringReplace(source, ''#13'', '', [rfReplaceAll]);
source := StringReplace(source, ' ', '', [rfReplaceAll]);
Das würde dann so aussehen:
Code:
source := <td>[url="?content=dictionary&amp;task=term&amp;dir=bla&amp;ID=456"]DASWILLICH[/url]</td><tdstyle="line-height:6pt;">
nun kann man einfach die Rückwärtssuche bemühen, sie sucht zuerst nach Ende, und geht dann rückwärts bis er Anfang findet:

Delphi-Quellcode:
source := '<td>[url="?content=dictionary&amp;task=term&amp;dir=bla&amp;ID=456"]DASWILLICH[/url]</td><tdstyle="line-height:6pt;">';
PosExUltra(source, '">', '</a></td><tdstyle="line-height:6pt', '', '', true, true, stringlist);


Mfg Novo
Takeo
Don't make me angry...
You wouldn't like me when I'm angry!
Blut ist leben, Leben ist Blut, ins Licht geboren suchen wir die Dunkelheit!
  Mit Zitat antworten Zitat