首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >保姆级实战:用 WorkBuddy 把 24 份乱名扫描件做成 153 页资料册(附 5 个必踩坑)

保姆级实战:用 WorkBuddy 把 24 份乱名扫描件做成 153 页资料册(附 5 个必踩坑)

原创
作者头像
用户8553481
修改于 2026-10-15 10:28:21
修改于 2026-10-15 10:28:21
180
举报

24 份乱名扫描件 → 153 页质量资料册:WorkBuddy 保姆级归档实战(附 5 个必踩坑)

用 WorkBuddy 完成一次真实的工程资料归档:从 24 份文件名全是流水号的扫描件,到一册 153 页、带封面和目录的质量资料。全程记录方法、代码和踩过的坑。

标签:#WorkBuddy#


目录

  • 一、这件事为什么值得自动化
  • 二、实战:五步走完全流程
    • 第 1 步:让"不可读"的扫描件变得可读
    • 第 2 步:建立「明细 ↔ 扫描件」映射
    • 第 3 步:数量勾稽(最值得做的一步)
    • 第 4 步:按序号合并与重命名
    • 第 5 步:目录页回填与成册
  • 三、5 个必踩的坑
  • 四、最终成果
  • 五、可复用检查清单

一、这件事为什么值得自动化

制造企业交付成套设备时,随产品提交的质量证明文件是多方来源的汇总物:外购件合格证、外协件质量证明、内部过程检验记录、装配记录、出厂检查报告。

纸质件扫描之后,得到的是一堆文件名毫无规律、内容无法检索的图像型 PDF:

doc05419720261012154222.pdf doc05419820261012154251.pdf doc05419920261012154323.pdf ...

人工按目录逐份核对、排序、合并、编页码,既费时又极易错漏。本次任务的对象是一个成套液压系统项目:

素材

说明

扫描件

24 份图像型 PDF,共 50 页,不含文本层

明细表

1 份 Excel,规定了应提交的 15 类材质证明及其份数

任务过程中又追加了 5 份过程记录扫描件、1 份出厂检查报告、2 个工作表的目录页,最终形成 153 页资料册。


二、实战:五步走完全流程

第 1 步:让"不可读"的扫描件变得可读

扫描件是纯图像、无文本层,常规文本提取直接返回空字符串。思路是先转成图,再交给视觉识别:

  1. 用 PDF 渲染库把每一页渲染为位图;
  2. 缩略到统一宽度(约 640 px),拼成 2 列 × 3 行的版式;
  3. 每个单元格上方压一条标签,写明「全局页码 + 源文件 + 文件内页序」;
  4. 交视觉识别,逐页判定它属于明细中的哪一类。
代码语言:python
复制
import pypdfium2 as pdfium
from PIL import Image, ImageDraw, ImageFont

doc = pdfium.PdfDocument("scan.pdf")
img = doc[0].render(scale=2.2).to_pil().convert("RGB")
W = 640
img = img.resize((W, int(img.height * W / img.width)), Image.LANCZOS)
img.save("page_01.png")

关键取舍:默认缩略图只够看清标题。遇到"一张纸上贴十几张小合格证"的密集页,要单独按 3 倍比例重渲染至 1500 px 宽,才能辨认小字与厂家标识。

为什么不用 OCR:本地 OCR 需要额外装模型,中文小字与印章的辨识效果反而更差;渲染拼版 + 视觉识别零依赖、更准。

第 2 步:建立「明细 ↔ 扫描件」映射

明细表给了 15 类条目,扫描件却有 24 份 —— 数量对不上,说明存在"一类条目对应多份扫描件"的情况。

逐页识别后得到三种典型形态:

形态

表现

处理

一对一

一份扫描件就是一个条目

直接对应

一对多

同类合格证分几次扫描

按序号合并为一个文件

多对一

一页纸张贴多张同类小证

归入同一条目,按张数计数

第 3 步:数量勾稽(最值得做的一步)

重命名之前,先做一次独立的总量校验:把明细表里每一类声明的份数,与逐页清点出来的实际张数逐条比对。

