Skip to content

Exemples d'utilisation avancée ​

Cette page présente des exemples avancés d'utilisation de l'API ParseMyFile pour des cas d'usage complexes.

Exemple 1 : Extraction de données de tableau ​

Configuration YAML pour tableau ​

yaml
# tableau-facturation.yaml
schemas:
  data:
    type: object
    properties:
      en_tete_tableau:
        type: string
        description: en-tête du tableau
      lignes_produits:
        type: array<object>
        description: lignes de produits du tableau
        items:
          type: object
          properties:
            produit:
              type: string
              description: nom du produit
            quantite:
              type: integer
              description: quantité du produit
            prix_unitaire:
              type: double
              description: prix unitaire du produit en euros
            total:
              type: double
              description: total de la ligne en euros
      total_general:
        type: double
        description: total général de la facture en euros

Code Python pour traitement de tableau ​

python
import requests
import pandas as pd
from typing import List, Dict, Any

def process_table_document(file_path: str, yaml_path: str, api_key: str) -> pd.DataFrame:
    """
    Traite un document contenant un tableau et retourne un DataFrame
    """
    url = "https://api.parsemyfile.com/api/v1/generate"
    headers = {"X-API-KEY": api_key}
    
    with open(file_path, 'rb') as file, open(yaml_path, 'rb') as yaml_file:
        files = {
            'file': (file_path, file, 'application/pdf'),
            'yaml_file': ('config.yaml', yaml_file, 'text/yaml')
        }
        
        response = requests.post(url, headers=headers, files=files)
        
        if response.status_code == 200:
            result = response.json()
            data = result['data']['extracted_fields']
            
            # Convertir les lignes de tableau en DataFrame
            if 'lignes_produits' in data:
                df = pd.DataFrame(data['lignes_produits'])
                return df
            else:
                return pd.DataFrame()
        else:
            raise Exception(f"Erreur API: {response.text}")

# Utilisation
try:
    df = process_table_document('facture_avec_tableau.pdf', 'tableau-facturation.yaml', 'votre_cle_api')
    print("Tableau extrait:")
    print(df)
    
    # Calculer des statistiques
    print(f"\nNombre de lignes: {len(df)}")
    print(f"Total général: {df['total'].sum():.2f} EUR")
    
except Exception as e:
    print(f"Erreur: {e}")

Exemple 2 : Extraction de données multi-pages ​

Configuration YAML pour document multi-pages ​

yaml
# document-multipage.yaml
schemas:
  data:
    type: object
    properties:
      titre_document:
        type: string
        description: titre du document
      resume_executif:
        type: string
        description: résumé exécutif du document
      chapitres:
        type: array<object>
        description: chapitres du document
        items:
          type: object
          properties:
            titre_chapitre:
              type: string
              description: titre du chapitre
            contenu_chapitre:
              type: string
              description: contenu du chapitre
      conclusion:
        type: string
        description: conclusion du document
      signatures:
        type: array<string>
        description: signatures détectées

Code JavaScript pour traitement multi-pages ​

javascript
class MultiPageProcessor {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://api.parsemyfile.com/api/v1/generate';
  }

  async processMultiPageDocument(file, yamlFile) {
    try {
      const formData = new FormData();
      formData.append('file', file);
      formData.append('yaml_file', yamlFile);

      const response = await fetch(this.baseUrl, {
        method: 'POST',
        headers: {
          'X-API-KEY': this.apiKey
        },
        body: formData
      });

      if (!response.ok) {
        throw new Error(`Erreur ${response.status}: ${response.statusText}`);
      }

      const result = await response.json();
      return this.organizeMultiPageData(result.data);
    } catch (error) {
      console.error('Erreur lors du traitement multi-pages:', error);
      throw error;
    }
  }

  organizeMultiPageData(data) {
    const organized = {
      metadata: data.metadata,
      content: {
        title: data.extracted_fields.titre_document,
        executiveSummary: data.extracted_fields.resume_executif,
        chapters: this.organizeChapters(data.extracted_fields.chapitres),
        conclusion: data.extracted_fields.conclusion,
        signatures: data.extracted_fields.signatures
      }
    };

    return organized;
  }

  organizeChapters(chaptersData) {
    if (!chaptersData || !Array.isArray(chaptersData)) {
      return [];
    }

    return chaptersData.map((chapter, index) => ({
      id: index + 1,
      title: chapter.titre_chapitre,
      content: chapter.contenu_chapitre
    }));
  }
}

