User since
2007-01-05
11
Artikel
BenutzerIn
Hallo,
ich habe ein Script geschrieben, das aus HTML-Dateien den reinen ASCII-Text extrahiert und anschließend abspeichert, welche Wörter mit welchen Anfangsbuchstaben auf welcher Seite zu finden sind. Dazu werden 39 Index-Dateien verwendet, in denen jeweils nur Wörter mit einem Anfangsbuchstaben bzw. -zeichen ( 0-9, a-z, ä, ö, ü ) auftauchen, in jeder Zeile die Wörter einer Datei. Beispiel:
In der Datei "d" findet sich dann etwa die Angabe:
Seite 1: dach, debatte, denkpause, ...
Seite 2: demenz, dieter, dortmund, durchschnitt, ...
.....
Seite n: david, diagnose, ...
Das Script läuft, es ist für meinen Geschmack nur recht zeitaufwändig, braucht auf einem Unix-Server knapp 3 Sekunden, um bei knapp 800 HTML-Dateien den HTML-Code zu entfernen, Stopwörter zu löschen usw. und dann alle Wörter aus den HTML-Seiten in den 39 Index-Seiten zu speichen.
Ich hatte das Ganze ursprünglich mal mit 2 Hashes gelöst, also für jede HTML-Seite:
- HTML-Code raus, Stopwörter raus, HTML-Sonderzeichen umwandeln in deutsche Umlaute usw.
- Dann für jedes Wort den Anfangsbuchstaben ermitteln, und das Wort auf einen Hash packen
- Wenn alle Wörter abgearbeitet sind, einen zweiten Hash verwenden, der als key ebenfalls Anfangsbuchstaben/-zahlen verwendet, aber die Wörter aller Dateien sammelt und auch die Datei festhält. Das Ganze dauerte aber sehr lange, ich glaube es waren 12 Sekunden.
Ich habe jetzt eine Lösung, die schneller ist, aber immer noch für 800 Dateien mit ca. 3 MB 3 Sekunden braucht. Ich gehe Datei für Datei und Wort für Wort vor. Die Wörter kommen dann nacheinander in einen array. Ich simuliere dabei einen zweidimensionalen array, mit 39 Zeilen ( 0-9, a-z, ä, ö, ü ) und 800 Spalten (=Dateien). Das Wort "Anton" aus Datei Nr. 12 kommt in $array[8811], bzw. allgemeiner:
$array[$position * $anzahl_dateien + $datei_nummer - 1] .= "$wort ";
wobei $position die laufende Nummer (0 ... 38) für den Anfangsbuchstaben (0-9, a-z, ä, ö, ü) des Wortes ist.
Das geht jetzt schon deutlich schneller, wie gesagt 3 Sekunden.
Trotzdem die Frage: Mache ich das noch umständlich, weiß jemand einen schnelleren Perl-Algorithmus?
PerlCharly\n\n
<!--EDIT|perlcharly|1182408314-->
User since
2007-05-11
923
Artikel
HausmeisterIn
Wieso machst du dir die ganze Arbeit?
Du könntest den ganzen Text doch einfach in eine Datenbank schieben, und die einen Index bauen lassen.
Und ich hoffe, du kennst
HTML::Strip ;-)
User since
2007-01-05
11
Artikel
BenutzerIn
Tja, das wär schön, aber geht leider für meine Zwecke nicht. Das Script (mit Funktion Indexieren + Suchen) soll von mehreren Freunden/Kollegen für ihre Homepage verwendet werden. Und die haben leider null Ahnung von MySQL odere anderen DB-Geheimnissen. Ihnen das Perl-Script zu installieren geht fix, bzw. können sie selbst. Sie in MySQL zu unterrichten (und bei Problemen zur Seite zu stehen), ist nicht meine liebste Freizeitbeschäftigung.
User since
2006-03-29
1520
Artikel
BenutzerIn
Oder spezielle Open Source Search Engines Nutzen.
http://swish-e.org/
Zu Swish-e gab es auch im Perl Snapshot vom Mike Schilli mal ein Skript wo er dies benutzt hat. Ansonsten gibt es da sogar etwas im CPAN.
HTML::Index
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
User since
2005-01-17
14761
Artikel
Admin1
Ich würde lynx verwenden und den Text dann in Wörter zerlegen ;)
$text=`lynx -dump http://example.org`;
User since
2007-03-26
47
Artikel
BenutzerIn
Hallo perlcharly,
entschuldigung, falls diese Frage zu dumm ist: Welcher Art sind denn die Suchanfragen, die du beantworten willst?
Grüße,
User since
2007-01-05
11
Artikel
BenutzerIn
Hi, es geht um eine Volltextsuche, darum das Indexieren nach Wörtern. Es ist aber noch etwas komplizierter, weshalb ich auch keine fertigen Freeware-Scripts verwenden kann, u.a. sollen nicht die kompletten HTML-Seiten oder Links dazu als Suchergebnis ausgegeben werden, sondern nur Teile der HTML-Seiten (einzelne Artikel).
perlcharly
User since
2006-07-10
2611
Artikel
BenutzerIn
Ohne einene Indexdatei wirst du nicht viel schneller werden können. Da bei jedem Scriptstart der Index neu aufgebaut werden muß.
Wenn du aber einen Schon geparsten Index Lädst und nur die Änderungen hinzufügst, und den neuen Index für den nächsten Scriptstart speicherst, sparst du dir eine Menge Zeit. Über die Modifikationszeit kannst du herausfinden welche Dateien neu indiziert werden müssen.
Und wenn es wirklich Schnell gehen soll, eportiere den bisherigen Index mit Data::Dumper, oder etwas selbstgeschriebenen, in eine Datei und importiere es am Scriptanfang mit "eval" (oder ähnlichem z.B. "require" wenn du selbst was geschrieben hast.)
"Data::Dumper" und "eval" ist hier sehr paktisch, da der Perlinterpreter das Parsen der Indexdatei übernimmt und das sehr viel schneller macht als du es mit mit einem pure-perl Parser machen könntest.
Das ganze hat natürlich auch ein paar Haken.
So ist es nicht ganz risikolos "eval" zu benutzen. Dann könnte es Probleme geben, wenn das Script zeitgleich mehrfach gestartet wird, b.z.w. den neuen Index speichern wollen. (du mußt ein Fehlverhalten bei "open" und "print" abfangen, b.z.w. die geöffnete Indexdatei Sperren)
Einen schnelleren Weg wüßte ich nicht. Selbst mit einer Datenbank bist du langsamer. :-)
User since
2006-03-29
1520
Artikel
BenutzerIn
@topeg
Ich wüste einen schnelleren Weg. ;) Anstatt Data::Dumper einfach Storable nutzen was glaube ich zu 6000% oder so schneller ist.
Auch ist das Speichern und vorallem das Einlesen deutlich einfacher und schneller:
"store \%data, 'file'"
und
"$data = retrieve 'file'"
Quote(du mußt ein Fehlverhalten bei "open" und "print" abfangen, b.z.w. die geöffnete Indexdatei Sperren)
Dafür kann man ja mit flock() die Datei Sperren. Wenn man das in seinem Programm nutzt dann blockt ein open() solange bis die Datei wieder frei wird. ( Oder blockt das flock()? Hmm, weiß niht mehr wie das genau war...)\n\n
<!--EDIT|sid burn|1182465556-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
User since
2006-07-10
2611
Artikel
BenutzerIn
Stimmt, sollte nicht mehr so spät solche Behauptungten aufstellen. :-)