Extracción y análisis sintáctico de datos web con Python y BeautifulSoup

Sorin-Gabriel Marica el 13 Jul 2021

Los raspadores web son herramientas valiosas que le ayudan a extraer información específica de un sitio web. En teoría, podría hacerlo manualmente, pero el web scraping le permite procesar grandes cantidades de datos de forma más eficaz y productiva.

Uno de los lenguajes de programación más populares para el web scraping es Python. Este lenguaje viene con la biblioteca BeautifulSoup, que simplifica el proceso. Juntos, este dúo hace que el web scraping sea mucho más fácil que en otros lenguajes.

En mi opinión personal, el uso de BeautifulSoup es la forma más fácil de construir un simple web scraper desde cero. Si quieres aprender más sobre esto, sigue leyendo porque te mostraré cómo crear tu propio web scraper usando Python y BeautifulSoup.

Visión general de BeautifulSoup

BeautifulSoup, como se indica en su documentación, es una biblioteca de Python para extraer datos de archivos HTML y XML. Por lo tanto, puede utilizar Python para extraer el contenido HTML de un sitio web y luego usar BeautifulSoup para analizar ese HTML para obtener sólo la información relevante.

La principal ventaja de utilizar BeautifulSoup es la sencilla sintaxis que ofrece. Con esta librería, puedes navegar por el árbol DOM, buscar elementos específicos o modificar el contenido HTML. Todas estas ventajas la han convertido en la librería python más popular para analizar documentos HTML y XML.

Instalación

Para instalar BeautifulSoup, debes consultar la guía desde aquí, ya que la instalación es diferente en función de la máquina que utilices. En este artículo, estoy usando un sistema Linux y sólo tengo que ejecutar el siguiente comando:

pip install beautifulsoup4

Si utiliza python3, es posible que tenga que instalar la biblioteca utilizando el siguiente comando en su lugar:

pip3 install beautifulsoup4

Ten en cuenta que mi máquina ya tiene python3 instalado. Si eres nuevo en Python, puedes encontrar una guía sobre cómo instalarlo aquí. También, usted debe comprobar fuera de nuestra guía definitiva para la construcción de un raspador web con python para obtener más información sobre el tema.

Creación de un rascador con BeautifulSoup

Ahora, si todo ha ido bien, estamos listos para empezar a construir nuestro propio scraper. Para este artículo, elegí recuperar las 100 mejores películas de todos los tiempos de RottenTomatoes y guardar todo en formatos JSON y CSV.

Recuperación de la fuente de la página

Para entrar en calor y familiarizarnos con BeautifulSoup, primero recuperaremos el HTML completo de la página y lo guardaremos en un nuevo archivo llamado "page.txt".

Si quieres ver la fuente HTML de cualquier página, puedes hacerlo en Google Chrome pulsando CTRL+U. Se abrirá una nueva pestaña y verás algo parecido a esto:

blog-image

Para obtener la misma fuente con BeautifulSoup y Python, podemos utilizar el siguiente código:

import requests
from bs4 import BeautifulSoup

scraped_url = 'https://www.rottentomatoes.com/top/bestofrt/'
page = requests.get(scraped_url)

soup = BeautifulSoup(page.content, 'html.parser')

file = open('page.txt', mode='w', encoding='utf-8')
file.write(soup.prettify())

En este código, hacemos una petición a la página RottenTomatoes y luego añadimos todo el contenido de la página en un objeto BeautifulSoup. El único uso de BeautifulSoup en este ejemplo es la función final llamada "prettify()", que formatea el código html para facilitar su lectura.

To understand the function better, for this HTML code “<div><span>Test</span></div>”, prettify, will add the tabulations and transform it in this formatted code:

<div>

   <span>

       Prueba

   </span>

</div>

El resultado final del código es la creación de un archivo llamado page.txt que contiene toda la fuente de la página de nuestro enlace:

blog-image

Tenga en cuenta que éste es el código fuente de la página antes de que se ejecute cualquier código Javascript. A veces, los sitios web pueden optar por cambiar el contenido de sus páginas de forma dinámica. En estos casos, la fuente de la página tendrá un aspecto diferente del contenido real que se muestra al usuario. Si necesita que su raspador ejecute Javascript, puede leer nuestra guía sobre la creación de un raspador web con Selenium, o puede utilizar WebScrapingAPI, nuestro producto que se ocupa de esta cuestión por usted.

Obtener los datos de la web

