Apuntes sobre Hpricot y web spidering

HpricotHpricot es un parser de HTML sencillo de usar y a la vez muy potente, escrito por _why the lucky stiff, un tío ¿o es una tía? que además de estar de la olla, controla muchísimo de Ruby y hace cosas muy interesantes, como por ejemplo esta gema.

He usado Hpricot para mejorar a Boris, la araña, en su tarea de extraer información de páginas HTML. Boris tiene la misión de visitar páginas web y almacenar su título, meta keywords y meta description, y además ver con qué páginas externas enlaza para visitarlas también. Así, un día la lancé a la Wild Wild Web para que rastreara a partir de www.railes.net, y a día de hoy lleva más de 200.000 URLs distintas, categorizadas por keywords.

La extracción de datos la hacía descargando las páginas con open-uri y después buscando la información con expresiones regulares, digamos, “a pelo”. Esto es complicado, no es fácil encontrar una expresión regular que cubra todos los casos que necesitas. Tenía fallos y a veces sacaba datos incorrectos.

El caso es que me decidí a probar Hpricot. La instalé como gema en mi Ubuntu:


jaime@zimpa:~$ sudo gem install hpricot
Password:
 (...)
Building native extensions.  This could take a while...
Successfully installed hpricot-0.6
Installing ri documentation for hpricot-0.6...
Installing RDoc documentation for hpricot-0.6...

Y después probé algún ejemplo (ejemplo01.rb.gz):

  1. require ‘rubygems’
  2. require ‘open-uri’
  3. require ‘hpricot’
  4.  
  5. doc = Hpricot(open(‘http://www.railes.net))
  6.  
  7. puts doc.at(‘title’).inner_html
  8. puts doc.at("meta[@name='description']")[‘content’]
  9. puts doc.at("meta[@name='keywords']")[‘content’]

Los códigos son fáciles de entender. Las tres primeras líneas son los tres “require” necesarios para incluir las gemas. Obviamente necesitamos Hpricot, pero también necesitamos open-uri, que es la encargada de bajarse la página que le digamos (el churro HTML que después parsearemos con Hpricot). El primer require, rubygems, es necesario para poder cargar Hpricot.La siguiente línea asigna al objeto doc un objeto Hpricot resultante de parsear la página descargada con open-uri. Viendo desde dentro del paréntesis, primero hacemos open(’http://www.railes.net’), y eso lo pasamos como parámetro a Hpricot(), con lo que conseguimos un árbol con toda la jerarquía del documento HTML. Si haces esto desde irb, podrás ver esto mejor. También puedes hacer un “pp doc”.Las tres siguientes líneas muestran por pantalla el resultado de tres búsquedas en este objeto Hpricot. Básicamente, para buscar algo en el documento emplearemos doc.search(), que devolverá una colección con todo lo encontrado si hay varias coincidencias, o doc.at(), que devolverá sólo la primera coincidencia.

Para este primer ejemplo, usaremos doc.at(). Le pasamos un patrón de lo buscado, en el primer caso ‘title’, y nos localiza el título. Finalmente le aplicamos inner_html para que nos devuelva sólo lo que hay entre las etiquetas HTML de definición de título. Otra opción sería to_html para que las incluya.

Veamos las diferencias en este ejemplo:


  1. irb(main):009:0>doc.at(‘title’)
  2. => {elem }
  3. irb(main):010:0> doc.at(‘title’).inner_html
  4. => "Railes.net - Desarrollo web ágil - Inicio"
  5. irb(main):011:0> doc.at(‘title’).to_html
  6. => "<title>Railes.net - Desarrollo web ágil - Inicio</title>"

La búsqueda de meta tags es un pelín diferente. Aquí empleamos la opción de especificar valores de atributos, con la @. En el primer caso, buscamos la etiqueta meta cuyo atributo name sea “description”. Y del resultado, nos quedamos con el contenido del atributo “content”.Suficiente teoría! Lo ejecuto y… tachán! Funciona a la primera. Ahí tenía mi título, description y keywords para la página:

jaime@zimpa:~/hpricot$ ruby ejemplo01.rb
Railes.net - Desarrollo web ágil - Inicio
Desarrollo de aplicaciones web a medida. Formación y consultoría en Software Libre. Comunidades virtuales, gestores de contenidos. Ruby on Rails, PHP, MySQL...
desarrollo web, desarrollo ágil, ruby on rails, php, mysql, software libre, free software, open source, código abierto

La integración con Rails no tuvo más complicación que el hacerlo funcionar en Dreamhost. Explicaré esto en la siguiente entrega de esta serie de posts sobre Hpricot.Hasta la próxima!

2 comments ↓

#1 Antonio Pardo on 08.14.07 at 12:15 pm

escrito por _why the lucky stiff, un tío ¿o es una tía?

La Wikipedia es tu amiga :)

Lo interesante ahora creo que sería un método que en función de la popularidad de un sitio, en base a diversos factores (no solo PageRank), diera más crédito a un sitio en un keyword concreto ¿no?

#2 Jaime Iniesta on 08.15.07 at 2:55 am

Mmm, no sabía que estaba _why en la wikipedia… claro, tenía que ser un tío, por sus canciones… aunque también podía ser una tía con un amigo cantante. :) Allí vienen enlaces a sus proyectos y blogs, donde sigue en activo…

Sería interesante algo como lo que dices para futuras versiones de Boris… por ahora, sólo se trata de un mini-experimento para trastear con Hpricot, no tengo mucha intención de darle más funcionalidad. Quizá que almacene la relación entre páginas (cuáles enlazan con cuáles, backlinks, etc.).

Leave a Comment