Scrapy: Gateando por Webs

Uno de los trabajos que he estado realizando últimamente es la captura de información de diversas webs (productos y artículos) a una base de datos. Al principio hacía pequeños scripts, pero esta vez quise probar algo más estructurado y profesional. Scrapy. ¿Sabes lo fácil que es hacer scraping de una web con él?

El caso más complejo al que me he enfrentado a la hora de realizar scraping fue sobre diversas webs de venta de productos. El problem fue debido a la cantidad de información a obtener y la diversidad del formato de cada producto incluso dentro de la misma web.

En ese momento busqué información acerca de frameworks que pudieran hacer esta tarea de una forma más eficiente y topé con scrapy. A diferencia de otros que encontré Scrapy tiene la ventaja de ser extensible, tiene una estructura fácil, herramientas muy potentes y es completamente open source.

¿Qué puede hacer Scrapy?

Uno de los problemas a la hora de realizar la toma de webs es el formato. Descargar una web no es una tarea complicada e incluso podemos navegar por su HTML para encontrar otros enlaces e información que busquemos, pero si lo vamos acumulando todo en un script el mantenimiento puede ser imposible.

Scrapy tiene la integración de herramientas de tratamiento de web usando XPath o CSS al puro estilo de jQuery. Las características que ofrece su sistema XPath son impresionantes. Cada trozo capturado se convierte en un Selector que podemos anidar para volver a usarlo en varias instrucciones.

El primer punto de partida son las Request. Estas se disparan desde las Spider. Una Spider es un elemento que creamos para acumular las Request y poder navegar entre ellas. Hacer una solicitud es tan simple como:

yield scrapy.Request("http://miweb.com/nueva_uri")

Creando una recursividad, o cambiando a otra petición si usamos callback como argumento en la petición del Request.

Cada respuesta llega a la función y podemos trabajar con la información de las cabeceras o el contenido. Por ejemplo, para iterar todas las etiquetas a presentes y obtener todos los enlaces:

process_item(self, response):
    for href in response.xpath('//a/@href'):
        self.logger.info("encontrada: %s", href.extract())

La Spider obtiene la información y rellena un Item. Este Item es la unidad básica de información a ser rellenada por las Spider. Cada Item se procesa después a través de los Pipelines. Estos Pipelines es donde ponemos el código para almacenar esa información en base de datos, o guardar los ficheros descargados en el sistema de ficheros, o escribir información en log, hacer notificaciones, etc.

Hay muchos agregados que nos permiten o facilitan la descarga de ficheros e imágenes a través de un pipeline que podemos configurar u otros que podemos instalar como eggs de Python a través de pip y nos facilitan la inclusión de información en MongoDB, Redis, o emplear modelos de Django como Item, falsear el UserAgent empleado para descarga de información, uso de Proxy, estadísticas vía graphite o statsd, etc.

Aprender Scrapy

La documentación oficial de Scrapy incluye un tutorial (en inglés). Este tutorial puede guiarte a través de las funcionalidades básicas de Scrapy. No obstante, Scrapy tiene muchas funcionalidades y agregados como hemos comentado antes. Cada vez a destripar tendrá sus propios problemas en cuanto a seguridad y habrá que emplear argucias diferentes según el caso.

Conclusiones

Finalmente después de emplear Scrapy durante más de 6 meses con éxito y tener dos sistemas en producción obteniendo de forma periódica información de webs me doy cuenta de lo útil, rápido y mantenible que es Scrapy. Muy muy recomendable.

¿Te has topado con la necesidad de hacer scraping de alguna web? ¿has empleado alguna herramienta que te permita obtener datos de otras webs? ¿te gustaría aprender más? ¡Déjanos un comentario!