Алгоритм поиска ключевых слов и ключевых фраз в строке

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

Строка содержит:

  • Техническая информация, написанная на английском языке (GB)
  • Слова в основном разделены пробелами
  • Ключевое слово не содержит пробела, но может содержать дефис, апостроф, двоеточие и т.д.
  • keyphrase может содержать пробел, запятую или другую пунктуацию
  • Если два или более ключевых слова отображаются вместе, то, скорее всего, это ключевая фраза, например. "инверторный привод"
  • Текст также содержит HTML, но при необходимости его можно удалить заранее
  • Не-ключевые слова будут такими словами, как "и", "the", "we", "see", "look" и т.д.
  • Ключевые слова не чувствительны к регистру, например. "Инвертор" и "инвертор" - это одно и то же ключевое слово

Алгоритм имеет следующие требования:

  • Работайте в сценарии пакетной обработки, например. запускать один или два раза в день.
  • Строки процесса, изменяющиеся по длине от примерно от 200 до 7000 символов
  • Процесс 1000 строк менее чем за 1 час
  • Выполняется на сервере с умеренно хорошей мощностью
  • Написано в одном из следующих: С#, VB.NET или T-SQL, возможно, даже F #, Python или Lua и т.д.
  • Не полагаться на список предопределенных ключевых слов или ключевых фраз
  • Но может полагаться на список исключений ключевых слов, например. "и", "," идти" и т.д.
  • Идеально переносимый на другие языки, например. не полагается на специфические для языка функции, например. метапрограммированием
  • Вывести список ключевых фраз (порядок по убыванию), а затем список ключевых слов (по убыванию частоты)

Было бы здорово, если бы он обрабатывал до 8000 символов за считанные секунды, так что его можно было запустить в режиме реального времени, но я уже спрашиваю достаточно!

Просто ищите советы и указания:

  • Должны ли это рассматриваться как два отдельных алгоритма?
  • Существуют ли какие-либо установленные алгоритмы, которые я мог бы выполнить?
  • Возможны ли мои требования?

Большое спасибо.

P.S. Строки будут извлекаться из базы данных SQL Server 2008 R2, поэтому в идеале язык будет поддерживать это, если не тогда, он должен иметь возможность читать/записывать в STDOUT, канал, поток или файл и т.д.

Ответ 1

Приведенная логика усложняет программирование в T-SQL. Выберите язык, такой как С#. Сначала попробуйте сделать простое настольное приложение. Позже, если вы обнаружите, что загрузка всех записей в это приложение происходит слишком медленно, вы можете написать хранимую процедуру С#, которая выполняется на SQL-сервере. В зависимости от политики безопасности SQL-сервера он должен иметь сильный ключ.


Теперь алгоритм. Список исключенных слов обычно называют списком стоп-слов. Если вы выполняете поиск по поисковому запросу, вы можете найти список стоп-слов, с которых вы можете начать. Добавьте эти стоп-слова в HashSet<T> (я буду использовать С# здесь)

HashSet<string> stopWords = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
string[] lines = File.ReadAllLines("C:\stopwords.txt");
foreach (string s in lines) {
    stopWords.Add(s); // Assuming that each line contains one stop word.
}

Позже вы можете посмотреть, есть ли кандидат на ключевые слова в списке стоп-слов с помощью

If (!stopWords.Contains(candidate)) {
    // We have a keyword
}

HashSets быстр. Они имеют время доступа O (1), что означает, что время, необходимое для поиска, не зависит от содержащихся в нем элементов.

Поиск ключевых слов можно легко выполнить с помощью Regex.

string text = ...; // Load text from DB
MatchCollection matches = Regex.Matches(text, "[a-z]([:']?[a-z])*",
                                        RegexOptions.IgnoreCase);
foreach (Match match in matches) {
    if (!stopWords.Contains(match.Value)) {
        ProcessKeyword(match.Value); // Do whatever you need to do here
    }
}

Если вы обнаружите, что a-z слишком ограничительно для букв и вам нужны буквы с акцентом, вы можете изменить выражение регулярного выражения на @"\p{L}([:']?\p{L})*". Класс символов \p{L} содержит все модификаторы букв и букв.

Фразы более сложны. Сначала можно попытаться разбить текст на фразы, а затем применить поиск по ключевым словам для этих фраз вместо поиска ключевых слов во всем тексте. Это дало бы вам количество ключевых слов во фразе одновременно.

Разделение текста на фразы включает поиск предложений, заканчивающихся на "." или "?" или "!" или ":". Вы должны исключить точки и двоеточия, которые появляются в пределах слова.

string[] phrases = Regex.Split(text, @"[\.\?!:](\s|$)");

Здесь выполняется поиск прерываний, сопровождаемых пробелом или концом строки. Но я должен согласиться с тем, что это не идеально. Он может ошибочно обнаруживать сокращения в конце предложения. Вам нужно будет провести эксперименты, чтобы улучшить механизм расщепления.