Translate

lunes, 24 de marzo de 2014

Expresiones Regulares en detección de Entidades Nombradas con Java

(Artículo en proceso )

Introducción

Para el procesamiento automatizado de textosde nuestro programa espía internacional deberemos saber de lo que se está hablando, así que procederemos a etiquetar la información en Nombres, Organizaciones y Datos Misceláneos.

Decisión de la fuente de datos


En este caso el orígen de datos será un archivo de texto, por ello deberemos usar un reader para leer cadenas sin procuparnos por lidiar a nivel intermedio con los flujos de cadenas.

 Para ello importamos un lector de ficheros:

import java.io.FileReader;
public class CortaCadenas {
    public static void main(String[] args) {
 }  
}

Como doble precaución y para poderlo operar mejor, agregaremos un búffer.

¿Qué es un búffer?

Un buffer, en el sentido más estricto es un almacenamiento temporal, que se usa para contrarestar el desfase temporal asociado a una señal, proceso o recurso. En este caso, usaremos un búffer pensando que el programa podría correr en una máquina muy lenta (o tal vez muy rápida... en cualquiera de los dos extremos sirve), en la que la velocidad de lectura física del fichero podría ser más lenta que la velocidad a la que recibimos su contenido. En el caso de Java, la Clase BufferedReader contiene el método readLine que para nuesrtos propósitos será muy efectivo al permitrnos leer el texto línea por línea.

Por lo tanto nuestro código quedará algo así:

import java.io.BufferedReader;
import java.io.FileReader;

public class CortaCadenas {
    public static void main(String[] args) { 
     BufferedReader br = null;
 }  
}


Contemplando excepciones


Alguna veces, a pesar de todo, algo peude salir mal, por ello añadiremos un código de manejo deexcepciones de entrada y salida... ¿Qué cómo podría pasar esto? Pudiera ser que nuestro arcivo estuviera siendo escaneado por un antivirus, o lo tuviéramos abierto, o le estuviéramos guardando información, hay muchísimas explicaciones. 
Nuestro código quedaría así:

import java.io.BufferedReader;
import java.io.FileReader;

public class CortaCadenas {
    public static void main(String[] args) { 
     BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader("miarchivodetexto.txt")));
 

            String texto =""; //inicializamos
        } catch (IOException ex) {
            System.err.println("Problema de lectura/escritura");
        }
        finally{
            try {
                br.close();
            } catch (IOException ex) {
                System.err.println("Problemas al cerrar el archivo"); 
            }
        }
 

 }  
}


Usando Expresiones Regulares


Las expresiones regulares es una forma de decir que vamos a buscar expresiones comunes que se pueda expresar de manera matemáticamente regular mediante algún lenguaje.

Identificando Nombres Propios


Por suerte gramaticalmente los nombres propios se distinguen relativamente fácil porque siempre comienzan con la primera letra mayúscula. Existe sin embargo un caso en el que debemos decidir, y es el caso del inicio de texto, pues los textos casi siempre inician con una palabra en mayúscula que no es un nombre, así que omitiremos la primera palabra de los textos.
El código quedará así:

String connombre=texto.replaceAll("\\p{Space}[A-Z][a-z][a-z]+", " NOMBRE");
System.out.println(connombre);


Es importante notar que antes de la palabra NOMBRE hay un espacio, esto es porque nos comemos el espacio anterior para lograr evitar detectar la primera palabra.

Identificando Organizaciones


Otra de las entidades nominales comunmente encontradas son las organizaciones, estas por lo general se caracterizan porque tienen siglas.
En nuestro caso las identificaremos mediante el código:

String conorganizacion=texto.replaceAll("([A-z]+\\.)+", "ORGANIZACION");
System.out.println(conorganizacion);

Identificando Información miscelánea

