Posts Tagged ‘firefox’

Parsing de HTML con HtmlAgilityPack

February 5th, 2009

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?

SVG+Firefox me han fallado

January 8th, 2009

Recientemente me vi con la necesidad de crear una pagina web que visualizara gráficos dinámicos de acuerdo a ciertos datos recabados en tiempo real.

Debido a que ocupaba mostrar el gráfico tanto en una pantalla gigante como en dispositivos móviles pensé que la solución obvia era usar gráficos vectoriales. ¿Que tan difícil podía ser?.

Que ingenuo fui.

Innegablemente la clara solución era SVG (Scalable Vectors Graphics), sabia que me toparía con un par de problemas, principalmente con compatibilidad entre navegadores. Ninguna batalla que algún desarrollador web no haya luchado alguna vez. Un trabajo sucio pero alguien tiene que hacerlo.

IE no soporta SVG, a su vez usa un formato propietario VML (Vector Markup Language) el cual no tengo interés de aprender (ningún otro navegador lo soporta), pero afortunadamente Adobe ofrece un plugin que le da a IE la posibilidad de visualizar SVG, una pequeña molestia pero nada infranqueable.

Entre otras cosas lo que requería hacer era insertar varias instancias de una misma imagen SVG sobre otra imagen SVG base y manipularla a través de scripting para asignar su posicionamiento, mascara, etc. Pero al intentar insertar la imagen no aparecía nada.

WTF?!
Después de batallar, leer, moverle, etc. Se me ocurre insertar una imagen PNG a la vez de SVG y todo funciona correctamente. WHAT?. Resulta que Firefox solo soporta insertar imágenes rasterizadas (jpg, png) dentro de SVG, y no puedo insertar otras imágenes vectoriales dentro de imágenes vectoriales.

DAMN!
En ese instante quede aturdido, que sentido tiene usar SVG por ser escalable si no puedo insertar imágenes escalables (Ojo, es un bug de Firefox, la recomendación de SVG especifica que esto debe de ser permitido). No tenia sentido que siguiera con mi esfuerzo de implementarlo a golpe de SVG con javascript.

Por mucho que me doliera tuve que abandonar la solución que utilizaba estandares para usar formatos propietarios.

Una ves mas, Flash ha ganado la batalla.