Formatos y fuentes de datos 4 min de lectura

Parseo de CSV: separadores, comillas, codificaciones y ejemplos en varios lenguajes

Todo sobre la lectura de CSV: separadores, comillas, codificaciones, archivos problemáticos de Excel y ejemplos de código en Python, PHP, JavaScript y Go.

EW
Equipo Web-Scraping.es
Recopilación de datos para las necesidades del negocio
Publicado: 26 febrero 2025

CSV (Comma-Separated Values) es el formato tabular más simple: las líneas del archivo se corresponden con las filas de la tabla y los valores dentro de cada línea van separados por una coma u otro carácter. En él llegan las exportaciones de los CRM y los ERP, las descargas de Excel, los informes de las plataformas publicitarias y de analítica. El formato parece trivial, y justo por eso es donde más errores se cometen. Este artículo forma parte de nuestro panorama del parseo de documentos y está dedicado a cómo leer CSV correctamente.

Por qué el «split por comas» es un error

La tentación de trocear el CSV a mano — line.split(",") — la sufre todo el mundo, y casi siempre acaba en bugs. La razón es que CSV tiene escapado: un valor con una coma dentro se encierra entre comillas, y las comillas dentro de un valor se duplican.

csv
sku,name,price
101,"Molinillo de café, manual",3490
102,"Tetera ""Retro""",2190

Aquí "Molinillo de café, manual" es un único valor, no dos, y Tetera "Retro" contiene comillas. Cualquier split manual lo romperá. Por eso se usa siempre un lector de CSV ya hecho: conoce las comillas, el escapado y los saltos de línea dentro de las celdas.

Separadores, codificaciones y BOM

Pese al «comma» del nombre, el separador resulta ser muchas veces el punto y coma (;): así guarda Excel los archivos en las configuraciones regionales donde la coma es el separador decimal — la española entre ellas. También se encuentran la tabulación (TSV) y la barra vertical. Un buen parser sabe detectar el separador automáticamente o lo acepta como parámetro.

El segundo problema constante es la codificación. Los archivos de los sistemas de gestión antiguos llegan a menudo en windows-1252 (latin-1) y no en UTF-8. Además, los archivos de Excel empiezan con frecuencia con un BOM (una marca invisible al principio) por cuya culpa el nombre de la primera columna se lee como \ufeffsku en lugar de sku. Se cura indicando la codificación correcta al leer (en Python, encoding="utf-8-sig", que elimina el BOM por sí sola).

Python

La biblioteca estándar incluye el módulo csv, suficiente en la mayoría de los casos. Lo más cómodo es DictReader, que entrega cada fila como un diccionario según las cabeceras.

python
import csv

with open("prices.csv", encoding="utf-8-sig", newline="") as f:
    reader = csv.DictReader(f, delimiter=";")
    for row in reader:
        print(row["sku"], row["name"], row["price"])

Cuando el CSV es grande o hay que analizarlo sobre la marcha — filtrar, agrupar, calcular —, se recurre a pandas. Una sola línea lee el archivo a una tabla (DataFrame).

python
import pandas as pd

df = pd.read_csv("prices.csv", sep=";", encoding="utf-8-sig")
expensive = df[df["price"] > 3000]
print(expensive[["sku", "name"]])

Pandas también resulta práctico para convertir: ese mismo DataFrame se guarda con un solo comando de vuelta en CSV, Excel o JSON.

JavaScript / Node.js

En el navegador y en Node, el parser más popular es Papa Parse: detecta el separador automáticamente, entiende las cabeceras y sabe trabajar con flujos.

javascript
const Papa = require("papaparse");
const fs = require("fs");

const file = fs.readFileSync("prices.csv", "utf-8");
const result = Papa.parse(file, { header: true, skipEmptyLines: true });

for (const row of result.data) {
  console.log(row.sku, row.name, row.price);
}

Para los pipelines de servidor con archivos grandes se elige más a menudo csv-parse — el parser en flujo del ecosistema Node CSV.

PHP

La función integrada fgetcsv ya incorpora el tratamiento de las comillas, así que basta para las tareas simples.

php
<?php
$f = fopen("prices.csv", "r");
$headers = fgetcsv($f, 0, ";");

while (($row = fgetcsv($f, 0, ";")) !== false) {
    $record = array_combine($headers, $row);
    echo $record["sku"] . " — " . $record["name"] . "\n";
}
fclose($f);

Para un trabajo más cómodo — con filtrado, selección de columnas y conversión de codificaciones — se usa la biblioteca league/csv.

Go

La biblioteca estándar de Go trae el paquete encoding/csv, que cubre la mayoría de los casos, separador no estándar incluido.

go
package main

import (
    "encoding/csv"
    "fmt"
    "os"
)

func main() {
    f, _ := os.Open("prices.csv")
    defer f.Close()

    r := csv.NewReader(f)
    r.Comma = ';'
    rows, _ := r.ReadAll()

    for _, row := range rows[1:] { // omitimos la fila de cabecera
        fmt.Println(row[0], row[1], row[2])
    }
}

Cuándo el CSV deja de dar la talla

El CSV funciona mientras los datos son planos. En cuanto aparecen anidamiento, varias tablas en un mismo archivo, formato, fórmulas o celdas combinadas, eso ya no es tarea para CSV, sino para el parseo de Excel. Y al revés: si el original en Excel es demasiado complejo para leerlo directamente, muchas veces se exporta primero a CSV y se procesa de manera uniforme. Y si el CSV es, en el fondo, una descarga de eventos o de líneas de un registro, eche un vistazo a los enfoques de los artículos sobre el parseo de TXT y el parseo de logs.

Si sus descargas llegan con codificaciones «flotantes», separadores que cambian de una entrega a otra o comillas rotas, las unificaremos y configuraremos un parseo estable con la carga del resultado en el sistema que necesite.