Creando tu propio Web Crawler / Web Spider

 webcrawlers.jpg

Ya hemos hablado antes en CyberHades sobre los Web Spiders, ahora os proponemos crear uno propio. Básicamente, un Web Spider es una aplicación que realiza una acción cuando encuentra una página web en concreto (o un link). Por ejemplo puedes crear uno que busque entre todos los links de tus páginas si alguna está caída (error 404), y que luego cree un informe, te envíe un email, etc …

La creación de un Web Spider se divide en tres partes:

1. Accediendo a una página web: tenemos que crear una conexión http, un ejemplo usando telnet:

telnet paginaweb.com 80
GET /index.html HTTP/1.0
Pulsa ENTER dos veces

Obtenemos el fichero index.html con el comando GET del telnet, fichero fundamental para poder explorar luego la web. El puerto habitual es el 80 pero puedes encontrar también el 8080 (o incluso otros). Esta acción es realmente simple, pero existen en Ruby una librerías muy completas y avanzadas para crear más interacción con las páginas Web, por ejemplo WWW::Mechanize.

 

2. Analizar la página HTML: si encontramos links en una web, hay que analizarlos. El autor usa nokogiri, pero hay otras formas de hacerlo, HTML parser, o usando expresiones regulares.

 

3. Crear el Spider: una vez sabiendo cómo cargar la página y analizar los enlaces, lo que queda es pura recursión. En pseudocódigo:

cargar página
por cada enlace en los enlaces de la página hacer
  si(enlace coincide con nuestras condiciones y no hemos estado antes en él)
    hacer algo con el enlace
    añadir el enlace a enlaces visitados
    volver al primer paso usando como página en enlace encontrado

El autor del artículo ha creado un simple crawler en Ruby usando la librería que antes he mencionado, WWW::Mechanize. Os lo pongo aquí porque es fácil de entender y es muy instrucctivo (además de aprender un poco de Ruby):

require “rubygems”
require “mechanize”

class Crawler < WWW::Mechanize   attr_accessor :callback   INDEX = 0   DOWNLOAD = 1   PASS = 2   def initialize     super     init     @first = true     self.user_agent_alias = “Windows IE 6″   end   def init     @visited = []   end   def remember(link)     @visited << link   end   def perform_index(link)     self.get(link)     if(self.page.class.to_s == “WWW::Mechanize:: Page”)       links = self.page.links.map {|link| link.href } - @visited       links.each do |alink|         start(alink)       end     end   end   def start(link)     return if link.nil?     if([email protected]?(link))       action = @callback.call(link)       if(@first)         @first = false         perform_index(link)       end       case action         when INDEX           perform_index(link)         when DOWNLOAD           self.get(link).save_as(File.basename(link))         when PASS           puts “passing on #{link}”       end     end   end   def get(site)     begin       puts “getting #{site}”       @visited << site       super(site)     rescue       puts “error getting #{site}”     end   end end

El código toma como argumento un link, y devuelve int (INDEX, DOWNLOAD, PASS). Si devuevle INDEX, se procesa en link y todos los links de la página. Si devuelve DOWNLOAD, se descarga ese link. Si devuelve PASS, se ignora el link.

Un ejemplo de como usarlo:

require “crawler”
x = Crawler.new
callback = lambda do |link|
  if(link =~/\.(zip|rar|gz|pdf|doc)
    x.remember(link)
    return Crawler:: PASS
  elsif(link =~/\.(jpg|jpeg)/)
    return Crawler:: DOWNLOAD
  end
  return Crawler::INDEX;
end

Con este script, sólo descargará ficheros jpg, y se ignoran los zip,rar,gz,pdf y doc. El resto de enlaces se indexan.

Excelente artículo, gracias a:

ssssssssssssssscripting !!!