image-to-pdf

Polar Sponsor
爱发电 赞助
.NET 9.0

自动旋转并合并多张图片为PDF,支持按Excel清单重命名并提取OCR文字。

Image to PDF Merger Skill

功能概述

Image to PDF Merger Skill是一项面向实际任务的技能,主要用于将多张图片合并成一个 PDF 文档,适合处理会计凭证、扫描文件等;支持自动旋转调整方向;

核心要点

  • 用户说"合并 PDF"、"把图片合成 PDF"、"生成 PDF";
  • 用户发送多张图片并要求合并;
  • 用户发送 PDF 并要求添加摘要;

使用与执行

用户发送扫描版 PDF 并要求"提取文字"、"总结";1. 收集图片/PDF;让用户一次性发送所有需要处理的。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。

结果检查与注意事项

从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。

Image to PDF Merger Skill

将多张图片合并成一个 PDF 文档,适合处理会计凭证、扫描文件等。支持自动旋转调整方向。

依赖

# Python
pip3 install Pillow pypdf openpyxl

# 系统工具
brew install poppler tesseract tesseract-lang

触发条件

  • 用户说"合并 PDF"、"把图片合成 PDF"、"生成 PDF"
  • 用户发送多张图片并要求合并
  • 用户发送 PDF 并要求添加摘要
  • 用户发送扫描版 PDF 并要求"提取文字"、"总结"

使用方法

1. 收集图片/PDF

让用户一次性发送所有需要处理的 PDF,不要分开多次发。

2. 执行合并(图片转 PDF)

适用于图片文件(.jpg):

import os
from pypdf import PdfWriter
from PIL import Image

# 获取所有新上传的图片
images = sorted(glob.glob(f"{inbound_dir}*.jpg"), key=os.path.getmtime, reverse=True)[:20]

merger = PdfWriter()
for img_path in images:
    img = Image.open(img_path)
    # 自动旋转:横版图片旋转90度
    width, height = img.size
    if width > height:
        img = img.rotate(90, expand=True)
    pdf_path = img_path.replace('.jpg', '.pdf')
    img.save(pdf_path, 'PDF', resolution=100.0)
    merger.append(pdf_path)

output_path = f"{output_dir}{凭证号}.pdf"
merger.write(output_path)

3. PDF 重命名(带完整摘要 + 船名归属)

根据 Excel 清单自动重命名 PDF:

Excel 结构:

  • F列 = Index(凭证序号)
  • H列 = 摘要(Description)
  • M列 = 船名/归属

关键:使用字母索引法,避免列号混淆!

import openpyxl
import re
import shutil
import os

# Excel 路径
excel_path = "~/.openclaw/media/inbound/Vouching_list---*.xlsx"

# 加载 Excel(使用字母索引)
wb = openpyxl.load_workbook(excel_path)
ws = wb.active

# 需要处理的文件列表 (序号, 原始文件名)
files = [
    (1, "1._1月79号---xxx.pdf"),
    (2, "2_1月109号---xxx.pdf"),
    # ...
]

for idx, filename in files:
    # Index N -> Excel Row N+1(因为 Row 1 是表头)
    excel_row = idx + 1
    
    # 使用字母索引直接访问列
    desc = ws[f'H{excel_row}'].value    # H列 = 摘要
    ship = ws[f'M{excel_row}'].value    # M列 = 船名归属
    
    # 从文件名提取凭证号(如 "1月79号")
    date_match = re.search(r'(d+月d+号)', filename)
    date_part = date_match.group(1) if date_match else ""
    
    # 命名格式:序号_凭证号-【船名】摘要.pdf
    # 例如:01_1月79号-【祥瀚8】V2501运费收入.pdf
    new_name = f"{idx:02d}_{date_part}-【{ship}】{desc}.pdf"
    
    # 复制并重命名
    src = os.path.join(inbound_dir, filename)
    dst = os.path.join(output_dir, new_name)
    shutil.copy(src, dst)

文件名格式规范:

序号_凭证号-【船名/公司】摘要.pdf

示例:
01_1月79号-【祥瀚8】V2501运费收入.pdf
02_1月109号-【River】坞修2411001.pdf
03_1月135号-【Alice】2503航次收入.pdf
04_1月169号-【Anna】DBS融资款付船款.pdf

4. 发送到 Telegram

message(
    action="send",
    filePath=output_path,
    message=f"{序号}. {凭证号} - 【{船名}】{摘要}",
    target="用户ID"
)

关键要点

  1. 一次性收集 - 让用户一次发完所有文件
  2. 使用字母索引 - 用 ws[f'H{row}'] 而非 row[7]
  3. 正确映射 - Index N → Excel Row N+1
  4. 完整命名 - 序号_凭证号-【船名】摘要
  5. 自动发送 - 处理完成后自动推送给用户

错误处理

  • 如果 Excel 找不到对应 Index,跳过或用原文件名
  • 如果 PDF 是图片合并的(无文字层),使用 OCR 功能提取文字
  • 文件名中的特殊字符(如 /)需要清理