Aparte de la información importante, también puede que nos interese alguna información miscelánea, como pueden ser precios, fechas, porcentajes y cosas similares.
La información Miscelánea normalmente se etiqueta como MISC, es decir se remplaza toda la palabra de ese carácter por la palabra MISC, en nuestro caso lo haremos con la palabra MISCELANEA.

Lo haremos en nuestro caso mediante:

String conmiscelanea=texto.replaceAll("[\\p{Punct}*[0-9][0-9]+\\p{Punct}*]+[0-9]+", "MISCELANEA");
System.out.println(conmiscelanea);



Contando las ocurrencias


Finalmente contaremos cuantas veces se han detectado:

public class EntidadesNombradas {

    public static void main(String[] args) {
        BufferedReader br = null;

        String texto = "";
        texto = "Ayer fui con Arturo al supermercado Wallmart y me compré 10 chicles en $5.50, enfrente de la O.N.U. en EE.UU.A. solamente al 20% de descuento el día 20/02/2014";

        String[] nombres;
        nombres = texto.split("\\p{Space}[A-Z][a-z][a-z]+");
        System.out.println("Su texto tiene " + (nombres.length-1) + " Nombres");

        String[] organizaciones;
        organizaciones = texto.split("([A-z]+\\.)+");
        System.out.println("Su texto tiene " + (organizaciones.length-1) + " Organizaciones");

        String[] miscelaneas;
        miscelaneas = texto.split("\\B[\\p{Punct}*[0-9][0-9]+\\p{Punct}*]+");
        System.out.println("Su texto tiene " + (miscelaneas.length-1) + " entidades misceláneas");

        String connombre = texto.replaceAll("\\p{Space}[A-Z][a-z][a-z]+", " NOMBRE");
        System.out.println(connombre);
        String conorganizacion = connombre.replaceAll("([A-z]+\\.)+", "ORGANIZACION");
        System.out.println(conorganizacion);
        String conmiscelanea = conorganizacion.replaceAll("[\\p{Punct}*[0-9][0-9]+\\p{Punct}*]+", "MISCELANEA");
        System.out.println(conmiscelanea);

    }
}

Código

El código completo quedaría de la siguiente manera:


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import javax.swing.JOptionPane;

public class EntidadesNombradas {

    public static void main(String[] args) {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(JOptionPane.showInputDialog("Escriba al ruta a su archivo de texto por favor")));
            String texto = "";
            //texto = "Ayer fui con Arturo al supermercado Wallmart y me compré 10 chicles en $5.50, enfrente de la O.N.U. en EE.UU.A. solamente al 20% de descuento el día 20/02/2014";
            String lineaLeida = br.readLine();
            do {
                System.out.println(texto);
                texto += lineaLeida;
                lineaLeida = br.readLine();
            } while (lineaLeida != "" && lineaLeida != null);


            String[] nombres;
            nombres = texto.split("\\p{Space}[A-Z][a-z][a-z]+");
            System.out.println("Su texto tiene " + (nombres.length - 1) + " Nombres");

            String[] organizaciones;
            organizaciones = texto.split("([A-z]+\\.)+");
            System.out.println("Su texto tiene " + (organizaciones.length - 1) + " Organizaciones");

            String[] miscelaneas;
            miscelaneas = texto.split("\\B[\\p{Punct}*[0-9][0-9]+\\p{Punct}*]+");
            System.out.println("Su texto tiene " + (miscelaneas.length - 1) + " entidades misceláneas");

            String connombre = texto.replaceAll("\\p{Space}[A-Z][a-z][a-z]+", " NOMBRE");
            System.out.println(connombre);
            String conorganizacion = connombre.replaceAll("([A-z]+\\.)+", "ORGANIZACION");
            System.out.println(conorganizacion);
            String conmiscelanea = conorganizacion.replaceAll("[\\p{Punct}*[0-9][0-9]+\\p{Punct}*]+", "MISCELANEA");
            System.out.println(conmiscelanea);
        } catch (IOException ex) {
        }
    }
}


No hay comentarios:

Publicar un comentario