Software Guru Conference & Expo 2014

Quitar etiquetas HTML

Me preguntaba si existe una librería Java para quitar las etiquetas de un documento HTML y pues no pude buscar mucho y decidi hacer un pequeño ejercicio.

Para mi es un tema complejo por que una pagina html se ejecuta casi normal aun que no este validado el documento, o X, X, X, cosa, también si deseo quietar los CSS o los Scripts se convierte en algo más rudo.

Les dejo lo que pude hacer y si saben o quieren compartirme otra forma de resolverlo (haber si pueden? jejeje es broma ) se los agradezco mucho.

Nop, no es para producción ni para algo que llegara a ser lo, solo es por pasar el rato :D.

import java.io.IOException;

public class Main {

    public static void main(String args[]) throws IOException {
        ReadUrlContent readUrlContent = new ReadUrlContent();
        String html = readUrlContent.getContent("http://www.javamexico.org/foros/comunidad/ayuda_lista_enlazada");
        TakeOutTags takeOutTags = new TakeOutTags();
        String text = takeOutTags.getText(html, "<", ">");
        //Solo para ponerlo mas bonito se quitan los saltos de linea
        // y se reemplazan los simbolos html por ascii
        for (String s : text.split(System.getProperty("line.separator"))) {
            s = s.trim();
            if (!s.isEmpty()) {
                System.out.println(
                        s.trim().replace(
                        "&nbsp;", " ").replace(
                        "&quot;", "\"").replace(
                        "&#40;", "(").replace(
                        "&#41;", ")").replace(
                        "&#123;", "{").replace(
                        "&#125;", "}").replace(
                        "&#91;", "[").replace(
                        "&#93;", "]"));
            }
        }
    }
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLEncoder;

public class ReadUrlContent {

    /**
     * @param url direccion valida para extraer la informacion
     * @return un String con el contenido de la pagina
     * @throws IOException [:S]
     */

    public String getContent(String url) throws IOException {
        URL htmlStream = new URL(url);
        StringBuilder out = new StringBuilder();
        Reader in = new InputStreamReader(htmlStream.openStream(), "UTF-8");
        int read = 0;
        final char[] buffer = new char[0x2048];
        while ((read = in.read(buffer)) > 0) {
            out.append(buffer, 0, read);
        }
        return out.toString();
    }
}

public class TakeOutTags {

    /**
     * @param html String con el texto con etiquetas
     * @param openString caracter(String) que inicia la etiqueta '<'
     * @param closeString caracter(String) que cierra la etiqueta '>'
     * @return String sin etiquetas
     */

    public String getText(String html, String openString, String closeString) {
        int indexOfOpenString = html.indexOf(openString);
        int indexOfCloseString = html.indexOf(closeString);
        if (indexOfOpenString != -1 && indexOfCloseString != -1) {
            String substring = html.substring(indexOfOpenString, indexOfCloseString + 1);
            html = getText(html.replace(substring, ""), openString, closeString);
        }
        return html;
    }
}

Entrada:
<i>¿Hola como te va?</i>

SALIDA:
¿Hola como te va?

Nota: Se que esta mal que ponga tanta basura en mi blog, pero no tengo donde poner las pocas cosas que me interesan y claro que no es para ver javamexico.org en el trabajo y sin que nadie lo note, que ver código de otros es una forma de relajación ammm bueno no solo es divertido.

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

generalizar

Para que no tengas que poner una lista gigantesca de los caracteres especiales, te recomiendo que mejor busques la regex &#\d+; y simplemente sustituyas por el caracter indicado (esa notación es para poner un caracter Unicode).

Imagen de OscarRyz

Puedes poner un ejemplo de

Puedes poner un ejemplo de entrada y de salida (breves)?

En tu ejemplo puedes leer todo el stream sin que lo hagas linea por línea. Es más eficiente y no modificas el contenido ( eliminando los saltos de línea )

Toma algún ejemplo de aquí ( a mi me gusta más la segunda respuesta )

http://stackoverflow.com/questions/326390/how-to-create-a-java-string-fr...

Imagen de rodrigo salado anaya

A muchas gracias.

Gracias a ambos voy a poner lo que me recomiendan... me quedan dudas con lo de 'regex &#\d+;' pero lo voy a buscar : ).

