Delphi-PRAXiS
Seite 1 von 5  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi PosExUltra - Ultimative Stringsuche/Parser (https://www.delphipraxis.net/148055-posexultra-ultimative-stringsuche-parser.html)

Novo 21. Feb 2010 15:19


PosExUltra - Ultimative Stringsuche/Parser
 
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

himitsu 21. Feb 2010 15:32

Re: PosExUltra - Ultimative Stringsuche/Parser
 
Sowas wie
Delphi-Quellcode:
if reversesearch = true then
bitte durch
Delphi-Quellcode:
if reversesearch then
ersetzen (die Gründe wurden schon oft im Forum erwähnt)

Und der Name ist definitiv verwirrend, denn gesucht wird hier nix, also nicht entsprechend des Funktionsergebnisses.
StringReplaceUltra wäre da schon besser.

Novo 21. Feb 2010 15:37

Re: PosExUltra - Ultimative Stringsuche/Parser
 
Zitat:

Zitat von himitsu
Sowas wie
Delphi-Quellcode:
if reversesearch = true then
bitte durch
Delphi-Quellcode:
if reversesearch then
ersetzen (die Gründe wurden schon oft im Forum erwähnt)

Was ist denn der Grund?

Zitat:

Zitat von himitsu
Und der Name ist definitiv verwirrend, dann ggesucht wird hier nix, also nicht entsprechend des Funktionsergebnisses.
StringReplaceUltra wäre da schon besser.

Hm?
Klar wird hier gesucht!
ist sozusagen eine bessere PosEx -> PosExUltra :)

Matze 21. Feb 2010 15:40

Re: PosExUltra - Ultimative Stringsuche/Parser
 
Jupp, "StringReplace" wäre falsch. Es wird zwar nicht die Position zurückgegeben (also doch eher kein "PosEx"), aber es wird gesucht.

Zitat:

Zitat von Novo
Was ist denn der Grund?

Über den Umgang mit Boolean

Deine Funktion sieht viel versprechend aus bzw. was sie alles kann. Kannst du etwas über die Performance sagen, da du schreibst, sie sei für große Texte geeignet?
Es gibt zahlreiche, schnelle Suchalgorithmen (Rabin-Karp & Co.), aber du verwendest keinen davon, wenn ich das richtig sehe.

alzaimar 21. Feb 2010 15:43

Re: PosExUltra - Ultimative Stringsuche/Parser
 
Das ist eine nette Funktion. Nenne sie doch lieber
Delphi-Quellcode:
Function PosEierlegendeWollmilchSau
Der Zusatz 'Ultra' erinnert so an Waschmittel.

Im Ernst: Was kann die Funktion, was ein TRegExpr nicht kann?

Novo 21. Feb 2010 15:45

Re: PosExUltra - Ultimative Stringsuche/Parser
 
Zitat:

Zitat von Matze
Deine Funktion sieht viel versprechend aus bzw. was sie alles kann. Kannst du etwas über die Performance sagen, da du schreibst, sie sei für große Texte geeignet?
Es gibt zahlreiche, schnelle Suchalgorithmen (Rabin-Karp & Co.), aber du verwendest keinen davon, wenn ich das richtig sehe.

Nunja die Performance hängt ganz nach dem Aufbau der suchquelle ab, ob du vorwärts oder Rückwärts suchen musst, und natürlich auch wie viele Zeichen dein searchwordbefore und searchwordafter hat.

Ein Beispiel:

http://dict-navi.com/api.php
800 Wörter -> Vorwärts -> SAUSCHNELL
( ja ich weis ist XML, dazu gibts ne XML Komponente, die bekomm ich aber partout nicht zum laufen :( FAIL )

http://dict-navi.com/?content=dictio...=list&type=all
Das gleiche mit ebenfalls 800 Wörter -> Rückwärtssuche nötig -> 30 Sekunden lang 25% CPU auslastung :D

Sind aber schon heftig viele Zeilen.

Wenn man z.B. Quellcode von Youtube parst, um die Video ID zu finden, ist das ruckzuck!


Zitat:

Zitat von alzaimar
Im Ernst: Was kann die Funktion, was ein TRegExpr nicht kann?

ähm z.B. das einfache und komfortable universelle einsetzen, OHNE Regular Expression Regeln zu kennen?

himitsu 21. Feb 2010 15:52

Re: PosExUltra - Ultimative Stringsuche/Parser
 
Ich hätte aer noch was:
Delphi-Quellcode:
Application.ProcessMessages;
Dieses hat in soeiner Funktion besser nichts drin zu suchen.

Novo 21. Feb 2010 15:53

Re: PosExUltra - Ultimative Stringsuche/Parser
 
Zitat:

Zitat von himitsu
Ich hätte aer noch was:
Delphi-Quellcode:
Application.ProcessMessages;
Dieses hat in soeiner Funktion besser nichts drin zu suchen.

ok dann mach ich sie raus, aber dann freezed halt bei großen Texten solang die Form, das ist auch nicht schön.

Namenloser 21. Feb 2010 15:56

Re: PosExUltra - Ultimative Stringsuche/Parser
 
Zitat:

Zitat von Novo
ok dann mach ich sie raus, aber dann freezed halt bei großen Texten solang die Form, das ist auch nicht schön.

Die sauberere Lösung wäre in dem Fall eh, die Funktion in einem zweiten Thread auszuführen.

Novo 21. Feb 2010 16:00

Re: PosExUltra - Ultimative Stringsuche/Parser
 
Zitat:

Zitat von NamenLozer
Die sauberere Lösung wäre in dem Fall eh, die Funktion in einem zweiten Thread auszuführen.

Das einzige, was ich je Threaded gemacht habe, war ein idhhttp.get :D
Mal schaun, ob das denn funktioniert, bin mal weiter am Rumbasteln.
Falls du es schon kannst, codeschnipsel :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:51 Uhr.
Seite 1 von 5  1 23     Letzte »    

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