v3.1.6: text strategy только при отсутствии рамок, мин 3 колонки
This commit is contained in:
+26
-7
@@ -150,8 +150,9 @@ def _parse_pdf(file_bytes: bytes) -> dict:
|
|||||||
"page": pn,
|
"page": pn,
|
||||||
})
|
})
|
||||||
|
|
||||||
# ── Таблицы: только с рамками ──
|
# ── Таблицы: с рамками + без рамок ──
|
||||||
tables = page.extract_tables()
|
tables = page.extract_tables()
|
||||||
|
found_any = False
|
||||||
if tables:
|
if tables:
|
||||||
for tbl in tables:
|
for tbl in tables:
|
||||||
if tbl and _table_has_content(tbl):
|
if tbl and _table_has_content(tbl):
|
||||||
@@ -160,29 +161,49 @@ def _parse_pdf(file_bytes: bytes) -> dict:
|
|||||||
"rows": tbl,
|
"rows": tbl,
|
||||||
"page": pn,
|
"page": pn,
|
||||||
})
|
})
|
||||||
|
found_any = True
|
||||||
|
|
||||||
|
# Если рамок нет — пробуем text strategy с жёстким фильтром
|
||||||
|
if not found_any:
|
||||||
|
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, min_cols=3):
|
||||||
|
result["elements"].append({
|
||||||
|
"type": "table",
|
||||||
|
"rows": tbl,
|
||||||
|
"page": pn,
|
||||||
|
})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result["errors"].append(f"pdfplumber: {e}")
|
result["errors"].append(f"pdfplumber: {e}")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _table_has_content(tbl: list, min_fill_ratio: float = 0.0) -> bool:
|
def _table_has_content(tbl: list, min_fill_ratio: float = 0.0, min_cols: int = 0) -> bool:
|
||||||
"""
|
"""
|
||||||
Проверить что таблица содержит осмысленные ТАБЛИЧНЫЕ данные.
|
Проверить что таблица содержит осмысленные ТАБЛИЧНЫЕ данные.
|
||||||
|
|
||||||
Отбрасываем:
|
Отбрасываем:
|
||||||
- Полностью пустые
|
- Полностью пустые
|
||||||
- Менее 2 строк (обычно это текст, не таблица)
|
- Менее 2 строк
|
||||||
- Менее 4 заполненных ячеек (слишком мало для таблицы)
|
- Менее min_cols колонок (если задано)
|
||||||
|
- Менее 4 заполненных ячеек
|
||||||
- Менее 40% ячеек заполнены
|
- Менее 40% ячеек заполнены
|
||||||
"""
|
"""
|
||||||
if not tbl or not tbl[0]:
|
if not tbl or not tbl[0]:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Одна строка — не таблица, а текст
|
|
||||||
if len(tbl) <= 1:
|
if len(tbl) <= 1:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Проверить минимальное число колонок
|
||||||
|
if min_cols > 0 and len(tbl[0]) < min_cols:
|
||||||
|
return False
|
||||||
|
|
||||||
total = 0
|
total = 0
|
||||||
filled = 0
|
filled = 0
|
||||||
|
|
||||||
@@ -195,11 +216,9 @@ def _table_has_content(tbl: list, min_fill_ratio: float = 0.0) -> bool:
|
|||||||
if cell_str:
|
if cell_str:
|
||||||
filled += 1
|
filled += 1
|
||||||
|
|
||||||
# Минимум 4 заполненных ячейки
|
|
||||||
if filled < 4:
|
if filled < 4:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Не менее 40% ячеек должны быть заполнены
|
|
||||||
if total > 0 and filled / total < 0.4:
|
if total > 0 and filled / total < 0.4:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user