# Web scraping con Python: introducción y tutorial

La World Wide Web está compuesta por muchos millones de documentos enlazados entre sí, conocidos también como páginas web. El texto fuente de las páginas web está escrito en el lenguaje Hypertext Markup Language (HTML). Los [códigos fuente en HTML](https://www.ionos.com/es-us/digitalguide/paginas-web/desarrollo-web/aprende-html-tutorial-para-principiantes/ "Aprende HTML: tutorial para principiantes") son una **mezcla de informaciones legibles para los humanos y códigos legibles para las máquinas**, llamados *tags* o *etiquetas*. El navegador, como puede ser Chrome, Firefox, Safari o Edge, procesa el texto fuente, interpreta las etiquetas y presenta al usuario la información que contienen.

Para extraer del texto fuente únicamente la información que le interesa al usuario, se utiliza un tipo *software* especial. Se trata de los programas llamados *web scrapers*, *crawlers*, *spiders* o, simplemente, *bots*, que **examinan el texto fuente de las páginas en busca de patrones concretos** y extraen la información que contienen. Los datos conseguidos mediante *[web scraping](https://www.ionos.com/es-us/digitalguide/paginas-web/desarrollo-web/que-es-el-web-scraping/ "¿Qué es el web scraping?")* posteriormente se resumen, combinan, evalúan o almacenan para ser usados más adelante.

En este artículo te contamos por qué el lenguaje Python resulta especialmente útil para la creación de *web scrapers* y te presentamos una introducción a este tema junto con un práctico tutorial.

## ¿Por qué usar precisamente Python para web scraping?

[Python](https://www.ionos.com/es-us/digitalguide/paginas-web/desarrollo-web/tutorial-de-python/ "Tutorial de Python"), el popular lenguaje de programación se presta especialmente bien para la creación de programas de *web scraping*. Puesto que las páginas web han de ser constantemente modificadas y actualizadas, sus contenidos cambian con el tiempo. Puede que cambie su diseño, por ejemplo, o que se les añadan nuevos elementos. Los *web scrapers* se desarrollan teniendo en cuenta la estructura específica de una página web, de forma que, si dicha estructura cambia, **el *scraper* también debe modificarse**. Este proceso resulta especialmente sencillo con Python.

Asimismo, Python tiene como puntos fuertes el procesamiento de texto y la apertura de recursos web, dos de las bases técnicas del *web scraping*. Python es, además, un estándar consolidado en materia de análisis y procesamiento de datos. Por si esto fuera poco, **Python ofrece un amplísimo ecosistema de programación**, que cuenta con bibliotecas, proyectos de código abierto, documentación y referencias explicativas del lenguaje, así como entradas de foros, informes de error y artículos de blog.

Más concretamente, existen **varias herramientas consolidadas diseñadas para hacer *web scraping* con Python**. Te presentamos tres de las más conocidas: [Scrapy](https://scrapy.org/ "Scrapy - A Fast and Powerful Scraping and Web Crawling Framework"), [Selenium](https://www.selenium.dev/ "SeleniumHQ Browser Automation") y [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/bs4/doc/ "Beautiful Soup Documentation"). Si quieres empezar a practicar, puedes echarle un vistazo a nuestro tutorial de *web scraping* con Python, en el que utilizamos BeautifulSoup, que te ayudará a entender el proceso de *scraping*.

## Web scraping en términos generales

El esquema básico del *web scraping* es sencillo de explicar. En primer lugar, **el desarrollador del *scraper* analiza el texto fuente en HTML** de la página web en cuestión. Por lo general, encontrará patrones claros que permitirán extraer la información deseada. El ***scraper*** será entonces programado para identificar dichos patrones y **realizará el resto del trabajo automáticamente**:

1. Abrir la página web a través del URL
2. Extraer automáticamente los datos estructurados a partir de los patrones
3. Resumir, almacenar, evaluar o combinar los datos extraídos, entre otras acciones

### Casos de aplicación del web scraping

El *web scraping* puede tener aplicaciones muy diversas. Además de para la **indexación de buscadores**, el *web scraping* también puede usarse con los siguientes fines, entre muchos otros:

- Crear bases de datos de contactos
- Controlar y comparar ofertas *online*
- Reunir datos de diversas fuentes *online*
- Observar la evolución de la presencia y la reputación *online*
- Reunir datos financieros, meteorológicos o de otro tipo
- Observar cambios en el contenido de páginas web
- Reunir datos con fines de investigación
- Realizar exploraciones de datos o [data mining](https://www.ionos.com/es-us/digitalguide/online-marketing/analisis-web/data-mining-excavando-en-montanas-de-datos/)

### Un ejemplo sencillo de web scraping

Imagina una página web de venta coches de segunda mano que muestre, al abrirla en el navegador, una lista de los coches disponibles. El **texto fuente de este ejemplo** podría ser el de la entrada de uno de los coches:

```none
raw_html = """
<h1>Coche de segunda mano en venta</h1>
<ul class="cars-listing">
    <li class="car-listing">
        <div class="car-title">
            Volkswagen Escarabajo
        </div>
        <div class="car-description">
            <span class="car-make">Volkswagen</span>
            <span class="car-model">Escarabajo</span>
            <span class="car-build">1973</span>
        </div>
        <div class="sales-price">
            € <span class="car-price">14.998,—</span>
        </div>  
    </li>    
</ul>    
 """
```

Un web *scraper* podría, por ejemplo, examinar la lista *online* de coches en venta y, según la intención con la que haya sido creado, buscar un modelo concreto. En nuestro ejemplo, se trata de un Volkswagen Escarabajo. En el texto fuente, la marca y el modelo del coche están indicados con las clases CSS *car-make* y *car-model*, respectivamente. **Gracias a los nombres de las clases, los datos buscados pueden extraerse o *scrapearse* fácilmente**. A continuación, presentamos el ejemplo de *scraping* correspondiente con BeautifulSoup:

```none
# Analizar sintácticamente el texto fuente HTML guardado en raw_html
html = BeautifulSoup(raw_html, 'html.parser')
# Extraer el contenido de la etiqueta con la clase 'car-title' 
car_title = html.find(class_ = 'car-title').text.strip()
# Si el coche en cuestión resulta ser un Volkswagen Escarabajo
if (car_title == 'Volkswagen Escarabajo'):
    # Subir del título del coche a la siguiente etiqueta de elemento de lista <li></li>
    html.find_parent('li')
    
    # Determinar el precio del coche
    car_price = html.find(class_ = 'sales-price').text.strip()
    
    # Mostrar el precio del coche
    print(car_price)
```

### Riesgos legales del web scraping

Las técnicas de *web scraping* pueden ser de gran utilidad, pero no siempre están libres de riesgos legales. Puesto que el operador de la web la ha diseñado con usuarios humanos en mente, su apertura automática mediante un *web scraper* puede suponer un **incumplimiento de las condiciones de uso**. Estas acciones se vuelven especialmente relevantes cuando se accede a grandes volúmenes de información procedente de varias páginas al mismo tiempo o en sucesión rápida, de un modo en el que una persona nunca sería capaz de interactuar con la página.

Si se realizan de forma automática, la apertura, el almacenamiento y la evaluación de los datos publicados en una página web podrían **infringir los derechos de propiedad intelectual**. Además, si los datos obtenidos son de carácter personal, almacenarlos y analizarlos sin la autorización de las personas afectadas infringe la normativa vigente de protección de datos. Por esta razón, no está permitido, por ejemplo, *scrapear* perfiles de Facebook para obtener datos personales.

---

### Nota

**Las infracciones en materia de protección de datos y de propiedad intelectual están penadas con multas importantes**. Asegúrate, por lo tanto, de actuar dentro de la legalidad siempre que utilices técnicas de *web scraping*. Si te topases con barreras técnicas de seguridad, no trates de eludirlas en ningún caso.

---

### Limitaciones técnicas del web scraping

Para los operadores de las páginas web suele ser **ventajoso limitar las posibilidades de *scraping* automático en su contenido *online.*** Por un lado, porque el acceso masivo a la web que realizan los *scrapers* puede perjudicar el rendimiento del sitio y, por otro, porque suele haber secciones internas de la web que no deberían mostrarse en los resultados de búsqueda.

Para limitar el acceso a los *scrapers*, se ha extendido el uso del estándar [robots.txt](https://www.ionos.com/es-us/digitalguide/hosting/cuestiones-tecnicas/gestiona-la-indexacion-de-tu-sitio-con-robotstxt/ "Gestiona la indexación de tu sitio con robots.txt"). Se trata de un archivo de texto que los operadores web ubican en el directorio principal de la página web. En él hay entradas especiales que establecen **qué *scrapers* o *bots* están autorizados a acceder a qué áreas de la web**. Las entradas del archivo *robots.txt* siempre se aplican a un dominio entero.

A continuación, mostramos un ejemplo del contenido de un archivo *robots.txt* que prohíbe el *scraping* mediante cualquier tipo de *bot* en todo el sitio:

```none
# Cualquier bot
User-agent: *
# Excluir todo el directorio principal
Disallow: /
```

El archivo *robots.txt* solo actúa como medida de seguridad ya que invita a una limitación voluntaria por parte de los *bots*, que deberían adherirse a las prohibiciones del archivo. A nivel técnico, sin embargo, no supone ningún obstáculo. Por ello, **para controlar de forma efectiva el acceso mediante *web scrapers***, los operadores web implementan también técnicas más agresivas. Una de ellas es, por ejemplo, limitar el rendimiento; otra es bloquear la dirección IP del *scraper* tras varios intentos de acceso que infrinjan las normas de la web.

### Las API como alternativa al web scraping

A pesar de su efectividad, el *web scraping* no es el mejor método para obtener datos de páginas web. De hecho, a menudo existe una alternativa mejor: muchos **operadores web ponen publican los datos de forma estructurada y en un formato legible para las máquinas**. Para acceder a este tipo de datos se usan interfaces de programación especiales llamadas [*Application Programming Interfaces*](https://www.ionos.com/es-us/digitalguide/paginas-web/desarrollo-web/application-programming-interface-api/) (interfaces de programación de aplicaciones, API por sus siglas en inglés).

El uso de una API ofrece importantes ventajas:

- **El propietario de la web crea la API precisamente para permitir el acceso a los datos.** De esta forma se reduce el riesgo de infracciones y el operador web puede regular mejor el acceso a los datos. Una manera de hacerlo es, por ejemplo, solicitando una clave API para acceder a ellos. Este método también permite al operador regular de forma más precisa las limitaciones del rendimiento.
- **La API presenta los datos directamente en un formato legible para las máquinas.** Con ello, ya no es necesaria la laboriosa tarea de extraer los datos del texto fuente. Además, la estructura de los datos se separa de su representación visual, por lo que se mantiene sin importar si cambia el diseño de la web.

Siempre que haya una API disponible y que ofrezca datos completos, este será **el mejor método para acceder a la información**, sin olvidar que mediante el *web scraping* pueden extraerse, en principio, todos los textos que una persona podría leer en una página web.

## Herramientas de scraping para Python

El ecosistema Python incluye diversas **herramientas consolidadas** para realizar proyectos de *scraping*:

- **Scrapy**
- **Selenium**
- **BeautifulSoup**

A continuación, te presentamos las ventajas e inconvenientes de cada una de estas tecnologías.

### Web scraping con Scrapy

*Scrapy*, una de las herramientas para hacer *web scraping* con Python que presentamos, utiliza un analizador sintáctico o ***parser* HTML** para extraer datos del texto fuente (en HTML) de la web siguiendo este esquema:

URL → Solicitud HTTP → HTML → Scrapy

El concepto clave del desarrollo de *scrapers* con Scrapy son los llamados *web spiders,* programas de *scraping* sencillos y basados en Scrapy. **Cada *spider* (*araña*) está programado para *scrapear* una web concreta** y va *descolgándose* de página a página. La programación usada está orientada a objetos: cada *spider* es una clase de Python propia.

Además del paquete de Python en sí, la instalación de Scrapy incluye una herramienta de línea de comandos, la Scrapy Shell, que permite controlar los *spiders*. Además, los *spiders* ya creados pueden almacenarse en la [Scrapy Cloud](https://www.scrapinghub.com/scrapy-cloud "Scrapy Cloud - The Most Advanced Platform for Running Web Crawlers"). Desde allí, se ejecutan con tiempos establecidos. De esta forma **pueden *scrapearse* también sitios web complejos** sin necesidad de utilizar para ello el propio ordenador ni la propia conexión a Internet. Otra manera de hacerlo es crear un servidor de *web scraping* propio usando el *software* de código abierto [Scrapyd](https://scrapyd.readthedocs.io/en/stable/ "Scrapyd — Scrapyd 1.2.0 documentation").

Scrapy es una plataforma consolidada para aplicar técnicas de *web scraping* con Python. Su arquitectura está **orientada a las necesidades de proyectos profesionales**. Scrapy cuenta, por ejemplo, con una tubería o *pipeline* integrada para procesar los datos extraídos. La apertura de las páginas en Scrapy se produce de forma asíncrona, es decir, con la posibilidad de descargar varias páginas simultáneamente. Por ello, Scrapy es una buena opción para proyectos de *scraping* que hayan de procesar de grandes volúmenes de páginas.

### Web scraping con Selenium

El *software* libre Selenium es un *framework* para realizar test automatizados de *software* a aplicaciones web. En principio, fue **desarrollado para poner a prueba páginas y *apps* web**, pero el [WebDriver de Selenium](https://www.ionos.com/es-us/digitalguide/paginas-web/desarrollo-web/tutorial-de-selenium-webdriver/ "Tutorial de Selenium WebDriver") también puede usarse con Python para realizar *scraping*. Si bien Selenium en sí no está escrito en Python, con este lenguaje de programación es posible acceder a las funciones del *software*.

A diferencia de Scrapy y de BeautifulSoup, Selenium no trabaja con el texto fuente en HTML de la web en cuestión, sino que **carga la página en un navegador sin interfaz de usuario**. El navegador interpreta entonces el código fuente de la página y crea, a partir de él, un [*Document Object Model*](https://www.ionos.com/es-us/digitalguide/paginas-web/desarrollo-web/presentacion-de-document-object-model-dom/ "Presentación de Document Object Model (DOM)") (modelo de objetos de documento o DOM). Esta interfaz estandarizada permite poner a prueba las interacciones de los usuarios. De esta forma se consigue, por ejemplo, simular clics y rellenar formularios automáticamente. Los cambios en la web que resultan de dichas acciones se reflejan en el DOM. La estructura del proceso de *web scraping* con Selenium es la siguiente:

URL → Solicitud HTTP → HTML → Selenium → DOM

Puesto que el DOM se genera de manera dinámica, Selenium permite ***scrapear* también páginas cuyo contenido ha sido generado mediante JavaScript**. El acceso a contenidos dinámicos es la ventaja más importante de Selenium. En términos prácticos, Selenium también puede usarse en combinación con Scrapy o con BeautifulSoup: Selenium proporcionaría el texto fuente, mientras que la segunda herramienta se encargaría del análisis sintáctico y la evaluación de los datos. En este caso, el esquema que se seguiría tendría esta forma:

URL → Solicitud HTTP → HTML → Selenium → DOM → HTML → Scrapy / BeautifulSoup

### Web scraping con BeautifulSoup

De las tres herramientas que presentamos **para realizar *web scraping* con Python, BeautifulSoup es la más antigua**. Al igual que en el caso de Scrapy, se trata de un *parser* o analizador sintáctico HTML. El *web scraping* con BeautifulSoup tiene la siguiente estructura:

URL → Solicitud HTTP → HTML → BeautifulSoup

Sin embargo, a diferencia de Scrapy, en BeautifulSoup el desarrollo del *scraper* no requiere una programación orientada a objetos, sino que **el *scraper* se redacta como una sencilla secuencia de comandos o *script***. Con ello, BeautifulSoup ofrece el método más fácil para *pescar* información de la *sopa de tags* a la que hace honor su nombre.

### Comparación de las herramientas de web scraping con Python

Cada una de las tres herramientas presentadas tiene sus ventajas e inconvenientes, que hemos resumido en la siguiente tabla:

<table>
  <thead>
    <tr>
      <th></th>
      <th>Scrapy</th>
      <th>Selenium</th>
      <th>BeautifulSoup</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Facilidad de aprendizaje y manejo</td>
      <td>++</td>
      <td>+</td>
      <td>+++</td>
    </tr>
    <tr>
      <td>Lectura de contenidos dinámicos</td>
      <td>++</td>
      <td>+++</td>
      <td>+</td>
    </tr>
    <tr>
      <td>Realización de aplicaciones complejas</td>
      <td>+++</td>
      <td>+</td>
      <td>++</td>
    </tr>
    <tr>
      <td>Robustez frente a fallos HTML</td>
      <td>++</td>
      <td>+</td>
      <td>+++</td>
    </tr>
    <tr>
      <td>Optimización del rendimiento del scraping</td>
      <td>+++</td>
      <td>+</td>
      <td>+</td>
    </tr>
    <tr>
      <td>Calidad del ecosistema</td>
      <td>+++</td>
      <td>+</td>
      <td>++</td>
    </tr>
  </tbody>
</table>

---

### En resumen

¿Qué herramienta deberías elegir para tu proyecto? En resumen: escoge **BeautifulSoup** si necesitas un desarrollo rápido o si quieres familiarizarte primero con los conceptos de Python y de *web scraping*. **Scrapy**, por su parte, te permite realizar complejas aplicaciones de *web scraping* en Python si dispones de los conocimientos necesarios. **Selenium** será tu mejor opción si tu prioridad es extraer contenidos dinámicos con Python.

---

## Web scraping con Python y BeautifulSoup – Tutorial

Aquí te mostramos cómo extraer datos de una página web usando BeautifulSoup. El primer paso será **instalar Python y algunas herramientas** que te serán de ayuda. Necesitarás:

- Python a partir de la versión 3.4
- El gestor de paquetes *pip* para Python
- El módulo *venv*

Para instalar Python, sigue las [instrucciones de instalación](https://www.python.org/downloads/ "Download Python — Python.org") de su página web.

Una vez hayas instalado en tu sistema el gestor de paquetes libre [Homebrew](https://brew.sh/ "The Missing Package Manager for macOS (or Linux) — Homebrew"), podrás instalar Python usando el siguiente comando:

```none
brew install python
```

---

### Nota

Las explicaciones y los ejemplos de código que presentamos a continuación se refieren a **Python 3 en macOS**. El código, en teoría, debería funcionar también en otros sistemas operativos, pero puede que requiera ciertas modificaciones, especialmente si se trata de Windows.

---

### Configurar el proyecto de web scraping con Python en tu propio ordenador

Para nuestro tutorial de Python queremos ubicar la carpeta de proyecto *web Scraper* en el escritorio. Para ello, abrimos en primer lugar la interfaz de línea de comandos (Terminal.App en Mac), copiamos las siguientes líneas de código en ella y las ejecutamos:

```none
# Cambiar a la carpeta de escritorio
cd ~/Desktop/
# Crear directorio de proyecto
mkdir ./web Scraper/ && cd ./web Scraper/
# Crear entorno virtual
# Se encarga, entre otras cosas, de que posteriormente se use pip3
python3 -m venv ./env
# Activar entorno virtual
source ./env/bin/activate
# Instalar paquetes
pip install requests
pip install beautifulsoup4
```

### Extraer citas y autores con Python y BeautifulSoup

La página web [Quotes to Scrape](http://quotes.toscrape.com/ "Quotes to Scrape") ofrece toda una colección de citas de personajes famosos pensadas especialmente **para ser objeto de test de *scraping***, para que no tengas que preocuparte por incumplir las condiciones de uso.

Pongámonos manos a la obra. Abre la interfaz de línea de comandos (Terminal.App en Mac) e **inicia el intérprete de Python** desde la carpeta de proyecto *web Scraper*. Para ello, copia las siguientes líneas de código en la interfaz y ejecútalas:

```none
# Ir al directorio de proyecto
cd ~/Desktop/web Scraper/
# Activar entorno virtual
source ./env/bin/activate
# Iniciar el intérprete de Python
# Puesto que nos encontramos en el entorno virtual, se usa python3
python
```

Ahora, copia el siguiente código y **pégalo en el intérprete de Python, en la interfaz de línea de comandos**. Pulsa luego Intro (varias veces, si es necesario) para ejecutarlo. También puedes guardar el código como archivo con el nombre de *scrape\_quotes.py* en la carpeta de proyecto *web Scraper*. Si lo haces, podrás ejecutar el *script* de Python con el comando *python scrape\_quotes.py*.

Como **resultado final tras la ejecución del código**, en tu carpeta de proyecto *web Scraper* debería haber un archivo llamado *zitate.csv*. Este archivo contiene una **tabla con las citas y los autores** y puedes abrirlo con el programa de hoja de cálculo que desees.

```none
# Importar módulos
import requests
import csv
from bs4 import BeautifulSoup
# Dirección de la página web
url = "http://quotes.toscrape.com/"
# Ejecutar GET-Request
response = requests.get(url)
# Analizar sintácticamente el archivo HTML de BeautifulSoup del texto fuente
html = BeautifulSoup(response.text, 'html.parser')
# Extraer todas las citas y autores del archivo HTML
quotes_html = html.find_all('span', class_="text")
authors_html = html.find_all('small', class_="author")
# Crear una lista de las citas
quotes = list()
for quote in quotes_html:
    quotes.append(quote.text)
# Crear una lista de los autores
authors = list()
for author in authors_html:
    authors.append(author.text) 
# Para hacer el test: combinar y mostrar las entradas de ambas listas
for t in zip(quotes, authors):
print(t)
# Guardar las citas y los autores en un archivo CSV en el directorio actual
# Abrir el archivo con Excel / LibreOffice, etc.
with open('./zitate.csv', 'w') as csv_file:
    csv_writer = csv.writer(csv_file, dialect='excel')
    csv_writer.writerows(zip(quotes, authors))
```

### Usar paquetes de Python para hacer scraping

No hay dos proyectos de *web scraping* iguales. A veces solo se quiere comprobar si ha habido cambios en una página y a veces se quieren llevar a cabo evaluaciones complejas, entre otras opciiones. Python pone a tu alcance una **amplia gama de paquetes** entre los que elegir:

1. Instalar paquetes en la interfaz de línea de comandos con *pip3*

```none
pip3 install <package></package>
```

2. Integrar módulos dentro de los *scripts* de Python con *import*

```none
from <package> import <module></module></package>
```

Estos son algunos de los paquetes más usados en proyectos de *web scraping*:

<table>
  <thead>
    <tr>
      <th>Paquete</th>
      <th>Finalidad</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>venv</td>
      <td>Gestionar el entorno virtual del proyecto</td>
    </tr>
    <tr>
      <td>request</td>
      <td>Abrir una página web</td>
    </tr>
    <tr>
      <td>lxml</td>
      <td>Usar analizadores sintácticos alternativos para HTML y XML</td>
    </tr>
    <tr>
      <td>csv</td>
      <td>Leer y escribir datos en tablas en formato CSV</td>
    </tr>
    <tr>
      <td>pandas</td>
      <td>Procesar y evaluar datos</td>
    </tr>
    <tr>
      <td>scrapy</td>
      <td>Utilizar Scrapy</td>
    </tr>
    <tr>
      <td>selenium</td>
      <td>Utilizar Selenium WebDriver</td>
    </tr>
  </tbody>
</table>

---

### Consejo

Utiliza el [Índice de paquetes de Python](https://pypi.org/ "PyPI - The Python Package Index") (PyPI) para ver todos los paquetes disponibles.

---

Por favor, ten en cuenta el [aviso legal](https://www.ionos.com/es-us/digitalguide/exencion-de-responsabilidad/ "Exención de responsabilidad") relativo a este artículo.


This is a markdown version of: [https://www.ionos.com/es-us/digitalguide/paginas-web/desarrollo-web/web-scraping-con-python/](https://www.ionos.com/es-us/digitalguide/paginas-web/desarrollo-web/web-scraping-con-python/) for AI/LLM consumption.