v3.1.3: pdfplumber — только рамки, фильтр 30% заполнения

This commit is contained in:
2026-06-18 08:21:42 +04:00
parent 2b851505c3
commit 0151a380ea
+37 -28
View File
@@ -125,9 +125,10 @@ def _parse_pdf(file_bytes: bytes) -> dict:
"""
Извлечь текст и таблицы из PDF через pdfplumber.
Таблицы: пробуем два режима — с рамками (lines) и без (text).
Отбрасываем полностью пустые таблицы.
Текст: извлекаем построчно, сохраняем номера страниц.
Таблицы: только с видимыми рамками (lines). Безрамковые (text)
дают слишком много ложных срабатываний — не используем.
Отбрасываем таблицы где >50% ячеек пусты или где все ячейки
содержат фрагменты одной строки текста.
"""
result = {"elements": [], "errors": []}
try:
@@ -149,26 +150,11 @@ def _parse_pdf(file_bytes: bytes) -> dict:
"page": pn,
})
# ── Таблицы: с рамками (lines) ──
# ── Таблицы: только с рамками ──
tables = page.extract_tables()
if tables:
for tbl in tables:
if tbl and _table_has_content(tbl):
result["elements"].append({
"type": "table",
"rows": tbl,
"page": pn,
})
# ── Таблицы: без рамок (text) — если lines ничего не дал ──
if not tables:
tbl_text = page.extract_tables({
"vertical_strategy": "text",
"horizontal_strategy": "text",
})
if tbl_text:
for tbl in tbl_text:
if tbl and _table_has_content(tbl):
if tbl and _table_has_content(tbl, min_fill_ratio=0.3):
result["elements"].append({
"type": "table",
"rows": tbl,
@@ -180,18 +166,41 @@ def _parse_pdf(file_bytes: bytes) -> dict:
return result
def _table_has_content(tbl: list) -> bool:
def _table_has_content(tbl: list, min_fill_ratio: float = 0.0) -> bool:
"""
Проверить что в таблице есть хоть одна непустая ячейка.
Игнорирует None и пустые строки.
Проверить что таблица содержит осмысленные данные.
Фильтры:
- Хотя бы одна непустая ячейка
- Не менее min_fill_ratio ячеек заполнены (по умолчанию 0 — без фильтра)
"""
for row in tbl:
if row:
for cell in row:
if cell and str(cell).strip():
return True
if not tbl or not tbl[0]:
return False
total = 0
filled = 0
all_text = ""
for row in tbl:
if not row:
continue
for cell in row:
total += 1
cell_str = str(cell).strip() if cell else ""
if cell_str:
filled += 1
all_text += " " + cell_str
if filled == 0:
return False
# Фильтр по доле заполненных ячеек
if min_fill_ratio > 0 and total > 0:
if filled / total < min_fill_ratio:
return False
return True
# ── ZIP ──