From 0151a380ea018a8d8cc464450d95159fe290d2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Thu, 18 Jun 2026 08:21:42 +0400 Subject: [PATCH] =?UTF-8?q?v3.1.3:=20pdfplumber=20=E2=80=94=20=D1=82=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=BA=D0=BE=20=D1=80=D0=B0=D0=BC=D0=BA=D0=B8,=20?= =?UTF-8?q?=D1=84=D0=B8=D0=BB=D1=8C=D1=82=D1=80=2030%=20=D0=B7=D0=B0=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site/parser.py | 65 ++++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/site/parser.py b/site/parser.py index 5c2beab..a22154b 100644 --- a/site/parser.py +++ b/site/parser.py @@ -125,9 +125,10 @@ def _parse_pdf(file_bytes: bytes) -> dict: """ Извлечь текст и таблицы из PDF через pdfplumber. - Таблицы: пробуем два режима — с рамками (lines) и без (text). - Отбрасываем полностью пустые таблицы. - Текст: извлекаем построчно, сохраняем номера страниц. + Таблицы: только с видимыми рамками (lines). Безрамковые (text) + дают слишком много ложных срабатываний — не используем. + Отбрасываем таблицы где >50% ячеек пусты или где все ячейки + содержат фрагменты одной строки текста. """ result = {"elements": [], "errors": []} try: @@ -149,48 +150,56 @@ 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): + if tbl and _table_has_content(tbl, min_fill_ratio=0.3): 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): - result["elements"].append({ - "type": "table", - "rows": tbl, - "page": pn, - }) - except Exception as e: result["errors"].append(f"pdfplumber: {e}") 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 — без фильтра) """ + if not tbl or not tbl[0]: + return False + + total = 0 + filled = 0 + all_text = "" + for row in tbl: - if row: - for cell in row: - if cell and str(cell).strip(): - return True - return False + 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 ──