Last Updated on octubre 25, 2024 by Álvaro
El web scraping es de gran utilidad en diferentes disciplinas: análisis de datos, investigación de mercados, SEO… por lo que independientemente del ámbito al que pertenezcas, considero que no está de más aprender a cómo scrapear ya que te puede sacar de algún apuro en cualquier momento.
Aunque la programación suele asustar a muchos. déjame decirte que hacer web scraping con Python es más sencillo de lo que parece. Este tutorial va dirigido especialmente a principiantes, ya que se detallan incluso los pasos más sencillos. Se requieren los mínimos conocimientos de Python y HTML.
Antes de nada: elige un entorno de desarrollo en el que te sientas cómodo
Si no tienes mucha experiencia, antes de lanzarte a entornos como Visual Studio Code, te recomiendo empezar por Jupyer Notebooks. Jupyter Notebooks es una especie de cuaderno en el que puedes crear varias celdas de código y acompañarlas de texto. Es muy útil para ejecutar pequeños fragmentos de código en el mismo documento y es muy usado en entornos profesionales para crear dashboards.
Guía paso a paso: Cómo hacer web scraping con Python desde 0
Para realizar el tutorial, yo procedería de la siguiente manera: reproduciría el vídeo que te de dejo por aquí abajo y lo seguiría junto a este artículo, ya que contiene todos los fragmentos de código que se utilizan y podrás copiarlos fácilmente.
El tutorial se realizará en base a un caso práctico. El objetivo es extraer todos los nombres y precios de los productos de la gama Botanical Collection de Lego, que se encuentran en la siguiente URL: https://www.lego.com/es-es/themes/adults-welcome/botanical-collection/artificial-flowers
Puedes descargar directamente el código clicando en el siguiente botón:
Paso 1: Instalación de las librerías
Es muy probable que no tengas instaladas las librerías que se necesitan. En este caso, estaremos trabajando con Beautiful Soup, Requests y Pandas.
Para instalarlas, simplemente ejecuta este código. *Este proceso solo tendrás que hacerlo la primera vez, una vez instaladas, no es necesario repetir esta operación*
pip install beautifulsoup4 pip install requests pip install pandas
Paso 2: Importar las librerías
Una vez tengas instaladas las librerías, necesitarás importarlas. Este proceso lo tendrás que realizar cada vez que entres al documento de Jupyter Notebooks o a cualquier otro entorno de desarrollo.
En este caso, las estoy importando con alias (as + ‘abreviatura’). ¿Por qué? Ya que a la hora de escribir el código, habrá menos texto. Cuando necesites una función, por ejemplo, de Requests, en lugar de escribir ‘Requests’ al completo, bastará con especificar rq.
from bs4 import BeautifulSoup as bs import requests as rq import pandas as pd
Paso 3: lanzar una petición a la URL que queremos scrapear
Lo siguiente es lanzar una petición a la URL que queremos scrapear.
Es posible que este proceso sea algo lento (lento en términos de programación básica es que a lo mejor tarda 5-10 segundos).
response = rq.get('https://www.lego.com/es-es/themes/adults-welcome/botanical-collection/artificial-flowers')
*Al utilizar alias (as) en el import, en lugar de escribir request.get(‘…’) acortamos el código a rq.get(‘…’)*
Una vez finalice la petición (dejarás de ver [*] a la izquierda del código y en lugar de un asterisco aparecerá un número) podrás verificar si se ha realizado de manera correcta lanzando un print de response.
print(response)
Si la salida es Response [200], todo ha ido correctamente. Cualquier otra salida indicaría que ha habido un problema.
Paso 4: extraer el código HTML
Ahora necesitamos extraer el código HTML de la URL a la que lanzamos la petición.
soup = bs(response.text, 'html.parser')
La función BeautifulSoup (bs) tiene dos argumentos. El primero es el contenido de la respuesta HTTP. En otras palabras, el código HTML de la URL, que se obtiene ejecutando la propiedad .text en la variable en la que hemos guardado la petición (response). El segundo es el parser (analizador por así decirlo). Otros analizadores populares incluyen lxml y html5lib, que pueden ser más rápidos o manejar mejor ciertos casos de HTML mal formado.
Si lanzamos un print sobre soup, lo que obtenemos es todo el código HTML de la URL.
Paso 5: identificar como se representan los elementos que queremos scrapear en el HTML
Para saber qué etiqueta HTML y qué clase/atributo identifica al valor que queremos scrapear, situamos el cursor encima de este elemento > hacemos clic derecho > y hacemos clic izquierdo en inspeccionar. Esto abrirá la consola de desarrollo por la línea en la que se encuentra dicho valor.
En este caso, el objetivo es extraer tanto el nombre como el precio de los productos.
Para extraer el nombre tenemos la opción de hacerlo a través del <h3>, <a> o <span>, por tratarse de una secuencia de etiquetas anidadas. En este caso yo me he decantado por utilizar como referencia el anchor <a>. ¿Por qué? tiene elementos que identifican inequívocamente al nombre del producto, en este caso el atributo ‘data-test’ con valor ‘product-leaf-title’. Ten en cuenta que pueden existir valores que no nos interesa extraer que comparten etiquetas y clases o atributos con los que sí.
¿Y cómo sé si hay valores que no me interesan que comparten etiquetas y clase o atributos? Si en la consola de desarrollo hacemos ctrl + f, podemos buscar determinadas clases o atributos y comprobar cuántos elementos las tienen. En este caso vemos que el atributo ‘data-test’ con valor ‘product-leaf-title’ aparece 13 veces. Como tenemos solamente 13 productos, confirmamos que efectivamente ese atributo ubicado en las etiquetas <a> identifica inequívocamente a los productos.
El precio, en cambio, se encuentra en un <div>. En este caso sí recurriremos a la etiqueta <span> para extraer el valor. Podríamos escoger de nuevo el atributo ‘data-test’, esta vez con valor ‘product-leaf-price’, pero para explicaros cómo se extrae un valor a partir de una clase, trabajaremos con la ‘class=”price-sm-bold”‘.
Resumen:
- El nombre del producto está en una etiqueta <a> con atributo data-test=’product-leaf-price’.
- El precio en una etiqueta <span> con clase class=”price-sm-bold”.
Paso 6: extraer los valores
El objetivo ahora es extraer las etiquetas que hemos identificado en el caso anterior. Para ello, nos ayudaremos de la función find_all(), que recibe dos argumentos. El primero, y que debe ir siempre en comillas, la etiqueta en la que se almacena el valor (‘a’, ‘div’, ‘span’, ‘h2’…) y el segundo el atributo o clase que lo acompaña e identifica.
Para los productos, nos estamos apoyando en un atributo:
buscar_productos = soup.find_all('a', attrs={'data-test': 'product-leaf-title'})
Y para los precios en una clase:
buscar_precios = soup.find_all('span', class_="price-sm-bold")
Como ves, el segundo argumento es distinto en cada caso. En el primero, los atributos se especifican dentro de attrs={} y se separa el nombre del valor con ‘:’.
Para las clases resulta más sencillo, ya que basta con simplemente copiar la clase tal cual del código HTML y añadirle a class un ‘_’ al final (esto se debe a que class es una palabra reservada en Python).
Si hacemos un print sobre cualquiera de estas variables, veremos que ahora tenemos una especie de lista que guarda todas las etiquetas. Fíjate que entre cada <a…>…</a> hay una coma. (Si nos ponemos estrictos esta variable no es realmente de tipo lista, aunque en la práctica esto no nos importa demasiado).
Ahora bien, necesitamos extraer, de una vez por todas, el valor que está dentro de estas etiquetas. Como en la práctica estas variables se comportan como una lista, las recorreremos con un ‘for’, extraeremos los valores y los guardaremos en una nueva lista con la función append().
Código para extraer los productos:
productos = [] for i in buscar_productos: productos.append(i.get_text()) print(productos)
Y su salida
Y para precios:
precios = [] for i in buscar_precios: precios.append(i.get_text()) print(precios)
Para extraer el valor nos estamos ayudando de la función get_text(), que ejecutamos sobre el elemento que itera ‘i’ (en este caso, cada una de las etiquetas).
Como ves, los valores de precios tienen caracteres que no nos interesan. En el siguiente paso los eliminaremos.
Paso 7: limpiar los valores (cuando sea pertinente)
Para limpiar los valores simplemente recorreremos la lista ‘precios’, eliminaremos los caracteres que no nos sirven y guardaremos el valor en una nueva lista.
Para eliminar los caracteres utilizaremos la función replace(), que necesita de dos argumentos. El primero, los caracteres que queremos sustituir/eliminar (entre comillas), y el segundo los caracteres por los que queremos sustituirlos. En este caso, como queremos eliminarlos, simplemente ponemos comillas simples sin nada dentro ”.
precios_limpios = [] for i in precios: precios_limpios.append(i.replace('\xa0', '')) print(precios_limpios)
Paso 8: crear un data frame y exportarlo a Excel
En primer lugar, necesitamos crear un diccionario (una estructura de datos de Python) a partir de las dos listas que contienen los valores scrapeados. Para ello ejecutamos el siguiente código:
data = { "Productos": productos, "Precios": precios_limpios }
Y el siguiente paso es convertir este diccionario en un data frame.
df = pd.DataFrame(data)
Finalmente, exportamos este marco de datos a un archivo xlsx con el siguiente código.
df.to_excel('output.xlsx', index=False)
¡Y listo! ya tenemos nuestros datos exportados a Excel. El archivo se guardará en la misma carpeta en la que tienes este proyecto de Python.
Ejemplos de web scraping en Python
El web scraping es muy útil para numerosas profesiones y en especial para los analistas de datos. Permite espiar a la competencia, crear marcos de datos a partir de elementos en la web…
Pero es también muy útil en otros ámbitos. Yo como SEO, he utilizado los siguientes algoritmos:
Un lujo, me sirve de base para un scraper de precios en la SERP que estoy tratando de resolver
Gracias