Войти

Показать полную графическую версию : поиск по сайту на PHP


Vlad Drakula
02-04-2008, 04:28
как лучше сделать поиск по сайты на PHP
ес ли бы сайт был динамический то через MySQL делается не сложно.
но сайт статический примерно 3000стр
перезаливать каждый раз MySQL базу как то не очень хочется

может кто сможет что посоветовать?

Arrest
02-04-2008, 06:42
Vlad Drakula
А как он устроен? Просто plain-text файлы в поддиректориях? У Смирнова был скрипт
из двух частей. первая - индексатор:
<?php

// Spectator's Indexing Script
// (C) Spectator.ru
// Для работы требуется PHP 4 или выше.
// Если вы будете использовать этот скрипт, ссылка на Spectator.ru крайне желательна. Спасибо.

// ставим скрипт "на счетчик" (чтобы знать, как долго он выполнялся
$ttt=microtime();
$ttt=((double)strstr($ttt, ' ')+(double)substr($ttt,0,strpos($ttt,' ')));


$indexdir="text"; #индексируемая директория
$indexfile="indexfile.txt"; #файл, в котором будет лежать индекс
// если вы хотите индексировать файлы в нескольких директориях, надо внести несколько махоньких добавлений...


// делаем так, чтобы не было таймаута из-за того, что скрипт будет долго выполняться (на всякий случай)
// и из-за того, что пользователь нажмет кнопку "стоп" в браузере
$abort = ignore_user_abort(1);
set_time_limit(600);

// Функция, удалающая слова, короче 3х букв. Пригодится дальше.
function sw (&$item1, $key) { if (strlen($item1)<3) $item1=""; }

// по очереди открываем все файлы в директории и проверяем, можно ли их индексировать
// у меня можно индексировать только файлы, которые имеют вид "число.txt"
// то есть && (is_numeric(str_replace (".txt","", $file))) - это вам наверняка не понадобится.

$handle=opendir('./'.$indexdir);
while (false!==($file = readdir($handle))):
if ($file != "." && $file != ".." && (is_numeric(str_replace (".txt","", $file))) ):

// открываем очередной файл
$fd = fopen ($indexdir."/".$file, "r");
$contents = fread ($fd, filesize ($indexdir."/".$file));
Fclose ($fd);


// убираем переводы строк
$contents=str_replace ("n"," ", $contents);
$contents=str_replace ("r","", $contents);


// убираем хтмл-тэги
$contents=str_replace ('<br>', ' ', $contents);
$contents=str_replace ('<p>', ' ', $contents);
$contents=strip_tags ($contents);


// убираем знаки препинания и цифры
// все эти строки работают быстрей, чем один eregi_replace!

$contents=str_replace (' -', ' ', $contents);
$contents=str_replace ('.', ' ', $contents);
$contents=str_replace (',', ' ', $contents);
$contents=str_replace ('!', ' ', $contents);
$contents=str_replace ('?', ' ', $contents);
$contents=str_replace (':', ' ', $contents);
$contents=str_replace (';', ' ', $contents);
$contents=str_replace (')', ' ', $contents);
$contents=str_replace ('(', ' ', $contents);
$contents=str_replace ('"', ' ', $contents);

// убираем заглавные буквы
$contents=strtolower ($contents);

// разбиваем на слова, убираем слова, короче 3х букв
$contents=explode (" ", $contents);
// вот и функция пригодилась...
array_walk ($contents, 'sw');


// убираем повторяющиеся слова
$contents=array_unique ($contents);


// соединяем слова
$contents=implode (" ", $contents);


// формируем соответствующую строку в индексе.
$fullfile.=$file."| ".$contents." n";


// индекс-файл будет иметь вид:
// имя_файла|индекс_для_данного_файла n
// имя_файла|индекс_для_данного_файла n
// имя_файла|индекс_для_данного_файла n

echo ($file." проиндексирован<br>");
// переходим к следующему файлу

endif;
endwhile;
closedir($handle);

// убираем двойные пробелы
while (stristr($fullfile, " ")) $fullfile=str_replace (" "," ",$fullfile);

// индекс готов, сохраняем его
$fp = fopen($indexfile, "w+");
fwrite($fp, $fullfile);
fclose($fp);

// считаем, как долго работал скрипт
$ddd=microtime();
$ddd=((double)strstr($ddd, ' ')+(double)substr($ddd,0,strpos($ddd,' ')));

echo ("<br>Время индексации: ".(number_format(($ddd-$ttt),3))." секунд<br>");
echo ("Размер индекса: ".(number_format((round ((filesize($indexfile))/1024)) , 0, ".",".")))." Kb";

?>
и собственно поисковой части:
<?php

// Spectator's Site Search Script
// (C) Spectator.ru
// Для работы требуется PHP 4 или выше.
// Если вы будете использовать этот скрипт, ссылка на Spectator.ru крайне желательна. Спасибо.


// файл с индексом
$indexfile="indexfile.txt";

// обрабатываем запрос

$total=0;
$qu2=str_replace ("+","&",$words);

// убираем заглавные буквы
$qu2=strtolower ($qu2);

// обрубаем в конце лишние пробелы
$qu2=chop($qu2);