// Utilisation
const processor = new MultiPageProcessor('votre_cle_api');

document.getElementById('processBtn').addEventListener('click', async () => {
  const fileInput = document.getElementById('fileInput');
  const yamlInput = document.getElementById('yamlInput');
  
  if (fileInput.files.length === 0 || yamlInput.files.length === 0) {
    alert('Veuillez sélectionner un fichier et une configuration YAML');
    return;
  }

  try {
    const result = await processor.processMultiPageDocument(
      fileInput.files[0],
      yamlInput.files[0]
    );
    
    console.log('Document multi-pages traité:', result);
    displayResults(result);
  } catch (error) {
    console.error('Erreur:', error);
    alert('Erreur lors du traitement: ' + error.message);
  }
});

function displayResults(result) {
  const output = document.getElementById('output');
  output.innerHTML = `
    <h3>Titre: ${result.content.title}</h3>
    <h4>Résumé exécutif:</h4>
    <p>${result.content.executiveSummary}</p>
    <h4>Chapitres (${result.content.chapters.length}):</h4>
    ${result.content.chapters.map(ch => `
      <div>
        <strong>Chapitre ${ch.id}: ${ch.title}</strong>
        <p>${ch.content}</p>
      </div>
    `).join('')}
    <h4>Conclusion:</h4>
    <p>${result.content.conclusion}</p>
  `;
}

Exemple 3 : Extraction avec validation avancée ​

Configuration YAML avec validation ​

yaml
# validation-avancee.yaml
schemas:
  data:
    type: object
    properties:
      numero_commande:
        type: string
        description: numéro de commande (format CMD-XXXXXX)
      client_email:
        type: string
        description: email du client
      montant_commande:
        type: double
        description: montant de la commande en euros
      date_livraison:
        type: string
        description: date de livraison prévue (format YYYY-MM-DD)
      produits:
        type: array<object>
        description: liste des produits commandés
        items:
          type: object
          properties:
            nom_produit:
              type: string
              description: nom du produit
            quantite:
              type: integer
              description: quantité du produit
            prix:
              type: double
              description: prix unitaire du produit en euros

Code Python avec validation ​

python
import requests
import re
from datetime import datetime, timedelta
from typing import Dict, List, Any, Optional
from dataclasses import dataclass

@dataclass
class ValidationError:
    field: str
    message: str
    value: Any

