[PHP][Wyszukiwarki] Jak stworzyć prostą wyszukiwarkę dla własnych stron WWW?
Chcesz stworzyć wyszukiwarkę dla własnych stron, która umożliwi podanie szukanego słowa (lub kilku słów), a użytkownik zobaczy listę stron, na której to słowo występuje. Mechanizm do wyszukiwania jest szybki i wydajny dla niewielkich witryn.
Skuteczna wyszukiwarka jest bardzo ważnym elementem każdego serwisu i często przyczynia się wygodniejszego korzystania z jego zasobów. Wszędzie tam gdzie nie musisz wyszukiwać wśród tysięcy stron WWW z powodzeniem możesz użyć poniższej wyszukiwarki:
<?
function szukanie($szukane) {
$sciezki[] ="artykuly/";
$sciezki[] ="porady/";
$sciezki[] ="./"; // katalog, w którym jest skrypt
$roz = "\.txt|\.html|\.htm";
for ($i=0;$i<count($sciezki);$i++) {
$katalog = opendir($sciezki[$i]);
while ($plik = readdir($katalog)) {
if (($plik<>".")&&($plik<>"..")and(!is_dir($sciezki[$i].$plik))) {
if (eregi("($roz)($)",$plik)) $lista[] = $sciezki[$i].$plik;
}
}
closedir($katalog);
}
$ile = count($lista);
for ($i=0;$i<$ile;$i++) {
$f = fopen($lista[$i], "r");
$zawartosc = fread($f,filesize($lista[$i]));
fclose($f);
preg_match_all("/$szukane/i", $zawartosc, $li);
if (count($li[0])>0) $sa[] = $lista[$i];
}
$ile = count($sa);
if ($ile>0) {
sort($sa);
for ($i=0;$i<$ile;$i++) {
echo "<br><a href=\"".$sa[$i]."\">" . $sa[$i]. "</a>";
}
}
}
$szukane=$_GET["szukane"];
if ($szukane<>"") { szukanie($szukane); }
else {echo "nie ma co szukać!"; }
?>
Funkcja szukanie() wymaga aby jako parametr podać w niej dowolne słowo (wyrażenie) do szukania. Nie zwraca wyniku, ale dla uproszczenia wypisuje na ekranie znalezione pliki w postaci linków do nich. Umożliwia to szybkie przejście do poszukiwanych stron WWW.
Tablica $sciezki[] przechowuje nazwy katalogów, w których znajdują się pliki do wyszukiwania. Może ich być więcej niż dwa przykładowe. Ponieważ nie chcemy szukać w każdym pliku, zmienna $roz (rozszerzenia) określa jakie pliki będą przeszukiwane. Przed kropką postawiony jest ukośnik, ponieważ bez niego kropka nie jest kropką lecz dowolnym znakiem w wyrażeniu regularnym. Znaki | rozdzielają rozszerzenia i powodują, że każde z nich brane jest pod uwagę przy wyszukiwaniu.
Pierwsza pętla for() szuka w naszych katalogach plików o podanych rozszerzeniach. Jeżeli je znajdzie, są one dodawane do tablicy $lista[], która przechowuje pełne ścieżki do plików.
Po chwili mamy kompletną listę plików, które zostaną następnie przeszukane, aby znaleźć w nich jakieś słowo. Kolejna pętla for() pobiera plik i szuka w nim podanego wcześniej wyrażenia. Jeżeli wyrażenie wystąpi w pliku co najmniej raz plik trafia do kolejnej tablicy $sa[] (czyli są bez polskiego "ą").
Teraz tablica $sa[] przechowuje pliki, w których znajduje się poszukiwany wyraz. Warto posortować pliki, aby następnie wypisać je na stronie w postaci odnośnika, który zapewni przejście do znalezionych stron WWW.
Zmienną $szukane można zainicjować na różne sposoby, np. tworząc formularz na stronie, który prześle wpisane przez użytkownika słowo do poszukiwania:
<form action="index.php" method=get>
<input name="szukane" type="text">
<input type="submit" value=" szukaj w serwisie">
</form>
Warto sprawdzić czy słowo zawiera jakieś znaki przed wywołaniem fukcji poszukującej (jak to ma miejsce w przykładzie).
Wyszukiwarka działa szybko i sprawnie pod warunkiem, że Twój serwis nie zawiera bardzo dużej ilości stron. Bez problemu poradzi sobie nawet z 500 stronami WWW jeżeli nie będą większe niż 100 kb każda.
Jeżeli strony są niewielkie, może ich być nawet 1000. Wyszukiwanie w dalszym ciągu jest niemal natychmiastowe.
Wyszukiwarka poszukuje obecnie tylko jednego słowa lub jednego wyrażenia. Łatwo możesz stworzyć wyszukiwarkę znajdującą więcej wyrazów występujących na stronie jednocześnie (domyślny operator AND).
W tym celu dopisz tą linijkę zaraz nad deklaracją katalogów do wyszukiwania:
$szukaj=explode(" ", $szukane);
Rozbije one wyrazy oddzielone spacją na tablicę z wyrazami. Teraz przetwarzając każde słowo możesz sprawdzić czy występuje ono na stronie. Jeżeli wystąpią wszystkie, strona jest dodawana do wyszukanych, jeżeli choć jedno z kilku słów nie wystąpi, strona jest pomijana. Aby uzyskać ten efekt zmodyfikuj nieco drugą pętlę:
$ile = count($lista);
for ($i=0;$i<$ile;$i++) {
$f = fopen($lista[$i], "r");
$zawartosc = fread($f,filesize($lista[$i]));
fclose($f);
$jest="tak";
$ileszuk=count($szukaj);
for ($j=0;$j<$ileszuk;$j++) {
preg_match_all("/".$szukaj[$j]."/i", $zawartosc, $li);
if (count($li[0])<1) {$jest="nie"; break;}
}
if ($jest=="tak") $sa[] = $lista[$i];
}
Teraz dodany został warunek gwarantujący, że wszystkie słowa muszą wystąpić na stronie aby znalazła się na liście znalezionych stron.
Cały skrypt wygląda więc następująco:
<?
function szukanie($szukane) {
$szukaj=explode(" ", $szukane);
$sciezki[] ="artykuly/";
$sciezki[] ="porady/";
$sciezki[] ="./"; // katalog, w którym jest skrypt
$roz = "\.txt|\.html|\.htm";
for ($i=0;$i<count($sciezki);$i++) {
$katalog = opendir($sciezki[$i]);
while ($plik = readdir($katalog)) {
if (($plik<>".")&&($plik<>"..")and(!is_dir($sciezki[$i].$plik))) {
if (eregi("($roz)($)",$plik)) $lista[] = $sciezki[$i].$plik;
}
}
closedir($katalog);
}
$ile = count($lista);
for ($i=0;$i<$ile;$i++) {
$f = fopen($lista[$i], "r");
$zawartosc = fread($f,filesize($lista[$i]));
fclose($f);
$jest="tak";
$ileszuk=count($szukaj);
for ($j=0;$j<$ileszuk;$j++) {
preg_match_all("/".$szukaj[$j]."/i", $zawartosc, $li);
if (count($li[0])<1) {$jest="nie"; break;}
}
if ($jest=="tak") $sa[] = $lista[$i];
}
$ile = count($sa);
if ($ile>0) {
sort($sa);
for ($i=0;$i<$ile;$i++) {
echo "<br><a href=\"".$sa[$i]."\">" . $sa[$i]. "</a>";
}
}
}
$szukane=$_GET["szukane"];
if ($szukane<>"") { szukanie($szukane); }
else {echo "nie ma co szukać!"; }
?>
Kolejna przydatna modyfikacja to wyszukiwanie tylko w określonych fragmentach strony, np. po tytułach i w treści, czyli pomiędzy tagami TITLE i BODY. Aby poszukiwać tylko pomiędzy tymi tagami zastąp fragment:
preg_match_all("/$szukane/i", $zawartosc, $li);
nowym:
$zawartosc = preg_replace("/\n/i","",$zawartosc);
$zawartosc = preg_replace("/\r/i","",$zawartosc);
preg_match_all(
"/(<title>.*$szukane.*?<\/title>|<body.*?\>.*$szukane.*?<\/body>)/i",
$zawartosc, $li);
Usuwa on ze strony wszystkie przejścia do nowej linii, więc strona staje jedną długą linijką i znajduje w niej tekst w obrębie wskazanych tagów - albo w tytule albo w treści. Omijasz w ten sposób np. wyszukiwanie wyrazów w deklaracjach stylów i w innych elementach HTML na początku strony.