Mnogosearch installieren
Die Suchmaschine für die eigene Webseite
Mnogosearch ist eine Suchmaschine, die bei Hostsharing als Debian Paket installiert ist und für die eigene Webseite verwendet werden kann. Die bei HS installierte Version verwendet SQLite als Datenbank und ist für Webseiten bis einige hundert Seiten und Traffic, wie er auf einem Shared-Webserver vorkommt, gut geeignet.
Hier wird die Grundinstallation beschrieben. Mnogosearch ist eine sehr umfangreiche Software mit mannigfaltigen Konfigurationsmöglichkeiten. Für die weitergehende Konfiguration muß auf die Dokumentation von Mnogosearch verwiesen werden.
Mnogosearch ist sehr mächtig (und kann vor allen Dingen mit Unicode umgehen), es können viele Dinge eingestellt werden. In dieser Konfiguration funktioniert der indexer als "Crawler", er surft die eigene Webseite ab und speichert die Einträge für spätere Suchergebnisse. Dabei beachtet er die /robots.txt.
Es kann aber auch das Dateisystem durchsucht werden, es können Bereiche der Webseite ausgeschlossen werden und es können Sektionen in Webseiten definiert werden, die für die Auflistung der Suchergebnisse als wichtiger gewertet werden. Diese Dinge müssen zusätzlich konfiguriert werden. Dies ist nur eine Grundkonfiguration, die aber in den meisten Fällen ausreichen dürfte.
Installation
Für die Datenbank und die Konfigurationsdatei wird am besten pro Domain ein Verzeichnis "mnogosearch" eingerichtet und da die Konfigurationsdatei indexer.conf erstellt. Diese Datei kann auch von /etc/mnogosearch/indexer.conf kopiert werden und muss dann entsprechend geändert werden.
# cd /home/doms/example.com # mkdir mnogosearch # cd mnogosearch # touch indexer.conf # edit indexer.conf
Inhalt der Basis indexer.conf
Dies ist die stark gekürzte und auf das Notwendigste reduzierte Fassung. Ganz zu Beginn wird die Datenbankdatei und am Ende der zu indizierende Webserver definiert:
########################################################################### # DBAddr <URL-style database description> # Options (type, host, database name, port, user and password) # to connect to SQL database. # Should be used before any other commands. # Has global effect for whole config file. # Format: #DBAddr <DBType>:[//[DBUser[:DBPass]@]DBHost[:DBPort]]/DBName/[?dbmode=mode] DBAddr sqlite://mnogo:@/home/doms/example.com/mnogosearch/mnogosearch.db/?dbmode=multi # Default LocalCharset is iso-8859-1 (latin1). # Full UNICODE # Folgendes auskommentieren für UTF8 # LocalCharset UTF-8 ########################################################################### # StopwordFile <filename> # Load stop words from the given text file. You may specify either absolute # file name or a name relative to mnoGoSearch /etc directory. You may use # several StopwordFile commands. # StopwordFile stopwords/de.sl ####################################################################### # HTTPHeader <header> # You may add your desired headers in indexer HTTP request. # You should not use "If-Modified-Since","Accept-Charset" headers, # these headers are composed by indexer itself. # "User-Agent: mnoGoSearch/version" is sent too, but you may override it. # Command has global effect for all configuration file. # HTTPHeader "User-Agent: example.com-indexer" ########################################################################## # Section 2. # URL control configuration. # Allow Configuration # Examples # Allow everything: #Allow * # Allow everything but .php .cgi .pl extensions case insensitively using regex: #Allow NoMatch Regex \.php$|\.cgi$|\.pl$ # Allow .HTM extension case sensitively: #Allow Case *.HTM Allow *.html ########################################################################## #Disallow [Match|NoMatch] [NoCase|Case] [String|Regex] <arg> [<arg> ... ] # # Examples: # Disallow URLs that are not in udm.net domains using "string" match: #Disallow NoMatch *.udm.net/* # Disallow any except known extensions and directory index using "regex" match: #Disallow NoMatch Regex \/$|\.htm$|\.html$|\.shtml$|\.phtml$|\.php$|\.txt$ # Exclude cgi-bin and non-parsed-headers using "string" match: #Disallow */cgi-bin/* *.cgi */nph-* # Exclude anything with '?' sign in URL. Note that '?' sign has a # special meaning in "string" match, so we have to use "regex" match here: #Disallow Regex \? # Exclude some known extensions using fast "String" match: Disallow *.b *.sh *.md5 *.rpm Disallow *.arj *.tar *.zip *.tgz *.gz *.z *.bz2 Disallow *.lha *.lzh *.rar *.zoo *.ha *.tar.Z Disallow *.gif *.jpg *.jpeg *.bmp *.tiff *.tif *.xpm *.xbm *.pcx Disallow *.vdo *.mpeg *.mpe *.mpg *.avi *.movie *.mov *.wmv Disallow *.mid *.mp3 *.rm *.ram *.wav *.aiff *.ra Disallow *.vrml *.wrl *.png *.ico *.psd *.dat Disallow *.exe *.com *.cab *.dll *.bin *.class *.ex_ Disallow *.tex *.texi *.xls *.doc *.texinfo Disallow *.rtf *.pdf *.cdf *.ps Disallow *.ai *.eps *.ppt *.hqx Disallow *.cpt *.bms *.oda *.tcl Disallow *.o *.a *.la *.so Disallow *.pat *.pm *.m4 *.am *.css Disallow *.map *.aif *.sit *.sea Disallow *.m3u *.qt # Exclude Apache directory list in different sort order using "string" match: Disallow *D=A *D=D *M=A *M=D *N=A *N=D *S=A *S=D # More complicated case. RAR .r00-.r99, ARJ a00-a99 files # and UNIX shared libraries. We use "Regex" match type here: Disallow Regex \.r[0-9][0-9]$ \.a[0-9][0-9]$ \.so\.[0-9]$ ################################################################ # Section 3. # Mime types and external parsers. ################################################################ #AddType [String|Regex] [Case|NoCase] <mime type> <arg> [<arg>...] # This command associates filename extensions (for services # that don't automatically include them) with their mime types. # Currently "file:" protocol uses these commands. # Use optional first two parameter to choose comparison type. # Default type is "String" "NoCase" (case sensitive string match with # '?' and '*' wildcards for one and several characters correspondingly). # AddType image/x-xpixmap *.xpm AddType image/x-xbitmap *.xbm AddType image/gif *.gif AddType text/plain *.txt *.pl *.js *.h *.c *.pm *.e AddType text/html *.html *.htm AddType text/rtf *.rtf AddType application/pdf *.pdf AddType application/msword *.doc AddType application/vnd.ms-excel *.xls AddType text/x-postscript *.ps # Default unknown type for other extensions: AddType application/unknown *.* # Use ParserTimeOut to specify amount of time for parser execution # to avoid possible indexer hang. ParserTimeOut 300 ####################################################################### # Section 5. # Servers configuration. ####################################################################### # Document sections. # # Format is: # # Section <string> <number> <maxlen> [clone] [sep] [{expr} {repl}] # # where <string> is a section name and <number> is section ID # between 0 and 255. Use 0 if you don't want to index some of # these sections. It is better to use different sections IDs # for different documents parts. In this case during search # time you'll be able to give different weight to each part # or even disallow some sections at a search time. # <maxlen> argument contains a maximum length of section # which will be stored in database. # "clone" is an optional parameter describing whether this # section should affect clone detection. It can # be "DetectClone" or "cdon", or "NoDetectClone" or "cdoff". # By default, url.* section values are not taken in account # for clone detection, while any other sections take part # in clone detection. # "sep" is an optional argument to specify a separator between # parts of the same section. It is a space character by default. # "expr" and "repl" can be used to extract user defined sections, # for example pieces of text between the given tags. "expr" is # a regular expression, "repl" is a replacement with $1, $2, etc # meta-characters designating matches "expr" matches. # Standard HTML sections: body, title Section body 1 256 Section title 2 128 # META tags # For example <META NAME="KEYWORDS" CONTENT="xxxx"> # Section meta.keywords 3 128 Section meta.description 4 128 # HTTP headers example, let's store "Server" HTTP header # # #Section header.server 5 64 # Document's URL parts Section url.file 6 0 Section url.path 7 0 Section url.host 8 0 Section url.proto 9 0 # CrossWords Section crosswords 10 0 # # If you use CachedCopy for smart excerpts (see below), # please keep Charset section active. # Section Charset 11 32 Section Content-Type 12 64 Section Content-Language 13 16 # Uncomment the following lines if you want tag attributes # to be indexed #Section attribute.alt 14 128 #Section attribute.label 15 128 #Section attribute.summary 16 128 #Section attribute.title 17 128 #Section attribute.face 27 0 # Uncomment the following lines if you want use NewsExtensions # You may add any Newsgroups header to be indexed and stored in urlinfo table #Section References 18 0 #Section Message-ID 19 0 #Section Parent-ID 20 0 # Uncomment the following lines if you want index MP3 tags. #Section MP3.Song 21 128 #Section MP3.Album 22 128 #Section MP3.Artist 23 128 #Section MP3.Year 24 128 # Comment this line out if you don't want to store "cached copies" # to generate smart excerpts at search time. # Don't forget to keep "Charset" section active if you use cached copies. # NOTE: 3.2.18 has limits for CachedCopy size, 32000 for Ibase and # 15000 for Mimer. Other databases do not have limits. # If indexer fails with 'string too long' error message then reduce # this number. This will be fixed in the future versions. # Section CachedCopy 25 64000 # A user defined section example. # Extract text between <h1> and </h1> tags: #Section h1 26 128 "<h1>(.*)</h1>" $1 ######################################################################### #Server [Method] [SubSection] <URL> [alias] # This is the main command of the indexer.conf file. It's used # to describe web-space you want to index. It also inserts # given URL into database to use it as a start point. # You may use "Server" command as many times as a number of different # servers or their parts you want to index. # To index whole server "www.example.com": Server http://www.example.com/
Unbedingt im ganzen Dokument example.com durch den eigenen Domainnamen ersetzen!
Datenbank erstellen
Die Datenbank wird mit dem Programm indexer erstellt. Dabei muss indexer natürlich (und wie bei jedem Aufruf) der Pfad zur eigenen Konfiguration mitgeteilt werden.
# indexer -Ecreate /home/doms/example.com/mnogosearch/indexer.conf
Erster Indexlauf
# indexer -a /home/doms/example.com/mnogosearch/indexer.conf
Mit diesem Befehl wird die Datenbank gefüllt. Wir haben in der Konfigurationsdatei definiert, dass alle Seiten mit der Endung .html unter http://www.example.com/ durchsucht und indiziert werden.
Die Option -a ersetzt alle vorhandenen Einträge.
Die Suche auf der eigenen Webseite
Damit die Suche funktionieren kann, legen wir einen symbolischen Link zu dem Suchprogramm /usr/lib/cgi-bin/search.cgi in das eigene cgi-Verzeichnis:
# ln -s /usr/lib/cgi-bin/search.cgi /home/doms/example.com/cgi/search.cgi
Das zugehörige Suchformular kann entweder von /etc/mnogosearch/search.htm in das eigene Webverzeichnis kopiert und anschließend editiert werden. Wichtig ist der Verweis auf die eigene Datenbankdatei in der Sektion "variables" ganz zu Beginn:
- DBAddr sqlite://mnogo:@/home/doms/example.com/mnogosearch/mnogosearch.db/?dbmode=multi
Minimales Suchformular in Deutsch
Folgendes Formular ist bereits eingedeutscht und kann direkt als /home/doms/example.com/subs/www/suche.zhtml abgespeichert werden (man beachte die Endung "zhtml"):
# start <!--variables # Database parameters # Format: <DBType>:[//[DBUser[:DBPass]@]DBHost[:DBPort]]/DBName/[?dbmode=mode] DBAddr sqlite://mnogo:@/home/doms/example.com/mnogosearch/mnogosearch.db/?dbmode=multi # Use proper local and browser charsets # Default charset is iso-8859-1 (latin1) # which is suitable for the most Western European languages # Comment this out for iso-8859-1 LocalCharset utf-8 BrowserCharset utf-8 # Minimum and maximum word lengths # #MinWordLength 1 #MaxWordLength 32 # Number of pages in navigator bar # #PagesPerScreen 10 # How to hilight searched words. # HlBeg '<span style="background-color: #ff0; color: #f00; font-weight: bold;">' HlEnd '</span>' # Suche auf html-dokumente beschraenken ReplaceVar type "text/html" --> <!--top--> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=$&(BrowserCharset)" /> <title>Suche: $&(q)</title> <style type="text/css"> body { background-color: #fff; } a { color: #00c; } div.center { text-align: center; } table.grey { background-color: #eee; width: 100%; } table.white { background-color: #fff; width: 100%; } img.logo { border: none; } </style> </head> <body> <div class="center"> <form method="get" action=""> <table class="grey" summary=""> <tr> <td> <br /> Suche nach: <INPUT TYPE="text" NAME="q" VALUE="$&(q)" SIZE=50 /> <INPUT TYPE="submit" NAME="cmd" VALUE="Suche!" /> <br /><br /> </td> </tr> </table> </form> </div> <!--/top--> <!--restop--> <table bgcolor=#EEEEEE width=100% border=0> <tr> <td> <small>Suche nach <b>$&(q)</b>.</small> <small>Gefunden: <b>$&(WE)</b>.</small> </td> <td> <small>Ergenbisse <b>$(first)-$(last)</b> von <B>$(total)</B>.</small> <small>Die Suche dauerte <b>$(SearchTime)</b> Sekunden</small> </td> </tr> <tr><td colspan="2"> Sortieren: <!IF NAME="s" CONTENT="DRP"> <a href="$(FirstPage)&s=RPD">Relevanz</a> | <b>Datum</b> | <a href="$(FirstPage)&s=SRPD&su=title">Titel</a> <!ELSEIF NAME="s" CONTENT="SRPD"> <a href="$(FirstPage)&s=RPD">Relevanz</a> | <a href="$(FirstPage)&s=DRP">Datum</a> | <b>Titel</b> <!ELSE> <b>Relevanz</b> | <a href="$(FirstPage)&s=DRP">Datum</a> | <a href="$(FirstPage)&s=SRPD&su=title">Titel</a> <!ENDIF> </td></tr> </table> <!--/restop--> <!--res--> <DL> <!IFNOT NAME="Alias" CONTENT=""><!COPY NAME="URL" CONTENT="Alias"><!ENDIF> <!IF NAME="fmt" CONTENT="url"> <DT>$(Order). <a href="$(URL)">$(URL:40)</a> <small>[<b>$(Score)</b>]</small> <!ELSEIF NAME="fmt" CONTENT="short"> <DT>$(Order). <a href="$(URL)"> <!IF NAME="Title" CONTENT="">$(URL:40)<!ELSE>$&(Title)<!ENDIF> </a> <small>[<b>$(Score)</b>]</small> <!ELSE> <DT>$(Order). <a href="$(URL)"> <!IF NAME="Title" CONTENT="">$(URL:40)<!ELSE>$&(Title)<!ENDIF> </a> <small> [ <b>$(Score)</b> <!IFNOT NAME="Pop_Rank" CONTENT="0.00000">Popularity: <b>$(Pop_Rank)</b><!ENDIF> ] </small> <DD> <table width=60%> <tr> <td> <small>$&(Body)...</small> </td> </tr> <tr> <td> <UL> <li> <small> <A HREF="$(URL)">$(URL:40)</A> <font color="#008800"> - $(Content-Length) bytes [$(Content-Type)] - $(Last-Modified) <!IFNOT NAME="stored_href" CONTENT=""> <DD><small>[<a href="$(stored_href)">Cached copy</a>]</small></DD> <!ENDIF> <!IFNOT NAME="sitelimit_href" CONTENT=""> <!IFGT NAME="PerSite" CONTENT="0"> <DD><small> [<a href="$(sitelimit_href)">More results from this site ($(PerSite) total) </a>] </small></DD> <!ENDIF> <!ENDIF> </font> </small> <BR> $(CL) </UL> $(STORED) </td> </tr> </table> <!ENDIF> </DL> <!--/res--> <!--resbot--> <table width=100% bgcolor=#FFFFFF> <tr> <td align=center> <TABLE BORDER=0> <TR><TD><small>Ergebnis Seiten: <TD> </TD></TD>$(NL)$(NB)$(NR)</TD></TR> </TABLE> </td> </tr> </table> <!--/resbot--> <!--clone--> <!IFNOT NAME="Alias" CONTENT=""><!COPY NAME="URL" CONTENT="Alias"><!ENDIF> <li> <small> <A HREF="$(URL)">$(URL:40)</A> <font color="#008800"> - $(Content-Length) bytes - $(Last-Modified) </font> </small> <!--/clone--> <!--navleft--> <TD><small><A HREF="$(NH)"><< Vorherige</A></TD> <!--/navleft--> <!--navleft_nop--> <TD><small><FONT COLOR=gray><< Vorherige</FONT></TD> <!--/navleft_nop--> <!--navbar1--> <TD><small><A HREF="$(NH)">$(NP)</A></TD> <!--/navbar1--> <!--navbar0--> <TD><small>$(NP)</TD> <!--/navbar0--> <!--navright--> <TD><small><A HREF="$(NH)">Nächste >></A></TD> <!--/navright--> <!--navright_nop--> <TD><small><FONT COLOR=gray>Nächste >></FONT></TD> <!--/navright_nop--> <!--notfound--> <!IFNOT NAME="WS" CONTENT=""> Meinten Sie <b><a href="?q=$%(WS)">$(WS)</a></b>? <!ENDIF> <table bgcolor=#EEEEEE width=100%> <tr> <td> <small>Suche nach <b>$&(q)</b>.</small> <small>Suchergebnisse: <b>$&(WE)</b></small> </td> </tr> </table> <p> Sorry, Ihre Suche nach <b>$&(q)</b> hat kein Ergebnis.<br> Es wurden keine Dokumente gefunden, die <b>"$&(q)" enthalten</b>.<br> <p> Hinweise: <UL> <LI> Stellen Sie sicher, dass Ihre Wörter richtig geschrieben sind. <LI> Versuchen Sie andere Suchworte. <LI> Versuchen Sie allgemeinere Suchwörter. </UL> <!--/notfound--> <!--noquery--> <div class="center">Bitte geben Sie eines oder mehrere Wörter ein und dücken Sie Suche.</div> <!--/noquery--> <!--error--> <CENTER> <FONT COLOR="#FF0000">Es ist ein Fehler aufgetreten!</FONT> <P><B>$(E)</B> </CENTER> <!--/error--> <!--bottom--> <table class="grey" summary=""> <tr><td> </td></tr> </table> </body> </html> <!--/bottom--> <!--storedoc_top--> <BASE HREF="$(URL)"> <table border="1" cellpadding="2" cellspacing="0"><tr> <td><b>Document ID:</b> $(ID)</td> <td><b>Last modified:</b> $(Last-Modified)</td> <td><b>Language:</b> $(Content-Language)</td> <td><b>Charset:</b> $(Charset)</td> <td><b>Size:</b> $(Content-Length)</td> </tr></table> <hr> <!--/storedoc_top--> <!--storedoc--> $^(document) <!--/storedoc--> <!--storedoc_bottom--> <!--/storedoc_bottom-->
suche.zhtml sucht search.cgi
Das Suchformular hat keine "action" definiert, es lässt sich per .htaccess an search.cgi als Template übergeben:
Wenn noch nicht vorhanden, im gleichen Verzeichnis, in dem das Suchformulat liegt, eine Datei .htaccess erstellen und editieren:
# touch .htaccess # edit .htaccess
Und da folgendes reinschreiben (vorausgesetzt, das Formular heißt suche.zhtml:
AddType text/html .zhtml AddHandler zhtml .zhtml Action zhtml /cgi-bin/search.cgi
Es gibt etliche weitere Möglichkeiten, search.cgi zu benutzen, sie stehen in der Dokumentation.
Cronjob zum Update der Suchdatenbank in der Nacht
Sollten sich die Webseiten öfter mal ändern, ist es sinnvoll, die Suchdatenbank nachts zu aktualisieren. Die Datei für die eigenen Cronjobs wird editiert:
# crontab -e
und reingeschrieben wird das:
# suche mnogosearch indexer 19 23 * * * nice indexer /home/doms/example.com/mnogosearch/indexer.conf
Bitte eine andere Uhrzeit wählen, damit nicht alle indexer-Jobs um 23:19 Uhr anlaufen!!!