El feed de los que no tienen feed
Desde hace unos días tenía pendiente un favorcillo que alguien me pidió. No es (reconozcámoslo) que me apeteciera mil porque me olía que la solución, conociéndome a mí y conociendo el problema, sería guarra a más no poder. Pero como quien me lo pidió es alguien adorable que bien merece dedicarle algunos minutos (y mucho más), pues me puse a la tarea, ayer, con pijama, manta, y la ola de frío al otro lado de la puerta. Por supuesto, en Ruby, el lenguaje sexy y buzz-compliant.
Hete aquí que cuando acabo (sí, amigos, por una vez el cuento acaba bien) me encuentro con que mi buen amigo Felipe acaba de publicar una solución completamente diferente a un problema completamente igual (aunque en realidad su script hace alguna cosa más). También en Ruby. Y como, para mi gusto (esto es como con los hijos), mi solución es más limpia, bonita y fácil, heme aquí compartiéndola, con él, y con todos los demás.
La tarea es simple, obtener un feed de una página que no lo tiene, para poder usarlo en un agregador, incluírlo en otra página, o para cualquiera de las cosas chupis y bonitas que se pueden hacer con un feed. Para ello no queda más remedio que parsear el HTML de la página, buscar el contenido relevante, y luego construir con él el feed. Se dice rápido. Y se hace casi más.
scrAPI es una librería de Ruby que sirve exactamente para eso: scrapear (si tuviera que traducir la palabra, diría guarrear, y me parece un poco ofensivo =:-P) HTML.
Para hacerlo, hemos de definir, con un minilenguaje al efecto, las estructuras de datos que se van a buscar, y mapear en qué elementos HTML se encuentran, usando selectores CSS. Se entiende más fácil que se explica (perdón por la ausencia de sangrado):
recording = Scraper.define do process 'a img', :img => "@src" process 'div.datosGrabacion h3 a', :author => :text, :url => "@href" process 'p', :title => :text result :url, :author, :title, :img end
Con ese código definimos una estructura llamada recording, formada por url, autor, título e imagen, y los selectores que nos permiten encontrar esos atributos.
Alguno dirá (yo lo diría): "¡Qué mierda de filtro! Si buscas por 'a img' o por 'p' vas a encontrar mogollón de resultados que no te interesan". Una de las cosas que más molan de scrAPI es que se pueden definir las estructuras de forma anidada, lo cual permite afinar mucho más, y además es DRY:
recordings = Scraper.define do array :recordings process "div#contenido ul.listado li", :recordings => recording result :recordings end
Con ésto definimos una estructura llamada recordings (nótese el plural), compuesta de muchos recording (la estructura que definimos antes), cada uno de ellos dentro de un "div#contenido ul.listado li". Ahora sí que no podemos fallar =;-)
Así pues, ya sólo nos queda aplicar este scraper a la página en cuestión:
recordings_data = recordings.scrape(URI.parse("http://thebellemusic.com/grabaciones.asp"))
Y crear el feed con FeedTools, que además de ser muy fácil ya lo contó Manuel hace poco", así que no hace falta mucho detalle, ¿no?
require 'rubygems'
require 'scrapi'
require 'feed_tools'
recording = Scraper.define do
process 'a img', :img => "@src"
process 'div.datosGrabacion h3 a', :author => :text, :url => "@href"
process 'p', :title => :text
result :url, :author, :title, :img
end
recordings = Scraper.define do
array :recordings
process "div#contenido ul.listado li", :recordings => recording
result :recordings
end
recordings_data = recordings.scrape(URI.parse("http://thebellemusic.com/grabaciones.asp"))
recordings_feed = FeedTools::Feed.new
recordings_feed.title = 'TBM - Grabaciones'
recordings_feed.author = 'The Belle Music'
recordings_feed.link = 'http://thebellemusic.com/'
recordings_feed.language = 'es-ES'
recordings_data.each do |recording|
item = FeedTools::FeedItem.new
item.title = "#{recording[:author]} - #{recording[:title]}"
item.link = "#{recordings_feed.link}#{recording[:url]}"
item.description = "
"
recordings_feed.items << item
end
puts recordings_feed.build_xml('rss', 2.0)
Por Dios, qué horror, sin sangrado ni colores; se recomienda bajarlo y abrirlo con un editor decente =;-)
Y bueno, para otro día dejamos la reflexión sobre qué pueden significar este tipo de técnicas para la web, permitiendo ir más allá, en cuanto al intercambio de contenidos, que los feeds (que ya es), y en definitiva de lo que el autor de los mismos haya tenido a bien prever. Y sin olvidar los microformatos, claro.



Ale Muñoz dijo
Hombre, pues esto nos va a venir de coña para la próxima barrabasada del departamento de chapa y pintura :D
Mi pregunta es... scrAPI o hPricot?
29 Enero 2007 | 11:58 PM