Text auf Wortliste durchsuchen
Text auf Wortliste durchsuchen
am 27.02.2006 00:10:53 von ch_pingel
Hallo,
ich möchte bei meinem Gästebuch einen Spamfilter einbauen - dafür
habe ich eine Liste mit Wörtern bzw. Wortgruppen - jetzt möchte ich
neue Einträge checken, ob dort eines der Wörter/Wortgruppen drin
enthalten ist - wenn es so ist, wird der Eintrag nicht eingetragen.
Man könnte natürlich jetzt ne Schleife über ein Array mit der Liste
laufen lassen und jede Wortgruppe gegen den Text prüfen ... aber die
Variante ist sicherlich die langsamste.
Weiß jemand eine andere Variante, die eventuell schneller ist ?
MFG,
Christoph Pingel
Re: Text auf Wortliste durchsuchen
am 27.02.2006 07:27:19 von Helmut Wollmersdorfer
ch_pingel@gmx.de wrote:
> Man könnte natürlich jetzt ne Schleife über ein Array mit der Liste
> laufen lassen und jede Wortgruppe gegen den Text prüfen ... aber die
> Variante ist sicherlich die langsamste.
> Weiß jemand eine andere Variante, die eventuell schneller ist ?
Du zerlegst den Text in Worte, was mit 'split' grösstenteils
funktioniert, und schaust ganz einfach in Deinem Stop-Wort-Hash nach.
Hier auf die Schnelle ein Snippet, das zwar einem anderen Zweck dient,
aber brauchbar sein müsste:
my @word_list = split (/ /, $content);
for my $word ( @word_list ) {
$TOTAL_WORDS++;
$word =~ s/(.+[\w\'\"\)\]\}])[\.\:\!\;\,\?]*/$1/g;
my $lowerword = lc $word;
$lowerword =~ s/\W//g; # remove all non-wordy
if (exists $STOP_WORDS_HASH{$lowerword}) { ... }
else {
...
}
Hashes sind sehr schnell, und obige Methode vermeidet Zehnerpotenzen von
unnötigen Match-Versuchen.
Helmut Wollmersdorfer
Re: Text auf Wortliste durchsuchen
am 27.02.2006 07:29:16 von Frank Haschick
Am 27.02.2006, 00:10 Uhr, schrieb :
> Hallo,
Hallo,
> ich möchte bei meinem Gästebuch einen Spamfilter einbauen - dafür
> habe ich eine Liste mit Wörtern bzw. Wortgruppen - jetzt möchte ich
> neue Einträge checken, ob dort eines der Wörter/Wortgruppen drin
> enthalten ist - wenn es so ist, wird der Eintrag nicht eingetragen.
>
> Man könnte natürlich jetzt ne Schleife über ein Array mit der Liste
> laufen lassen und jede Wortgruppe gegen den Text prüfen ... aber die
> Variante ist sicherlich die langsamste.
>
> Weiß jemand eine andere Variante, die eventuell schneller ist ?
Also ob es schneller ist weiß ich leider nicht, aber probieren könntest du
es indem du dir mit oder-Verknüpfungen einen regulären Ausdruck
zusammenbastelst.
Rauskommen sollte dann irgendwas wie
if (gbeintrag =~ /böseswort1|böseswort2|böseswort3|böseswort4/)
{
nicht_eintragen();
} else
{
eintragen();
}
Aber wie gesagt, keine Ahnung ob das schneller geht.
>
> MFG,
> Christoph Pingel
HTH,
Frank
Re: Text auf Wortliste durchsuchen
am 27.02.2006 18:38:22 von ch_pingel
Hi,
das ist zwar eine gute Idee, aber in dem Fall kann ich keine
Wortgruppen erkennen. Also ganz konkret das Beispiel "viagra online".
Und einfach nur beim Vorkommen von "viagra" oder "online" Alarm zu
schlagen, halte ich nicht für gut, denn es könnte das Wort ja auch in
einem normalen Beitrag verwendet werden, der kein Spam ist.
Bekommst solch Problematik auch noch irgendwie in deiner Idee mit unter
?
MFG,
Christoph Pingel
Re: Text auf Wortliste durchsuchen
am 27.02.2006 21:43:29 von Slaven Rezic
ch_pingel@gmx.de writes:
> Hallo,
>
> ich möchte bei meinem Gästebuch einen Spamfilter einbauen - dafür
> habe ich eine Liste mit Wörtern bzw. Wortgruppen - jetzt möchte ich
> neue Einträge checken, ob dort eines der Wörter/Wortgruppen drin
> enthalten ist - wenn es so ist, wird der Eintrag nicht eingetragen.
>
> Man könnte natürlich jetzt ne Schleife über ein Array mit der Liste
> laufen lassen und jede Wortgruppe gegen den Text prüfen ... aber die
> Variante ist sicherlich die langsamste.
>
> Weiß jemand eine andere Variante, die eventuell schneller ist ?
>
Du könntest eine optimierte Regexp einmalig bauen lassen, z.B. mit
Regexp::Optimizer oder etwas auf Basis von Text::Trie.
Gruß,
Slaven
--
Slaven Rezic - slaven rezic de
need xpm or ppm output from GD?
http://search.cpan.org/search?mode=module&query=GD::Convert
Re: Text auf Wortliste durchsuchen
am 28.02.2006 00:05:26 von Helmut Wollmersdorfer
ch_pingel@gmx.de wrote:
> das ist zwar eine gute Idee, aber in dem Fall kann ich keine
> Wortgruppen erkennen. Also ganz konkret das Beispiel "viagra online".
> Und einfach nur beim Vorkommen von "viagra" oder "online" Alarm zu
> schlagen, halte ich nicht für gut, denn es könnte das Wort ja auch in
> einem normalen Beitrag verwendet werden, der kein Spam ist.
> Bekommst solch Problematik auch noch irgendwie in deiner Idee mit unter
> ?
Ja, wird dadurch aber etwas langsamer, jedoch immer noch wesentlich
schneller als _jedes_ Muster auszuprobieren.
- Du speicherst die Muster in einem HashOfHashes, mit den ersten n
Zeichen des Musters als Key.
- Du durchwanderst den Text, indem Du immer das erste Wort
weg-'split'est, und mit den ersten n Zeichen des Restes in den Hash
gehst, und dort alle Muster in einer Schleife am Rest des Textes
durchprobierst.
Wie gross das optimale n sein muss, hängt von der Anzahl der Muster und
der Textmenge ab. In meinem Fall (Logzeilen mit durchschnittlich 200
Zeichen, ca. 3000 Muster) lag das laufzeitminimale 'n' bei 40. Bei 30
Mio. Logzeilen täglich zahlt sich so eine Heuristik aus - die CPU läuft
trotzdem ca. 100 min auf Volllast.
Bei ein paar tausend Zeilen pro Tag und ein paar hundert Mustern tät ich
garnicht viel optimieren - Perl ist sauschnell.
Helmut Wollmersdorfer
Re: Text auf Wortliste durchsuchen
am 04.03.2006 00:12:22 von ch_pingel
Hallo,
also ich habe das jetzt mit Regex::Optimizer gemacht bzw. Regex::List
reichte mir auch.
Aber jetzt mal eine ganz interessante Frage dazu - wenn ich eine Liste
von realistischen 400 Wörtern/Wortgruppen habe, die ich per
Regex::List zu einer optimierten Regel bauen lasse. ....
Wie lang darf eigentlich eine RegEx werden ? - gibt es da eine
Begrenzung ? Sollte ich eventuell die Liste in je 100 oder so
unterteilen und dann nen Array mit den generierten RegEx anlegen, um
die nacheinander durchzutesten ?
Bei 53 Wörtern/Wortgruppen kommt schon solch nette lange RegEx raus -
wie mag das erst bei 400 sein:
(?-xism:(?i:(?=3D[abcdehijlopsuvw])(?:a(?:lprazolam|tivan\s+ online)|b(?:fed=
\(?:biz|info|nl)|uy\s+(?:v(?:i(?:agra|codin)|alium)|ativa n|cialis|loraze=
pam))|c(?:heap\s+(?:v(?:i(?:agra|codin)|alium)|ativan|cialis |lorazepam)|ial=
is\s+(?:online|soft\s+tabs)|asino\-tribune|lonazepam)|discou nt\s+(?:v(?:i(?=
:agra|codin)|alium)|ativan|cialis|lorazepam)|j(?:ournalspace |uicy\-pussy\-p=
ix)\.com|o(?:nline(?:\s+(?:v(?:i(?:agra|codin)|alium)|ativan |cialis|lorazep=
am)|\-casino)|rder\s+(?:v(?:i(?:agra|codin)|alium)|ativan|ci alis|lorazepam)=
)|v(?:i(?:agra|codin)\s+online|alium\s+online)|(?:(?:ephedr| lorazepam\s+onl=
|phenterm)i|hydrocodo)ne|ionamin|spycounter\.net|(?:unglaubl ichkeiten|wet\-=
videos)\.com)))
MFG,
Christoph Pingel
Re: Text auf Wortliste durchsuchen
am 04.03.2006 08:11:23 von Frank Seitz
ch_pingel@gmx.de wrote:
> Wie lang darf eigentlich eine RegEx werden ? - gibt es da eine
> Begrenzung ?
Perl kann beliebig lange Zeichenketten verarbeiten.
Ich gehe davon aus, dass dies auch für Reguläre Ausdrücke gilt.
Die Grenze dürfte also der zur Verfügung stehende Speicher sein.
> Sollte ich eventuell die Liste in je 100 oder so
> unterteilen und dann nen Array mit den generierten RegEx anlegen, um
> die nacheinander durchzutesten ?
Mit Sicherheit nicht, denn das würde dem Gedanken des Moduls
zuwider laufen.
> Bei 53 Wörtern/Wortgruppen kommt schon solch nette lange RegEx raus -
> wie mag das erst bei 400 sein:
[langer Regex]
Schau mal in den Abschnitt BENCHMARK in Regexp::List.
Der Autor wendet das Modul da auf ein Wörterbuch mit 235881 Einträgen an.
Es sieht also nicht so aus, als müsstest Du Dir bei 400 Wörtern
irgendwelche Sorgen machen.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Text auf Wortliste durchsuchen
am 04.03.2006 12:10:01 von Slaven Rezic
ch_pingel@gmx.de writes:
> Hallo,
>
> also ich habe das jetzt mit Regex::Optimizer gemacht bzw. Regex::List
> reichte mir auch.
>
> Aber jetzt mal eine ganz interessante Frage dazu - wenn ich eine Liste
> von realistischen 400 Wörtern/Wortgruppen habe, die ich per
> Regex::List zu einer optimierten Regel bauen lasse. ....
>
> Wie lang darf eigentlich eine RegEx werden ? - gibt es da eine
> Begrenzung ? Sollte ich eventuell die Liste in je 100 oder so
> unterteilen und dann nen Array mit den generierten RegEx anlegen, um
> die nacheinander durchzutesten ?
>
> Bei 53 Wörtern/Wortgruppen kommt schon solch nette lange RegEx raus -
> wie mag das erst bei 400 sein:
>
Perl hat eigentlich keine Einschränkungen, außer diejenigen, die das
Betriebssystem oder die Hardware auferlegt. Eigentlich, weil es hier
und da tatsächlich welche gibt:
$ perl5.8.8 -we '$x=~m{a{1,32767}}'
Quantifier in {,} bigger than 32766 in regex; marked by <-- HERE in
m/a{ <-- HERE 1,32767}/ at -e line 1.
Aber ich glaube, dass du noch weit von etwaigen Einschränkungen
entfernt bist.
Gruß,
Slaven
--
Slaven Rezic - slaven rezic de
sf-upload: make batch releases on SourceForge
http://sf-upload.sf.net