Selaa lähdekoodia

pdf_converter_v2: 默认 API 指向 127.0.0.1

同时增强去水印流程:PDF 转图片支持在缺少 poppler 时回退到 pypdfium2。
何文松 3 viikkoa sitten
vanhempi
commit
a2f3e1c918

+ 6 - 6
pdf_converter_v2/README.md

@@ -4,7 +4,7 @@ PDF转换工具 v2版本 - 使用新的API接口进行PDF转换
 
 ## 主要特性
 
-v2版本通过调用新的API接口(`http://192.168.2.3:8000/file_parse`)进行PDF转换,API返回zip文件,然后从zip中提取md文件进行原有的json解析逻辑。
+v2版本通过调用新的API接口(`http://127.0.0.1:5282/file_parse`)进行PDF转换,API返回zip文件,然后从zip中提取md文件进行原有的json解析逻辑。
 
 ## 主要改进
 
@@ -32,7 +32,7 @@ python -m pdf_converter_v2 input.pdf -o ./output
 python -m pdf_converter_v2 input.pdf --output-json
 
 # 自定义API服务器地址
-python -m pdf_converter_v2 input.pdf --url http://192.168.2.3:8000
+python -m pdf_converter_v2 input.pdf --url http://127.0.0.1:5282
 
 # 更多选项
 python -m pdf_converter_v2 input.pdf --help
@@ -49,7 +49,7 @@ async def main():
         input_file="input.pdf",
         output_dir="./output",
         output_json=True,
-        url="http://192.168.2.3:8000"
+        url="http://127.0.0.1:5282"
     )
     print(f"Markdown文件: {result['markdown_file']}")
     if result.get('json_file'):
@@ -103,7 +103,7 @@ curl "http://localhost:4214/task/{task_id}/json"
 
 v2版本内部调用的外部API接口:
 
-- **URL**: `http://192.168.2.3:8000/file_parse`
+- **URL**: `http://127.0.0.1:5282/file_parse`
 - **方法**: POST
 - **Content-Type**: multipart/form-data
 - **返回格式**: zip文件
@@ -295,7 +295,7 @@ sudo journalctl -u pdf-converter-v2 -f
 ### 环境变量配置
 
 主要环境变量:
