[PHP][Wyszukiwarki] Jak stworzyć prostą wyszukiwarkę dla własnych stron WWW?

0x01 graphic

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.

0x01 graphic

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.