Si miras en la fuente de la página anterior, verás que puedes encontrar los nombres de las películas y su calificación. Afortunadamente para nosotros, RottenTomatoes no carga la lista de películas dinámicamente, así que podemos seguir adelante y raspar la información necesaria.

En primer lugar, inspeccionamos la página y vemos cómo está estructurado el HTML. Para ello, puedes hacer clic con el botón derecho en el título de una película y elegir la opción "Inspeccionar elemento". Debería aparecer la siguiente ventana:

blog-image

I used the red line to highlight the useful information from this image. You can see that the page displays the top movies in a table and that there are four cells on each table row (<tr> element).

La primera celda contiene la posición de la película, la segunda tiene información sobre las valoraciones (elemento con clase tMeterScore ), la tercera incluye el título de la película, y la última celda nos da el número de críticas.

Conociendo esta estructura, ya podemos empezar a extraer la información que necesitamos.

import requests
from bs4 import BeautifulSoup

links_base = 'https://www.rottentomatoes.com'
scraped_url = 'https://www.rottentomatoes.com/top/bestofrt/'
page = requests.get(scraped_url)

soup = BeautifulSoup(page.content, 'html.parser')

table = soup.find("table", class_="table") # We extract just the table code from the entire page
rows = table.findAll("tr") # This will extract each table row, in an array

movies = []

for index, row in enumerate(rows):
if index > 0: # We skip the first row since this row only contains the column names
link = row.find("a") # We get the link from the table row
rating = row.find(class_="tMeterScore") # We get the element with the class tMeterScore from the table row
movies.append({
"link": links_base + link.get('href'), # The href attribute of the link
"title": link.string.strip(), # The strip function removes blank spaces at the beginning and the end of a string
"rating": rating.string.strip().replace("&nbsp;", ""), # We remove &nbsp; from the string and the blank spaces
})

print(movies)

Al ejecutar este código, deberías obtener un resultado como éste:

blog-image

En este ejemplo, extraemos el contenido de la tabla y recorremos las filas de la tabla. Como la primera fila sólo contiene los nombres de las columnas, la omitiremos.

On the rest of the rows, we continue the process by extracting the anchor (<a>) element and the span element with the class “tMeterScore”. Having them, we can now retrieve the information needed.

El título de la película está dentro del elemento anchor, el enlace es el atributo "href" del anchor, y la calificación está dentro del elemento span con la clase "tMeterScore". Simplemente creamos un nuevo diccionario para cada fila y lo añadimos a nuestra lista de películas.

Guardar los datos de la web

Hasta ahora, el scraper ha recuperado y formateado los datos, pero sólo los hemos visualizado dentro del terminal. Alternativamente, podemos guardar la información en nuestro ordenador como JSON o como CSV. El código completo del scraper (incluyendo la creación de un fichero local) es:

import requests
from bs4 import BeautifulSoup
import csv
import json

links_base = 'https://www.rottentomatoes.com'
scraped_url = 'https://www.rottentomatoes.com/top/bestofrt/'
page = requests.get(scraped_url)

soup = BeautifulSoup(page.content, 'html.parser')

table = soup.find("table", class_="table") # We extract just the table code from the entire page
rows = table.findAll("tr") # This will extract each table row from the table, in an array

movies = []

for index, row in enumerate(rows):
if index > 0: # We skip the first row since this row only contains the column names
link = row.find("a") # We get the link from the table row
rating = row.find(class_="tMeterScore") # We get the element with the class tMeterScore from the table row
movies.append({
"link": links_base + link.get('href'), # The href attribute of the link
"title": link.string.strip(), # The strip function removes blank spaces at the beginning and the end of a string
"rating": rating.string.strip().replace("&nbsp;", ""), # We remove &nbsp; from the string and the blank spaces
})

file = open('movies.json', mode='w', encoding='utf-8')
file.write(json.dumps(movies))

writer = csv.writer(open("movies.csv", 'w'))
for movie in movies:
writer.writerow(movie.values())

Rascar aún más

Ahora que ya tienes toda la información, puedes optar por profundizar en el scraping. Recuerda que cada película tiene un enlace. Podrías continuar raspando las páginas de las películas y extraer aún más información sobre ellas.

Por ejemplo, si consulta la página de la película Sucedió una noche (1934), podrá ver que aún puede extraer información útil como la puntuación del público, la duración de la película, el género, etc.

Sin embargo, hacer todas estas peticiones en un corto periodo de tiempo parece muy inusual y podría llevar a validaciones CAPTCHA o incluso bloqueos de IP. Para evitarlo, deberías usar proxies rotatorios para que el tráfico enviado parezca natural y provenga de múltiples IPs.

