Tutorial - Automatizando la descarga de una lista de links con Scrapy

Automatizar las tareas de descargas es un tarea muy común que nos encontraremos tanto en el trabajo como en nuestra vida. En esta ocasión quiero enseñarlos como utilizar Scrapy para descargar automaticamente una lista de Libros en PDF de un artículo en Medium: Springer has released 65 Machine Learning and Data books for free.

En todo proyecto de Scraping, es importante primero analizar como está estructurada la data y como puedo accedarla programaticamente y así planificar nuestro desarrollo. En este caso, podemos ver que existe una lista de URL en el artículo:

Lista de Artículos

¿Qué observamos?

  • Al hacer click al link nos lleva el sitio Web de Springer, directamente a link del libro

Presentación del Libro

Y ahora, vemos que hay un botón de acción "Download PDF" para poder efectivamente descargar el libro.

Y es aquí donde damos nuestros primeros pasos hacia el scraping: debemos analizar la estructura del html y chequear de que manera se da el flujo del proceso para poder automatizarlo. Recuerda, en este punto, el Inspector de tu navegador es tu mejor amigo. Yo ya he identificado la manera de como obtener los links y como ejecutar la descarga. No te preocupes si aún no lo ven. Podrán ver este tutorial completado en mi Github y les dejaré el link hacia el repositorio.

Ahora si vamos a lo divertido! comenzamos con Scrapy


Recuerda siempre tener claramente tu estratégia de acceso al Dato para poder trabajar eficientemente!


Lo primero que vamos a hacer es crear un directorio en nuestro ordenador:

mkdir simple-scrapy-pdf-scrapper

Luego crearemos nuestro Virtual Environment para instalar las diferentes librerias que vayamos a utilizar:

virtualenv -p python3.7 venv  
source venv/bin/activate

e instalamos Scrapy

pip install scrapy

Estamos listos para continuar!!

Lo primero que debo hacer es crear el proyecto en scrapy. Para ello debo ejecutar la siguiente instrucción dentro del bash y posicionados en el directorio que hemos creado

scrapy startproject pdf_download  

Este comando generará nuestro proyecto Scrapy. ¿Puedes adivinar como se llama? Pues si dijistes pdf_download has acertado.

Ahora, un proyecto puede estar compuesto por uno o más Spider. Pero es necesario crearlas.

scrapy genspider scrape_springer_books https://towardsdatascience.com/springer-has-released-65-machine-learning-and-data-books-for-free-961f8181f189

El comando scrape genspider toma dos argumentos: el primero el nombre de la clase y del spider como tal y el segundo es el start_url que no es más que la dirección URL que buscará en primer lugar nuestro spider. En este caso, estamos generando una spider llamada scrape_springer_books. Veamos como está quedando la estructura de archivos del proyecto:

Estructura de Proyecto

Tenemos nuestro template listo. Para afinar la estrategia de código y el método para obtener la data siempre recomiendo usar primero el shell del framework. En este caso pueden verlo funcionando con el siguiente comando:

scrapy shell "https://towardsdatascience.com/springer-has-released-65-machine-learning-and-data-books-for-free-961f8181f189"

El shell les permitirá hacer uso de todos los métodos del framework y plantear a manera de prueba sus ideas. Por ejemplo al cargar el shell con la página inicial que deseamos scrapear veremos los siguiente:

Presentación del Libro

Yo ya he definido que los links que necesito están dentro de un anchor tag en html, y se que el href contiene "link.springer" en su contenido, entonces para seleccionar todos los urls que quiero scrapear uso el siguiente comando:

response.xpath('//a[contains(@href, "link.springer")]/@href')

Presentación del Libro

Vemos que tenemos 64 urls para descargar. Muy bien. Con eso, ya puedo modificar mi archivo scrape_springer_books.py con la sentencia que necesito. Luego necesito hacer lo mismo pero dentro de la página objetivo. No necesito hacer lo en todas, solo debe ver como es la estructura y luego generalizar para automatizar.

Para el caso de la página donde se encuentra el libro como tal, podemos ver que botón produce la descarga

Presentación del Libro

Esto, en el codigo final correspondería a la siguiente función:

def gotospringer(self, response):
    link = 'https://' + allowed_domains[1] + \
        response.xpath('//a[contains(@data-track-action, "pdf")]/@href')[0].get()
    
    yield scrapy.Request(link, callback=self.save_pdf)

Luego, cuando el spider ya tenga tenga el PDF lo salvará haciendo uso de la función save_pdf

    def save_pdf(self, response):
        path = response.url.split('/')[-1]
        with open(path, 'wb') as f:
            f.write(response.body)

En este punto se está guardando localmente, pero facilmente podría guardarlo en DropBox, en S3, en un FTP o donde se quiera.

Finalmente, para llamar a nuestra Spider debemos ejecutar desde nuestro bash:

scrapy crawl scrape_springer_books


Bonus track

Si quieren nombrar el archivo con el título del libro, deben utilizar el selector h1 y utilizarlo en el save_pdf para generar el nombre del archivo!

De nada!!! :)


Repositorio del Tutorial

Github - Simple Scrapy PDF Scrapper


Necesitas ayuda con tu Proyecto o tienes una idea para desarrollar y necesitas de un Full Stack Developer?

Contáctame!


Te ha ayudado esta página? Considera compartirlo 🙌


Avatar
José Fernando González Montero
Data Scientist / FullStack Python Web Developer

Siempre aprendiendo y queriendo saber más. Me encanta ser parte de proyectos en donde continuo desarrollando mis habilidades.

Relacionado