From 4a068ede5929736698dadab29883e2f9f3b187a8 Mon Sep 17 00:00:00 2001 From: zk Date: Mon, 27 Jul 2026 14:35:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=81=E8=A3=85=E6=B5=81=E7=A8=8B=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/tool/page_extract.py | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 app/tool/page_extract.py diff --git a/app/tool/page_extract.py b/app/tool/page_extract.py new file mode 100644 index 0000000..a20132d --- /dev/null +++ b/app/tool/page_extract.py @@ -0,0 +1,80 @@ +"""公告页内容提取工具。 + +流程: +1. 打开公告页,取 `#page-content` 的正文文字与图片地址; +2. 图片地址下载成字节流; +3. 每张图片 OCR 提取文字; +4. 每张图片检测二维码,有则解出内容; +5. 正文 + 图片文字 + 二维码内容合并为一段字符串。 + +图片下载、OCR、二维码识别都允许失败,单张出错只记日志并跳过。 +""" + +from __future__ import annotations + +from app.core.logger import log +from app.tool.browser import open_page, query +from app.tool.cv import has_qr +from app.tool.image_download import download_image +from app.tool.ocr import ocr +from app.tool.qr_decode import decode_qr + +# 正文容器选择器 +_SELECTOR = "#page-content" + +# 打开页面后的等待时间(毫秒),等懒加载图片就位 +_WAIT_MS = 3000 + + +def extract_page(url: str) -> str: + """提取公告页的全部文字信息。 + + Args: + url: 公告页地址。 + + Returns: + 正文文字、图片 OCR 文字、二维码内容合并后的字符串; + 页面打开失败时返回空字符串。 + """ + if not url or not url.startswith("http"): + return "" + + try: + page_id = open_page(url, _WAIT_MS) + nodes = query(page_id, _SELECTOR) + except Exception as exc: + log.error(f"公告页打开失败: {url} | {exc}") + return "" + + texts: list[str] = [] + image_urls: list[str] = [] + + for node in nodes: + if node.text: + texts.append(node.text) + image_urls.extend(node.image_urls) + + for image_url in image_urls: + image = download_image(image_url) + if image is None: + continue + + # OCR 提取图片文字 + try: + image_text = ocr(image) + except Exception as exc: + log.warning(f"图片 OCR 失败: {image_url} | {exc}") + else: + if image_text: + texts.append(image_text) + + # 有二维码则解出内容 + try: + if has_qr(image): + texts.extend(decode_qr(image)) + except Exception as exc: + log.warning(f"二维码识别失败: {image_url} | {exc}") + + content = "\n".join(text for text in texts if text) + log.info(f"公告页提取完成(图片 {len(image_urls)} 张,文本 {len(content)} 字): {url}") + return content