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