pdf-extractor / app.py
kryman27's picture
Update app.py
7489f6d verified
import gradio as gr
import pdfplumber
import re
from transformers import LayoutLMForTokenClassification, AutoTokenizer
import torch
model_name = "kryman27/layoutlmv3-finetuned"
model = LayoutLMForTokenClassification.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# Wzorce regex dla nowych p贸l
nip_pattern = re.compile(r'\b(?:PL\s?)?\d{10}\b')
invoice_number_pattern = re.compile(r'Faktura\s*(?:VAT)?\s*(?:nr\.?|#)\s*([\w\-/]+)', re.IGNORECASE)
sale_date_pattern = re.compile(r'Data\s+wystawienia[:\s]*([\d]{2}[.\-/][\d]{2}[.\-/][\d]{4})', re.IGNORECASE)
delivery_date_pattern = re.compile(r'Data\s+dostawy[:\s]*([\d]{2}[.\-/][\d]{2}[.\-/][\d]{4})', re.IGNORECASE)
payment_date_pattern = re.compile(r'(?:Termin\s+p艂atno艣ci|Data\s+p艂atno艣ci)[:\s]*([\d]{2}[.\-/][\d]{2}[.\-/][\d]{4})', re.IGNORECASE)
order_number_pattern = re.compile(r'Zam贸wienie\s*Nr[:\s]*([\w\-/]+)', re.IGNORECASE)
order_date_pattern = re.compile(r'Data\s+zam贸wienia[:\s]*([\d]{2}[.\-/][\d]{2}[.\-/][\d]{4})', re.IGNORECASE)
sale_order_pattern = re.compile(r'Zlecenie\s+sprzeda偶y\s*Nr[:\s]*([\w\-/]+)', re.IGNORECASE)
payment_amount_pattern = re.compile(r'(?:Kwota\s+zap艂acona)[:\s]*([\d.,]+)', re.IGNORECASE)
payment_method_pattern = re.compile(r'(?:Forma\s+p艂atno艣ci)[:\s]*([\w/]+)', re.IGNORECASE)
def extract_section(text, section_title):
pattern = re.compile(rf'{section_title}:(.*?)(?=\n\S|$)', re.IGNORECASE | re.DOTALL)
match = pattern.search(text)
return match.group(1).strip() if match else None
def extract_invoice_data(pdf_file):
with pdfplumber.open(pdf_file) as pdf:
full_text = "\n".join(page.extract_text() for page in pdf.pages if page.extract_text())
# Wyodr臋bnienie sekcji na podstawie tytu艂贸w
sprzedawca_section = extract_section(full_text, "Sprzedawca")
nabywca_section = extract_section(full_text, "Nabywca")
sprzedawca = {}
nabywca = {}
faktura = {}
platnosc = {}
pozycje = [] # Do implementacji ekstrakcji tabelarycznej
podsumowanie = {}
# Ekstrakcja danych Sprzedawcy
if sprzedawca_section:
lines = sprzedawca_section.splitlines()
sprzedawca['Nazwa'] = lines[0].strip() if lines else "Nie znaleziono"
nip_match = nip_pattern.search(sprzedawca_section)
sprzedawca['NIP'] = nip_match.group() if nip_match else "Nie znaleziono"
bdo_match = re.search(r'BDO[:\s]*([\w\d]+)', sprzedawca_section, re.IGNORECASE)
sprzedawca['Numer Rejestracyjny BDO'] = bdo_match.group(1) if bdo_match else "Nie znaleziono"
sprzedawca['Adres'] = lines[1].strip() if len(lines) > 1 else "Nie znaleziono"
telefon_match = re.search(r'tel\.?[:\s]*([\+\d\s()-]+)', sprzedawca_section, re.IGNORECASE)
sprzedawca['Telefon'] = telefon_match.group(1).strip() if telefon_match else "Nie znaleziono"
fax_match = re.search(r'fax\.?[:\s]*([\+\d\s()-]+)', sprzedawca_section, re.IGNORECASE)
sprzedawca['Fax'] = fax_match.group(1).strip() if fax_match else "Nie znaleziono"
else:
sprzedawca = {
"Nazwa": "Nie znaleziono",
"NIP": "Nie znaleziono",
"Numer Rejestracyjny BDO": "Nie znaleziono",
"Adres": "Nie znaleziono",
"Telefon": "Nie znaleziono",
"Fax": "Nie znaleziono"
}
# Ekstrakcja danych Nabywcy
if nabywca_section:
lines = nabywca_section.splitlines()
nabywca['Nazwa'] = lines[0].strip() if lines else "Nie znaleziono"
nip_match = nip_pattern.search(nabywca_section)
nabywca['NIP'] = nip_match.group() if nip_match else "Nie podano"
nabywca['Adres'] = lines[1].strip() if len(lines) > 1 else "Nie znaleziono"
klient_match = re.search(r'Nr\s+Klienta[:\s]*([\w\d]+)', nabywca_section, re.IGNORECASE)
nabywca['Nr Klienta'] = klient_match.group(1) if klient_match else "Nie znaleziono"
else:
nabywca = {
"Nazwa": "Nie znaleziono",
"NIP": "Nie podano",
"Adres": "Nie znaleziono",
"Nr Klienta": "Nie znaleziono"
}
# Ekstrakcja danych faktury
invoice_number_match = invoice_number_pattern.search(full_text)
faktura['Numer'] = invoice_number_match.group(1) if invoice_number_match else "Nie znaleziono"
sale_date_match = sale_date_pattern.search(full_text)
faktura['Data Wystawienia'] = sale_date_match.group(1) if sale_date_match else "Nie znaleziono"
delivery_date_match = delivery_date_pattern.search(full_text)
faktura['Data Dostawy'] = delivery_date_match.group(1) if delivery_date_match else "Nie znaleziono"
order_number_match = order_number_pattern.search(full_text)
faktura['Zam贸wienie Nr'] = order_number_match.group(1) if order_number_match else "Nie znaleziono"
order_date_match = order_date_pattern.search(full_text)
faktura['Data Zam贸wienia'] = order_date_match.group(1) if order_date_match else "Nie znaleziono"
sale_order_match = sale_order_pattern.search(full_text)
faktura['Zlecenie Sprzeda偶y Nr'] = sale_order_match.group(1) if sale_order_match else "Nie znaleziono"
# Ekstrakcja danych p艂atno艣ci
payment_date_match = payment_date_pattern.search(full_text)
platnosc['Termin Zap艂aty'] = payment_date_match.group(1) if payment_date_match else "Nie znaleziono"
payment_method_match = payment_method_pattern.search(full_text)
platnosc['Forma Zap艂aty'] = payment_method_match.group(1) if payment_method_match else "Nie znaleziono"
payment_amount_match = payment_amount_pattern.search(full_text)
platnosc['Kwota Zap艂acona'] = float(payment_amount_match.group(1).replace(',', '.')) if payment_amount_match else "Nie znaleziono"
# Ekstrakcja podsumowania (przyk艂adowo)
podsumowanie_match = re.search(r'Razem[:\s]*([\d.,]+)', full_text)
podsumowanie['Suma Brutto'] = float(podsumowanie_match.group(1).replace(',', '.')) if podsumowanie_match else "Nie znaleziono"
result = {
"Sprzedawca": sprzedawca,
"Nabywca": nabywca,
"Faktura": faktura,
"P艂atno艣膰": platnosc,
"Pozycje": pozycje,
"Podsumowanie": podsumowanie
}
return result
iface = gr.Interface(
fn=extract_invoice_data,
inputs=gr.File(label="Wybierz plik PDF"),
outputs="json",
title="Ekstrakcja danych z faktury",
description="Prze艣lij plik PDF, a narz臋dzie zwr贸ci szczeg贸艂owe dane faktury."
)
#UI start
if __name__ == "__main__":
iface.launch()