class AdvancedValidator:
    def __init__(self):
        self.errors: List[ValidationError] = []
    
    def validate_order_number(self, value: str) -> bool:
        pattern = r"^CMD-[0-9]{6}$"
        if not re.match(pattern, value):
            self.errors.append(ValidationError(
                "numero_commande",
                "Le numéro de commande doit être au format CMD-XXXXXX",
                value
            ))
            return False
        return True
    
    def validate_email(self, value: str) -> bool:
        pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
        if not re.match(pattern, value):
            self.errors.append(ValidationError(
                "client_email",
                "Format d'email invalide",
                value
            ))
            return False
        return True
    
    def validate_delivery_date(self, value: str) -> bool:
        try:
            date = datetime.strptime(value, "%d/%m/%Y")
            today = datetime.now()
            max_date = today + timedelta(days=365)
            
            if date < today:
                self.errors.append(ValidationError(
                    "date_livraison",
                    "La date de livraison ne peut pas être dans le passé",
                    value
                ))
                return False
            
            if date > max_date:
                self.errors.append(ValidationError(
                    "date_livraison",
                    "La date de livraison ne peut pas dépasser un an",
                    value
                ))
                return False
                
            return True
        except ValueError:
            self.errors.append(ValidationError(
                "date_livraison",
                "Format de date invalide (DD/MM/YYYY attendu)",
                value
            ))
            return False
    
    def validate_amount(self, value: float) -> bool:
        if value < 0 or value > 10000:
            self.errors.append(ValidationError(
                "montant_commande",
                "Le montant doit être entre 0 et 10000 EUR",
                value
            ))
            return False
        return True
    
    def validate_products(self, products: List[Dict]) -> bool:
        if len(products) < 1 or len(products) > 10:
            self.errors.append(ValidationError(
                "produits",
                "Le nombre de produits doit être entre 1 et 10",
                len(products)
            ))
            return False
        
        for i, product in enumerate(products):
            if not product.get('nom_produit'):
                self.errors.append(ValidationError(
                    f"produits[{i}].nom_produit",
                    "Le nom du produit est requis",
                    product
                ))
                return False
            
            if not (1 <= product.get('quantite', 0) <= 100):
                self.errors.append(ValidationError(
                    f"produits[{i}].quantite",
                    "La quantité doit être entre 1 et 100",
                    product.get('quantite')
                ))
                return False
        
        return True

def process_with_validation(file_path: str, yaml_path: str, api_key: str) -> Dict[str, Any]:
    """
    Traite un document avec validation avancée
    """
    # Appel API
    url = "https://api.parsemyfile.com/api/v1/generate"
    headers = {"X-API-KEY": api_key}
    
    with open(file_path, 'rb') as file, open(yaml_path, 'rb') as yaml_file:
        files = {
            'file': (file_path, file, 'application/pdf'),
            'yaml_file': ('config.yaml', yaml_file, 'text/yaml')
        }
        
        response = requests.post(url, headers=headers, files=files)
        
        if response.status_code != 200:
            raise Exception(f"Erreur API: {response.text}")
        
        result = response.json()
        data = result['data']['extracted_fields']
        
        # Validation
        validator = AdvancedValidator()
        
        # Validation des champs individuels
        validator.validate_order_number(data.get('numero_commande', ''))
        validator.validate_email(data.get('client_email', ''))
        validator.validate_delivery_date(data.get('date_livraison', ''))
        validator.validate_amount(float(data.get('montant_commande', 0)))
        validator.validate_products(data.get('produits', []))
        
        return {
            'data': data,
            'valid': len(validator.errors) == 0,
            'errors': validator.errors,
            'metadata': result['data']['metadata']
        }

# Utilisation
try:
    result = process_with_validation('commande.pdf', 'validation-avancee.yaml', 'votre_cle_api')
    
    if result['valid']:
        print("✅ Document traité et validé avec succès")
        print(f"Numéro de commande: {result['data']['numero_commande']}")
        print(f"Client: {result['data']['client_email']}")
        print(f"Montant: {result['data']['montant_commande']} EUR")
    else:
        print("❌ Erreurs de validation détectées:")
        for error in result['errors']:
            print(f"  - {error.field}: {error.message} (valeur: {error.value})")
            
except Exception as e:
    print(f"Erreur: {e}")

Exemple 4 : Intégration avec une base de données ​

Code Python avec intégration BDD ​

python
import sqlite3
import requests
import json
from typing import Dict, Any
from datetime import datetime

