Web Scraping usando Python sobre Jupyter notebooks

Web Scraping usando Python sobre Jupyter notebooks

Scraping es una técnica, la cual podemos utilizar, para hacer barridos de web completas. Por ejemplo la podemos utilizar para descargarnos los metadatos de un Blog, para descargarnos precios de viviendas y/o productos y crear comparativas con dicha información, para descargarnos anuncios, etc… realmente la lista de posibilidades es larga. También es cierto, que muchas web ponen barreras a tal técnica, creando simples “redirect”. Bien, quizás el “Framework” más utilizando para ello es Scrapy, aunque existen otros como, variantes del mismo. En nuestro caso utilizaremos Scrapy y lo ejecutaremos en un env de Python.

Scrapy Architecture

La Arquitectura de un web Scraping como Scrapy es bien simple, veamos:

Scrapy Architecture

  • El primer paso será crear el “Engine”, el cual obtiene las “Requests” iniciales que los “Spiders” le envían.
  • El “Engine” programa las “Requests” en el planificador y solicita las siguientes “Requests” que se deben rastrear (crawl).
  • El Programador o “Scheduler” devuelve las próximas “Requests” al “Engine”.
  • El “Engine” envía las “Requests” al “Downloader”, pasando por los diferentes “Middlewares” del “Downloader”.

Bien, los anteriores pasos son cuando, requerimos al sistema de un proceso de descarga de información, entonces cuando la página termina de descargar el contenido que le hemos solicitado, el “Downloader” genera una Respuesta con dicho contenido y la envía al “Engine”, pasando de nuevo por los “Middlewares” del “Downloader”. Cuando el “Engine” recibe la respuesta del “Downloader”, la envía a los “Spiders”, de nuevo, para que sea procesada la información.

  • Los “Spiders” procesan la respuestas y son devueltos los elementos identificados (scraped) y las nuevas “Requests” al “Engine”, pasando a través de los Middleware de los “Spiders”.
  • El “Engine” envía los elementos procesados a las “Pipeline” de elementos, luego envía las solicitudes procesadas al “Scheduler” y pide posibles próximas solicitudes para rastrear.
  • El proceso se repite, desde el paso 1, hasta que no haya más solicitudes del “Scheduler”.

El proceso, como tal, no es complejo pero es recurrente. En el anterior diagrama se muestra una visión general de la arquitectura Scrapy con sus componentes y un esquema del flujo de datos que tiene lugar dentro del sistema. Que seguramente ayuda y mucho a interpretar el texto de explicación.

Nuestro primer Scrapy

Podemos ejecutar, muy rápidamente, nuestro primer Scrapy símplemente teniendo Python y Scrapy instalados. En caso de no tener Scrapy, podemos utilizar pip:

pip install scrapy

Una vez superado el anterior paso, ejecutaremos:

cat > myspider.py <<EOF

import scrapy

class ToScrapeCSSSpider(scrapy.Spider):
    name = "toscrape-css"
    start_urls = [
        'http://quotes.toscrape.com/',
    ]

    def parse(self, response):
        for quote in response.css("div.quote"):
            yield {
                'text': quote.css("span.text::text").extract_first(),
                'author': quote.css("small.author::text").extract_first(),
                'tags': quote.css("div.tags > a.tag::text").extract()
            }

        next_page_url = response.css("li.next > a::attr(href)").extract_first()
        if next_page_url is not None:
            yield scrapy.Request(response.urljoin(next_page_url))

EOF

Y si queremos lanzar el proceso: scrapy runspider myspider.py, recomiendo hacer una salida a fichero, por lo tanto al final será añadido “-o some.json”

scrapy runspider myspider.py -o some.json

En la raíz del proyecto, tendremos el fichero “some.json” y podremos leerlo sin problema con los resultados obtenidos. Aunque durante el proceso, se mostrará por pantalla si no especificamos lo contrario. En el GitHub de Scrapy podemos encontrar algunos ejemplos interesantes, como también en Scrapinghub encontraremos algunos casos de uso muy recomendables, por ejemplo: Product & Price Intelligence, News and Content Monitoring o Alternative Data For Finance.

Autor: Joakim Vivas

comments powered by Disqus