结果全部吻合,其中两类很能说明问题:

  • 某类声明「数十份」,实际是 16+16+16+16+11 = 75 张,分装在 5 个扫描文件里;
  • 另一类声明「若干份」,实际是 9 张 + 1 张,跨了两个扫描文件。

为什么这一步值得单独做:如果直接按顺序改名而不校验数量,一旦扫描时漏扫一张或重复扫一张,错误会被"整齐的重命名"掩盖过去,后面几乎不可能发现。先勾稽,等于给整个归档上了第一道保险。

第 4 步:按序号合并与重命名

命名规则:{两位序号} {明细名称}({厂家}).pdf,同一条目下的多份扫描件合并为一个 PDF。

代码语言:python
复制
from pypdf import PdfReader, PdfWriter

wr = PdfWriter()
for src in ["a.pdf", "b.pdf", "c.pdf"]:
    for page in PdfReader(src).pages:
        wr.add_page(page)
with open("01 合格证(某公司).pdf", "wb") as f:
    wr.write(f)

合并完成后:

  • 原始文件不删除,整体移入备份子目录(可随时回退);
  • 输出「重命名对照表」CSV(新文件名 ↔ 合并前源文件 ↔ 合并后页数)。

第 5 步:目录页回填与成册

明细表里的清单是"活的",而资料册里的目录还停留在纸质表格阶段。于是把明细表的两个工作表回填成 PDF 并入册:

  • 工作表 A(封面型):企业名 + 项目名 + 项目编号 + 「总目录」+ 日期;
  • 工作表 B(清单型):序号 / 名称 / 厂家 / 数量 四列。

最终成册结构:

P1 封面(由工作表 A 导出) P2 质量数据目录(由工作表 B 导出,共 20 条) P3 ~ P152 正文:序号 01~19 的全部证明与记录 P153 序号 20:出厂检查报告

把目录页放进同一册,而不是让目录和正文分离,是这次一个明显的改进:拿到册子的人翻第一页就知道里面有什么、共几页。


三、5 个必踩的坑

坑 1:含图片的 xlsx 不能"整体重存"

要往明细表里追加行。常规做法是「读 → 写回」,但该工作簿里嵌有图片(每个工作表一张企业 logo)。

用常规库整体重存,图片与打印设置会丢失 —— 文件能打开、数据也对,但图片没了,而且往往过几天才发现。

正确做法:外科式改包。 把 xlsx 当作 zip,只重写需要变的部件:

代码语言:python
复制
# 只重写 worksheet XML 与 sharedStrings.xml
# 其余部件字节级原样搬运,连目录项与压缩元数据一起复刻
zout = zipfile.ZipFile(tmp, "w", zipfile.ZIP_DEFLATED)
for info in zin.infolist():
    zi = zipfile.ZipInfo(info.filename, date_time=info.date_time)
    zi.compress_type = info.compress_type
    zi.external_attr = info.external_attr
    zout.writestr(zi, b"" if info.is_dir() else blobs[info.filename])

坑 2:样式索引会"漂移"(最坑的一个)

第一次追加行时按之前记录的样式编号写入,结果新行字号变大、没有边框、文字不换行、跑到表格外面去了。

根因:期间文件被用 Excel 手工打开并保存过。Excel 重存会重排样式表 —— 样式总数从 12 变成 16,所有样式编号整体位移。

代码语言:python
复制
# ❌ 错误:硬编码样式编号
'<c r="B25" s="10" t="s"><v>54</v></c>'

# ✅ 正确:从相邻行现场提取
smap = dict(re.findall(r'<c r="([A-D])24" s="(\d+)"', row24_xml))
'<c r="B25" s="{}" t="s"><v>54</v></c>'.format(smap['B'])

这个坑还有个副作用:它把我引向了错误方向 —— 我以为是"分页裁切/缩放不当",在页面设置上反复调整,白费了好几轮。看到"新加的行样式异常",第一反应应该是查样式索引,而不是查排版。

坑 3:FitToPage 不生效

把工作表导出成 PDF 时,想用"缩放以适应一页"保证表格落在一页内,但设置后没有生效 —— 读回缩放比例仍是 100%,工作表仍被判定为跨页。

