Extracción de datos de tablas HTML y guardado en CSV con Python

Estructura estándar de una tabla HTML con elementos tr y td:

| Fila 1, Columna 1 | Fila 1, Columna 2 | Fila 1, Columna 3 |
|---|---|---|
| Fila 2, Columna 1 | Fila 2, Columna 2 | Fila 2, Columna 3 |
| Fila 3, Columna 1 | Fila 3, Columna 2 | Fila 3, Columna 3 |

Método通用 para extraer datos utilizando dos ciclos for:

from bs4 import BeautifulSoup
import csv

# Abrir archivo HTML y analizar con BeautifulSoup
with open('datos_clima.html', 'r', encoding='utf-8') as archivo:
    soup = BeautifulSoup(archivo.read(), 'lxml')

# Seleccionar todas las filas de la tabla usando selector CSS
filas = soup.select('div.contenedor tr')

# Crear archivo CSV y preparar para escritura
with open('resultado.csv', mode='w', newline='', encoding='utf-8') as archivo_csv:
    escritor_csv = csv.writer(archivo_csv)
    
    # Iterar sobre cada fila de la tabla
    for fila in filas:
        # Obtener todas las celdas de la fila
        celdas = fila.select('td')
        
        # Lista para almacenar el contenido de texto de cada celda
        datos_fila = []
        
        # Iterar sobre cada celda
        for celda in celdas:
            # Obtener texto de la celda y eliminar espacios en blanco
            texto_celda = celda.get_text(strip=True)
            datos_fila.append(texto_celda)
        
        # Escribir la fila de datos en el archivo CSV
        escritor_csv.writerow(datos_fila)

Convertir tabla a formato de diccionario

Para este ejemplo utilizaremos una tabla de empleados con información salarial:

<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Información Salarial</title>
    <style>
        table {
            border-collapse: collapse;
            width: 100%;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
    </style>
</head>
<body>
| Nombre | Salario Base | Salario Puesto | Bono Rendimiento | Descuento Ausencia | Seguro Médico | Salario Total |
|---|---|---|---|---|---|---|
| Juan | 6000 | 3000 | 1500 | 300 | 500 | 11700 |
| Pedro | 5000 | 2000 | 1000 | 0 | 500 | 8500 |
| Carlos | 3500 | 1500 | 800 | 0 | 0 | 5800 |
| Miguel | 5000 | 1200 | 120 | 0 | 0 | 6320 |
| Diego | 5000 | 1200 | 0 | 0 | 0 | 6200 |
</body>
</html>

La estrategia consiste en utilizar los elementos th como claves del dicccionario y los elementso td como valores correspondientes. El resultado será una estructura como:


[{'Nombre': 'Juan', 'Salario Base': '6000', 'Salario Puesto': '3000', 'Bono Rendimiento': '1500', ...},
 {'Nombre': 'Pedro', 'Salario Base': '5000', 'Salario Puesto': '2000', ...},
 ...]

Código de implementación:

from bs4 import BeautifulSoup

# Abrir archivo HTML y analizar
with open('./tabla_salarios.html', 'r', encoding='utf-8') as f:
    soup = BeautifulSoup(f.read(), 'lxml')

# Extraer datos de la tabla
tabla = soup.find('table')
filas = tabla.find_all('tr')

# Extraer encabezados (elementos th)
encabezados = []
celdas_encabezado = filas[0].find_all('th')
for celda in celdas_encabezado:
    encabezados.append(celda.text.strip())

# Extraer datos y crear lista de diccionarios
lista_datos = []
for fila in filas[1:]:
    diccionario = {}
    celdas_datos = fila.find_all('td')
    for i in range(len(encabezados)):
        diccionario[encabezados[i]] = celdas_datos[i].text.strip()
    lista_datos.append(diccionario)

# Mostrar resultados
for elemento in lista_datos:
    print(elemento)

Para guardar la lista de dicccionarios en un archivo CSV:

import csv
from bs4 import BeautifulSoup

# Abrir y analizar archivo HTML
with open('./tabla_salarios.html', 'r', encoding='utf-8') as f:
    soup = BeautifulSoup(f.read(), 'lxml')

# Extraer tabla
tabla = soup.find('table')
filas = tabla.find_all('tr')

# Obtener encabezados
encabezados = []
celdas_encabezado = filas[0].find_all('th')
for celda in celdas_encabezado:
    encabezados.append(celda.text.strip())

# Crear lista de diccionarios
lista_datos = []
for fila in filas[1:]:
    diccionario = {}
    celdas_datos = fila.find_all('td')
    for i in range(len(encabezados)):
        diccionario[encabezados[i]] = celdas_datos[i].text.strip()
    lista_datos.append(diccionario)

# Ruta del archivo CSV
ruta_csv = 'salarios_exportados.csv'

# Escribir archivo CSV
with open(ruta_csv, 'w', newline='', encoding='utf-8') as archivo_csv:
    escritor = csv.DictWriter(archivo_csv, fieldnames=lista_datos[0].keys())
    escritor.writeheader()
    escritor.writerows(lista_datos)

print(f'Archivo CSV creado: {ruta_csv}')

Convertir tabla a formato de lista

import csv
from bs4 import BeautifulSoup

# Abrir y analizar archivo HTML
with open('./tabla_salarios.html', 'r', encoding='utf-8') as f:
    soup = BeautifulSoup(f.read(), 'lxml')

# Extraer todas las celdas de datos
tabla = soup.find('table')
celdas = tabla.find_all('td')

# Extraer texto de cada celda
lista_datos = []
for celda in celdas:
    lista_datos.append(celda.text.strip())

# Dividir en filas (7 elementos por fila)
filas_datos = []
for i in range(0, len(lista_datos), 7):
    fila = lista_datos[i:i+7]
    filas_datos.append(fila)

# Ruta del archivo CSV
ruta_csv = 'salarios_lista.csv'

# Escribir archivo CSV
with open(ruta_csv, 'w', newline='', encoding='utf-8') as archivo_csv:
    escritor = csv.writer(archivo_csv)
    # Escribir encabezados
    escritor.writerow(["Nombre", "Salario Base", "Salario Puesto", "Bono", "Descuento", "Seguro", "Total"])
    # Escribir datos
    escritor.writerows(filas_datos)

print(f'Archivo CSV creado: {ruta_csv}')

Etiquetas: Python BeautifulSoup HTML CSV web-scraping

Publicado el 6-29 21:53