Si estás interesado en el scraping web, entender HTML es clave porque todos los sitios web están construidos con él. El scraping web puede usarse en todo tipo de escenarios y puede ayudar a recopilar datos de sitios web sin APIs, monitorear precios de productos, crear listas de leads, realizar investigaciones académicas y más.
En este artículo, aprenderás los conceptos básicos de HTML y cómo extraer, parsear y procesar datos usando Python.
¿Interesado en una guía detallada de scraping web con Python? Haz clic aquí.
Cómo hacer Scraping de Sitios Web y Extraer HTML
Antes de comenzar este tutorial, tomemos un momento para revisar los componentes esenciales del HTML.
Introducción a HTML
HTML es una colección de etiquetas que le indican a un navegador la estructura y los elementos de un sitio web. Por ejemplo, <h1> Text </h1> le indica a un navegador que el texto que sigue a la etiqueta es un encabezado, y <a href=""> link </a> identifica un hipervínculo.
Un atributo HTML proporciona información adicional sobre una etiqueta. Por ejemplo, el atributo href de la etiqueta <a> </a> te da información sobre la URL de la página a la que apunta el atributo.
Las clases e IDs son atributos críticos para identificar con precisión los elementos de una página. Las clases agrupan elementos similares para darles estilo de forma consistente con CSS o manipularlos uniformemente con JavaScript. Las clases se seleccionan usando .class-name.
En el sitio web de W3Schools, los grupos de clases se ven así:
<div class="city">
<h2>London</h2>
<p>London is the capital of England.</p>
</div>
<div class="city">
<h2>Paris</h2>
<p>Paris is the capital of France.</p>
</div>
<div class="city">
<h2>Tokyo</h2>
<p>Tokyo is the capital of Japan.</p>
</div>
Puedes ver cómo cada título y bloque de ciudad está envuelto con un div que tiene la misma clase city.
En cambio, los IDs son únicos para cada elemento (es decir, dos elementos no pueden tener el mismo ID). Por ejemplo, los siguientes H1s tienen IDs únicos y pueden ser estilizados/manipulados de forma única:
<h1 id="header1">Hello World!</h1>
<h1 id="header2">Lorem Ipsum Dolor</h1>
La sintaxis para seleccionar elementos con IDs es #id-name.
Ahora que conoces los conceptos básicos de HTML, comencemos con el scraping web.
Configura tu Entorno de Scraping
Este tutorial utiliza Python ya que ofrece muchas bibliotecas de scraping HTML y el lenguaje es fácil de aprender. Para verificar si Python está instalado en tu computadora, ejecuta el siguiente comando en PowerShell (Windows) o en tu terminal (macOS):
python3
Si Python está instalado, verás tu número de versión; si no, recibirás un error. Adelante, instala Python si aún no lo tienes.
A continuación, crea una carpeta llamada WebScraper y crea un archivo dentro de la carpeta WebScraper llamado scraper.py. Luego ábrelo en tu entorno de desarrollo integrado (IDE) de preferencia. Visual Studio Code se usa aquí:

Un IDE es una aplicación multipropósito que permite a los programadores escribir código, depurarlo, probar programas, automatizar compilaciones y más. Lo usarás aquí para codificar tu scraper HTML.
A continuación, necesitas separar tu instalación global de Python de tu proyecto de scraping creando un entorno virtual. Esto ayuda a evitar conflictos de dependencias y mantiene toda la aplicación organizada.
Para hacerlo, instala la biblioteca virtualenv usando el siguiente comando:
pip3 install virtualenv
Navega a tu carpeta de proyecto:
cd WebScraper
Luego crea un entorno virtual:
python<version> -m venv <virtual-environment-name>
Este comando crea una carpeta para todos los paquetes y scripts dentro de tu carpeta de proyecto:

Ahora necesitas activar el entorno virtual usando uno de los siguientes comandos (según tu plataforma):
source <virtual-environment-name>/bin/activate #In MacOS and Linux
<virtual-environment-name>/Scripts/activate.bat #In CMD
<virtual-environment-name>/Scripts/Activate.ps1 #In Powershell
Tras una activación exitosa, verás el nombre de tu entorno virtual en el lado izquierdo de la pantalla:

Ahora que tu entorno virtual está activado, necesitas instalar una biblioteca de scraping web. Hay numerosas opciones, incluyendo Playwright, Selenium, Beautiful Soup y Scrapy. Aquí utilizarás Playwright porque es fácil de usar, admite múltiples navegadores, puede manejar contenido dinámico y ofrece un modo sin cabeza (scraping sin interfaz gráfica de usuario (GUI)).
Ejecuta pip install pytest-playwright para instalar Playwright; luego instala los navegadores requeridos con playwright install.
Después de instalar Playwright, estás listo para comenzar con el scraping web.
Extraer HTML de un Sitio Web
El primer paso de cualquier proyecto de scraping web es identificar el sitio web que deseas raspar. Aquí utilizarás este sitio de prueba.
A continuación, necesitas identificar la información que deseas extraer de la página. En este caso, es el contenido HTML completo de la página.
Una vez que hayas identificado la información que intentas extraer, puedes comenzar a codificar el scraper. En Python, el primer paso es importar las bibliotecas requeridas para Playwright. Playwright te permite importar dos tipos de APIs: sync y async. La biblioteca async se usa solo al escribir código asíncrono, por lo que importas la biblioteca sync con el siguiente comando:
from playwright.sync_api import sync_playwright
Después de importar la biblioteca sync, necesitas declarar una función Python usando el siguiente fragmento de código:
def main():
#Rest of the code will be inside this function
Como puedes ver en la nota anterior, escribes tu código de scraping web dentro de esta función.
Normalmente, para obtener información de un sitio web, abrirías un navegador web, crearías una nueva pestaña y visitarías ese sitio web. Para hacer scraping del sitio, necesitas traducir estas acciones en código, que es para lo que usarás Playwright. Su documentación muestra que puedes llamar a la sync_api importada anteriormente y abrir un navegador con este fragmento:
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
Al agregar headless=False dentro de los paréntesis, puedes ver el contenido del sitio web.
Después de abrir tu navegador, abre una nueva pestaña y visita la URL objetivo:
page = browser.new_page()
try:
page.goto("https://webscraper.io/test-sites/e-commerce/static")
except:
print("Error")
Nota: Las líneas anteriores deben añadirse debajo de las líneas previas que iniciaron el navegador. Todo este código va dentro de la función main y dentro de un solo archivo.
Este fragmento de código envuelve la función goto() dentro de un bloque try-except para un mejor manejo de errores.
Cuando ingresas la URL de un sitio en la barra de búsqueda, debes esperar a que cargue. Para imitar eso en el código, puedes usar lo siguiente:
page.wait_for_timeout(7000) #millisecond value in brackets
Nota: Estas líneas anteriores deben añadirse debajo de las líneas previas.
Finalmente, es momento de extraer todo el contenido HTML de la página usando esta línea de código:
print(page.content())
El código completo para extraer el HTML de una página se ve así:
from playwright.sync_api import sync_playwright
def main():
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
try:
page.goto("https://webscraper.io/test-sites/e-commerce/static")
except:
print("Error")
page.wait_for_timeout(7000)
print(page.content())
main()
En Visual Studio Code, el HTML extraído se ve así:

Extraer HTML Usando Atributos Específicos
Anteriormente, extrajiste todos los elementos de la página web del Scraper Web; sin embargo, el scraping web no es útil a menos que te limites a extraer solo la información que necesitas. En esta sección, extraerás solo los títulos de todos los portátiles en la primera página del sitio web:

Para extraer elementos específicos, necesitas entender la estructura del sitio web objetivo. Puedes hacerlo haciendo clic derecho y seleccionando la opción Inspeccionar de esta manera:

