import os import zipfile import tempfile import pandas as pd from read_image import read_datamatrix_zxing, extract_barcodes_from_pdf from pathlib import Path import click import render_eps def extract_eps_from_zip(zip_path: str) -> list: """ Распаковывает zip-архив, ищет eps-файлы, прогоняет их через read_datamatrix_zxing. Возвращает список кортежей (текст, base64). """ results = [] # Используем временную директорию для безопасного извлечения файлов with tempfile.TemporaryDirectory() as tmpdir: with zipfile.ZipFile(zip_path, 'r') as zf: # Отбираем только файлы с расширением .eps (независимо от регистра) eps_files = [f for f in zf.namelist() if f.lower().endswith('.eps')] for eps_file in eps_files: # Извлекаем конкретный файл во временную директорию extracted_path = zf.extract(eps_file, path=tmpdir) # Прогоняем через функцию чтения code_data = read_datamatrix_zxing(extracted_path) # Убеждаемся, что код найден и вернулся ожидаемый кортеж if code_data and isinstance(code_data, tuple): results.append(code_data) return results def extract_dm_from_pdf(pdf_path: str) -> list: """ Использует extract_barcodes_from_pdf для получения кодов из многостраничного PDF. Возвращает список кортежей (текст, base64). """ results = [] # Получаем список словарей с информацией о кодах barcodes_info = extract_barcodes_from_pdf(pdf_path) for info in barcodes_info: # Извлекаем текст и base64 по ключам text_val = info.get("text", "") base64_val = info.get("base64", "") results.append((text_val, base64_val)) return results def save_to_excel(data: list, output_path: str): """ Принимает список кортежей (текст, base64) и сохраняет в XLSX файл. """ if not data: print("Нет данных для сохранения в Excel.") return # Преобразуем путь в объект Path для удобной работы с файловой системой path_obj = Path(output_path) # Создаем родительскую директорию (вместе со всеми промежуточными), если ее нет # Метод parent возвращает путь к папке, в которой должен лежать файл # exist_ok=True гарантирует отсутствие ошибки, если папка уже существует path_obj.parent.mkdir(parents=True, exist_ok=True) # Формируем DataFrame из списка кортежей df = pd.DataFrame(data, columns=["Текст", "Base64"]) # Сохраняем в XLSX, исключая колонку индексов df.to_excel(output_path, index=False, engine='openpyxl') print(f"Данные успешно сохранены в {output_path}") @click.group(help="Утилита для массового извлечения DataMatrix кодов и сохранения их в Excel.") def cli(): """Основная группа команд для CLI.""" pass @cli.command(help="Извлекает коды из EPS-файлов внутри ZIP-архива.") @click.argument('input_zip', type=click.Path(exists=True, dir_okay=False, path_type=Path)) @click.argument('output_xlsx', type=click.Path(dir_okay=False, writable=True, path_type=Path)) def from_zip(input_zip: Path, output_xlsx: Path): """ Пакетная обработка ZIP-архива. INPUT_ZIP: Путь к исходному .zip файлу с EPS-этикетками. OUTPUT_XLSX: Путь для сохранения результата (например, result.xlsx). """ click.echo(f"Начинаю обработку архива: {input_zip.name}") try: data = extract_eps_from_zip(str(input_zip)) if data: save_to_excel(data, str(output_xlsx)) click.secho(f"Успех! Найдено кодов: {len(data)}. Файл сохранен: {output_xlsx.name}", fg="green") else: click.secho("Внимание: в архиве не найдено читаемых кодов.", fg="yellow") except Exception as e: click.secho(f"Ошибка при обработке ZIP: {e}", fg="red") @cli.command(help="Извлекает коды со всех страниц PDF-документа.") @click.argument('input_pdf', type=click.Path(exists=True, dir_okay=False, path_type=Path)) @click.argument('output_xlsx', type=click.Path(dir_okay=False, writable=True, path_type=Path)) def from_pdf(input_pdf: Path, output_xlsx: Path): """ Пакетная обработка PDF-документа. INPUT_PDF: Путь к исходному многостраничному .pdf файлу. OUTPUT_XLSX: Путь для сохранения результата (например, result.xlsx). """ click.echo(f"Начинаю обработку PDF-документа: {input_pdf.name}") try: data = extract_dm_from_pdf(str(input_pdf)) if data: save_to_excel(data, str(output_xlsx)) click.secho(f"Успех! Найдено кодов: {len(data)}. Файл сохранен: {output_xlsx.name}", fg="green") else: click.secho("Внимание: в PDF-файле не найдено читаемых кодов.", fg="yellow") except Exception as e: click.secho(f"Ошибка при обработке PDF: {e}", fg="red") if __name__ == "__main__": cli()