php full-text-search analytics keyword pagerank

Análisis de palabras clave en PHP



full-text-search analytics (5)

@ refinación ''pasos''

En cuanto a hacer estos muchos pasos, me gustaría ir con una solución ''mejorada'', suturando algunos de sus pasos juntos.

Sin embargo, no estoy seguro de si es mejor un lexer completo, si lo diseñas perfectamente para que se ajuste a tus necesidades, por ejemplo, busca solo texto dentro de hX, etc. Pero deberías hacerte cargo de seriedad ya que puede ser un dolor de cabeza implementar. A pesar de que lo expresaré y diré que una solución Flex / Bison en otro idioma (PHP ofrece poca asistencia, ya que es un lenguaje de tan alto nivel) sería un aumento de velocidad "insano".

Sin embargo, afortunadamente libxml proporciona características magníficas y, como debería mostrarse a continuación, terminarás teniendo varios pasos en uno. Antes del punto donde analiza los contenidos, configure el idioma (palabras clave), minimice el conjunto NodeList y trabaje desde allí.

  1. cargar la página completa en
  2. detectar idioma
  3. extraer solo <body> en el campo separado
  4. libere un poco de memoria de <head> y otros como, por ejemplo. unset($fullpage);
  5. active su algoritmo (si pcntl - host de Linux está disponible, forking y release browser es una buena característica)

Al usar analizadores DOM, se debe tener en cuenta que la configuración puede introducir una validación adicional para los atributos href y src, según la biblioteca (como parse_url y likes)

Otra forma de superar el tiempo de espera / el consumo de memoria es llamar a php-cli (también funciona para un host de Windows) y "continuar con el negocio" y comenzar el próximo documento. Vea esta pregunta para más información.

Si se desplaza un poco hacia abajo, mire el esquema propuesto: el rastreo inicial colocará solo el cuerpo en la base de datos (y adicionalmente lang en su caso) y luego ejecutará una secuencia de comandos cron, completando el ft_index mientras usa la siguiente función

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); }

Lo anterior es una clase, similar a su base de datos que tiene el campo ''cuerpo'' de la página cargado de antemano.

Nuevamente, en lo que respecta al manejo de la base de datos, terminé insertando el resultado analizado anterior en una tabla de texto marcada con un texto completo para que las búsquedas futuras salieran aparentemente. Esta es una gran ventaja para los motores db .

Nota sobre la indexación de texto completo:

Cuando se trata de una pequeña cantidad de documentos, es posible que el motor de búsqueda de texto completo escanee directamente el contenido de los documentos con cada consulta, una estrategia llamada escaneo en serie. Esto es lo que hacen algunas herramientas rudimentarias, como grep, al buscar.

Su algoritmo de indexación filtra algunas palabras, está bien ... Pero estos se enumeran por la cantidad de peso que tienen: hay una estrategia para pensar aquí, ya que una cadena de texto completo no supera los pesos dados. Es por eso que en el ejemplo, se proporciona una estrategia básica para dividir cadenas en 3 cadenas diferentes.

Una vez colocadas en la base de datos, las columnas deberían parecerse a esto, por lo que un esquema podría ser así, en el que mantendríamos ponderaciones y aún ofrecer un método de consulta súper rápido.

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;

Uno puede agregar un índice como tal:

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

La cuestión de detectar el idioma y luego seleccionar su base de datos de palabras clave a partir de ese punto es una característica que yo mismo he omitido, pero es ingeniosa: ¡y por el libro! Así que felicitaciones por sus esfuerzos y esta respuesta :)

Además, tenga en cuenta que no solo existe la etiqueta de título, sino también los atributos de título de ancla / img. Si, por alguna razón, su análisis entra en un estado similar a una araña , sugeriría combinar el título del enlace de referencia ( <a> ) y el contenido de texto con la página de destino <title>

Para una aplicación web que estoy creando, necesito analizar un sitio web, recuperar y clasificar las palabras clave más importantes y mostrarlas.

Obtener todas las palabras, su densidad y mostrarlas es relativamente simple, pero esto da resultados muy sesgados (por ejemplo, palabras de parada muy altas).

Básicamente, mi pregunta es: ¿Cómo puedo crear una herramienta de análisis de palabras clave en PHP que resulte en una lista ordenada correctamente por importancia de palabra?


Probablemente sea una pequeña contribución, pero la mencionaré de todas formas.

Puntuación de contexto

Hasta cierto punto, ya estás mirando el contexto de una palabra usando la posición en la que está colocada. Puede agregar otro factor a esto al clasificar las palabras que aparecen en un encabezado (H1, H2, etc.) más alto que las palabras dentro de un párrafo, más alto que quizás las palabras en una lista con viñetas, etc.

Desinfección de frecuencia