Alternativamente, puedes usar estos atajos de teclado:
- Para macOS, usa Cmd + Option + I
- Para Windows, usa Control + Shift + C
Aquí está la estructura de la página objetivo:

Puedes ver el código de un elemento específico en una página usando la herramienta de selección en la parte superior izquierda de la ventana Inspeccionar:

Selecciona uno de los títulos de portátiles en tu ventana Inspeccionar:

Puedes ver que el título está dentro de una etiqueta <a> </a>, que está envuelta por una etiqueta h4, y el enlace tiene una clase de title. Eso significa que buscas etiquetas <a href> (URLs) dentro de etiquetas <h4> que tienen una clase title.
Para crear un programa de scraping que seleccione con precisión estos elementos, necesitas importar las bibliotecas para crear una función Python, lanzar el navegador y navegar al sitio web objetivo:
from playwright.sync_api import sync_playwright
def main():
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
try:
page.goto("https://webscraper.io/test-sites/e-commerce/static/computers/laptops")
except:
print("Error")
page.wait_for_timeout(7000)
Observa que la URL objetivo dentro de la función page.goto() ha sido actualizada para apuntar a la primera página que contiene la lista de portátiles.
Una vez que hayas creado el programa de scraping, necesitas localizar el elemento objetivo basándote en tu análisis de la estructura del sitio web. Playwright tiene una herramienta llamada locators que te permite localizar elementos en una página basándote en varios atributos, como los siguientes:
get_by_label()localiza el elemento objetivo usando la etiqueta asociada a un elemento.get_by_text()localiza el elemento objetivo usando el texto que contiene el elemento.get_by_alt_text()localiza el elemento objetivo y realiza acciones en imágenes usando su texto alternativo.get_by_test_id()localiza el elemento objetivo usando el ID de prueba de un elemento.
Puedes consultar la documentación oficial para más métodos de localización de elementos.
Para extraer todos los títulos de portátiles, necesitas localizar las etiquetas <h4> ya que envuelven todos los títulos de portátiles. Puedes usar el localizador get_by_role() para encontrar elementos basándote en su función, como botones, casillas de verificación y encabezados. Eso significa que, para encontrar todos los encabezados en la página, necesitas escribir lo siguiente:
titles = page.get_by_role("heading").all()
Después de eso, puedes imprimirlo en tu consola con el siguiente código:
print(titles)
Después de imprimir, notarás que devuelve un array de elementos:

Esta salida no incluye títulos, pero sí hace referencia a elementos que coinciden con las condiciones del selector. Debes recorrer estos elementos para encontrar una etiqueta <a> con una clase title y el texto dentro de ella.
Se recomienda usar el localizador CSS para encontrar un elemento basándose en su ruta y clase, y puedes usar la función all_inner_texts() para extraer el texto interno de un elemento así:
for title in titles:
laptop = title.locator("a.title").all_inner_texts()
Al ejecutar este código, tu salida debería verse así:

Para rechazar arrays sin valores, escribe lo siguiente:
if len(laptop) == 1:
print(laptop[0])
Una vez que rechaces los arrays sin valores, habrás construido exitosamente un programa de scraping que extrae solo elementos específicos.
Aquí está el código completo para este scraper:
from playwright.sync_api import sync_playwright
def main():
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
try:
page.goto("https://webscraper.io/test-sites/e-commerce/static/computers/laptops")
except:
print("Error")
page.wait_for_timeout(7000)
titles = page.get_by_role("heading").all()
for title in titles:
laptop = title.locator("a.title").all_inner_texts()
if len(laptop) == 1:
print(laptop[0])
main()
Interactuar con Elementos
Subamos un nivel ahora y construyamos un programa que extraiga los títulos de la primera página que contiene portátiles, navegue a la segunda página y extraiga también esos títulos.
Ya que sabes cómo extraer títulos de una página, solo necesitas descubrir cómo navegar a la siguiente página de portátiles.
Puede que ya hayas notado los botones de Paginación en la página en la que te encuentras actualmente.
Debes localizar 2 y hacer clic en él usando tu programa de scraping. Al inspeccionar la página, verás que el elemento requerido es un elemento de lista (etiqueta <li>) y tiene el texto interno 2:

