Поиск с учётом русской морфологии
php-скрипты, Полезные скрипты, Технологии Сентябрь 25th. 2007, 4:19ппСудя по всему (google & yandex) единственной современной разработкой на ниве поиска с учётом морфологии является phpMorphy. Раньше я использовал RiSearch, но сейчас он похоже почил в бозе. Поэтому буду пробовать новое решение.
Далее привожу полезную запись из блога «Ежовый угол».
На мой взгляд любой поиск по сайту должен обладать русской морфологией. На деле лишь единицы из проектов обладают этой возможностью. Разработчики ссылаются на сложность разработки и я до сего дня думал так же. На деле все оказалось проще – есть готовые словари. К примеру, phpMorphy.
Данный проект незаслуженно забыт программистами, хотя является удобным средством для организации поиска по сайту с учетом морфологии русского, английского или немецкого языков. Словари на каждый язык занимают порядка 2 Мб, сам скрипт – около 20 Кб.
В составе phpMorphy нет инструментария дла работы с базой данных – его придется написать самостоятельно. Но в нем есть самое ценное:
- Определение словоформ указанного слова;
- Определение корня слова;
- Определение начальной формы слова.
Этого хватит слихвой для создания более-менее адекватного поиска. Лично я использовал определение корня слова, а затем каждый корень искал в полях, к примеру, так:
SELECT * FROM `tbl1` WHERE UPPER(`col1`) LIKE ‘%АФИШ%’;
UPPER() используется из-за того, что phpMorphy возвращает все слова в верхнем регистре.
Как я понял, последние версии phpMorphy не работают на PHP4, поэтому стоит начать миграцию на PHP5, хотя если ваши скрипты обновляются более-менее часто, правки будут незначительны.
Подготовка текста
Для обработки введенной пользователем строки удобно пользоваться регулярными выражениями — пример есть на http://php.spb.ru/php/word.html.
Работа со словарями
Для начала нужно скачать требуемые словари (на ваш выбор – русские, английские, немецкие) и готовые модули для работы с ними.
Распаковав модули, у нас получаются файлы со справкой, а также 3 папки: dicts, src и examples. В первую нужно распаковать словари, во второй находятся модули для работы со словарями, а в третьей — пример использования phpMorphy.
Приводить текст примера не буду, вы можете увидеть его самостоятельно. Остановлюсь лишь на его ключевых моментах.
Все, что находится выше строки:
// Hint: in this example words $word_one, $word_two are in russian language(cp1251 encoding)
используется для инициализации словарей. Там ничего не нужно править. Исключение составляют закомментированные строки:
// $codepage = $morphy->getCodepage();
// setlocale(LC_CTYPE, array(’ru_RU.CP1251?, ‘Russian_Russia.1251?));
которые в случае необходимости правите для изменения рабочей кодировки — в немецком это cp1252, а в английском cp1250. Но наверняка вам это не понадобится.
Ниже идет пример работы. У phpMorphy есть 2 режима работы — одиночный (single mode) и блочный (bulk mode). Первый используется для обработки каждого слова по отдельности, второй — для обработки целого массива слов. Остановимся на втором, как наиболее удобном, по крайней мере на мой взгляд.
Для начала задаем входные слова:
$word_one = ‘ПРОВЕРКА’;
$word_two = ‘МОРФОЛОГИЗАТОРА’;
…
$bulk_words = array($word_one, $word_two);
С помощью phpMorphy мы можем получить у них начальную форму:
$base_form = $morphy->getBaseForm($bulk_words);
получить все словоформы:
$all_forms = $morphy->getAllForms($bulk_words);
или получить корень слова:
$pseudo_root = $morphy->getPseudoRoot($bulk_words);
Что для вас — ваш выбор. Я остановился на определении корня слова — максимально короткий SQL-запрос при аналогичной точности выборки.
В качестве результата возвращается массив, который мы можем использовать для поиска. К примеру, так:
$request_words = array();
$columns = array(”title”, “description”);
foreach($pseudo_root as $group_form)
if($group_form)
foreach($group_form as $one_form)
foreach($columns as $col)
$request_words[] = “UPPER(`”.$col.”`) LIKE ‘%”.$one_form.”%’”;
$request = “SELECT * FROM `tbl1` WHERE (”.join(” OR “,$request_words).”);”;
Дам комментарий — в $columns мы указываем список полей таблицы, по которым производим поиск. В $request, соответственно, формируется окончательный SQL-запрос, который остается лишь выполнить.
PS Попробовать поиск можно на KamWeb.ru. На данный момент результаты сотрируются по рейтингу сайта, но несложно организовать сортировку и по релевантности. Если кому-то нужны полные листинги — пишите.
Апрель 18th, 2009 at 11:30
Для перла легко прикручивается mystem от яндекса (http://company.yandex.ru/technology/mystem/)
Для пхп тоже, кстати, его можно использовать, но в случае провайдерского запрета на системные вызовы придется дописать обертку (на том же перле
)
Апрель 19th, 2009 at 05:59
http://sourceforge.net/projects/phpmorphy/ – более актуальная ссылка на скачку
Июнь 11th, 2009 at 23:48
Здравствуйте!
Очень бы для меня сейчас понадобился этот скрипт..Исходники конечно я нашел, поставил на денвере, но никак не могу посмотреть example, потому что постоянно выдает ошибку:
Зачем он ищет какой-то common_aut.ru_ru.bin, или генерирует его..я бросил словари в dicts и все, со словарями еще нужно что-то делать?
В свой скрипт common.php не подключал, да и нужно, если я хочу посмотреть examle?
В чем может быть ошибка, подскажите пожалуйста.
Июнь 12th, 2009 at 00:02
Ага, вроде бы догадался в чем проблема. Paul, а вы не могли бы проверить или у вас будут работать словари на последней версии? Дело в том, что словари для версий 0.3.* представлены не в биновских файлах, а в XML, а скрипт ищет старые биновские, и не умеет работать с новой базой. Это действительно так?