Подтвердить что ты не робот

Анализ ключевых слов в PHP

Для веб-приложения, которое я создаю, мне нужно проанализировать веб-сайт, получить и ранжировать его наиболее важные ключевые слова и отобразить их.

Получение всех слов, их плотность и отображение их относительно просты, но это дает очень искаженные результаты (например, рейтинг стоп-слов очень высокий).

В основном, мой вопрос: как я могу создать инструмент анализа ключевых слов в PHP, который приводит к списку, правильно упорядоченному по значению слова?

4b9b3361

Ответ 1

Недавно я работал над этим сам, и я попытаюсь объяснить, что я сделал как можно лучше.

Действия

  • Отфильтровать текст
  • Разделить слова
  • Удалить 2 символьных слова и стоп-слова
  • Определение частоты слов + плотность
  • Определить протуберанту слова
  • Определить контейнеры слов
    • Название
    • Мета-описание
    • URL
    • Заголовки
    • Мета ключевые слова
  • Вычислить значение ключевого слова

1. Фильтровать текст

Первое, что вам нужно сделать, это фильтр, чтобы убедиться, что кодировка верна, поэтому конвертировать в UTF-8:

iconv ($encoding, "utf-8", $file); // where $encoding is the current encoding

После этого вам нужно снять все теги html, знаки препинания, символы и цифры. Посмотрите на функции, как это сделать в Google!

2. Разделить на слова

$words = mb_split( ' +', $text );

3. Удалить 2 символьных слова и стоп-слова

Любое слово, состоящее из 1 или 2 символов, не будет иметь никакого значения, поэтому мы удалим все из них.

Чтобы удалить стоп-слова, сначала нужно определить язык. Мы можем сделать несколько способов:  - Проверка HTTP-заголовка Content-Language  - Проверка атрибута lang = "или xml: lang =" "  - Проверка тегов метаданных языка и контента Если ни один из них не установлен, вы можете использовать внешний API, например AlchemyAPI.

Вам понадобится список стоп-слов на язык, который можно легко найти в Интернете. Я использовал этот: http://www.ranks.nl/resources/stopwords.html

4. Определить частоту слов + плотность

Чтобы подсчитать количество вхождений на слово, используйте это:

$uniqueWords = array_unique ($keywords); // $keywords is the $words array after being filtered as mentioned in step 3
$uniqueWordCounts = array_count_values ( $words );

Теперь перебираем массив $uniqueWords и вычисляем плотность каждого слова следующим образом:

$density = $frequency / count ($words) * 100;

5. Определите протуберант слова

Слово протуберанца определяется положением слов в тексте. Например, второе слово в первом предложении, вероятно, более важно, чем шестое слово в 83-м предложении.

Чтобы вычислить его, добавьте этот код в тот же цикл из предыдущего шага: '

$keys = array_keys ($words, $word); // $word is the word we're currently at in the loop
$positionSum = array_sum ($keys) + count ($keys);
$prominence = (count ($words) - (($positionSum - 1) / count ($keys))) * (100 /   count ($words));

6. Определить контейнеры слов

Очень важная часть - определить, где находится слово - в названии, описании и многом другом.

Во-первых, вам нужно захватить заголовок, все теги метаданных и все заголовки, используя что-то вроде DOMDocument или PHPQuery ( dont пытаться использовать регулярное выражение!) Затем вам нужно проверить, в том же цикле, содержат ли они слова.

7. Вычислить значение ключевого слова

Последний шаг - рассчитать значение ключевых слов. Для этого вам нужно взвесить каждый фактор - плотность, известность и контейнеры. Например:

$value = (double) ((1 + $density) * ($prominence / 10)) * (1 + (0.5 * count ($containers)));

Этот расчет далек от совершенства, но он должен дать вам достойные результаты.

Заключение

Я не упоминал каждую деталь того, что я использовал в своем инструменте, но я надеюсь, что он предлагает хорошее представление о анализе ключевых слов.

N.B. Да, это было вдохновлено сегодняшним blogpost о том, как отвечать на ваши вопросы!

Ответ 2