// убираем двойные пробелы
while (stristr($qu2," ")) $qu2=str_replace (" "," ",$qu2);


echo ('Запрос: '.$qu2);
echo ('<p><p><p>');

// разбиваем запрос на слова
$words = explode (' ', $qu2);

// удаляем в запросе все лишнее (знаки препинания, и прочее)
$qu2=eregi_replace ('[.?,!()#":;|]', '', $qu2);

// проверяем длинну запроса
if (strlen($qu2)>2):


// открываем индекс
$index=file ($indexfile);
$num= (count($index)-1);

// для каждой сточки из индекса (одна строчка=один файл) выполняем:
for ($i=1; $i<$num+2; $i++):

$contents=$index[$i-1];

$wordcount =0;
$mustfound=1;

// выполняем для каждого их запрошенных слов:
$mustntfound=1;

for ($q=0; $q<count($words); $q++):

// обработка знаков *, + и -

// знак *
if (stristr($words[$q], "*")) {$search=str_replace ("*","",$words[$q]); } else { $search=" ".$words[$q]." ";}

// если в слове есть звездочка, то убираем звездочку и добавляем в начало и конец слова по пробелу
// если нет проблелов, то слово будет искаться не целиком, а "вообще",
// то есть на запрос "чай" будет выводиться и слово "случайный".

// bug: скрипт не учитывает, где в слове стоит звездочка и считает, что в любом случае она стоит в конце (!!)

// знак & (или +)
if (stristr($search, "&")) {$search=str_replace ("&","",$search); $mustfound++; }

// если стоит знак +, то количество слов, которые _должны_ быть найдены, увеличиваются на 1

// знак -
if (stristr($search, "-")) {$search=str_replace ("-","",$search); $mustntfound=0; }

// если стоит знак +, то если слово найдено, весь результат умножается на 0 (смотри дальше).

// если слово найдено, считаем его и умножаем на $mustntfound, то есть на 1,
// если найдено "правильное" слово и на 0, если найдено слово, помеченное знаком -

if (stristr($contents, $search)) { $wordcount++; $wordcount=$wordcount*$mustntfound;}

endfor;

// проверяем, все ли слова, помеченные знаком + найдены,
// либо (если таких слов нет), найдено ли вообще хоть одно слово

if ($wordcount >= $mustfound):

// находим имя файла, в котором это найдено
$file=explode ("|",$contents);
$file=$file[0];

// выводим имя файла, в котором это найдено с ссылкой
// (этот кусочек вам надо будет переделать под собственные нужды).

$file=str_replace (".txt", "", $file);
$file=str_replace ("_", ".", $file);
echo ("<a href=".$file.">".$file."</a><br>");


// считаем, колько всего файлов надено
$total++;
endif;

// переходим к следующемуу файлу
endfor;

// выводим результаты
if ($total!=0) echo ('<br><br>Всего найдено страниц: '.$total); else echo ("<b>Ничего не найдено!</b><p>Возможно, вы просто не правильно составили запрос. Как это сделать правильно - смотрите <a href=search>вот здесь</a>.");

else:
echo ("<br>Слишком короткий запрос!");
endif;


?>

<!-- Форма для поиска: -->
<form method=get action=search.php>
<input type=text size=19 name=words value="" maxlength=150> <input type=submit class=frm value=Go>
</form>
Ссылка: http://spectator.ru/technology/php/php_search

Vlad Drakula
02-04-2008, 07:30
Arrest
3000 статических HTML страниц

этот скрипт работаешь лишь на маленьких объемах данных
у меня более 15мб чистого текста, в память так просто не влезет

vadimiron
02-04-2008, 10:12
Vlad Drakula,
Надо демона написать, который сканирует все папки на изменнёные/новые файлы и добавляет/удаляет информацию в базе данных. И так всё время по кругу....
А искать уже в базе

Короче мини гугл-crawler надо написать :) Может ещё туда количество кликов встроить, чтобы более популярные страницы в начале списка найденных страниц показывать :)

Vlad Drakula
02-04-2008, 11:20
vadimiron
зачем демона писать, мне вроде как не особо сложно написать скрипт который сформирует sql код для апдейта базы в момент деплоя новой версии контента, просто не очень хочется...

vadimiron
02-04-2008, 11:30
мне вроде как не особо сложно написать скрипт который сформирует sql код для апдейта базы в момент деплоя новой версии контента »
Ну если такое возможно - то да, лучше, наверно, так

просто не очень хочется »
А почему? Поиск же в любом случае надо организовать с помощью базы данных
С 3000 файлов не реально без базы данных организовать поиск - я сеье не представляю других вариантов. Каждый раз проходить по всем файлам и парсить содержимое - самоубийство.

Ещё одна мысль: можно использовать внешнюю программу. Например, Google Desktop создаёт же индекс файлов сам - то есть по идеи, если там есть какое нибудь API или хотя бы просто вызов результатов поиска через командную строку, то можно реализовать в PHP. Или посмотри другие подобные программы.... напиши потом, что получилось, мне тоже стало интересно

Вот Google Desktop Search API: жми тутта (http://code.google.com/apis/desktop/docs/searchapi.html)




© OSzone.net 2001-2012