Otras características de BeautifulSoup

Aunque nuestro raspador RottenTomatoes está completo, BeautifulSoup todavía tiene mucho que ofrecer. Siempre que trabajes en un proyecto, deberías mantener abierto el enlace a la documentación para poder buscar rápidamente una solución cuando estés atascado.

Por ejemplo, BeautifulSoup permite navegar por el árbol DOM de la página:

from bs4 import BeautifulSoup

soup = BeautifulSoup("<head><title>Title</title></head><body><div><p>Some text <span>Span</span></p></div></body>", 'html.parser')

print(soup.head.title) # Will print "<title>Title</title>"
print(soup.body.div.p.span) # Will print "<span>Span</span>"

Esta función puede ayudarle cuando necesite seleccionar un elemento que no puede identificarse por sus atributos. En ese caso, la única forma de encontrarlo es por la estructura del DOM.

Otra cosa buena de BeautifulSoup es que puedes modificar la fuente de la página:

from bs4 import BeautifulSoup

soup = BeautifulSoup("<head><title>Title</title></head><body><div><p>Some text <span>Span</span></p></div></body>", 'html.parser')

soup.head.title.string = "New Title"
print(soup)
# The line above will print "<head><title>New Title</title></head><body><div><p>Some text <span>Span</span></p></div></body>"

Esto puede ser muy valioso si quieres crear un servicio que permita a los usuarios optimizar sus páginas. Por ejemplo, puedes utilizar el script para raspar un sitio web, obtener el CSS, minificarlo y sustituirlo en el código fuente HTML. Las posibilidades son infinitas.

Rascar siempre de forma inteligente

Realmente quiero que recuerdes esto: usar Python y Beautifulsoup para el web scraping es una excelente idea. Hace que el proceso sea mucho más fácil en comparación con otros lenguajes de programación.

El scraper que construimos para recuperar las películas mejor valoradas de todos los tiempos de RottenTomatoes se puede codificar en sólo unos minutos, e incluso se puede utilizar junto con el scraper IMDB de nuestra guía definitiva para el scraping con PHP.

Sin embargo, algunos sitios web son más accesibles a los raspadores que otros. Aunque el proyecto de este artículo es sencillo y divertido, algunos son todo menos eso. A veces, los sitios web hacen todo lo que está en su mano para evitar que sus contenidos sean objeto de scraping.

En ciertas situaciones, la única manera de scrapear contenido es enmascarando tu trabajo con múltiples IPs y un navegador real. Para este tipo de situaciones, hemos creado WebScrapingAPI, una potente solución que ofrece proxies rotativos, renderizado Javascript, ¡y te permite scrapear cualquier sitio web que quieras con el mínimo de dolores de cabeza!

No te conformes con mi palabra, ¡pruébalo tú mismo! Puedes empezar tu prueba gratuita ahora mismo y conseguir 5000 llamadas API sin tener que dar datos sensibles como los de tu tarjeta de crédito.

Noticias y actualidad

Manténgase al día de las últimas guías y noticias sobre raspado web suscribiéndose a nuestro boletín.

We care about the protection of your data. Read our <l>Privacy Policy</l>.Privacy Policy.

Artículos relacionados

miniatura
GuíasCómo raspar datos de productos de Amazon: Guía completa de mejores prácticas y herramientas

Explore las complejidades del scraping de datos de productos de Amazon con nuestra guía en profundidad. Desde las mejores prácticas y herramientas como Amazon Scraper API hasta las consideraciones legales, aprenda a superar los desafíos, eludir los CAPTCHA y extraer información valiosa de forma eficiente.

Suciu Dan
avatar de autor
Suciu Dan
15 minutos de lectura
miniatura
Ciencia del Web ScrapingWeb Scraping simplificado: la importancia del análisis sintáctico de datos

Descubra cómo extraer y organizar datos de forma eficaz para el raspado web y el análisis de datos mediante el análisis sintáctico de datos, las bibliotecas de análisis sintáctico HTML y los metadatos de schema.org.

Suciu Dan
avatar de autor
Suciu Dan
12 min leer
miniatura
GuíasDesbloquea sitios web y protege tu identidad con proxies y Axios Node.js

Aprende a usar proxies con Axios y Node.js para un raspado web eficiente. Consejos, ejemplos de código y los beneficios de usar WebScrapingAPI incluidos.

Suciu Dan
avatar de autor
Suciu Dan
7 min leer