ARTICLE · 1031076
200份学历证书PDF传不上去?让AI写个脚本,30秒全部瘦身
200份学历证书PDF传不上去?让AI写个脚本,30秒全部瘦身
老登的懒人办公 · 每篇都是能直接抄走的 AI 办公方案
上周五下午,人事的同事在群里急了:报送系统单个附件限 2MB,可扫描仪出来的学历证书 PDF 一份就是 7、8MB,200 多份,手动在线压缩网站一次只能传一个,还要排队、还要下广告弹窗。
她问:“有没有快点的办法?”
我说:有,但别用手点的办法。让 AI 给你写个脚本。
从描述需求到跑完 200 多份,一共 12 分钟。这篇把脚本完整贴出来,你换个路径就能用。
一、先搞清楚:PDF 为什么这么大?
扫描件 PDF 大,99% 是因为里面塞的是未压缩的图片——扫描仪默认 300dpi 甚至 600dpi 出图,一张 A4 彩扫就是好几 MB。
所以压缩的本质只有两件事:
1. 重采样:把 300dpi 降到 150dpi(人眼几乎看不出差别,文件小 60%+)
2. 重新编码:用 JPEG / deflate 重新压一遍,顺手丢掉 PDF 里的历史版本、垃圾对象
想明白这点,脚本就只有几行。
二、实战一:最基础的批量压缩(30 行搞定)
环境准备,一条命令:
pip install pymupdf脚本本体,存成 shrink.py:
import fitzfrom pathlib import PathSRC = r"D:\学历证书\原始" # 改成你的源目录DST = r"D:\学历证书\已压缩" # 改成你的输出目录Path(DST).mkdir(parents=True, exist_ok=True)for f in Path(SRC).glob("*.pdf"): doc = fitz.open(f) out = Path(DST) / f.name doc.save( out, garbage=4, # 清理无用对象、丢弃历史版本 deflate=True, # 流压缩 deflate_images=True, clean=True, # 清理页面冗余内容 ) doc.close() print(f"{f.name} → {out.stat().st_size/1024:.0f} KB")跑起来:
python shrink.py💡 这一步只能压掉“水分”(冗余对象、未压缩的流),对纯图片扫描件大概能压 20%~40%。还想要更小的,看下一节。
三、实战二:直接压到 2MB 以内,超了自动降质
报送系统卡的是大小,不是“压过没有”。所以真正的做法是:设定上限,逐档降采样直到达标。
import fitzfrom pathlib import PathLIMIT = 2 * 1024 * 1024 # 目标上限:2MBdef shrink_to_limit(src, dst, limit=LIMIT): doc = fitz.open(src) buf = b"" for dpi in (200, 150, 120, 96, 72): # 由清晰到模糊逐档试 zoom = dpi / 300 # 假设原件是 300dpi mat = fitz.Matrix(zoom, zoom) tmp = fitz.open() for page in doc: pix = page.get_pixmap(matrix=mat) # 按目标 dpi 重新出图 p = tmp.new_page(width=page.rect.width, height=page.rect.height) p.insert_image(page.rect, pixmap=pix) buf = tmp.tobytes(garbage=4, deflate=True, deflate_images=True) tmp.close() if len(buf) <= limit: # 达标就收工 break Path(dst).write_bytes(buf) doc.close() return len(buf)SRC = Path(r"D:\学历证书\原始")DST = Path(r"D:\学历证书\已压缩")DST.mkdir(parents=True, exist_ok=True)for f in SRC.glob("*.pdf"): size = shrink_to_limit(f, DST / f.name) print(f"{f.name} → {size/1024:.0f} KB")我实测的一组数据(30 份示例文件,扫描件,非真实业务数据):
30 份 42 秒,200 份大概 4~5 分钟,全程不用碰鼠标。
⚠️ 两个坑提醒:1. 先备份原件。脚本是覆盖式输出,别直接压源文件目录。2. 如果 PDF 里是文字版(不是扫描图),不要降采样,实战一就够了,否则文字会糊。
四、实战三:压完顺手出一份清单
压完了总要交差。让脚本顺手生成一份 CSV,一眼看清哪些达标、哪些还是超标:
import fitz, csvfrom pathlib import PathLIMIT = 2 * 1024 * 1024rows = []for f in sorted(Path(r"D:\学历证书\已压缩").glob("*.pdf")): size = f.stat().st_size rows.append({ "文件名": f.name, "大小(KB)": round(size/1024), "是否达标": "✅" if size <= LIMIT else "❌ 需人工处理", })with open(r"D:\学历证书\压缩清单.csv", "w", newline="", encoding="utf-8-sig") as fp: w = csv.DictWriter(fp, fieldnames=["文件名", "大小(KB)", "是否达标"]) w.writeheader() w.writerows(rows)bad = sum(1 for r in rows if "❌" in r["是否达标"])print(f"共 {len(rows)} 份,达标 {len(rows)-bad} 份,超标 {bad} 份")utf-8-sig 是为了让 Excel 打开中文不乱码——这个细节,AI 一般也会主动给你加上。
五、方法论:什么活值得让 AI 写脚本?
写完这个脚本我总结了一条判断标准,三问全中,就别自己手动了:
① 这件事你一年会做 10 次以上吗?
学历/证件报送、月度报表、季度归档——这类“周期性重复”的活,一次性投入 10 分钟写脚本,之后每次 3 秒。手动做 10 次的时间,早就超过写脚本的时间了。
② 规则能不能用一句话说清楚?
“把目录下所有 PDF 压到 2MB 以内”——一句话,AI 就能写对。反之“帮我看看哪些文件要压缩”这种模糊需求,AI 也救不了你。需求越具体,AI 越靠谱。
③ 搞砸了代价大不大?
PDF、图片、表格这类可预览、可回滚的东西,随便试。但涉及真实数据删除、对外发送、财务口径的,脚本跑完一定要人工抽检 3~5 份再放行。我的习惯是:脚本负责批量,人负责签字。
说白了,AI 写脚本真正的价值不是“省了这一次的时间”,而是把你从“操作工”变成“出题人”——你只负责定义“压到 2MB 以内”这个标准,剩下的重复劳动,机器干。
六、没有 Python 环境怎么办?
三个选项,从省事到折腾:
1. 直接把这篇的脚本和需求一起丢给 AI,让它帮你打包成一个 .exe,双击就能跑(它会告诉你用 pyinstaller)
2. 让 AI 给你 PowerShell / 批处理版本,Windows 自带环境,不用装任何东西
3. 找台装了 Python 的电脑跑一次,脚本是通用的,拷走就行
我个人推荐第 1 个:打包一次,全办公室都能用。
写在最后
这套东西真正花时间的,其实只有“描述需求”那 2 分钟。
剩下的 10 分钟,AI 在写代码,你在刷手机。而过去这 10 分钟,你会在一个叫“免费PDF压缩”的网站上,点第 37 次上传。