Imagen de OscarRyz

Y mi ejemplo?

Y mi ejemplo? Por cierto esta es una de las cosas que ya se hacen, se llama HTML ( o quizá XML ) sanitizing y pues claro su utilidad está en para limpiar información agregada por el usuario:

   <a href="como esta">
Imagen de rodrigo salado anaya

ups...

@Oscar jejeje pues en el estoy en este instante ... me atore por que no encuentro aun como llegar de un URL a un FileChannel.
Estoy leyendo esto http://www.coderanch.com/t/278475/Streams/java/Filechannel, y la documentación, jajajaja pense que seria cosa de un par de minutos....

:O no sabia que se llamara así (html sanitization), tal ves por eso no logre encontrar mucho al respecto...

Imagen de ezamudio

sanitizing, sanitation

no hay sanitization, es sanitation (por si buscas algo porque con sanitization no aparece nada aunque probablemente san google te corregira).

De URL es mas facil llegar a stream que a channels.

Con replaceAll("\\<.*?>",""); quitas los HtmlTags

Podria funcionar a pura expresion regular... algo asi como un crawler.

se me hace que pudes eliminar las etiquetas algo asi

replaceAll("\\<.*?>","");

pero como dices, si el nodo tiene atributos los mocharia... mmmmm dejame ver.

Echale un lente a este post, http://haacked.com/archive/2004/10/25/usingregularexpressionstomatchhtml...
Ya un add a este tema podria ser de poner funcionalidad de extraer imagenes, links, correos, direcciones de twitter, telefonos, alguna informacion que pueda parecer util

Para convertir las palabras de escape no encuentro algo que te permita modificarlo sin tener que hacerte una lista de lo que quieres convertir a otra a lo que quieras obtener... Cmo dice @ezamudio: para buscar podrias usar &#\d+; lo interesante es "ok, ya lo encontraste, como lo reemplazas?"

encntre en StackOverflow que existe un apache commons org.apache.commons.lang.StringEscapeUtils.escapeHtml para hacer esta tarea, eso si quieres meterle una dependencia... si no pos a hacerlo a patita y por ahora no le veo que hacer listas de reemplazo

Imagen de OscarRyz

Algo que está relacionado, es

Algo que está relacionado, es la biblioteca para procesar Markdown que es un formato : WYSIWYM ( What you see is what you mean ) y que es usado pues.. ya en muchas partes. Notoriamente en StackOverflow, en GitHub y en code.googlacom/ ( bueno y seguramente en muchas partes )

Cuando entré aquí lo primero que dije fue Porque no tienen esto, luego en JavaMexico 2.0 quise ponerselo pero mi ignoracia de Javascript + Tapestry me lo impidió. Cuando supe como hacerlo ya se me había pasado la emoción. Ahora que fui a lo de las OpenTalks me surgió de nuevo, pero me estoy aguantando.

El markdown sirve para darle formato a lo que escribes. Por ejemplo una lista sería:

- a
- b
- c

Y el código sería ( dejando 4 espacios ):

<a href="lalalala>

Hay un port de esta biblioteca en: https://github.com/cletus/jmd y hace un uso extenso de expresiones regulares. Es una sola clase y no está tan larga, ahi se las dejo.

https://github.com/cletus/jmd/blob/master/src/main/java/com/cforcoding/j...

Espero poder ( algún día ) integrarlo a JavaMexico2.0 :)

Imagen de rodrigo salado anaya

Tarde : )

@Oscar ya puse un nuevo método para la lectura del HTML, y edite los ejemplos de entrada y salida; muy breves jejeje.

@JDD, gracias estoy leyendo las ligas que me dejaste están interesante, desconocía por completo todo esto.

@Zamudio Jejeje si en efecto, no hay sanitization, es sanitation, garcias.