Eso significa que puedes usar el selector get_by_role() para encontrar un elemento de lista y un selector get_by_text() para encontrar un elemento con 2 como texto.
Así es como codificarlo en tu archivo:
page.get_by_role("listitem").get_by_text("2", exact=True)
Esto encuentra un elemento que coincide con dos condiciones: primero, debe ser un elemento de lista, y segundo, debe tener 2 como texto.
exact=True es un argumento de función para encontrar el elemento con el texto dado.
Para hacer clic en el botón, modifica el código anterior para que se vea así:
page.get_by_role("listitem").get_by_text("2", exact=True).click()
En este código, la función click() hace clic en el elemento dado.
Espera a que la página cargue y extrae todos los títulos nuevamente:
page.wait_for_timeout(5000)
titles = page.get_by_role("heading").all()
for title in titles:
laptop = title.locator("a.title").all_inner_texts()
if len(laptop) == 1:
print(laptop[0])
Tu bloque de código completo debería verse así:
from playwright.sync_api import sync_playwright
def main():
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
try:
page.goto("https://webscraper.io/test-sites/e-commerce/static/computers/laptops")
except:
print("Error")
page.wait_for_timeout(7000)
titles = page.get_by_role("heading").all()
for title in titles:
laptop = title.locator("a.title").all_inner_texts()
if len(laptop) == 1:
print(laptop[0])
page.get_by_role("listitem").get_by_text("2", exact=True).click()
page.wait_for_timeout(5000)
titles = page.get_by_role("heading").all()
for title in titles:
laptop = title.locator("a.title").all_inner_texts()
if len(laptop) == 1:
print(laptop[0])
main()
Extraer HTML y Escribirlo en un CSV
Si no almacenas y analizas los datos que extraes, son inútiles. En esta sección, crearás un programa avanzado que toma como entrada del usuario el número de páginas de portátiles a extraer, extrae los títulos y los almacena en un archivo CSV en tu carpeta de proyecto.
Para este programa, necesitas una biblioteca CSV preinstalada, que se puede importar usando el siguiente comando:
import csv
Después de instalar la biblioteca CSV, necesitas descubrir cómo visitarás un número variable de páginas dependiendo de la entrada del usuario.
Si observas la estructura de URL del sitio web, notarás que cada página de portátiles se indica usando un parámetro de URL. Por ejemplo, la URL de la segunda página en el directorio de portátiles es https://webscraper.io/test-sites/e-commerce/static/computers/laptops?page=2.
Puedes visitar diferentes páginas modificando el parámetro de URL ?page=2 con diferentes valores numéricos. Eso significa que necesitas pedirle al usuario que ingrese el número de páginas a extraer con el siguiente comando:
pages = int(input("enter the number of pages to scrape: "))
Para visitar cada página desde 1 hasta el número de páginas ingresado por el usuario, usas un bucle for así:
for i in range(1, pages+1):
Dentro de esta función range, usas 1 y pages+1 como argumentos de función para representar los valores donde el bucle comienza y termina. El segundo argumento de función está excluido del bucle. Por ejemplo, si la función range es range(1,5), el programa haría un bucle de 1 a 4 solamente.
A continuación, necesitas visitar cada página ingresando el valor i como parámetro de URL en la iteración. Puedes añadir variables a una cadena usando f-strings de Python.
Al generar una cadena, prefijas las comillas con una f para indicar que es un f-string. Dentro de las comillas, puedes usar llaves para indicar variables.
Aquí hay un ejemplo de cómo puedes usar f-strings para imprimir variables junto con cadenas:
print(f"The value of the variable is {variable_name_goes_here}")
Volviendo al scraper, puedes utilizar f-strings escribiendo este bloque de código en el archivo:
try:
page.goto(f"https://webscraper.io/test-sites/e-commerce/static/computers/laptops?page={i}")
except:
print("Error")
Espera a que la página cargue con una función de tiempo de espera y extrae los títulos usando lo siguiente:
page.wait_for_timeout(7000)
titles = page.get_by_role("heading").all()
Una vez que tengas todos los elementos de título, necesitas abrir tu archivo CSV, recorrer cada título, extraer el texto requerido y escribirlo en tu archivo.
Para abrir un archivo CSV, usa la siguiente sintaxis:
with open("laptops.csv", "a") as csvfile:
Aquí, abres el archivo laptops.csv con el modo de anexar (a). Usas el modo de anexar aquí porque no quieres perder datos antiguos cada vez que se abre el archivo. Si el archivo no existe, la biblioteca crea uno en la carpeta del proyecto. CSV ofrece varios modos para abrir un archivo, incluyendo los siguientes:
- r es la opción predeterminada que se usa si no se especifica nada. Abre el archivo solo para lectura.
- w abre un archivo solo para escritura. Cada vez que se abre un archivo, los datos anteriores se sobrescriben.
- a abre un archivo para añadir datos. Los datos anteriores no se sobrescriben.
- r+ abre un archivo tanto para lectura como para escritura.
- x crea un nuevo archivo.
Debajo del código anterior, necesitas declarar un objeto writer que te permita manipular el archivo CSV:
writer = csv.writer(csvfile)
A continuación, recorre cada elemento de título y extrae el texto con lo siguiente:
for title in titles:
laptop = title.locator("a.title").all_inner_texts()
Esto te da múltiples arrays, cada uno conteniendo el título de portátiles individuales. Para rechazar arrays vacíos, escribe el siguiente código condicional en el archivo CSV:
if len(laptop) == 1:
writer.writerow([laptop[0]])
La función writerow te permite escribir nuevas filas en un archivo CSV.
Aquí está el código completo del programa:
from playwright.sync_api import sync_playwright
import csv
def main():
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
pages = int(input("enter the number of pages to scrape: "))
for i in range(1, pages+1):
try:
page.goto(f"https://webscraper.io/test-sites/e-commerce/static/computers/laptops?page={i}")
except:
print("Error")
page.wait_for_timeout(7000)
titles = page.get_by_role("heading").all()
with open("laptops.csv", "a") as csvfile:
writer = csv.writer(csvfile)
for title in titles:
laptop = title.locator("a.title").all_inner_texts()
if len(laptop) == 1:
writer.writerow([laptop[0]])
browser.close()
main()
Después de ejecutar este código, tu archivo CSV debería verse así:

Conclusión
En este artículo, aprendiste cómo extraer, parsear y almacenar HTML usando Python.
Si bien este tutorial fue relativamente sencillo, en un escenario del mundo real, probablemente te encontrarías con varios obstáculos al hacer scraping, incluyendo CAPTCHAs, límites de velocidad, cambios en el diseño del sitio web o requisitos regulatorios. Afortunadamente, Bright Data puede ayudar. Bright Data ofrece herramientas como proxies residenciales avanzados para mejorar tu scraping, un IDE de Web Scraper para construir scrapers a escala, y un Web Unlocker para desbloquear sitios web públicos, incluyendo la resolución de CAPTCHAs. Estas herramientas pueden ayudarte a recopilar datos precisos a escala y superar obstáculos. Además, el compromiso de Bright Data con el scraping ético garantiza que te mantengas dentro de los términos de servicio del sitio web y las regulaciones legales.
Con la infraestructura repleta de funciones de Bright Data, puedes concentrarte en extraer los datos valiosos que necesitas, dejando atrás las complejidades del scraping web. ¡Comienza tu prueba gratuita hoy!