Parsing de HTML con HtmlAgilityPack

February 5th, 2009 by AlbertEin Leave a reply »

La web esta llena de información, todo tipo de información, desde el vídeo divertido mas irrelevante hasta noticias o documentos de verdadera importancia. Hay un mundo de información a la cual tu computadora esta unida por el cordón umbilical de tu cable de red, dispuesta a ser accesada y mostrada en tu pantalla a la mas mínima orden tuya.

Pero tiene un problema.

Toda esta valiosa información se encuentra ofuscada en HTML, un lenguaje el cual a sido seriamente abusado durante el transcurso de los años, debido a que su especificación indica que los navegadores deben hacer lo mejor posible para corregir errores en el formateo de un documento, por lo que los usuarios terminaron en volverse descuidados, olvidando una etiqueta de cierre aquí y halla, al fin y al cabos el resultado es el mismo, ¿no?, los navegadores hacen todo lo posible por mostrar incluso los documentos mas mal formados.

Eso hace que hacer un programa para extraer información de un documento HTML pueda llegar a ser un poco complicado en ocasiones.

HtmlAgilityPack to the rescue!

HtmlAgilityPack es una librería para .NET que nos brinda un parser de HTML que nos permite leer, escribir y manipular documentos HTML y soporta Xpath, el cual discutí hace tiempo. Y lo que lo hace realmente especial es que es increíblemente permisivo, soportando los documentos mas perversamente malformados que te puedes encontrar en tu navegación día a día.

HtmlAgilityPack combinado con Firebug nos permite extraer hasta la ultima gota de información requerida, y para no hacérselas larga pondré un par de ejemplos en el resto del post.

Quiero obtener la lista de títulos del blog del AlbertEin

1
2
3
4
5
6
7
8
9
10
11
static void Main(string[] args)
{
    var client = new System.Net.WebClient();
    client.Encoding = System.Text.Encoding.UTF8;
    var document = new HtmlAgilityPack.HtmlDocument();
    document.LoadHtml(client.DownloadString("http://albertein.gamersla.net"));
 
    foreach (HtmlAgilityPack.HtmlNode node in 
        document.DocumentNode.SelectNodes("//a[@class='title']"))
            Console.WriteLine(node.InnerHtml);
}

Quiero obtener la lista de palabras listada en una web de un diccionario

1
2
3
4
5
6
7
8
9
10
11
12
static void Main(string[] args)
{
    var url = "http://diccionario.babylon.com/Humanidades/Mitolog%C3%ADa/A/1/";
    var client = new System.Net.WebClient();
    client.Encoding = System.Text.Encoding.UTF8;
    var document = new HtmlAgilityPack.HtmlDocument();
    document.LoadHtml(client.DownloadString(url));
 
    foreach (HtmlAgilityPack.HtmlNode node in
        document.DocumentNode.SelectNodes("//a[@class='words']"))
            Console.WriteLine(node.InnerHtml);
}

Quiero bajar todos los malditos comics de Penny Arcade

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
static void Main(string[] args)
{
    var url = "http://www.penny-arcade.com/comic/1998/11/18/";
    var baseUrl = "http://www.penny-arcade.com";
    bool lastStrip = false;
    var client = new System.Net.WebClient();
    client.Encoding = System.Text.Encoding.UTF8;
 
    while (!lastStrip)
    {
        var document = new HtmlAgilityPack.HtmlDocument();
        document.LoadHtml(client.DownloadString(url));
 
        var imageQuery = "/html/body/div[2]/div[3]/div/div[2]/img";
        var nextButtonQuery = "/html/body/div[2]/div[3]/div/div[3]/a[4]";
 
        var imageUrl = document.DocumentNode.
            SelectSingleNode(imageQuery).Attributes["src"].Value;
 
        //Aquí iria el codigo para descargar la imagen que se encuentra en
        //baseUrl + imageUrl
 
        //Obtenemos la dirección del próximo comic
 
        url = baseUrl + document.DocumentNode.
            SelectSingleNode (nextButtonQuery).Attributes ["href"].Value; 
 
        lastStrip = url == baseUrl; // Llegamos al ultimo comic?
    }
}

Podría seguir así todo el día, pero supongo que con eso es suficiente para que capten la idea.

¿Y tu, como lo has usado?

Advertisement

8 comments

  1. Fire_tony says:

    Lo imprimo y me lo como.

  2. monse says:

    Estoy trabajando con hatmlparser, y me gustaria saber como descarga una imagen que se encuntre dentro de un html, pero con java. Ya me muestra si existe el tag img, ahora solo quiero descargar la imgen apartir de lo que me arroja, le pido me ayude prorfavor.
    les dejo el codigo que llevo

    import org.htmlparser.NodeFilter;
    import org.htmlparser.Parser;
    import org.htmlparser.filters.TagNameFilter;
    import org.htmlparser.util.ParserException;

    public class IdenImagen {
    public static void main(String[] args) {
    Parser parser = new Parser();
    NodeFilter filter = new TagNameFilter (“IMG”);
    Parser.getConnectionManager ().setRedirectionProcessingEnabled(true);
    Parser.getConnectionManager ().setCookieProcessingEnabled(true);
    try{
    parser.setResource (“http://htmlparser.sourceforge.net/samples.html”);
    System.out.println(parser.parse (filter));
    }

    catch(ParserException e){
    e.printStackTrace();
    }
    }

    }

  3. AlbertEin says:

    @monse
    Ocupas usar HttpURLConnection (http://www.j2ee.me/j2se/1.4.2/docs/api/java/net/HttpURLConnection.html) en java.net conectandote a la url de la imagen que has extraído. Si ocupas detalles contactame y veo si te puedo ayudar.

    Saludos

  4. monse says:

    ok gracias por el aporte lo estare revisando y cuanquier duda que tenga te estare contactando, al igual si encuntro la solucion.

  5. edd says:

    me genera una excepcion en el foreach,
    que me hace falta?

Leave a Reply