Одна вещь, которая отсутствует в вашем алгоритме, - это документально-ориентированный анализ (если вы почему-то не пропустили его намеренно).

Каждый сайт построен на наборе документов. Подсчет частот слов для всех и каждого документа предоставит вам информацию о покрытии слов. Словами, которые встречаются в большинстве документов, являются слова остановки. Слова, относящиеся к ограниченному числу документов, могут составлять кластер документов по определенной теме. Количество документов, относящихся к определенной теме, может увеличить общую важность слов этой темы или, по крайней мере, предоставить дополнительный коэффициент, который будет учитываться в ваших формулах.

Возможно, вам может понадобиться предварительно сконфигурированный классификатор, который содержит категории/темы и ключевые слова для каждого из них (эта задача может быть частично автоматизирована путем индексации существующих общедоступных иерархий категорий, вплоть до Википедии, но это не простая задача). Затем вы можете включить категории в analisys.

Кроме того, вы можете улучшить статистику путем анализа уровня предложения. То есть, имея частоты того, как часто слова встречаются в одном и том же предложении или фразе, вы можете обнаружить клише и дубликаты и исключить их из статистики. Но, боюсь, это не так легко импигментировать в чистом PHP.

Ответ 3

Это, вероятно, небольшой вклад, но, тем не менее, я упомянул его.

Контекстная оценка

В какой-то степени вы уже смотрите на контекст слова, используя позицию, в которой он размещен. Вы могли бы добавить еще один фактор к этому, ранжируя слова, которые появляются в заголовке (H1, H2 и т.д.) Выше слов внутри абзаца, выше, чем, возможно, слова в маркированном списке и т.д.

Частотная дезинфекция

Обнаружение стоп-слов на основе языка может работать, но, возможно, вы могли бы использовать кривую колокола, чтобы определить, какие частоты/плотности слов слишком экстравагантны (например, полоса ниже 5% и верхняя 95%). Затем примените оценку остальных слов. Он не только предотвращает стоп-слова, но и злоупотребляет ключевыми словами, по крайней мере теоретически:)

Ответ 4

@уточнение "Шаги"

Что касается выполнения этих многих шагов, я бы пошел с немного расширенным решением, скрепляя некоторые из ваших шагов вместе.

Не уверен, но лучше ли lexer, если вы хорошо его спланируете в соответствии с вашими потребностями, например. посмотрите только на текст внутри hX и т.д. Но вы должны были бы обозначить _serious бизнес, так как это может стать головной болью для реализации. Хотя я остановлюсь и скажу, что решение Flex/Bison на другом языке (PHP предлагает плохую поддержку, поскольку это такой высокий уровень, уровень языка) будет "безумным" ускорением скорости.

Однако, к счастью, libxml предоставляет великолепные функции, и, как показано ниже, вы получите несколько шагов в одном. Перед тем, как вы анализируете содержимое, язык установки (стоп-слова), уменьшите набор NodeList и работайте оттуда.

  • загрузить полную страницу в
  • определить язык
  • извлечь только <body> в отдельное поле
  • освободите немного памяти от <head> и других, например, например. unset($fullpage);
  • запускайте свой алгоритм (если доступен pcntl - linux host, разворачивание и отключение браузера - хорошая функция)

При использовании парсеров DOM следует понимать, что настройки могут вводить дополнительную проверку атрибутов href и src, в зависимости от библиотеки (например, parse_url и нравится)

Другим способом получения ресурсов тайм-аута/потребления памяти является вызов php-cli (также работает для хоста Windows) и "работа с бизнесом" и запуск следующего документа. См. этот вопрос для получения дополнительной информации.

