Parsing HTML en Cocoa

Torrent Hunter 0.9.1 b2


Actualmente estoy trabajando en un proyecto OpenSource, un app sencillita (de momento solo para Mac OS X), escrita en Objective-C, cuya función es única y exclusivamente buscar torrents en distintos sitios web (de momento ThePirateBay y Demonoid) para realizar esta tarea de forma sencilla, con un simple double-click, se abrirá nuestro gestor de Torrents favorito.
En mi empeño por buscar una solución a realizar un búsqueda sobre sus servidores me encontré con una posible solución que me llevó sus quebraderos de cabeza. Esta posible solución era bajarme el texto en HTML de la búsqueda y parsearlo con expresiones regulares, a todos nos gusta curl/wget y a parsear que es gerundio con sed, pero esto no es BASH y ya que no es fácil trabajar con expresiones regulares en Objective-C, desde un principio rechacé esta opción.
Más tarde, jugué un poco con el objeto NSXMLParser disponible en el API de Apple desde la versión 10.3 (Mac OS X Panther), pero me di cuenta de que tampoco era fácil tratar un texto HTML con sus tags definidos con un parser específico para XML (o al menos yo no estoy preparado para ese trago).
Finalmente encontré una librería escrita enteramente en Objective-C por Ben Reeves (aquí podéis visitar su web en GItHub). Ben me solucionó la vida, ya que simplemente tuve que importar sus ficheros y tenía las funciones de parsing ya implementadas.
Vamos a analizar un poquito más en profundidad estas funciones y para ello vamos a poner un ejemplo de código sencillo.
NSError *error = nil;
NSURL *url = [NSURL URLWithString:@"http://www.example.com"];
HTMLParser *parser = [[HTMLParser alloc] initWithContentsOfURL:url error:&error];
Lo primero es que esta librería añade un objeto llamado HTMLParser, este contiene una serie de métodos propios, de los cuales el más interesante a la hora de iniciar el objeto, quizá sea el método "initWithContentsOfURL:" al cual se le pasa como parámetro un objeto NSURL (podemos darle valor con: "URLWithString:" que como parámetro recibe un NSString), y ya tendremos nuestro parser iniciado. Añadir que el método está implementado para que se pueda recoger un error en un objeto NSError si lo deseamos, si no pasaremos como parámetro nil, aunque siempre es preferible recoger el error.
HTMLNode *bodyNode = [parser body];
HTMLNode *titleNode = [bodyNode findChildTag:@"h1"];
NSLog(@"Titulo: %@",[titleNode contents]);
Nota: esta librería trata como nodos (node) los tags HTML, a partir de ahora voy a tratar los tags como nodo.
Una vez tenemos el parser podemos referirnos al nodo  indicando que genere un HTMLNode y empleando el método body. Con este objeto que contiene el nodo body podemos usar los metodos para buscar tags hijos del  mediante los distintos métodos que nos proporciona la librería: findChildTag:(devuelve un objeto HTMLNode), finChildTags:(devuelve un NSArray cuyo contenido son HTMLNodes), findChildWithAttribute: matchingName: allowPartial:(devuelve un objeto HTMLNode), findChildrenWithAttribute: matchingName: allowPartial:(devuelve un NSArray cuyo contenidos son HTMLNodes).
El método "contents" devuelve un NSString con el contenido de texto que contiene el tag. En este ejemplo recogemos el contenido del tag y lo mostramos por la consola.


Si tenéis alguna duda solo tenéis que contactar conmigo mediante el mail indicado en el blog.
La página del proyecto Torrent Hunter es esta: http://alexsays.me

No hay comentarios:

Publicar un comentario