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?