Spaces:
Sleeping
Sleeping
Download app.py from jayanth-2005/invoice_extractor: direct link, hf CLI and curl.
- Browser
- Download file 4.27 kB
-
https://huggingface.co/spaces/jayanth-2005/invoice_extractor/resolve/main/app.py
- Command line
-
hf download hf://spaces/jayanth-2005/invoice_extractor/app.py
-
curl -L -o app.py https://huggingface.co/spaces/jayanth-2005/invoice_extractor/resolve/main/app.py
4.27 kB
| import gradio as gr | |
| import pdfplumber | |
| import pandas as pd | |
| import re | |
| def extract_invoices(file): | |
| text = "" | |
| with pdfplumber.open(file.name) as pdf: | |
| for page in pdf.pages: | |
| t = page.extract_text() | |
| if t: | |
| text += t + "\n" | |
| # ---------------- INVOICE NUMBER ---------------- # | |
| invoice_pattern = r'(?:Invoice\s*No|Invoice\s*Number|InvoiceNo|Inv\.?\s*No|Invoice\s*#|Bill\s*No|Bill\s*Number|Bill\s*of\s*Supply\s*No|Bill\s*of\s*Supply\s*Number)\s*[:#\-]?\s*([A-Za-z0-9\-\/]+)' | |
| invoice_matches = list(re.finditer(invoice_pattern, text, re.IGNORECASE)) | |
| rows = [] | |
| processed_invoices = set() | |
| # ---------------- GSTIN PATTERN ---------------- # | |
| gstin_pattern = r'\b\d{2}[A-Z]{5}\d{4}[A-Z][A-Z\d]Z[A-Z\d]\b' | |
| for i, match in enumerate(invoice_matches): | |
| invoice_number = match.group(1) | |
| if not re.search(r'\d', invoice_number) or len(invoice_number) < 4: | |
| continue | |
| if invoice_number in processed_invoices: | |
| continue | |
| processed_invoices.add(invoice_number) | |
| start = match.start() | |
| if i + 1 < len(invoice_matches): | |
| end = invoice_matches[i + 1].start() | |
| else: | |
| end = len(text) | |
| block = text[start:end] | |
| # ---------------- DATE EXTRACTION ---------------- # | |
| date_pattern = r'(?:\d{1,2}[\/\-.]\d{1,2}[\/\-.]\d{2,4}|\d{4}[\/\-.]\d{1,2}[\/\-.]\d{1,2}|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\s+\d{1,2},?\s*\d{2,4}|\d{1,2}\s+(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\s*\d{2,4})' | |
| date_match = re.search( | |
| r'(Invoice\s*Date|Bill\s*Date|Date\s*of\s*Invoice)\s*[:\-]?\s*\n?\s*(' + date_pattern + ')', | |
| block, | |
| re.IGNORECASE | |
| ) | |
| if date_match: | |
| invoice_date = date_match.group(2) | |
| else: | |
| fallback_date = re.search(date_pattern, block, re.IGNORECASE) | |
| invoice_date = fallback_date.group(0) if fallback_date else "" | |
| # ---------------- GSTIN EXTRACTION (BEFORE + AFTER) ---------------- # | |
| # Look BEFORE invoice (important fix) | |
| pre_start = max(0, start - 500) | |
| pre_block = text[pre_start:start] | |
| # Combine both | |
| search_area = pre_block + block | |
| # Try keyword-based extraction | |
| gstin_match = re.search( | |
| r'(GSTIN|GST\s*No|Supplier\s*GSTIN|Vendor\s*GSTIN)\s*[:\-]?\s*(' + gstin_pattern + ')', | |
| search_area, | |
| re.IGNORECASE | |
| ) | |
| if gstin_match: | |
| gstin = gstin_match.group(2) | |
| else: | |
| # fallback: get all GSTINs | |
| gstin_list = re.findall(gstin_pattern, search_area, re.IGNORECASE) | |
| if len(gstin_list) > 0: | |
| gstin = gstin_list[0] # usually seller GSTIN | |
| else: | |
| gstin = "" | |
| # ---------------- FLOAT DETECTION ---------------- # | |
| float_pattern = r'(?:\d{1,3}(?:,\d{3})+|\d{1,2}(?:,\d{2})+(?:,\d{3}))\.\d{2}|\d+\.\d{2}' | |
| float_numbers = re.findall(float_pattern, block) | |
| float_numbers = [float(x.replace(",", "")) for x in float_numbers] | |
| total_amount = max(float_numbers) if float_numbers else "" | |
| # ---------------- ROW ---------------- # | |
| row = { | |
| "Invoice Number": invoice_number, | |
| "Invoice Date": invoice_date, | |
| "GSTIN": gstin, | |
| "Narration": "Invoice processed", | |
| "Debit Account": "Expense", | |
| "Credit Account": "Vendor", | |
| "Total Amount": total_amount | |
| } | |
| rows.append(row) | |
| df = pd.DataFrame(rows) | |
| excel_file = "invoice_output.xlsx" | |
| df.to_excel(excel_file, index=False) | |
| return df, excel_file | |
| # ---------------- GRADIO UI ---------------- # | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# Multiple Invoice PDF → Excel Extractor") | |
| file_input = gr.File(label="Upload Invoice PDF") | |
| extract_btn = gr.Button("Extract Invoices") | |
| output_table = gr.Dataframe(label="Extracted Invoice Data") | |
| download_file = gr.File(label="Download Excel") | |
| extract_btn.click( | |
| extract_invoices, | |
| inputs=file_input, | |
| outputs=[output_table, download_file] | |
| ) | |
| demo.launch() |