class DocumentProcessor:
    def __init__(self, api_key: str, db_path: str = "documents.db"):
        self.api_key = api_key
        self.db_path = db_path
        self.init_database()
    
    def init_database(self):
        """Initialise la base de données"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS documents (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                filename TEXT NOT NULL,
                document_type TEXT NOT NULL,
                processed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                status TEXT NOT NULL,
                confidence_score REAL,
                extracted_data TEXT,
                error_message TEXT
            )
        ''')
        
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS extracted_fields (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                document_id INTEGER,
                field_name TEXT NOT NULL,
                field_value TEXT,
                field_type TEXT,
                confidence REAL,
                FOREIGN KEY (document_id) REFERENCES documents (id)
            )
        ''')
        
        conn.commit()
        conn.close()
    
    def process_document(self, file_path: str, yaml_path: str, document_type: str) -> Dict[str, Any]:
        """Traite un document et sauvegarde en base"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        
        try:
            # Appel API
            result = self.call_api(file_path, yaml_path)
            
            if result['status'] == 'success':
                # Sauvegarde du document
                cursor.execute('''
                    INSERT INTO documents (filename, document_type, status, confidence_score, extracted_data)
                    VALUES (?, ?, ?, ?, ?)
                ''', (
                    file_path,
                    document_type,
                    'success',
                    result['data']['metadata']['confidence_score'],
                    json.dumps(result['data']['extracted_fields'])
                ))
                
                document_id = cursor.lastrowid
                
                # Sauvegarde des champs extraits
                for field_name, field_value in result['data']['extracted_fields'].items():
                    cursor.execute('''
                        INSERT INTO extracted_fields (document_id, field_name, field_value, field_type, confidence)
                        VALUES (?, ?, ?, ?, ?)
                    ''', (
                        document_id,
                        field_name,
                        str(field_value),
                        'text',  # Type par défaut
                        result['data']['metadata']['confidence_score']
                    ))
                
                conn.commit()
                
                return {
                    'success': True,
                    'document_id': document_id,
                    'data': result['data']
                }
            else:
                # Sauvegarde de l'erreur
                cursor.execute('''
                    INSERT INTO documents (filename, document_type, status, error_message)
                    VALUES (?, ?, ?, ?)
                ''', (file_path, document_type, 'error', str(result.get('error', 'Erreur inconnue'))))
                
                conn.commit()
                
                return {
                    'success': False,
                    'error': result.get('error', 'Erreur inconnue')
                }
                
        except Exception as e:
            # Sauvegarde de l'exception
            cursor.execute('''
                INSERT INTO documents (filename, document_type, status, error_message)
                VALUES (?, ?, ?, ?)
            ''', (file_path, document_type, 'error', str(e)))
            
            conn.commit()
            
            return {
                'success': False,
                'error': str(e)
            }
        finally:
            conn.close()
    
    def call_api(self, file_path: str, yaml_path: str) -> Dict[str, Any]:
        """Appel à l'API ParseMyFile"""
        url = "https://api.parsemyfile.com/api/v1/generate"
        headers = {"X-API-KEY": self.api_key}
        
        with open(file_path, 'rb') as file, open(yaml_path, 'rb') as yaml_file:
            files = {
                'file': (file_path, file, 'application/pdf'),
                'yaml_file': ('config.yaml', yaml_file, 'text/yaml')
            }
            
            response = requests.post(url, headers=headers, files=files)
            
            if response.status_code == 200:
                return response.json()
            else:
                return {
                    'status': 'error',
                    'error': f"Erreur API: {response.status_code} - {response.text}"
                }
    
    def get_document_stats(self) -> Dict[str, Any]:
        """Récupère les statistiques des documents traités"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        
        # Statistiques générales
        cursor.execute('''
            SELECT 
                COUNT(*) as total,
                SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) as success,
                SUM(CASE WHEN status = 'error' THEN 1 ELSE 0 END) as errors,
                AVG(confidence_score) as avg_confidence
            FROM documents
        ''')
        
        stats = cursor.fetchone()
        
        # Statistiques par type de document
        cursor.execute('''
            SELECT document_type, COUNT(*) as count
            FROM documents
            GROUP BY document_type
        ''')
        
        by_type = dict(cursor.fetchall())
        
        conn.close()
        
        return {
            'total_documents': stats[0],
            'successful': stats[1],
            'errors': stats[2],
            'average_confidence': stats[3],
            'by_type': by_type
        }
    
    def search_documents(self, field_name: str, field_value: str) -> List[Dict[str, Any]]:
        """Recherche des documents par valeur de champ"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        
        cursor.execute('''
            SELECT d.*, ef.field_value
            FROM documents d
            JOIN extracted_fields ef ON d.id = ef.document_id
            WHERE ef.field_name = ? AND ef.field_value LIKE ?
        ''', (field_name, f"%{field_value}%"))
        
        results = []
        for row in cursor.fetchall():
            results.append({
                'id': row[0],
                'filename': row[1],
                'document_type': row[2],
                'processed_at': row[3],
                'status': row[4],
                'confidence_score': row[5],
                'field_value': row[7]
            })
        
        conn.close()
        return results

# Utilisation
processor = DocumentProcessor('votre_cle_api')

# Traitement d'un document
result = processor.process_document('facture.pdf', 'facture.yaml', 'facture')

if result['success']:
    print(f"✅ Document traité avec succès (ID: {result['document_id']})")
else:
    print(f"❌ Erreur: {result['error']}")

# Statistiques
stats = processor.get_document_stats()
print(f"Statistiques: {stats['successful']}/{stats['total_documents']} documents traités avec succès")

# Recherche
results = processor.search_documents('client_email', 'jean@example.com')
print(f"Documents trouvés: {len(results)}")

Exemple 5 : API REST personnalisée ​

Code Flask pour API REST ​

python
from flask import Flask, request, jsonify
import requests
import os
from werkzeug.utils import secure_filename
import json

app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024  # 10 MB max

# Configuration
PARSE_MY_FILE_API_KEY = os.getenv('PARSE_MY_FILE_API_KEY')
PARSE_MY_FILE_BASE_URL = 'https://api.parsemyfile.com'

@app.route('/api/process', methods=['POST'])
def process_document():
    """Endpoint pour traiter un document"""
    try:
        # Vérification des fichiers
        if 'file' not in request.files or 'yaml_file' not in request.files:
            return jsonify({'error': 'Fichiers manquants'}), 400
        
        file = request.files['file']
        yaml_file = request.files['yaml_file']
        
        if file.filename == '' or yaml_file.filename == '':
            return jsonify({'error': 'Aucun fichier sélectionné'}), 400
        
        # Appel à l'API ParseMyFile
        files = {
            'file': (secure_filename(file.filename), file, file.content_type),
            'yaml_file': (secure_filename(yaml_file.filename), yaml_file, 'text/yaml')
        }
        
        headers = {'X-API-KEY': PARSE_MY_FILE_API_KEY}
        
        response = requests.post(
            f'{PARSE_MY_FILE_BASE_URL}/api/v1/generate',
            headers=headers,
            files=files
        )
        
        if response.status_code == 200:
            result = response.json()
            return jsonify({
                'success': True,
                'data': result['data'],
                'processing_info': result.get('processing_info', {})
            })
        else:
            return jsonify({
                'success': False,
                'error': f"Erreur API: {response.status_code}",
                'details': response.text
            }), response.status_code
            
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/health', methods=['GET'])
def health_check():
    """Vérification de la santé de l'API"""
    try:
        response = requests.get(f'{PARSE_MY_FILE_BASE_URL}/health')
        
        if response.status_code == 200:
            return jsonify({
                'status': 'healthy',
                'parse_my_file_api': response.json()
            })
        else:
            return jsonify({
                'status': 'unhealthy',
                'parse_my_file_api': 'unavailable'
            }), 503
            
    except Exception as e:
        return jsonify({
            'status': 'unhealthy',
            'error': str(e)
        }), 503

@app.route('/api/templates', methods=['GET'])
def get_templates():
    """Récupère les modèles de configuration disponibles"""
    templates = {
        'facture': {
            'name': 'Facture',
            'description': 'Configuration pour traiter des factures',
            'yaml': '''
fields:
  - name: "numero_facture"
    type: "text"
    position: "top-right"
    required: true
  - name: "montant_total"
    type: "currency"
    position: "bottom-right"
    currency: "EUR"
'''
        },
        'contrat': {
            'name': 'Contrat',
            'description': 'Configuration pour traiter des contrats',
            'yaml': '''
fields:
  - name: "titre_contrat"
    type: "text"
    position: "top-center"
  - name: "parties_contractantes"
    type: "text"
    position: "center"
    multiline: true
'''
        }
    }
    
    return jsonify(templates)

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)

Code HTML pour l'interface utilisateur ​

html
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ParseMyFile - Interface de traitement</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .container { max-width: 800px; margin: 0 auto; }
        .form-group { margin-bottom: 20px; }
        label { display: block; margin-bottom: 5px; font-weight: bold; }
        input[type="file"] { width: 100%; padding: 10px; }
        button { background: #007bff; color: white; padding: 10px 20px; border: none; cursor: pointer; }
        button:hover { background: #0056b3; }
        .result { margin-top: 20px; padding: 20px; background: #f8f9fa; border-radius: 5px; }
        .error { background: #f8d7da; color: #721c24; }
        .success { background: #d4edda; color: #155724; }
    </style>
</head>
<body>
    <div class="container">
        <h1>ParseMyFile - Traitement de documents</h1>
        
        <form id="processForm" enctype="multipart/form-data">
            <div class="form-group">
                <label for="file">Document à traiter :</label>
                <input type="file" id="file" name="file" accept=".pdf,.jpg,.jpeg,.png,.tiff,.bmp" required>
            </div>
            
            <div class="form-group">
                <label for="yaml_file">Configuration YAML :</label>
                <input type="file" id="yaml_file" name="yaml_file" accept=".yaml,.yml" required>
            </div>
            
            <button type="submit">Traiter le document</button>
        </form>
        
        <div id="result" class="result" style="display: none;"></div>
    </div>

    <script>
        document.getElementById('processForm').addEventListener('submit', async (e) => {
            e.preventDefault();
            
            const formData = new FormData();
            const fileInput = document.getElementById('file');
            const yamlInput = document.getElementById('yaml_file');
            const resultDiv = document.getElementById('result');
            
            if (fileInput.files.length === 0 || yamlInput.files.length === 0) {
                showResult('Veuillez sélectionner les deux fichiers', 'error');
                return;
            }
            
            formData.append('file', fileInput.files[0]);
            formData.append('yaml_file', yamlInput.files[0]);
            
            try {
                showResult('Traitement en cours...', 'info');
                
                const response = await fetch('/api/process', {
                    method: 'POST',
                    body: formData
                });
                
                const result = await response.json();
                
                if (result.success) {
                    showResult(`
                        <h3>✅ Document traité avec succès</h3>
                        <h4>Données extraites :</h4>
                        <pre>${JSON.stringify(result.data.extracted_fields, null, 2)}</pre>
                        <h4>Métadonnées :</h4>
                        <pre>${JSON.stringify(result.data.metadata, null, 2)}</pre>
                    `, 'success');
                } else {
                    showResult(`❌ Erreur : ${result.error}`, 'error');
                }
            } catch (error) {
                showResult(`❌ Erreur : ${error.message}`, 'error');
            }
        });
        
        function showResult(message, type) {
            const resultDiv = document.getElementById('result');
            resultDiv.innerHTML = message;
            resultDiv.className = `result ${type}`;
            resultDiv.style.display = 'block';
        }
    </script>
</body>
</html>

Ces exemples avancés montrent comment utiliser l'API ParseMyFile dans des contextes complexes et professionnels, avec validation, intégration base de données, et création d'APIs REST personnalisées.

Documentation ParseMyFile API