解决办法:改用固定缩放比例。先读出工作表实际内容高度(约 974 pt),A4 纸高 841.9 pt,扣除边距可用约 800 pt,据此把缩放定在 72%,一次成功。

代码语言:python
复制
ws.PageSetup.PrintArea = 'A1:D25'
ws.PageSetup.Zoom = 72          # 固定缩放,别用 FitToPage
ws.ExportAsFixedFormat(0, out)  # 0 = xlTypePDF

验证方法:导出后不要只看页数,还要用 PDF 文本定位接口搜索关键行文字,取出坐标框 —— 确认它落在页面矩形内,才算真的没被裁掉。

坑 4:文件名里的非法字符

期望的文件名里含一个半角星号。实测:半角 * 在 Windows 文件名中非法,直接抛权限错误;全角 *、乘号 ×、连字符 - 都可以。

这条看似琐碎,但一旦没测就写进脚本,会在最后一步整体失败。

坑 5:混入的其他项目文件

追加的扫描件里,有一份文件名与其余高度相似,但内容中的"用户名称"字段指向的是另一个客户。

判定依据:不看文件名,看单据内的"用户名称/项目名称"字段。文件名可以随手起,单据内的字段是业务事实。


四、最终成果

项目

结果

扫描件归类

24 份 → 按明细合并为 15 个规范命名文件

数量勾稽

全部条目声明份数与实际清点逐条吻合

追加素材

5 份 → 4 份并入(1 份判定为他项目,剔除)

明细表

15 条 → 20 条;图片与样式完好

资料册

153 页,含封面、目录、正文、出厂检查报告

页码核验

抽样 8 个关键页渲染比对,各段页界与序号完全对应

原始文件

全部保留(移入备份目录),零删除


五、可复用检查清单

归档前

  • 扫描件是否含文本层?(不含 → 走渲染 + 视觉识别路线)
  • 明细表的条目数与扫描件数是否一致?(不一致 → 先建映射)
  • 每一类声明的份数,能否与实际清点数逐条勾稽?
  • 文件名中的"用户名称"字段是否与本项目一致?

处理中

  • 目标文件是否含图片/图表/打印设置?(含 → 禁止整体重存)
  • 追加行之前,是否从相邻行现场提取了样式编号?
  • 合并后是否输出了「新名 ↔ 源文件 ↔ 页数」对照表?
  • 原始文件是否已备份而非删除?

交付前

  • 目录页是否已并入成册,而不是单独一份?
  • 全册页码分段是否正确?
  • 表格导出的 PDF,关键行是否真的落在页面内(用坐标验证)?
  • 成品文件名是否做过非法字符测试?

小结

这类任务的难点从来不是"写代码",而是判断在哪一步做校验、在哪里会被数据的"隐性变化"坑到。

5 个坑里,坑 2(样式索引漂移)和坑 5(混入他项目文件)最隐蔽 —— 前者让你以为是排版问题,后者让你以为是命名问题,而真正的原因是数据本身。

如果你也在做工程资料或审核材料的归档,希望这份实录能帮你少走两轮弯路。

#WorkBuddy#

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 24 份乱名扫描件 → 153 页质量资料册:WorkBuddy 保姆级归档实战(附 5 个必踩坑)
    • 目录
    • 一、这件事为什么值得自动化
    • 二、实战:五步走完全流程
      • 第 1 步:让"不可读"的扫描件变得可读
      • 第 2 步:建立「明细 ↔ 扫描件」映射
      • 第 3 步:数量勾稽(最值得做的一步)
      • 第 4 步:按序号合并与重命名
      • 第 5 步:目录页回填与成册
    • 三、5 个必踩的坑
      • 坑 1:含图片的 xlsx 不能"整体重存"
      • 坑 2:样式索引会"漂移"(最坑的一个)
      • 坑 3:FitToPage 不生效
      • 坑 4:文件名里的非法字符
      • 坑 5:混入的其他项目文件
    • 四、最终成果
    • 五、可复用检查清单
    • 小结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档