功能三:扫描版 PDF OCR 文字提取

当用户发送扫描版 PDF(无文字层)时,使用 tesseract 提取文字:

步骤 1:PDF 转图片

# 安装依赖
brew install poppler tesseract tesseract-lang

# PDF 转图片(300 DPI)
pdftocairo -png -r 300 input.pdf page

步骤 2:OCR 识别

# 识别中文+英文
tesseract page-01.png stdout -l chi_sim+eng > output.txt

# 批量识别
for p in page-*.png; do
  tesseract "$p" stdout -l chi_sim+eng >> combined.txt
done

步骤 3:提取关键信息

import re

# 读取 OCR 结果
with open('combined.txt', 'r', encoding='utf-8') as f:
    text = f.read()

# 提取关键信息(根据文档类型调整)
patterns = {
    '贷款人': r'([A-Z]+ BANK LTD.?.*?)n',
    '借款人': r'([A-Z]+ SHIPPING LIMITED.*?)n',
    '贷款金额': r'USD([d,]+)',
    '利率': r'([d.]+)%',
    '期限': r'(d+)s*years?',
}

results = {}
for key, pattern in patterns.items():
    match = re.search(pattern, text, re.IGNORECASE)
    if match:
        results[key] = match.group(1) if match.lastindex else match.group(0)

print(results)

完整流程脚本

#!/bin/bash
# pdf-ocr.sh - 从扫描版 PDF 提取文字

PDF_PATH="$1"
OUTPUT_DIR="/tmp/pdf_ocr_$(date +%s)"

mkdir -p "$OUTPUT_DIR"

# 1. PDF 转图片
echo "Converting PDF to images..."
pdftocairo -png -r 300 "$PDF_PATH" "$OUTPUT_DIR/page"

# 2. OCR 识别
echo "Running OCR..."
> "$OUTPUT_DIR/combined.txt"
for img in "$OUTPUT_DIR"/page-*.png; do
    echo "Processing: $img"
    tesseract "$img" stdout -l chi_sim+eng 2>/dev/null >> "$OUTPUT_DIR/combined.txt"
done

# 3. 提取关键信息
echo "Extracting key information..."
python3 << 'EOF'
import re

with open('$OUTPUT_DIR/combined.txt', 'r', encoding='utf-8', errors='ignore') as f:
    text = f.read()

patterns = {
    'lender': r'([A-Z]+ BANK LTD.?.*?)n',
    'borrower': r'([A-Z]+ SHIPPING LIMITED.*?)n',
    'amount': r'USD([d,]+)',
    'date': r'(d{1,2}s+w+s+d{4})',
}

for key, pattern in patterns.items():
    match = re.search(pattern, text, re.IGNORECASE)
    if match:
        print(f"{key}: {match.group(1)}")
EOF

echo "Output saved to: $OUTPUT_DIR/combined.txt"

改进:处理延时

为避免图片传输不完整,添加等待机制:

import time

# 等待所有图片传输完成
time.sleep(5)  # 等待5秒

# 获取最新上传的图片(按修改时间排序)
# 这样可以确保所有已传输的图片都被处理

为什么需要延时

  • 用户一次性发送多张图片
  • Telegram/网络传输需要时间
  • 如果立刻处理,后传输的图片可能还没到

延时建议

  • 5秒:适合少量图片(1-10张)
  • 10秒:适合大量图片(10张以上)

替代方案

如果不想用固定延时,也可以:

  1. 等待用户确认"还有吗?"
  2. 用心跳时检查inbound目录是否有新文件

相关专题

更多
Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

2026.10.28

0

16

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

2026.10.28

0

15

Vite 项目目录怎么看
Vite 项目目录怎么看

Vite项目目录专题汇集入口文件、src源码、public静态资源、路径别名、项目根目录和构建输出目录相关的已审核文章,帮助读者理解各文件夹的用途与引用方式。

2026.10.28

0

10

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

2026.10.22

0

11

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

2026.10.22

0

10

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

2026.10.22

0

15

Gradle怎么构建Java项目
Gradle怎么构建Java项目

本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。

2026.10.22

0

10

PHP时间戳漏洞修复教程
PHP时间戳漏洞修复教程

本专题汇总PHP常见时间戳漏洞,包括2038年溢出、时区漂移、时间戳伪造、重放攻击、时间盲注与日志审计失效等,并给出升级64位环境、使用 DateTimeImmutable、统一UTC、严格超时校验、预处理绑定、hash_equals 比对等修复方案,帮助开发者快速排查和加固时间相关代码。

2026.10.22

0

25

Golangci-lint配置文件与规则设置
Golangci-lint配置文件与规则设置

本专题聚焦Golangci-lint YAML配置文件,讲清运行参数、规则启停、目录排除、问题过滤及严重级别设置,便于团队统一检查标准。

2026.10.22

0

15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.1万人学习