camelot-pg / src /app /parser.py
morisono
Upload folder using huggingface_hub
f92f684 verified
import sys
import camelot
import polars as pl
import signal
import argparse
from rich.console import Console
from rich.progress import track
console = Console()
class PDFTableParser:
def __init__(self, input_files, output_files, delimiter, edge_tol, row_tol, pages):
self.input_files = input_files
self.output_files = output_files
self.delimiter = delimiter
self.edge_tol = edge_tol
self.row_tol = row_tol
self.pages = pages
def read_tables(self, file_name):
try:
console.print(f"Reading tables from {file_name}...")
tables = camelot.read_pdf(file_name, flavor='stream', edge_tol=self.edge_tol, row_tol=self.row_tol, pages=self.pages)
console.print(f"Found {len(tables)} tables in {file_name}.")
return tables
except Exception as e:
console.print(f"[red]Error reading {file_name}: {e}[/red]")
return None
def save_tables_as_csv(self, tables, output_file):
try:
console.print(f"Saving tables to {output_file}...")
df = pl.concat([pl.DataFrame(table.df) for table in tables])
df.write_csv(output_file, separator=self.delimiter)
console.print(f"Saved tables to {output_file}.")
except Exception as e:
console.print(f"[red]Error saving to {output_file}: {e}[/red]")
def estimate_processing_time(self, file_name):
try:
with open(file_name, 'rb') as f:
content = f.read().decode('utf-8', errors='ignore')
pages = content.count('\n')
words = len(content.split())
chars = len(content)
estimated_time = (lines / 1000) + (words / 1000) + (chars / 1000)
console.print(f"Estimated processing time for {file_name}: {estimated_time:.2f} seconds.")
return estimated_time
except Exception as e:
console.print(f"[red]Error estimating processing time for {file_name}: {e}[/red]")
return 0
def process_files(self):
for input_file, output_file in track(zip(self.input_files, self.output_files), description="Processing files"):
self.estimate_processing_time(input_file)
tables = self.read_tables(input_file)
if tables:
self.save_tables_as_csv(tables, output_file)
def handle_signal(signum, frame):
console.print("\n[red]Process interrupted.[/red]")
sys.exit(1)
if __name__ == "__main__":
signal.signal(signal.SIGINT, handle_signal)
signal.signal(signal.SIGTERM, handle_signal)
parser = argparse.ArgumentParser(description="PDF Table Parser")
parser.add_argument("input_files", nargs='+', help="List of input PDF files")
parser.add_argument("output_files", nargs='+', help="List of output CSV files")
parser.add_argument("--delimiter", default=',', help="Output file delimiter (default: ,)")
parser.add_argument("--edge_tol", type=int, default=50, help="Tolerance parameter used to specify the distance between text and table edges (default: 50)")
parser.add_argument("--row_tol", type=int, default=50, help="Tolerance parameter used to specify the distance between table rows (default: 50)")
parser.add_argument("--pages", type=str, default='all', help="Pages you can pass the number of pages to process. (default: all)")
parser.add_argument("--webui", action='store_true', help="Launch the web UI")
args = parser.parse_args()
if len(args.input_files) != len(args.output_files):
console.print("[red]The number of input files and output files must match.[/red]")
sys.exit(1)
if args.webui:
webui = WebUI()
webui.run()
else:
main(args)