como-parsear-html-en-c-con-html-agility-pack

Cómo parsear HTML en C# con HTML Agility Pack

En esta entrada vamos a ver cómo parsear una página web en Html con C# y leer su contenido cómodamente gracias a la librería HTML Agility Pack.

En la actualidad una gran parte de información se transmite al usuario a través de páginas web. Dotar a nuestro programa de la capacidad de hacer lo mismo es una funcionalidad muy útil a la hora de automatizar procesos.

Existen muchísimos casos donde podemos necesitar la lectura de HTML. Por ejemplo, podemos consultar automáticamente el estado de un pedido, o el tracking de un envío, o la variación del precio de un producto, entre un número casi infinito de aplicaciones.

Interpretar un texto HTML con C# no es demasiado difícil pero podemos hacerlo incluso mucho más fácilmente gracias a la librería HTML Agility Pack disponible en https://html-agility-pack.net/.

De momento la librería es Open Source y el código está alojado en https://github.com/zzzprojects/html-agility-pack. Y decimos, de momento, porque en el pasado el autor ha convertido algunas de sus librerías Open Source en comerciales.

Con HTML Agility Pack podemos parsear el HTML a un árbol de nodos. La librería incorpora funciones para localizar los nodos hijos, o que cumplan una serie de propiedades, e incluso podemos aplicar LINQ para las búsquedas.

Podemos cargar una página web con HTML Agility Pack bien desde un fichero de texto, un string en memoria, o directamente desde Internet.

// From File
var doc = new HtmlDocument();
doc.Load(filePath);

// From String
var doc = new HtmlDocument();
doc.LoadHtml(html);

// From Web
var url = "http://html-agility-pack.net/";
var web = new HtmlWeb();
var doc = web.Load(url);

Una vez cargado el documento, podemos obtener uno o varios nodos usando LINQ.

var node = htmlDoc.DocumentNode.SelectSingleNode("//head/title");
var nodes = doc.DocumentNode.SelectNodes("//article")

Una vez que tengamos un nodo, podemos usar HTML Agility Pack para encontrar sus nodos hijos o leer su contenido, incluidos atributos, nombre, clase, texto, etc.

node.Descendants("a").First().Attributes["data-price"].Value
node.Name
node.OuterHtml
node.InnerText

Si el contenido del nodo está codificado como HTML (que es lo normal) podemos “limpiarlo” para convertirlo en un texto “normal” con la ayuda de la función ‘HtmlDecode’ del ensamblado ‘System.Net.WebUtility’

System.Net.WebUtility.HtmlDecode(node.Descendants("a").First().InnerText);

Sin embargo, con HTML Agility Pack únicamente podemos leer el código HTML de la página pero no ejecuta el JavaScript asociado. Esto es un problema en las actuales páginas dinámicas, donde el código HTML cargado inicialmente (que en ocasiones está prácticamente vacío) se modifica por el JavaScript.

Una posible solución es cargar la página Web en un control WebViewer, que sí ejecuta los scripts de la página, y parsear con HTML Agility Pack el contenido del WebViewer.

En cualquier caso, una herramienta útil en multitud de aplicaciones, que merece la pena tener en nuestro inventario de librerías favoritas.