Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

Эвристическое (без словаря) извлечение корня из русского слова. (Дмитрий Котеров)
Author Message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 408
   поощрить/наказать


PostPosted: Wed Feb 16, 2005 10:13 pm (написано за 2 минуты 33 секунды)
   Post subject: Эвристическое (без словаря) извлечение корня из русского слова.
Reply with quote

Стеммер Портера.
Code (php): скопировать код в буфер обмена
<?php
class Lingua_Stem_Ru
{
    var $VERSION = "0.02";
    var $Stem_Caching = 0;
    var $Stem_Cache = array (www.php.net/array)();
    var $VOWEL = '/аеиоуыэюя/';
    var $PERFECTIVEGROUND = '/((ив|ивши|ившись|ыв|ывши|ывшись)|((?<=[ая])(в|вши|вшись)))$/';
    var $REFLEXIVE = '/(с[яь])$/';
    var $ADJECTIVE = '/(ее|ие|ые|ое|ими|ыми|ей|ий|ый|ой|ем|им|ым|ом|его|ого|ему|ому|их|ых|ую|юю|ая|яя|ою|ею)$/';
    var $PARTICIPLE = '/((ивш|ывш|ующ)|((?<=[ая])(ем|нн|вш|ющ|щ)))$/';
    var $VERB = '/((ила|ыла|ена|ейте|уйте|ите|или|ыли|ей|уй|ил|ыл|им|ым|ен|ило|ыло|ено|ят|ует|уют|ит|ыт|ены|ить|ыть|ишь|ую|ю)|((?<=[ая])(ла|на|ете|йте|ли|й|л|ем|н|ло|но|ет|ют|ны|ть|ешь|нно)))$/';
    var $NOUN = '/(а|ев|ов|ие|ье|е|иями|ями|ами|еи|ии|и|ией|ей|ой|ий|й|иям|ям|ием|ем|ам|ом|о|у|ах|иях|ях|ы|ь|ию|ью|ю|ия|ья|я)$/';
    var $RVRE = '/^(.*?[аеиоуыэюя])(.*)$/';
    var $DERIVATIONAL = '/[^аеиоуыэюя][аеиоуыэюя]+[^аеиоуыэюя]+[аеиоуыэюя].*(?<=о)сть?$/';

    function s(&$s, $re, $to)
    {
        $orig = $s;
        $s = preg_replace (www.php.net/preg_replace)($re, $to, $s);
        return $orig !== $s;
    }

    function m($s, $re)
    {
        return preg_match (www.php.net/preg_match)($re, $s);
    }

    function stem_word($word)
    {
        $word = strtolower (www.php.net/strtolower)($word);
        $word = strtr (www.php.net/strtr)($word, 'ё', 'е');
        # Check against cache of stemmed words
        if ($this->Stem_Caching && isset (www.php.net/isset)($this->Stem_Cache[$word])) {
            return $this->Stem_Cache[$word];
        }
        $stem = $word;
        do {
          if (!preg_match (www.php.net/preg_match)($this->RVRE, $word, $p)) break;
          $start = $p[1];
          $RV = $p[2];
          if (!$RV) break;

          # Step 1
          if (!$this->s($RV, $this->PERFECTIVEGROUND, '')) {
              $this->s($RV, $this->REFLEXIVE, '');

              if ($this->s($RV, $this->ADJECTIVE, '')) {
                  $this->s($RV, $this->PARTICIPLE, '');
              } else {
                  if (!$this->s($RV, $this->VERB, ''))
                      $this->s($RV, $this->NOUN, '');
              }
          }

          # Step 2
          $this->s($RV, '/и$/', '');

          # Step 3
          if ($this->m($RV, $this->DERIVATIONAL))
              $this->s($RV, '/ость?$/', '');

          # Step 4
          if (!$this->s($RV, '/ь$/', '')) {
              $this->s($RV, '/ейше?/', '');
              $this->s($RV, '/нн$/', 'н');
          }

          $stem = $start.$RV;
        } while(false);
        if ($this->Stem_Caching) $this->Stem_Cache[$word] = $stem;
        return $stem;
    }

