Aprenda a construir un raspador web en Python que rastrea un sitio web completo y extrae todos los datos importantes a través del raspado web.
El raspado web consiste en extraer datos de la Web. Específicamente, un web scraper (raspador web) es una herramienta que realiza el raspado web y generalmente está representado por un script. Python es uno de los lenguajes de programación más sencillos y fiables que existen. Además, viene con una amplia variedad de bibliotecas de raspado web. Esto hace que Python sea el lenguaje de programación perfecto para el raspado web. En detalle, raspado web con Python requiere sólo unas pocas líneas de código.
En este tutorial, aprenderás todo lo que necesitas saber para construir un raspador simple en Python. Esta aplicación recorrerá todo un sitio web, extrayendo datos de cada página. Luego, guardará todos los datos que hemos raspado con Python en un archivo CSV. Este tutorial le ayudará a entender cuáles son las mejores bibliotecas de raspado de datos de Python, cuáles adoptar y cómo utilizarlas. Sigue este tutorial paso a paso y aprende a construir un script para raspado de datos con Python.
Tabla de contenidos:
- Requisitos previos
- Las mejores bibliotecas de Python para raspado web
- Construcción de un raspador web en Python
- Conclusión
- Preguntas frecuentes
Requisitos previos
Para construir un raspador web en Python, es necesario cubrir los siguientes prerrequisitos:
Si no tiene Python instalado en su ordenador, puede seguir el primer enlace anterior para descargarlo. Si es usuario de Windows, asegúrese de marcar la casilla “Añadir python.exe al PATH” mientras instala Python, como se indica a continuación:
De esta forma, Windows reconocerá automáticamente los comandos python y pip en el terminal. En detalle, pip es un gestor de paquetes para los paquetes de Python. Tenga en cuenta que pip se incluye por defecto en Python versión 3.4 o posterior. Por lo tanto, no tiene que instalarlo manualmente.
Ahora está listo para construir su primer raspador web Python. Pero primero, ¡necesita una biblioteca Python de raspado web!
Las mejores bibliotecas de Python para raspado web
Puede construir un script de raspado web desde cero con Python vanilla, pero esta no es la solución ideal. Después de todo, Python es bien conocido por su amplia selección de bibliotecas disponibles. En detalle, hay varias bibliotecas de raspado web para elegir. Echemos un vistazo a las más importantes.
Peticiones
La librería requests permite realizar peticiones HTTP en Python. En detalle, requests facilita el envío de peticiones HTTP, especialmente en comparación con las librerías HTTP estándar de Python. requests juega un papel clave en un proyecto de raspado web en Python. Esto se debe a que, para raspar los datos contenidos en una página web, primero tiene que recuperarlos a través de una solicitud HTTP GET. Además, es posible que tenga que realizar otras peticiones HTTP al servidor del sitio web de destino.
Puede instalar requests con el siguiente comando pip:
pip install requests
Beautiful Soup
La librería de Python Beautiful Soup facilita la extracción de información de páginas web. En particular, Beautiful Soup funciona con cualquier analizador HTML o XML y proporciona todo lo necesario para iterar, buscar y modificar el árbol de análisis. Tenga en cuenta que puede usar Beautiful Soup con html.parser, el analizador que viene con la Librería Estándar de Python y que permite analizar archivos de texto HTML. En detalle, puede usar Beautiful Soup para recorrer el DOM y extraer de él los datos necesarios.
Puede instalar Beautiful Soup con pip de la siguiente manera:
pip install beautifulsoup4
Selenium
Selenium es un marco de pruebas automatizado, avanzado y de código abierto que permite ejecutar operaciones en una página web en un navegador. En otras palabras, puede utilizar Selenium para ordenar a un navegador que realice determinadas tareas. Tenga en cuenta que también puede utilizar Selenium como una biblioteca de raspado web debido a sus capacidades de navegador sin interfaz gráfica (headless browser). Si no está familiarizado con este concepto, un navegador headless es un navegador web que se ejecuta sin una GUI (Interfaz Gráfica de Usuario). Si se configura en modo libre de interfaz gráfica, Selenium ejecutará el navegador entre bastidores.
Así, las páginas web visitadas en Selenium se renderizan en un navegador real, que es capaz de ejecutar JavaScript. Como resultado, Selenium le permite raspar sitios web que dependen de JavaScript. Tenga en cuenta que no puede lograr esto con peticiones o cualquier otro cliente HTTP. Esto se debe a que necesita un navegador para ejecutar JavaScript, mientras que requests simplemente le permite realizar peticiones HTTP.
Selenium le equipa con todo lo que necesita para construir un raspador web, sin necesidad de otras librerías. Puede instalarlo con el siguiente comando pip:
pip install selenium
Construyendo un Web Scraper en Python
Ahora vamos a aprender cómo construir un raspador web en Python. El objetivo de este tutorial es aprender a extraer todos los datos de cotizaciones contenidos en el sitio web Quotes to Scrape. Para cada cita, aprenderá a extraer el texto, el autor y la lista de etiquetas.
Pero primero, echemos un vistazo a la página web de destino. A continuación, se muestra el aspecto de una página web de Quotes to Scrape:
Como puede ver, Quotes to Scrape no es más que un cajón de arena (sandbox) para el raspado web. En concreto, contiene una lista paginada de citas. El web scraper de Python que va a construir recuperará todas las citas contenidas en cada página y las devolverá como datos CSV.
Ahora es el momento de entender cuáles son las mejores bibliotecas Python de raspado web para lograr el objetivo. Como se puede observar en la pestaña Red de la ventana DevTools de Chrome, el sitio web de destino no realiza ninguna solicitud Fetch/XHR.
En otras palabras, Quotes to Scrape no depende de JavaScript para recuperar datos renderizados en páginas web. Esta es una situación común para la mayoría de los sitios web renderizados en servidor. Dado que el sitio web de destino no depende de JavaScript para renderizar la página o recuperar datos, no necesita Selenium para rasparlo. Puede utilizarlo, pero no es necesario.
Como ya se ha demostrado, Selenium abre páginas web en un navegador. Como esto lleva tiempo y recursos, Selenium introduce una sobrecarga de rendimiento. Puede evitarlo utilizando Beautiful Soup junto con Requests. Aprendamos ahora cómo construir un simple script Python de raspado web para recuperar datos de un sitio web con Beautiful Soup.
Empezando
Antes de empezar a escribir las primeras líneas de código, necesita configurar su proyecto Python de raspado web. Técnicamente, sólo necesita un único archivo .py. Sin embargo, el uso de un IDE avanzado (Entorno de Desarrollo Integrado) hará que su experiencia de codificación sea más fácil. Aquí, usted va a aprender cómo configurar un proyecto Python en PyCharm 2022.2.3, pero cualquier otro IDE servirá.
Primero, abra PyCharm y seleccione “Archivo > Nuevo Proyecto…”. En la ventana emergente “Nuevo proyecto”, seleccione “Pure Python” e inicialice su proyecto.
Por ejemplo, puede llamar a su proyecto python-web-scraper. Haga clic en “Crear”, y ahora tendrá acceso a su proyecto Python en blanco. Por defecto, PyCharm inicializará un archivo main.py. Para mayor claridad, puede cambiarle el nombre a scraper.py. Este es el aspecto que tendrá su proyecto:
Como puede ver, PyCharm inicializa automáticamente un archivo Python para usted. Ignora el contenido de este archivo y borra cada línea de código. De esta forma, empezará desde cero.
Ahora, es el momento de instalar las dependencias del proyecto. Puede instalar Requests y Beautiful Soup lanzando el siguiente comando en la terminal:
pip install requests beautifulsoup4
Este comando instalará ambas bibliotecas a la vez. Espere a que el proceso de instalación se complete. Ahora está listo para utilizar Beautiful Soup y Requests para construir su rastreador y raspador web en Python. Asegúrese de importar las dos librerías añadiendo las siguientes líneas al principio de su archivo scraper.py:
import requests
from bs4 import BeautifulSoup
PyCharm mostrará estas dos líneas en gris porque las bibliotecas no se utilizan en el código. Si las subraya en rojo, significa que algo fue incorrecto durante el proceso de instalación. En este caso, intente instalarlas de nuevo.
Este es el aspecto que debería tener su fichero scraper.py. Ahora está listo para empezar a definir la lógica de raspado web.
Conectarse a la URL de destino para hacer raspado web
Lo primero que hay que hacer en un raspador web es conectarse al sitio web de destino. Primero, recupere la URL completa de la página desde su navegador web. Asegúrese de copiar también la sección del protocolo HTTP http:// o https://. En este caso, se trata de la URL completa del sitio web de destino:
https://quotes.toscrape.com
Ahora, se puede utilizar peticiones para descargar una página web con la siguiente línea de código:
page = requests.get('https://quotes.toscrape.com')
Esta línea simplemente asigna el resultado del método request.get() a la variable page. Entre bastidores, request.get() realiza una petición GET utilizando la URL pasada como parámetro. Después, devuelve un objeto Response que contiene la respuesta del servidor a la petición HTTP.
Si la petición HTTP se ejecuta correctamente, page.status_code contendrá 200. Esto se debe a que el código de respuesta de estado HTTP 200 OK indica que la solicitud HTTP se ha ejecutado correctamente. Un código de estado HTTP 4xx o 5xx representará un error. Esto puede ocurrir por varias razones, pero tenga en cuenta que la mayoría de los sitios web bloquean las solicitudes que no contienen un encabezado User-Agent válido. En concreto, la cabecera de solicitud User-Agent es una cadena que caracteriza la aplicación y la versión del sistema operativo de donde procede una solicitud. Más información sobre User-Agent para raspado web.
Puede establecer una cabecera User-Agent válida en las peticiones de la siguiente manera:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
}
page = requests.get('https://quotes.toscrape.com', headers=headers)
requests ejecutará ahora la petición HTTP con las cabeceras pasadas como parámetro
A lo que debe prestar atención es a la propiedad page.text. Esta contendrá el documento HTML devuelto por el servidor en formato cadena. Introduzca la propiedad text en Beautiful Soup para extraer datos de la página web. Vamos a aprender cómo.
Extrayendo datos con el raspador web de Python
Para extraer datos de una página web, primero es necesario identificar los elementos HTML que contienen los datos que te interesan. En concreto, se debe encontrar los selectores CSS necesarios para extraer estos elementos del DOM. Se puede lograr utilizando las herramientas de desarrollo que ofrece su navegador. En Chrome, hacer clic con el botón derecho en el elemento HTML de interés y seleccione Inspeccionar.
Como se puede ver, el elemento HTML quote <div> se identifica por la clase quote. Contiene:
- El texto de la cita en un elemento HTML <span>.
- El autor de la cita en un elemento HTML <small>.
- Una lista de etiquetas en un elemento <div>, cada una contenida en un elemento HTML <a>.
En detalle, puede extraer estos datos utilizando los siguientes selectores CSS en .quote:
.text
.author
.tags .tag
Aprendamos a realizarlo usando Beautiful Soup en Python. Primero, pasemos el documento HTML page.text al constructor BeautifulSoup():
soup = BeautifulSoup(page.text, 'html.parser')
El segundo parámetro especifica el analizador que Beautiful Soup utilizará para analizar el documento HTML. La variable soup contiene ahora un objeto BeautifulSoup. Se trata de un árbol de análisis generado a partir del análisis del documento HTML contenido en page.text con el analizador html.parser incorporado en Python.
Ahora, inicialice una variable que contendrá la lista de todos los datos raspados.
quotes = []
Ahora es el momento de utilizar soup para extraer elementos del DOM de la siguiente manera:
quote_elements = soup.find_all('div', class_='quote')
El método find_all() devolverá la lista de todos los elementos HTML <div> identificados por la clase quote. En otros términos, esta línea de código equivale a aplicar el selector CSS .quote para recuperar la lista de elementos HTML quote de la página. A continuación, puede iterar sobre la lista de citas para recuperar los datos de la cita como se indica a continuación:
for quote_element in quote_elements:
# extracting the text of the quote
text = quote_element.find('span', class_='text').text
# extracting the author of the quote
author = quote_element.find('small', class_='author').text
# extracting the tag <a> HTML elements related to the quote
tag_elements = quote_element.find('div', class_='tags').find_all('a', class_='tag')
# storing the list of tag strings in a list
tags = []
for tag_element in tag_elements:
tags.append(tag_element.text)
Gracias al método find() de Beautiful Soup puede extraer el único elemento HTML de interés. Como las etiquetas asociadas a la cita son más de una, se deben almacenar en una lista.
A continuación, se puede transformar estos datos en un diccionario y añadirlos a la lista de citas del siguiente modo:
quotes.append(
{
'text': text,
'author': author,
'tags': ', '.join(tags) # merging the tags into a "A, B, ..., Z" string
}
)
Almacenar los datos extraídos en un formato de diccionario de este tipo facilitará el acceso y la comprensión de sus datos.
Acaba de aprender a extraer todos los datos de citas de una sola página. Pero tenga en cuenta que el sitio web de destino consta de varias páginas web. Aprendamos ahora a rastrear el sitio web completo.
Implementación de la lógica de recopilación de datos
En la parte inferior de la página de inicio, puede encontrar un elemento HTML “Next →” <a> que redireccione a la siguiente página del sitio web objetivo. Este elemento HTML está contenido en todas menos la última página. Dicho escenario es común en cualquier sitio web paginado.
Al seguir el vínculo contenido en el elemento HTML “Next →”, podrá navegar con facilidad el sitio web entero. Comencemos desde la página de inicio y veamos cómo repasar cada página que conforma el sitio web objetivo. Todo lo que debe hacer es buscar el elemento HTML .next <li> y extraer el vínculo relativo hacia la siguiente página.
Puede implementar la lógica de rastreo de la siguiente manera:
# the url of the home page of the target website
base_url = 'https://quotes.toscrape.com'
# retrieving the page and initializing soup...
# getting the "Next →" HTML element
next_li_element = soup.find('li', class_='next')
# if there is a next page to scrape
while next_li_element is not None:
next_page_relative_url = next_li_element.find('a', href=True)['href']
# getting the new page
page = requests.get(base_url + next_page_relative_url, headers=headers)
# parsing the new page
soup = BeautifulSoup(page.text, 'html.parser')
# scraping logic...
# looking for the "Next →" HTML element in the new page
next_li_element = soup.find('li', class_='next')
Este ciclo itera sobre cada página hasta que no hay página siguiente. En concreto, extrae la URL relativa de la página siguiente y la utiliza para crear la URL de la siguiente página a rastrear. A continuación, descargue la página siguiente. Después, raspe y repita la lógica.
Acaba de aprender cómo implementar la lógica de rastreo para raspar un sitio web completo. Ahora es el momento de ver cómo convertir los datos extraídos a un formato más útil.
Convertir los datos en formato CSV
Veamos cómo convertir la lista de diccionarios que contiene los datos de las citas raspadas en un archivo CSV. Consigámoslo con las siguientes líneas:
import csv
# scraping logic...
# reading the "quotes.csv" file and creating it
# if not present
csv_file = open('quotes.csv', 'w', encoding='utf-8', newline='')
# initializing the writer object to insert data
# in the CSV file
writer = csv.writer(csv_file)
# writing the header of the CSV file
writer.writerow(['Text', 'Author', 'Tags'])
# writing each row of the CSV
for quote in quotes:
writer.writerow(quote.values())
# terminating the operation and releasing the resources
csv_file.close()
Lo que hace este snippet es escribir los datos de citas contenidos en la lista de diccionarios en un archivo quotes.csv. Ten en cuenta que csv forma parte de la Librería Estándar de Python. Por lo tanto, puede importarlo y utilizarlo sin instalar una dependencia adicional. En detalle, simplemente tienes que crear un archivo con open(). Luego, puede rellenarlo con la función writerow() del objeto Writer de la librería csv. Esto escribirá cada diccionario de citas como una fila con formato CSV en el archivo CSV.
Ha pasado de los datos brutos contenidos en un sitio web a los datos estructurados almacenados en un archivo CSV. El proceso de extracción de datos ha terminado y ahora puede echar un vistazo a todo el web scraper de Python.
Conjunto de todo
Este es el aspecto del script completo de Python para raspado web:
import requests
from bs4 import BeautifulSoup
import csv
def scrape_page(soup, quotes):
# retrieving all the quote <div> HTML element on the page
quote_elements = soup.find_all('div', class_='quote')
# iterating over the list of quote elements
# to extract the data of interest and store it
# in quotes
for quote_element in quote_elements:
# extracting the text of the quote
text = quote_element.find('span', class_='text').text
# extracting the author of the quote
author = quote_element.find('small', class_='author').text
# extracting the tag <a> HTML elements related to the quote
tag_elements = quote_element.find('div', class_='tags').find_all('a', class_='tag')
# storing the list of tag strings in a list
tags = []
for tag_element in tag_elements:
tags.append(tag_element.text)
# appending a dictionary containing the quote data
# in a new format in the quote list
quotes.append(
{
'text': text,
'author': author,
'tags': ', '.join(tags) # merging the tags into a "A, B, ..., Z" string
}
)
# the url of the home page of the target website
base_url = 'https://quotes.toscrape.com'
# defining the User-Agent header to use in the GET request below
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
}
# retrieving the target web page
page = requests.get(base_url, headers=headers)
# parsing the target web page with Beautiful Soup
soup = BeautifulSoup(page.text, 'html.parser')
# initializing the variable that will contain
# the list of all quote data
quotes = []
# scraping the home page
scrape_page(soup, quotes)
# getting the "Next →" HTML element
next_li_element = soup.find('li', class_='next')
# if there is a next page to scrape
while next_li_element is not None:
next_page_relative_url = next_li_element.find('a', href=True)['href']
# getting the new page
page = requests.get(base_url + next_page_relative_url, headers=headers)
# parsing the new page
soup = BeautifulSoup(page.text, 'html.parser')
# scraping the new page
scrape_page(soup, quotes)
# looking for the "Next →" HTML element in the new page
next_li_element = soup.find('li', class_='next')
# reading the "quotes.csv" file and creating it
# if not present
csv_file = open('quotes.csv', 'w', encoding='utf-8', newline='')
# initializing the writer object to insert data
# in the CSV file
writer = csv.writer(csv_file)
# writing the header of the CSV file
writer.writerow(['Text', 'Author', 'Tags'])
# writing each row of the CSV
for quote in quotes:
writer.writerow(quote.values())
# terminating the operation and releasing the resources
csv_file.close()
Como se aprende aquí, en menos de 100 líneas de código se puede construir un web scraper. Este script Python es capaz de rastrear un sitio web entero, extraer automáticamente todos sus datos, y convertirlos en un archivo CSV.
¡Enhorabuena! Acabas de aprender a construir un web scraper en Python con las librerías Requests y Beautiful Soup.
Ejecutar el script Python de raspado web
Si eres usuario de PyCharm, ejecuta el script haciendo clic en el botón de abajo:
De lo contrario, ejecute el siguiente comando Python en el terminal dentro del directorio del proyecto:
python scraper.py
Espere a que finalice el proceso y tendrá acceso a un archivo quotes.csv. Ábralo y debería contener los siguientes datos:
¡Et voilà! Ya tiene las 100 citas del sitio web de destino en un archivo CSV.
Conclusión
En este tutorial, ha aprendido qué es el raspado web, qué necesita para empezar en Python, y cuáles son las mejores librerías de raspado web en Python. Luego, vio cómo usar Beautiful Soup y Requests para construir una aplicación de raspado web a través de un ejemplo de uso real. Como ha aprendido, el raspado web en Python sólo requiere unas pocas líneas de código.
Sin embargo, el raspado web plantea varios retos. En concreto, las tecnologías antibot y antiscraping se han hecho cada vez más populares. Por este motivo, necesita una herramienta automatizada, avanzada y completa, de raspado web, proporcionada por Bright Data.
Para evitar bloqueos, también recomendamos elegir un proxy basado en su caso de uso de los diferentes servicios de proxy que Bright Data proporciona.