- Implemented `get_filenames` command in `batch_extractor.py` to extract file names from a specified directory and generate a dated hash for each file. - Updated README.md with instructions for using the new command. - Enhanced PDF generation in `build_pdf.py` by modifying file naming conventions to include article and size. - Added example PowerShell script for batch processing tasks. - Introduced new example Excel file for user reference.
156 lines
7.5 KiB
Python
156 lines
7.5 KiB
Python
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
|
||
import hashlib
|
||
import random
|
||
from datetime import datetime
|
||
|
||
def get_dated_hash(text: str) -> str:
|
||
"""
|
||
Генерирует хэш с префиксом даты в формате ГГ_ММ_ДД.
|
||
Пример вывода: 26_02_21_d6f7a6b2c1
|
||
"""
|
||
# 1. Получаем текущую дату в формате ГГ_ММ_ДД (например, 26_02_21)
|
||
date_prefix = datetime.now().strftime("%y_%m_%d")
|
||
text = f"{text}_{random.randint(0,100000000)}"
|
||
# 2. Генерируем хэш-часть (SHA-256, 10 символов)
|
||
hash_part = hashlib.sha256(text.encode()).hexdigest()[:10]
|
||
|
||
# 3. Соединяем через нижнее подчеркивание
|
||
return f"{date_prefix}_{hash_part}"
|
||
|
||
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")
|
||
|
||
@cli.command(help="Подготавливает excel с именами файлов в директории")
|
||
@click.argument('input_dir', type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path))
|
||
@click.argument('output_xlsx', type=click.Path(dir_okay=False, writable=True, path_type=Path))
|
||
def get_filenames(input_dir: Path, output_xlsx: Path):
|
||
# Используем .glob('*') или .iterdir()
|
||
filenames = [f.name for f in input_dir.iterdir() if f.is_file()]
|
||
filenames_with_hashes = [(get_dated_hash(f), f) for f in filenames]
|
||
save_to_excel(filenames_with_hashes, str(output_xlsx))
|
||
|
||
|
||
if __name__ == "__main__":
|
||
cli()
|