    function stem_caching($parm_ref)
    {
        $caching_level = @$parm_ref['-level'];
        if ($caching_level) {
            if (!$this->m($caching_level, '/^[012]$/')) {
                die (www.php.net/die)(__CLASS__ . "::stem_caching() - Legal values are '0','1' or '2'. '$caching_level' is not a legal value");
            }
            $this->Stem_Caching = $caching_level;
        }
        return $this->Stem_Caching;
    }

    function clear_stem_cache()
    {
        $this->Stem_Cache = array (www.php.net/array)();
    }
}
?>
Пример использования:
Code (php): скопировать код в буфер обмена
$stemmer = new Lingua_Stem_Ru();
echo (www.php.net/echo) $stemmer->stem_word('');
Естественно, библиотека иногда ошибается, однако в большинстве случаев все же срабатывает вполне удовлетворительно. Может использоваться в поисковых системах (здесь на форуме, к примеру).

Last edited by Дмитрий Котеров on Sat Feb 26, 2005 7:30 pm; edited 2 times in total
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 408
   поощрить/наказать


PostPosted: Wed Feb 16, 2005 10:15 pm (спустя 2 минуты; написано за 33 секунды)
   Post subject:
Reply with quote

Алгоритм взят вот отсюда: search.cpan.org/~algdr/Lingua-Stem-Ru/Ru.pm
Back to top
View user's profile Send private message Send e-mail
Nick Bubelo
Заглянувший



Joined: 26 Feb 2005
Posts: 3
Карма: 0
   поощрить/наказать

Location: Днепропетровск

PostPosted: Sat Feb 26, 2005 2:03 pm (спустя 9 дней 15 часов 47 минут)
   Post subject:
Reply with quote

Это стеммер Портера:
snowball.tartarus.org/russian/stemmer.html

Алгоритм нуждается в маленькой доработке: перед началом стемминга в слове следует заменить все буквы 'ё' на 'е'. Сам Портер, кстати, на вышеуказанной страничке это же и советует.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 408
   поощрить/наказать


PostPosted: Sat Feb 26, 2005 7:32 pm (спустя 5 часов 28 минут; написано за 12 секунд)
   Post subject:
Reply with quote

Поправил, спасибо.
Back to top
View user's profile Send private message Send e-mail
Сый
Guest





Карма: 386
   поощрить/наказать


PostPosted: Sun Aug 14, 2005 1:47 pm (спустя 5 месяцев 15 дней 18 часов 14 минут; написано за 3 минуты 5 секунд)
   Post subject:
Reply with quote

Ну как я понял, скрипт вырезает лишь окончания и некоторые суффиксы. Но он не может различить (и не сможет) корень во многих словах, использующих, например суффикс "ок", ибо этот суффикс во многих случаях является частью корня. Так что словарь к такому скрипту должен прилагаться.
Back to top
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 408
   поощрить/наказать


PostPosted: Sun Aug 14, 2005 2:46 pm (спустя 59 минут; написано за 17 секунд)
   Post subject:
Reply with quote

Кому "должен"?
Вы читали, что такое "стеммер Портера"?
Back to top
View user's profile Send private message Send e-mail
Eugene Babushkin
Участник форума



Joined: 01 Aug 2003
Posts: 263
Карма: 4
   поощрить/наказать

Location: 59, Russia

PostPosted: Thu Aug 18, 2005 2:57 pm (спустя 4 дня 11 минут; написано за 29 секунд)
   Post subject:
Reply with quote

Ссылка
Nick Bubelo wrote:
snowball.tartarus.org/russian/stemmer.html
переехала
snowball.tartarus.org/algorithms/russian/stemmer.html
Back to top
View user's profile Send private message
vutsh
Guest





Карма: 386
   поощрить/наказать


PostPosted: Thu Feb 01, 2007 3:04 pm (спустя 1 год 5 месяцев 14 дней 6 минут; написано за 16 секунд)
   Post subject:
