Parsing CSV : séparateurs, guillemets, encodages et exemples dans différents langages

Tout sur le parsing des CSV : séparateurs, guillemets, encodages, fichiers mal formés issus d'Excel et exemples de lecture en Python, PHP, JavaScript et Go.

ÉW
Équipe Web-Scraping.fr
Collecte de données pour votre activité
Publié le: 26 février 2025

CSV (Comma-Separated Values) est le format tabulaire le plus simple : les lignes du fichier correspondent aux lignes du tableau, et les valeurs à l'intérieur d'une ligne sont séparées par une virgule ou un autre caractère. C'est sous cette forme qu'arrivent les exports de CRM et d'ERP, les exports depuis Excel, les rapports des régies publicitaires et des outils de mesure d’audience. Le format semble trivial, et c'est précisément pour cela qu'on s'y trompe le plus souvent. Cet article fait partie de notre panorama du parsing de documents et explique comment lire un CSV correctement.

Pourquoi un simple découpage sur la virgule est une erreur

La tentation de découper un CSV à la main — line.split(",") — vient à tout le monde et se termine presque toujours par des bugs. La raison : le CSV possède un mécanisme d'échappement — une valeur contenant une virgule est mise entre guillemets, et les guillemets à l'intérieur d'une valeur sont doublés.

csv
sku,name,price
101,"Кофемолка, ручная",3490
102,"Чайник ""Ретро""",2190

Ici, la première valeur entre guillemets est une seule valeur, pas deux, et la seconde contient des guillemets internes. N'importe quel split manuel casserait cela. C'est pourquoi on utilise toujours un lecteur CSV prêt à l'emploi : il gère les guillemets, l'échappement et les retours à la ligne à l'intérieur des cellules.

Séparateurs, encodages et BOM

Malgré le « comma » du nom, le séparateur est souvent un point-virgule (;) — c'est ainsi qu'Excel enregistre les fichiers dans les locales où la virgule sert de séparateur décimal, comme le français. On rencontre aussi la tabulation (TSV) et la barre verticale. Un bon parseur sait détecter le séparateur automatiquement ou l'accepte en paramètre.

Le deuxième problème récurrent est l'encodage. Les fichiers issus d'anciens systèmes de gestion arrivent souvent en windows-1251 ou windows-1252, et non en UTF-8. De plus, les fichiers issus d'Excel commencent fréquemment par un BOM (marque invisible en début de fichier), à cause duquel le nom de la première colonne se lit \ufeffsku au lieu de sku. Le remède : indiquer le bon encodage à la lecture (en Python, encoding="utf-8-sig", qui supprime le BOM automatiquement).

Python

La bibliothèque standard fournit le module csv, suffisant dans la plupart des cas. Le plus pratique est DictReader : il renvoie chaque ligne sous forme de dictionnaire indexé par les en-têtes.

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"])

Quand le CSV est volumineux ou qu'il faut l'analyser directement — filtrer, regrouper, calculer — on prend pandas. Une seule ligne charge le fichier dans un tableau (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 est également pratique pour la conversion : le même DataFrame se sauvegarde en une commande vers CSV, Excel ou JSON.

JavaScript / Node.js

Dans le navigateur comme dans Node, le parseur le plus populaire est Papa Parse : il détecte automatiquement le séparateur, gère les en-têtes et sait travailler en flux.

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);
}

Pour les pipelines côté serveur avec de gros fichiers, on choisit plus souvent csv-parse — un parseur en streaming issu de l'écosystème Node CSV.

PHP

La fonction native fgetcsv gère déjà les guillemets, elle suffit donc pour les tâches 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);

Pour un travail plus confortable — filtrage, sélection de colonnes, conversion d'encodage — on utilise la bibliothèque league/csv.

Go

La bibliothèque standard de Go fournit le paquet encoding/csv, qui couvre la plupart des besoins, y compris un séparateur non standard.

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:] { // on saute l'en-tête
        fmt.Println(row[0], row[1], row[2])
    }
}

Quand le CSV ne suffit plus

Le CSV est parfait tant que les données restent plates. Dès qu'apparaissent de l'imbrication, plusieurs tableaux dans un même fichier, de la mise en forme, des formules ou des cellules fusionnées, ce n'est plus une tâche pour le CSV mais pour le parsing d'Excel. Et inversement : si le fichier Excel source est trop complexe pour une lecture directe, on l'exporte souvent d'abord en CSV pour le traiter de façon uniforme. Et si le CSV est en réalité un export d'événements ou de lignes de journal, consultez les approches décrites dans nos articles sur le parsing de fichiers TXT et le parsing de logs.

Si vos exports arrivent avec des encodages « flottants », des séparateurs qui changent d'un export à l'autre ou des guillemets cassés, nous les normaliserons et mettrons en place un parsing stable avec livraison des données dans le système de votre choix.