Una visión general de BeautifulSoup
BeautifulSoup, tal y como se indica en su documentación, es una biblioteca de Python para extraer datos de archivos HTML y XML. Así, puedes usar Python para extraer el contenido HTML de un sitio web y luego usar BeautifulSoup para analizar ese HTML y obtener solo la información relevante.
La principal ventaja de utilizar BeautifulSoup es la sencilla sintaxis que ofrece. Con esta biblioteca, puedes navegar por el árbol DOM, buscar elementos específicos o modificar el contenido HTML. Todas estas ventajas la han convertido en la biblioteca de 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 varía en función del sistema que utilices. En este artículo, estoy utilizando un sistema Linux y solo necesito ejecutar el siguiente comando:
pip install beautifulsoup4
Si utilizas Python 3, es posible que tengas que instalar la biblioteca utilizando el siguiente comando en su lugar:
pip3 install beautifulsoup4
Ten en cuenta que mi máquina ya tiene Python 3 instalado. Si eres nuevo en Python, puedes encontrar una guía sobre cómo instalarlo aquí. Además, deberías consultar nuestra guía definitiva para crear un rastreador web con Python para obtener aún más información sobre el tema.
Creación de un scraper con BeautifulSoup
Ahora, si todo ha ido bien, estamos listos para empezar a crear nuestro propio rastreador. Para este artículo, he decidido recuperar las 100 mejores películas de todos los tiempos de RottenTomatoes y guardarlo todo en formatos JSON y CSV.
Recuperación del código fuente de la página
Para calentar motores 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 el código fuente HTML de cualquier página, puedes hacerlo en Google Chrome pulsando CTRL+U. Esto abrirá una nueva pestaña y verás algo como esto:
Para obtener el mismo código fuente con BeautifulSoup y Python, podemos usar 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, enviamos una solicitud a la página de RottenTomatoes y luego añadimos todo el contenido de la página a 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.
Para entender mejor la función, para este código HTML «<div><span>Test</span></div>», prettify añadirá las tabulaciones y lo transformará en este código formateado:
<div>
<span>
Test
</span>
</div>
El resultado final del código es la creación de un archivo llamado page.txt que contiene todo el código fuente de nuestra página:
Debes tener en cuenta que este 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, el código fuente de la página tendrá un aspecto diferente al contenido real que se muestra al usuario. Si necesitas que tu rastreador ejecute JavaScript, puedes leer nuestra guía sobre cómo crear un rastreador web con Selenium, o puedes utilizar WebScrapingAPI, nuestro producto que se encarga de este tema por ti.
Obtención de los datos web
Si miras el código fuente de la página anterior, verás que puedes encontrar los nombres de las películas y su puntuación. Afortunadamente para nosotros, RottenTomatoes no carga la lista de películas de forma dinámica, por lo que podemos seguir adelante y extraer 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 del ratón sobre el título de una película y seleccionar la opción «Inspeccionar elemento». Debería aparecer la siguiente ventana:
He utilizado la línea roja para resaltar la información útil de esta imagen. Puedes ver que la página muestra las películas más populares en una tabla y que hay cuatro celdas en cada fila de la tabla (elemento <tr>).
La primera celda contiene la posición de la película, la segunda tiene información sobre las valoraciones (elemento con la clase tMeterScore), la tercera incluye el título de la película y la última celda nos da el número de reseñas.
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(" ", ""), # We remove from the string and the blank spaces
})
print(movies)
Al ejecutar este código, deberías obtener un resultado como este:
En este ejemplo, estamos extrayendo el contenido de la tabla y recorriendo las filas de la tabla. Dado que la primera fila solo contiene los nombres de las columnas, la omitiremos.
En el resto de las filas, continuamos el proceso extrayendo el elemento de anclaje (<a>) y el elemento span con la clase «tMeterScore». Una vez que los tenemos, ya podemos recuperar la información necesaria.
El título de la película se encuentra dentro del elemento de ancla, el enlace es el atributo «href» del ancla y la puntuación se encuentra 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 web
Hasta ahora, el scraper ha recuperado y formateado los datos, pero solo los hemos mostrado en la terminal. Como alternativa, podemos guardar la información en nuestro ordenador como JSON o como CSV. El código completo del scraper (incluida la creación de un archivo 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(" ", ""), # We remove 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())Raspando aún más
Ahora que 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 consultas la página de la película It Happened One Night (1934), verás que aún puedes extraer información útil, como la puntuación del público, la duración de la película, el género, etc.
Sin embargo, realizar todas estas solicitudes en un breve periodo de tiempo parece muy inusual y podría dar lugar a validaciones CAPTCHA o incluso a bloqueos de IP. Para evitarlo, debes utilizar proxies rotativos para que el tráfico enviado parezca natural y provenga de múltiples IP.
Otras características de BeautifulSoup
Aunque nuestro scraper de RottenTomatoes está completo, BeautifulSoup sigue teniendo mucho que ofrecer. Siempre que trabajes en un proyecto, debes tener abierto el enlace a la documentación para poder buscar rápidamente una solución cuando te quedes 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 característica puede ayudarte cuando necesites seleccionar un elemento que no se pueda identificar por sus atributos. En ese caso, la única forma de encontrarlo es a través de la estructura del DOM.
Otra cosa interesante de BeautifulSoup es que puedes modificar el código 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 usar el script para extraer datos de un sitio web, obtener el CSS, minificarlo y sustituirlo en el código fuente HTML. ¡Las posibilidades son infinitas!
Extrae siempre de forma inteligente
Me gustaría que recordaras esto: utilizar Python y BeautifulSoup para el scraping web es una idea excelente. Facilita mucho el proceso en comparación con otros lenguajes de programación.
El rastreador que hemos creado para recuperar las películas mejor valoradas de todos los tiempos de RottenTomatoes se puede programar en solo unos minutos, e incluso puedes utilizarlo junto con el rastreador de IMDB de nuestra guía definitiva para el rastreo con PHP.
Sin embargo, algunos sitios web son más accesibles para los rastreadores que otros. Aunque el proyecto de este artículo es sencillo y divertido, otros no lo son en absoluto. A veces, los sitios web hacen todo lo posible para evitar que se extraiga su contenido.
En ciertas situaciones, la única forma de extraer contenido es enmascarando tu trabajo con múltiples direcciones IP y un navegador real. Para este tipo de situaciones, hemos creado WebScrapingAPI, una potente solución que ofrece proxies rotativos, renderización de JavaScript y te permite extraer datos de cualquier sitio web que desees con el mínimo de complicaciones.
¡No te fíes solo de mi palabra, pruébalo tú mismo! Puedes empezar tu prueba gratuita ahora mismo y obtener 5000 llamadas a la API sin tener que facilitar ningún dato confidencial, como los datos de tu tarjeta de crédito.