Reply with quote

'/((ив|ивши|ившись|ыв|ывши|ывшись)|((?<=[ая])(в|вши|вшись)))$/';
чем здесь віступает ая.
Back to top
cosmos
Guest





Карма: 386
   поощрить/наказать


PostPosted: Thu Jul 12, 2007 2:02 pm (спустя 5 месяцев 10 дней 22 часа 58 минут; написано за 24 секунды)
   Post subject:
Reply with quote

не могу понять на локале класс работает
копирую на хостинг не фига не пашет
Back to top
cosmos-web
Guest





Карма: 386
   поощрить/наказать


PostPosted: Sun Jul 22, 2007 11:23 am (спустя 9 дней 21 час 21 минуту; написано за 4 секунды)
   Post subject:
Reply with quote

strtolower
Back to top
Setti
Guest





Карма: 386
   поощрить/наказать


PostPosted: Fri Sep 14, 2007 9:38 am (спустя 1 месяц 22 дня 22 часа 14 минут; написано за 40 секунд)
   Post subject:
Reply with quote

Подскажите, пожалуйста, как подключить к этому стеммеру словарь словоформ? Спасибо.
Back to top
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 408
   поощрить/наказать


PostPosted: Thu Sep 27, 2007 6:38 pm (спустя 13 дней 9 часов 6 секунд; написано за 24 секунды)
   Post subject:
Reply with quote

Никак не подключить. Словоформы - совершенно отдельная штука. Ищите по словам "php ispell".
Back to top
View user's profile Send private message Send e-mail
Константин Жинько [tIT]
Сотрудник «Лаборатории»



Joined: 12 Jun 2004
Posts: 2264
Карма: 106
   поощрить/наказать

Location: Москва

PostPosted: Tue Oct 02, 2007 2:57 pm (спустя 4 дня 20 часов 19 минут; написано за 2 минуты 13 секунд)
   Post subject:
Reply with quote

