Refactor barcode extraction and enhance PDF processing capabilities
- Added extract_barcodes_from_pdf function to read barcodes from PDF files using fitz. - Updated read_datamatrix_zxing to return both the barcode text and its Base64 representation. - Modified main execution block to include PDF barcode extraction. - Improved image loading for better compatibility with zxing. - Updated requirements.txt to include pymupdf for PDF processing.
This commit is contained in:
78
batch_extractor.py
Normal file
78
batch_extractor.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import os
|
||||||
|
import zipfile
|
||||||
|
import tempfile
|
||||||
|
import pandas as pd
|
||||||
|
from read_image import read_datamatrix_zxing, extract_barcodes_from_pdf
|
||||||
|
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
|
||||||
|
|
||||||
|
# Формируем DataFrame из списка кортежей
|
||||||
|
df = pd.DataFrame(data, columns=["Текст", "Base64"])
|
||||||
|
|
||||||
|
# Сохраняем в XLSX, исключая колонку индексов
|
||||||
|
df.to_excel(output_path, index=False, engine='openpyxl')
|
||||||
|
print(f"Данные успешно сохранены в {output_path}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Тестовый пример оркестрации:
|
||||||
|
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
zip_path = "data/0109 черный xxl 720 шт. d46349f7-148a-4301-b6b5-f9a3c70fdf19_begin_offset_2000_number_of_codes_720.zip"
|
||||||
|
#zip_data = extract_eps_from_zip(zip_path)
|
||||||
|
|
||||||
|
pdf_path = 'data/0109, цвет синий, р.L 10шт_b3ba8577-7874-4dfa-a091-e6953fbe0ca7_gtin_04639970975214_quantity_10.pdf'
|
||||||
|
pdf_data = extract_dm_from_pdf(pdf_path)
|
||||||
@@ -407,8 +407,8 @@ if __name__ == "__main__":
|
|||||||
data = read_datamatrix_zxing(image_path)
|
data = read_datamatrix_zxing(image_path)
|
||||||
# Замените своими боевыми Base64 строками
|
# Замените своими боевыми Base64 строками
|
||||||
mock_base64_list = [
|
mock_base64_list = [
|
||||||
read_datamatrix_zxing(image_path),
|
read_datamatrix_zxing(image_path)[1],
|
||||||
read_datamatrix_zxing(image_path)
|
read_datamatrix_zxing(image_path)[1]
|
||||||
]
|
]
|
||||||
|
|
||||||
process_batch(
|
process_batch(
|
||||||
|
|||||||
@@ -1,18 +1,53 @@
|
|||||||
import zxingcpp as zxing_cpp
|
import zxingcpp as zxing_cpp
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import base64
|
import base64
|
||||||
|
import fitz
|
||||||
|
|
||||||
def read_datamatrix_zxing(file_path: str) -> str:
|
|
||||||
|
def extract_barcodes_from_pdf(pdf_path: str):
|
||||||
|
results = []
|
||||||
|
|
||||||
|
doc = fitz.open(pdf_path)
|
||||||
|
|
||||||
|
for page_num in range(len(doc)):
|
||||||
|
page = doc[page_num]
|
||||||
|
|
||||||
|
matrix = fitz.Matrix(2.0, 2.0)
|
||||||
|
pix = page.get_pixmap(matrix=matrix)
|
||||||
|
|
||||||
|
img = Image.frombytes(mode="RGB", size=(pix.width, pix.height), data=pix.samples)
|
||||||
|
|
||||||
|
barcodes = zxing_cpp.read_barcodes(img)
|
||||||
|
|
||||||
|
for barcode in barcodes:
|
||||||
|
b64_string = base64.b64encode(barcode.bytes).decode('ascii')
|
||||||
|
results.append({
|
||||||
|
"page": page_num + 1,
|
||||||
|
"text": barcode.text,
|
||||||
|
"base64": b64_string,
|
||||||
|
"format": barcode.format.name
|
||||||
|
})
|
||||||
|
|
||||||
|
doc.close()
|
||||||
|
return results
|
||||||
|
|
||||||
|
def read_datamatrix_zxing(file_path: str) -> tuple[str, str]:
|
||||||
# Открываем изображение через Pillow
|
# Открываем изображение через Pillow
|
||||||
img = Image.open(file_path)
|
with Image.open(file_path) as img:
|
||||||
|
img.load(scale=10)
|
||||||
|
# Для EPS файлов (и других специфичных форматов) Pillow загружает данные "лениво".
|
||||||
|
# Чтобы избежать ошибки "does not support the buffer protocol" в zxing,
|
||||||
|
# нам нужно принудительно загрузить данные и конвертировать их в понятный цветовой режим,
|
||||||
|
# например, в 'L' (оттенки серого) или 'RGB', который zxing гарантированно поддерживает.
|
||||||
|
img = img.convert("RGB")
|
||||||
|
|
||||||
# Читаем штрих-код.
|
# Читаем штрих-код.
|
||||||
# zxing_cpp.read_barcodes умеет работать напрямую с объектами PIL
|
# zxing_cpp.read_barcodes умеет работать напрямую с объектами PIL
|
||||||
results = zxing_cpp.read_barcodes(img)
|
results = zxing_cpp.read_barcodes(img)
|
||||||
|
|
||||||
if not results:
|
if not results:
|
||||||
print("Коды не найдены на изображении.")
|
print("Коды не найдены на изображении.")
|
||||||
return ''
|
return ('','')
|
||||||
|
|
||||||
# Берем первый найденный код
|
# Берем первый найденный код
|
||||||
result = results[0]
|
result = results[0]
|
||||||
@@ -24,11 +59,13 @@ def read_datamatrix_zxing(file_path: str) -> str:
|
|||||||
# b64encode возвращает bytes, поэтому делаем .decode('ascii') для получения строки
|
# b64encode возвращает bytes, поэтому делаем .decode('ascii') для получения строки
|
||||||
b64_string = base64.b64encode(raw_bytes).decode('ascii')
|
b64_string = base64.b64encode(raw_bytes).decode('ascii')
|
||||||
|
|
||||||
return b64_string
|
return (result.text, b64_string)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
image_path = "data/output.png"
|
image_path = "data/output.png"
|
||||||
data = read_datamatrix_zxing(image_path)
|
text, data = read_datamatrix_zxing(image_path)
|
||||||
|
pdf_read_path = 'data/output_pdfs/Labels_04639970975115.pdf'
|
||||||
|
results = extract_barcodes_from_pdf(pdf_read_path)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
print(f"Успешно прочитано: {data}")
|
print(f"Успешно прочитано: {data}")
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ reportlab
|
|||||||
pandas
|
pandas
|
||||||
treepoem
|
treepoem
|
||||||
openpyxl
|
openpyxl
|
||||||
|
pymupdf
|
||||||
Reference in New Issue
Block a user