Если вы немного прокрутите список, посмотрите на предлагаемую схему - первоначальный обход поместил бы только тело в базу данных (и, кроме того, занесен в ваш случай), а затем запустил cron- script, заполнив ft_index, используя следующие функция

    function analyse() {
        ob_start(); // dont care about warnings, clean ob contents after parse
        $doc->loadHTML("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\"/></head><body><pre>" . $this->html_entity_decode("UTF-8") . "</pre></body>");
        ob_end_clean();
        $weighted_ft = array('0'=>"",'5'=>"",'15'=>"");

        $includes = $doc->getElementsByTagName('h1');
        // relevance wieght 0
        foreach ($includes as $h) {


                $text = $h->textContent;
                // check/filter stopwords and uniqueness
                // do so with other weights as well, basically narrow it down before counting
                $weighted_ft['0'] .= " " . $text;


        }
        // relevance wieght 5
        $includes = $doc->getElementsByTagName('h2');
        foreach ($includes as $h) {
            $weighted_ft['5'] .= " " . $h->textContent;
        }
        // relevance wieght 15
        $includes = $doc->getElementsByTagName('p');
        foreach ($includes as $p) {
            $weighted_ft['15'] .= " " . $p->textContent;
        }
            // pseudo; start counting frequencies and stuff
            // foreach weighted_ft sz do 
            //   foreach word in sz do 
            //      freqency / prominence
 }

    function html_entity_decode($toEncoding) {
        $encoding = mb_detect_encoding($this->body, "ASCII,JIS,UTF-8,ISO-8859-1,ISO-8859-15,EUC-JP,SJIS");
        $body = mb_convert_encoding($this->body, $toEncoding, ($encoding != "" ? $encoding : "auto"));
        return html_entity_decode($body, ENT_QUOTES, $toEncoding);
    }

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

Опять же, что касается обработки базы данных, я закончил тем, что вставлял вышеприведенный результат в текстовую таблицу с полными текстами, так что будущие поисковые запросы выглядели бы без видимых на вид. Это огромное преимущество для db-движков.

Примечание по полнотекстовому индексированию:

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

Ваш алгоритм индексирования отфильтровывает некоторые слова, нормально. Но они перечислены тем, сколько веса они несут - есть стратегия, чтобы придумать здесь, поскольку полнотекстовая строка не переносит приведенные веса. Вот почему в примере, как основная стратегия по разбиению строк на 3 разных строки, дается.

После ввода в базу данных столбцы должны напоминать это, поэтому схема может быть такой, где мы будем поддерживать весовые коэффициенты, и по-прежнему предлагаем метод сверхбыстрого запроса

CREATE TABLE IF NOT EXISTS `oo_pages` (
  `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  `body` mediumtext COLLATE utf8_danish_ci NOT NULL COMMENT 'PageBody entity encoded html',
  `title` varchar(31) COLLATE utf8_danish_ci NOT NULL,
  `ft_index5` mediumtext COLLATE utf8_danish_ci NOT NULL COMMENT 'Regenerated cron-wise, weighted highest',
  `ft_index10` mediumtext COLLATE utf8_danish_ci NOT NULL COMMENT 'Regenerated cron-wise, weighted medium',
  `ft_index15` mediumtext COLLATE utf8_danish_ci NOT NULL COMMENT 'Regenerated cron-wise, weighted lesser',
  `ft_lastmodified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'last cron run',
  PRIMARY KEY (`id`),
  UNIQUE KEY `alias` (`alias`),
  FULLTEXT KEY `ft_index5` (`ft_index5`),
  FULLTEXT KEY `ft_index10` (`ft_index10`),
  FULLTEXT KEY `ft_index15` (`ft_index15`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_danish_ci;

Можно добавить такой индекс:

ALTER TABLE `oo_pages` ADD FULLTEXT (
`named_column`
)

Дело об обнаружении языка, а затем выбирая свою базу данных о секундах с этой точки - это особенность, которую я сам забыл, но ее изящный - и по книге! Так что, слава за ваши усилия и этот ответ:)

Кроме того, имейте в виду не только тег title, но также атрибуты title/img title. Если по какой-то причине ваша аналитика переходит в состояние паука, я бы предложил объединить ссылку ссылки (<a>) и textContent с целевой страницей <title>

Ответ 5

Я бы рекомендовал вместо того, чтобы изобретать колесо, вы используете Apache SoIr для поиска и анализа. У него есть почти все, что вам может понадобиться, в том числе обнаружение стоп-слова для 30 + языков (насколько я помню, может быть еще больше), и делать множество вещей с данными, хранящимися в нем.