Пришло письмо недавно от некой конторы, которая вроде как подрядилась нашей текстовой оптимизацией заниматься примерно следующего содержания:
Quote:
Мы вот тут нашли код для определения словоформ, который поможет вам улучшить поиск на сайте:
Code (php): скопировать код в буфер обмена
class Lingua_Stemmer_Ru {
//...
 
Посмеялся (-;
Back to top
View user's profile Send private message
Никита Ковалев
Guest





Карма: 386
   поощрить/наказать


PostPosted: Fri Jan 18, 2008 11:40 am (спустя 3 месяца 15 дней 20 часов 43 минуты; написано за 1 минуту 14 секунд)
   Post subject:
Reply with quote

Замену нужно делать не так:
$word = strtr($word, 'ё', 'е');

а так
$word = strtr($word, array('ё'=>'е'));

В теории отличаться не должно, в реальности с Unicode работает правильно только второй вариант. (PHP 5.2.3)
Back to top
deli6z
Заглянувший



Joined: 03 Oct 2007
Posts: 3
Карма: 1
   поощрить/наказать


PostPosted: Mon Mar 03, 2008 11:37 pm (спустя 1 месяц 16 дней 11 часов 56 минут; написано за 1 минуту 10 секунд)
   Post subject:
Reply with quote

никому не попадалось на глаза вот такое:

Пользователь вводит русскуюсловоформу и получает нормальную форму и морфологические атрибуты либо, по желанию, всю парадигму слова.

пример сервиса

www.aot.ru/demo/morph.html
Back to top
View user's profile Send private message
Gilthoniel
Guest





Карма: 386
   поощрить/наказать


PostPosted: Sat Mar 08, 2008 9:21 pm (спустя 4 дня 21 час 43 минуты; написано за 31 секунду)
   Post subject:
Reply with quote

А нет ли где-нибудь такой же красивой и готовой на PHP реализации того же алгоритма, только для английского языка?
Back to top
virus126
Guest





Карма: 386
   поощрить/наказать


PostPosted: Fri Mar 28, 2008 11:25 am (спустя 19 дней 14 часов 3 минуты; написано за 24 секунды)
   Post subject:
Reply with quote

эхх... кровать-кроватить... :\
Back to top
bolteg86
Guest





Карма: 386
   поощрить/наказать


PostPosted: Fri Jun 06, 2008 1:20 pm (спустя 2 месяца 9 дней 1 час 54 минуты; написано за 2 минуты 18 секунд)
   Post subject:
Reply with quote

У меня всё отлично работает на денвере. ВСЁ ПРСТО ОТМЕННО. Разработал такую штуку, которая ищет введённые слова по базе данных во всех формах с учётом чередований в корнях даже. Но на сервере, на зеноне эта хрень не работает. Корень не выделяется. Чё делать, подскажите, плиз
Back to top
rassol
Guest





Карма: 386
   поощрить/наказать


PostPosted: Sat Jun 21, 2008 3:34 pm (спустя 15 дней 2 часа 14 минут; написано за 2 минуты 23 секунды)
   Post subject:
Reply with quote

Спасибо за стеммер.
Работает на ура (правда таки да, ошибается).
Небольшое дополнение от мну:
Code (php): скопировать код в буфер обмена
$word = strtr (www.php.net/strtr)($word, 'ё', 'е');
у меня некорректно работала с UTF-8 general_ci;
Поэтому советую заменить на более универсальную
Code (php): скопировать код в буфер обмена
$word= str_ireplace('', '', $word);
Back to top
qfox.ru
Guest





Карма: 386
   поощрить/наказать


PostPosted: Mon Dec 01, 2008 10:05 pm (спустя 5 месяцев 10 дней 6 часов 30 минут; написано за 4 минуты 26 секунд)
   Post subject: script, utf8 & debian
Reply with quote

С утф изза регулярок дикая проблема.
После танцов с бубном выяснилось, что класс выделяет НЕ КОРЕНЬ слова, а его ОСНОВУ.
Жалко :(

p.s. Работу скрипта под дебианом с утф решал примерно так:
Code (any language): скопировать код в буфер обмена
Back to top
Миша Спларов
Участник форума



Joined: 17 Nov 2003
Posts: 821
Карма: 67
   поощрить/наказать

Location: Россия, Москва

PostPosted: Tue Dec 02, 2008 7:27 am (спустя 9 часов 21 минуту; написано за 1 минуту 4 секунды)
   Post subject:
Reply with quote

qfox.ru
Не правильно решали, в preg_replace есть модификатор "u". И синтаксис pcre отличается от синтаксиса posix - одинаковая работа тех же регулярных выражений - случайное совпадение.
Back to top
View user's profile Send private message
Elfet
Заглянувший
Banned


Joined: 27 Jan 2007
Posts: 8
Карма: -1
   поощрить/наказать


PostPosted: Thu Feb 05, 2009 12:24 pm (спустя 2 месяца 3 дня 4 часа 57 минут; написано за 20 секунд)
   Post subject:
Reply with quote

У меня под UTF-8 выдаёт вот что: �������
Как исправить?
Back to top
View user's profile Send private message
almix
Guest





Карма: 386
   поощрить/наказать


PostPosted: Mon Jun 08, 2009 4:03 pm (спустя 4 месяца 3 дня 3 часа 38 минут; написано за 14 секунд)
   Post subject:
Reply with quote

спасибо! очень помогло qfox.ru , вамотдельное спасибо за правки!
Back to top
Gamer09
Guest





Карма: 386
   поощрить/наказать


PostPosted: Thu Jun 18, 2009 3:16 am (спустя 9 дней 11 часов 12 минут; написано за 19 секунд)
   Post subject:
Reply with quote

А как это реализовать на Delphi кто-нибудь знает?
Back to top
Александр Firestarte1987
Guest





Карма: 386
   поощрить/наказать


PostPosted: Mon Nov 30, 2009 12:52 am (спустя 5 месяцев 11 дней 21 час 36 минут; написано за 15 секунд)
   Post subject: Не подскажите как по этому алгиритму определить часть речи
Reply with quote

Подскажите пожалуйста
Back to top
78464
Guest





Карма: 386
   поощрить/наказать


PostPosted: Tue Jan 12, 2010 7:43 pm (спустя 1 месяц 12 дней 18 часов 51 минуту; написано за 36 секунд)
   Post subject:
Reply with quote

ваще не могу прочитать!!! на китайском написано чтоли????!!!!
Back to top
bæv
Модератор «Дзена»



Joined: 27 Aug 2003
Posts: 7275
Карма: 9997
   поощрить/наказать


PostPosted: Tue Jan 12, 2010 8:36 pm (спустя 52 минуты; написано за 34 секунды)
   Post subject:
Reply with quote

78464 wrote:
ваще не могу прочитать!!! на китайском написано чтоли????!!!!
— это Вы про что?
Back to top
View user's profile Send private message
Guest






Карма: 386
   поощрить/наказать


PostPosted: Thu Feb 18, 2010 5:57 pm (спустя 1 месяц 5 дней 21 час 20 минут; написано за 54 секунды)
   Post subject:
Reply with quote

Gamer09 wrote:
А как это реализовать на Delphi кто-нибудь знает?
Uses
RegExpr

function TForm1.WordStem(InWord: String):String;

     function ExistReg(var InStr:String; RgExp, RpStr : String):Boolean;
     var
     TempStr: String;
     begin
     TempStr := ReplaceRegExpr(RgExp, InStr, RpStr);
     Result := TempStr <> InStr;
     InStr := TempStr;
     end;
var
RVRE, PERFECTIVEGROUND, REFLEXIVE, ADJECTIVE, PARTICIPLE, VERB, NOUN, DERIVATIONAL: String;
RE: TRegExpr;
Stem, Start, Rv: String;
begin
  Result := '';
  RE := TRegExpr.Create;
  try
  RVRE := '^(.*?[аеиоуыэюя])(.*)$';

  PERFECTIVEGROUND := '((ив|ивши|ившись|ыв|ывши|ывшись)|(((?i)[ая])(в|вши|вшись)))$';
  REFLEXIVE := '(с[яь])$';

  ADJECTIVE := '(ее|ие|ые|ое|ими|ыми|ей|ий|ый|ой|ем|им|ым|ом|его|ого|ему|ому|их|ых|ую|юю|ая|яя|ою|ею)$';
  PARTICIPLE := '((ивш|ывш|ующ)|(((?i)[ая])(ем|нн|вш|ющ|щ)))$';

  VERB := '((ила|ыла|ена|ейте|уйте|ите|или|ыли|ей|уй|ил|ыл|им|ым|ен|ило|ыло|ено|ят|ует|уют|ит|ыт|ены|ить|ыть|ишь|ую|ю)|(((?i)[ая])(ла|на|ете|йте|ли|й|л|ем|н|ло|но|ет|ют|ны|ть|ешь|нно)))$';
  NOUN := '(а|ев|ов|ие|ье|е|иями|ями|ами|еи|ии|и|ией|ей|ой|ий|й|иям|ям|ием|ем|ам|ом|о|у|ах|иях|ях|ы|ь|ию|ью|ю|ия|ья|я)$';

  DERIVATIONAL := '[^аеиоуыэюя][аеиоуыэюя]+[^аеиоуыэюя]+[аеиоуыэюя].*((?i)о)сть?$';

  InWord := LowerCase(InWord);
  InWord := StringReplace(InWord, 'ё', 'е', [rfReplaceAll]);
  Stem := InWord;

     repeat
     RE.Expression := RVRE;
     if not RE.Exec(Stem) then Break;
     Start := RE.Match[1];
     Rv := RE.Match[2];
     if not ExecRegExpr(RVRE, Rv) then Break;

     if not(ExistReg(Rv, PERFECTIVEGROUND, '')) then ExistReg(Rv, REFLEXIVE, '');

     if (ExistReg(Rv, ADJECTIVE, '')) then ExistReg(Rv, PARTICIPLE, '') else
     if not(ExistReg(Rv, VERB, '')) then ExistReg(Rv, NOUN, '');

     ExistReg(Rv, 'и$', '');

     if ExecRegExpr(DERIVATIONAL, Rv) then ExistReg(Rv, 'ость?$', '');

     if not ExistReg(Rv, 'ь$', '') then
          begin
          ExistReg(Rv, 'ейше?', '');
          ExistReg(Rv, 'нн$', 'н');
          end;

     Stem := Start+Rv;
     Until true;

  Result := Stem;
  finally
  if Assigned (RE) then RE.Free;
  end;
end;
Back to top
Guest






Карма: 386
   поощрить/наказать


PostPosted: Wed May 26, 2010 11:48 am (спустя 3 месяца 7 дней 17 часов 51 минуту; написано за 2 минуты 30 секунд)
   Post subject:
Reply with quote

Можно алгоритм в коммерческих проектах использоть? К примеру поиск в системе управления сайтом реализовать на этом алгорите, потом получить патент и продавать?
Back to top
zael
Заглянувший
Banned


Joined: 28 May 2010
Posts: 3
Карма: -3
   поощрить/наказать


PostPosted: Fri May 28, 2010 3:20 pm (спустя 2 дня 3 часа 31 минуту; написано за 3 минуты 59 секунд)
   Post subject:
Reply with quote

Anonymous wrote:
Можно алгоритм в коммерческих проектах использоть? К примеру поиск в системе управления сайтом реализовать на этом алгорите, потом получить патент и продавать?
это что-бы как у google однокоренные в выдачу попадали, так что не получится запатентовать.
Back to top
View user's profile Send private message
Guest






Карма: 386
   поощрить/наказать


PostPosted: Sun May 30, 2010 9:26 pm (спустя 2 дня 6 часов 6 минут; написано за 5 минут 21 секунду)
   Post subject:
Reply with quote

zael wrote:
это что-бы как у google однокоренные в выдачу попадали, так что не получится запатентовать.
Нет, не систему поиска запатентовать, а CMS с поиском, использующем этот алгоритм? Т. е. имею ли я право пользоваться алготритмом как хочу, и в коммерческих целях?
Back to top
TruBrite
Заглянувший
Banned


Joined: 06 Jun 2010
Posts: 3
Карма: -1
   поощрить/наказать


PostPosted: Sun Jun 06, 2010 4:43 pm (спустя 6 дней 19 часов 16 минут; написано за 12 секунд)
   Post subject:
Reply with quote

Спасибо!!!
Back to top
View user's profile Send private message
Nurmaga
Заглянувший



Joined: 14 Nov 2010
Posts: 1
Карма: 0
   поощрить/наказать


PostPosted: Sun Nov 14, 2010 12:28 pm (спустя 5 месяцев 7 дней 19 часов 45 минут; написано за 6 секунд)
   Post subject:
Reply with quote

Подскажите пожалуйста, как все это реализовать на самописанном сайте? этот скрипт ищет совпадений в файлах или в базе?
Back to top
View user's profile Send private message
TheWall
Заглянувший



Joined: 13 Jan 2011
Posts: 1
Карма: 0
   поощрить/наказать


PostPosted: Thu Jan 13, 2011 10:51 pm (спустя 1 месяц 29 дней 10 часов 22 минуты; написано за 1 минуту 18 секунд)
   Post subject:
Reply with quote

подскажите как это реальзовать на windows-1251 (cp1251)
все, вроде бы, работает но вместо слов вылазят краказябры
Back to top
View user's profile Send private message
bæv
Модератор «Дзена»



Joined: 27 Aug 2003
Posts: 7275
Карма: 9997
   поощрить/наказать


PostPosted: Fri Jan 21, 2011 3:36 pm (спустя 7 дней 16 часов 44 минуты)
   Post subject:
Reply with quote


М

Ветка выделена в отдельную тему «мусор»,
расположенную в форуме Мусоропровод (21 Января 2011, 15:36).
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML