| import re |
| import io |
| import pytesseract |
| from PIL import Image |
| from pdf2image import convert_from_bytes |
| from typing import Dict, Any |
|
|
| |
| RE_DATE = re.compile(r"(\d{1,2}[\/\.-]\d{1,2}[\/\.-]\d{2,4})") |
| RE_TOTAL = re.compile(r"(?:total|montant|ttc|à payer).*?(\d+[\.,]\d{2})", re.IGNORECASE) |
| RE_TVA = re.compile(r"(\d{1,2}(?:[\.,]\d)?)\s*%", re.IGNORECASE) |
| RE_PAYMENT = re.compile(r"(?:payé par|moyen de paiement|paiement)\s*[:\-]?\s*(.*)", re.IGNORECASE) |
| RE_VENDEUR_LABEL = re.compile(r"(?:vendeur|fournisseur|vendor)\s*[:\-]?\s*(.*)", re.IGNORECASE) |
|
|
| def ocr_document(file_bytes: bytes, is_pdf: bool): |
| """Étape 1 : Extraction du texte brut via Tesseract [cite: 19, 21]""" |
| if is_pdf: |
| |
| images = convert_from_bytes(file_bytes) |
| else: |
| images = [Image.open(io.BytesIO(file_bytes))] |
|
|
| full_text = "" |
| for img in images: |
| full_text += pytesseract.image_to_string(img, lang="fra+eng") + "\n" |
| |
| return full_text, images |
|
|
| def extract_fields(text: str) -> Dict[str, Any]: |
| """Étape 2 : Parsing des informations clés [cite: 22, 24, 26]""" |
| lines = [l.strip() for l in text.split('\n') if len(l.strip()) > 2] |
| |
| |
| supplier = None |
| label_match = RE_VENDEUR_LABEL.search(text) |
| if label_match and label_match.group(1).strip(): |
| supplier = label_match.group(1).strip() |
| |
| if not supplier: |
| |
| for line in lines: |
| if "page" not in line.lower() and not any(char.isdigit() for char in line[:3]): |
| supplier = line |
| break |
|
|
| |
| total_matches = RE_TOTAL.findall(text) |
| total_amount = float(total_matches[-1].replace(",", ".")) if total_matches else None |
|
|
| |
| tva_match = RE_TVA.search(text) |
| tva_rate = tva_match.group(1).replace(",", ".") + "%" if tva_match else None |
|
|
| |
| payment_match = RE_PAYMENT.search(text) |
| payment_method = None |
| if payment_match: |
| raw_p = payment_match.group(1).strip() |
| |
| payment_method = re.sub(r'[\d\*\.]+', '', raw_p).strip() |
|
|
| |
| date_match = RE_DATE.search(text) |
| invoice_date = date_match.group(1) if date_match else None |
|
|
| return { |
| "nom_marchand": supplier, |
| "prix_total": total_amount, |
| "tva_pourcentage": tva_rate, |
| "moyen_paiement": payment_method, |
| "invoice_date": invoice_date |
| } |