-- `API_URL`: 外部API地址(默认: http://192.168.2.3:8000
+- `API_URL`: 外部API地址(默认: http://127.0.0.1:5282
 - `API_HOST`: 服务监听地址(默认: 0.0.0.0)
 - `API_PORT`: 服务监听端口(默认: 4214)
 - `LOG_LEVEL`: 日志级别(默认: info)
@@ -303,7 +303,7 @@ sudo journalctl -u pdf-converter-v2 -f
 
 ## 注意事项
 
-1. **API服务器**: 确保外部API服务器(`http://192.168.2.3:8000`)正常运行
+1. **API服务器**: 确保外部API服务器(`http://127.0.0.1:5282`)正常运行
 2. **网络连接**: v2版本需要网络连接以访问外部API
 3. **页数限制**: 文件页数不能超过300页,超过会自动拒绝
 4. **文件格式**: 支持PDF和常见图片格式(PNG、JPG、JPEG、BMP、TIFF、WEBP)

+ 1 - 1
pdf_converter_v2/api/main.py

@@ -41,7 +41,7 @@ except ImportError:
     DEFAULT_GPU_MEMORY_UTILIZATION = 0.9
     DEFAULT_DPI = 200
     DEFAULT_MAX_PAGES = 10
-    DEFAULT_API_URL = os.getenv("API_URL", "http://192.168.2.3:8000")
+    DEFAULT_API_URL = os.getenv("API_URL", "http://127.0.0.1:5282")
     DEFAULT_BACKEND = os.getenv("BACKEND", "vlm-vllm-async-engine")
     DEFAULT_PARSE_METHOD = os.getenv("PARSE_METHOD", "auto")
     DEFAULT_START_PAGE_ID = int(os.getenv("START_PAGE_ID", "0"))

+ 1 - 1
pdf_converter_v2/config.py

@@ -13,7 +13,7 @@ DEFAULT_DPI = 200
 DEFAULT_MAX_PAGES = 10
 
 # v2 特有配置(外部API相关)
-DEFAULT_API_URL = os.getenv("API_URL", "http://192.168.2.3:5282")
+DEFAULT_API_URL = os.getenv("API_URL", "http://127.0.0.1:5282")
 DEFAULT_BACKEND = os.getenv("BACKEND", "vlm-vllm-async-engine")
 DEFAULT_PARSE_METHOD = os.getenv("PARSE_METHOD", "auto")
 DEFAULT_START_PAGE_ID = int(os.getenv("START_PAGE_ID", "0"))

+ 1 - 1
pdf_converter_v2/main.py

@@ -32,7 +32,7 @@ def main():
     parser.add_argument('--max-pages', type=int, default=10, help='最大转换页数(默认: 10,通过end_page_id控制)')
     
     # API选项
-    parser.add_argument('--url', default='http://192.168.2.3:8000', help='API服务器URL(默认: http://192.168.2.3:8000)')
+    parser.add_argument('--url', default='http://127.0.0.1:5282', help='API服务器URL(默认: http://127.0.0.1:5282)')
     parser.add_argument('--backend', default='vlm-vllm-async-engine', help='处理后端(默认: vlm-vllm-async-engine)')
     parser.add_argument('--parse-method', default='auto', help='解析方法(默认: auto)')
     parser.add_argument('--start-page-id', type=int, default=0, help='起始页ID(默认: 0)')

+ 1 - 1
pdf_converter_v2/processor/converter.py

@@ -157,7 +157,7 @@ async def convert_to_markdown(
     table_enable: bool = True,
     language: str = "ch",
     backend: str = "vlm-vllm-async-engine",
-    url: str = "http://192.168.2.3:8000",
+    url: str = "http://127.0.0.1:5282",
     embed_images: bool = True,
     output_json: bool = False,
     start_page_id: int = 0,

+ 1 - 1
pdf_converter_v2/test_converter.py

@@ -41,7 +41,7 @@ async def test_api_conversion(input_file: str, output_dir: str = "./test_output"
             table_enable=True,
             language="ch",
             backend="vlm-vllm-async-engine",
-            url="http://192.168.2.3:8000",
+            url="http://127.0.0.1:5282",
             embed_images=True,
             output_json=True,  # 启用JSON转换
             start_page_id=0,

+ 1 - 1
pdf_converter_v2/utils/mineru_service_manager.py

@@ -26,7 +26,7 @@ logger = get_logger("pdf_converter_v2.mineru_manager")
 MINERU_SERVICE_NAME = "mineru-api.service"
 
 # MinerU API 地址和端口(用于健康检查)
-MINERU_API_HOST = os.getenv("MINERU_API_HOST", "192.168.2.3")
+MINERU_API_HOST = os.getenv("MINERU_API_HOST", "127.0.0.1")
 MINERU_API_PORT = int(os.getenv("MINERU_API_PORT", "5282"))
 
 # 空闲超时时间(秒),超过此时间无任务则停止服务

+ 66 - 12
pdf_converter_v2/utils/pdf_watermark_remover.py

@@ -6,10 +6,59 @@ PDF去水印工具
 """
 
 from pathlib import Path
-from typing import Optional
+from typing import List, Optional
 import tempfile
 import shutil
 
+try:
+    from PIL import Image
+    PIL_AVAILABLE = True
+except ImportError:
+    PIL_AVAILABLE = False
+
+
+def _pdf_to_pil_images(input_pdf: str, dpi: int = 200) -> Optional[List["Image.Image"]]:
+    """
+    将 PDF 转为 PIL 图片列表。优先 pdf2image(需 poppler),失败时用 pypdfium2(无需 poppler)。
+    """
+    # 1) 尝试 pdf2image(需系统安装 poppler-utils)
+    try:
+        from pdf2image import convert_from_path
+        return convert_from_path(input_pdf, dpi=dpi)
+    except Exception as e:
+        err_msg = str(e).lower()
+        if "pdfinfo" in err_msg or "poppler" in err_msg or "no such file" in err_msg:
+            pass  # 无 poppler,尝试 pypdfium2
+        else:
+            raise
+    # 2) 备用:pypdfium2(无需 poppler)
+    try:
+        import pypdfium2 as pdfium
+        pdf = pdfium.PdfDocument(input_pdf)
+        try:
+            scale = dpi / 72.0
+            images = []
+            for i in range(len(pdf)):
+                page = pdf[i]
+                bitmap = page.render(scale=scale)
+                try:
+                    pil_image = bitmap.to_pil()
+                    images.append(pil_image)
+                finally:
+                    bitmap.close()
+            return images
+        finally:
+            try:
+                pdf.close()
+            except Exception:
+                pass
+    except ImportError:
+        raise FileNotFoundError(
+            "PDF 转图片需要 pdf2image+poppler 或 pypdfium2。"
+            " 安装其一:apt install poppler-utils 或 pip install pypdfium2"
+        )
+
+
 def remove_watermark_from_pdf(
     input_pdf: str,
     output_pdf: str,
@@ -36,25 +85,22 @@ def remove_watermark_from_pdf(
         bool: 是否成功
     """
     try:
-        # 导入必要的库
-        from pdf2image import convert_from_path
         from PIL import Image
-        import PyPDF2
         from utils.image_preprocessor import remove_watermark, check_opencv_available
         
-        # 检查OpenCV是否可用
         if not check_opencv_available():
             print("⚠ OpenCV 未安装,无法进行去水印处理")
             return False
         
-        # 创建临时目录
         temp_dir = tempfile.mkdtemp(prefix="pdf_watermark_")
         temp_path = Path(temp_dir)
         
         try:
             print(f"正在将PDF转换为图片(DPI={dpi})...")
-            # 将PDF转换为图片
-            images = convert_from_path(input_pdf, dpi=dpi)
+            images = _pdf_to_pil_images(input_pdf, dpi=dpi)
+            if not images:
+                print("⚠ 未得到任何页面图片")
+                return False
             print(f"✓ 转换完成,共 {len(images)} 页")
             
             # 处理每一页
@@ -113,7 +159,10 @@ def remove_watermark_from_pdf(
     
     except ImportError as e:
         print(f"⚠ 缺少必要的库: {e}")
-        print("请安装: pip install pdf2image pillow PyPDF2 opencv-python")
+        print("请安装: pip install pypdfium2 或 pdf2image pillow PyPDF2 opencv-python;pdf2image 需系统安装 poppler-utils")
+        return False
+    except FileNotFoundError as e:
+        print(f"⚠ {e}")
         return False
     except Exception as e:
         print(f"⚠ 去水印处理失败: {e}")
@@ -150,7 +199,6 @@ def crop_header_footer_from_pdf(
         bool: 是否成功
     """
     try:
-        from pdf2image import convert_from_path
         from PIL import Image
         from utils.image_preprocessor import crop_header_footer, check_opencv_available
 
@@ -163,7 +211,10 @@ def crop_header_footer_from_pdf(
 
         try:
             print(f"正在将 PDF 转换为图片(DPI={dpi})...")
-            images = convert_from_path(input_pdf, dpi=dpi)
+            images = _pdf_to_pil_images(input_pdf, dpi=dpi)
+            if not images:
+                print("⚠ 未得到任何页面图片")
+                return False
             print(f"✓ 转换完成,共 {len(images)} 页")
 
             processed_images = []
@@ -206,7 +257,10 @@ def crop_header_footer_from_pdf(
                 print(f"⚠ 清理临时目录失败: {e}")
     except ImportError as e:
         print(f"⚠ 缺少必要的库: {e}")
-        print("请安装: pip install pdf2image pillow opencv-python")
+        print("请安装: pip install pypdfium2 或 pdf2image pillow opencv-python;pdf2image 需系统安装 poppler-utils")
+        return False
+    except FileNotFoundError as e:
+        print(f"⚠ {e}")
         return False
     except Exception as e:
         print(f"⚠ 页眉页脚裁剪失败: {e}")