La detección de palabras de parada basadas en un idioma podría funcionar, pero quizás podría considerar el uso de una curva de campana para determinar qué frecuencias / densidades de palabras son demasiado extravagantes (por ejemplo, eliminar el 5% y el 95% superior). Luego aplique el puntaje en las palabras restantes. No solo evita las palabras vacías, sino también el abuso de palabras clave, al menos en teoría :)


Recientemente, he estado trabajando en esto, e intentaré explicar lo que hice lo mejor posible.

Pasos

  1. Filtrar texto
  2. Dividir en palabras
  3. Eliminar palabras de 2 caracteres y palabras de parada
  4. Determinar frecuencia de palabras + densidad
  5. Determinar la palabra prominencia
  6. Determinar contenedores de palabras
    1. Título
    2. Metadescripción
    3. URL
    4. Encabezados
    5. Palabras clave meta
  7. Calcular el valor de la palabra clave

1. filtrar texto

Lo primero que debe hacer es filtrar para asegurarse de que la codificación sea correcta, por lo que convertir es a UTF-8:

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

Después de eso, debes eliminar todas las etiquetas html, signos de puntuación, símbolos y números. ¡Busque funciones sobre cómo hacer esto en Google!

2. dividir en palabras

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

3. Elimina palabras de 2 caracteres y palabras de parada

Cualquier palabra que conste de 1 o 2 caracteres no tendrá ningún significado, por lo que los eliminamos todos.

Para eliminar las palabras clave, primero debemos detectar el idioma. Hay un par de maneras en que podemos hacer esto: - Verificar el encabezado HTTP de Content-Language - Comprobar el atributo lang = "" o xml: lang = "" - Comprobar las etiquetas de metadatos Language y Content-Language Si no se establece ninguna de ellas, puedes usar una API externa como la AlchemyAPI .

Necesitará una lista de palabras clave por idioma, que puede encontrar fácilmente en la web. He estado usando este: http://www.ranks.nl/resources/stopwords.html

4. Determinar frecuencia de palabras + densidad

Para contar el número de ocurrencias por palabra, usa esto:

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

Ahora recorra la matriz $ uniqueWords y calcule la densidad de cada palabra de esta manera:

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

5. Determinar la prominencia de la palabra.

La palabra prominencia se define por la posición de las palabras dentro del texto. Por ejemplo, la segunda palabra en la primera oración es probablemente más importante que la sexta palabra en la oración 83.

Para calcularlo, agregue este código dentro del mismo bucle del paso anterior: ''

$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. Determinar contenedores de palabras

Una parte muy importante es determinar dónde reside una palabra: en el título, la descripción y más.

Primero, debe capturar el título, todas las etiquetas de metadatos y todos los encabezados utilizando algo como DOMDocument o PHPQuery (¡ no intente usar expresiones regulares!) Luego debe verificar, dentro del mismo bucle, si contienen las palabras.

7. Calcular el valor de la palabra clave

El último paso es calcular un valor de palabras clave. Para hacer esto, necesita pesar cada factor: densidad, prominencia y contenedores. Por ejemplo:

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

Este cálculo está lejos de ser perfecto, pero debería darle resultados decentes.

Conclusión

No he mencionado todos los detalles de lo que utilicé en mi herramienta, pero espero que ofrezca una buena visión del análisis de palabras clave.

NB Sí, esto se inspiró en la publicación de blog de hoy sobre cómo responder a sus propias preguntas.


Recomendaría que, en lugar de reinventar la rueda, utilice Apache SoIr para la búsqueda y el análisis. Tiene casi todo lo que pueda necesitar, incluida la detección de palabras de parada para más de 30 idiomas [hasta donde puedo recordar, podría ser aún más] y hacer toneladas de cosas con los datos almacenados en él.


Una cosa que falta en su algoritmo es el análisis orientado a documentos (si no lo omitió intencionalmente por algún motivo).

Cada sitio está construido sobre un conjunto de documentos. Contar las frecuencias de palabras para todos y cada uno de los documentos le proporcionará información sobre la cobertura de palabras. Las palabras que aparecen en la mayoría de los documentos son palabras vacías. Las palabras específicas para un número limitado de documentos pueden formar un grupo de documentos sobre un tema específico. La cantidad de documentos que pertenecen a un tema específico puede aumentar la importancia general de las palabras del tema, o al menos proporcionar un factor adicional para ser contado en sus fórmulas.

Tal vez, podría beneficiarse de un clasificador preconfigurado que contiene categorías / temas y palabras clave para cada uno de ellos (esta tarea se puede automatizar parcialmente al indexar las jerarquías públicas de categorías existentes, hasta Wikipedia, pero esto no es una tarea trivial en sí). Entonces puedes involucrar categorías en el análisis.

Además, puede mejorar las estadísticas por análisis en el nivel de la oración. Es decir, al tener frecuencias de la frecuencia con que aparecen las palabras en la misma frase o frase, puede descubrir clichés y duplicados y eliminarlos de las estadísticas. Pero, me temo que esto no se ve afectado fácilmente en PHP puro.