Python办公自动化之Excel/Word/PDF实战完整教学
作者:菩提风
简介:本资源是一份面向零基础学习者与职场办公人员的Python自动化办公实战指南,聚焦Excel、Word、PDF、PPT及CSV等高频办公文档的程序化处理,解决重复性文档操作效率低、跨格式数据整合难等实际问题。压缩包为RAR格式,共包含百余个结构化文件,以PDF教程、代码脚本、学习笔记和案例源码为主——其中PDF覆盖五大核心模块(PDF/PPT/Excel处理篇+综合学习笔记+案例集锦),代码示例可直接运行调试,笔记详述关键API用法与典型报错解决方案,案例均来自真实办公场景。资源大小102.94MB,目录层级清晰,便于按需检索各模块内容。目前已有202人下载学习,适合希望系统掌握Python办公自动化技能、快速提升文档处理效率的初学者与转岗技术人员。
1. Python办公自动化:Excel、Word、PDF等集合PDF完整版最新版本
你有没有遇到过这种场景:财务同事凌晨三点发来27个Excel,要求把每张表里“客户编号”列统一补全UUID,再按地区拆成子表,最后合并生成带目录的PDF报告,附上Word版摘要——而你手头只有Excel双击打开、Ctrl+C/V、打印另存为PDF这三板斧?这不是效率问题,是工具链断层。这份被误称为“PDF完整版”的资源,本质是一套经过真实业务压测的Python办公自动化工程包:它不教print("Hello World"),而是直接给你 excel_to_pdf_pipeline.py 、 word_template_filler.py 、 pdf_merge_with_bookmarks.py 三个主力脚本,配套12个真实数据样例(含带合并单元格的财务报表、含OLE对象的旧版Word、含扫描件图层的PDF),所有依赖已锁定在 requirements.txt 里,连 openpyxl==3.1.2 和 python-docx==1.1.2 的兼容性坑都提前填好了。适合两类人:一是被重复报表压得喘不过气的业务岗(行政/HR/财务),想用5行代码替代2小时手工;二是刚学完基础语法的转行者,需要一个能立刻跑通、看到结果、还能反向拆解的“生产级样板”。别被标题里的“PDF完整版”误导——它最值钱的部分,是那个能让你在Windows/Mac/Linux上一键复现的 ./scripts/run_all.bat (或 ./scripts/run_all.sh )。
2. 从零启动:环境隔离、依赖安装与核心模块选型逻辑
2.1 为什么必须用venv隔离环境?——避开Office COM组件与现代库的版本战争
很多初学者直接 pip install openpyxl python-docx PyPDF2 ,结果在Windows上跑 win32com 时爆红,或在Mac上因 pypdf 和 PyPDF2 混装导致PDF页码错乱。这不是你的错,是办公自动化特有的“生态撕裂”:
- Excel处理:
openpyxl(纯Python,支持.xlsx,但不读.xls) vsxlwings(调用本地Excel进程,支持.xls/.xlsx/宏,但需Office安装) - Word处理:
python-docx(生成/修改.docx,不支持.doc或公式渲染) vsdocxtpl(Jinja2模板驱动,适合批量填充合同) - PDF处理:
PyPDF2(稳定但不支持表单/注释) vspypdf(v3.x后取代PyPDF2,支持更多PDF特性) vspdfplumber(精准提取表格/文字,但速度慢)
本项目采用 分层选型策略 :
- 基础读写 →
openpyxl+python-docx+pypdf(v3.10.0,非PyPDF2) - 高阶需求(如Excel宏、PDF表单填写)→ 单独提供
xlwings和reportlab扩展模块,不默认安装 - 所有依赖版本锁死在
requirements.txt中,避免pip install -r requirements.txt时出现版本漂移
提示:项目根目录下 env_setup.md 文件详细记录了各系统(Win10/11, macOS Sonoma, Ubuntu 22.04)的venv创建命令。Windows用户务必注意:PowerShell需先执行 Set-ExecutionPolicy RemoteSigned -Scope CurrentUser 解除脚本限制,否则 run_all.ps1 会报错。
2.2 三步完成环境初始化:命令、验证与常见失败点
步骤1:创建并激活虚拟环境(以Windows PowerShell为例)
# 进入项目根目录(含requirements.txt的位置) cd C:\path\to\your\project # 创建名为venv的虚拟环境 python -m venv venv # 激活虚拟环境(PowerShell) venv\Scripts\Activate.ps1 # 若提示执行策略被禁止,运行以下命令后再激活 Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
逻辑说明 : python -m venv venv 调用Python内置venv模块,在当前目录下创建独立环境。 Activate.ps1 是PowerShell专用激活脚本, .bat 文件用于CMD, source venv/bin/activate 用于Linux/macOS。激活后命令行前缀会显示 (venv) ,表示已进入隔离环境。
步骤2:安装锁定依赖
pip install --upgrade pip pip install -r requirements.txt
参数说明 :
--upgrade pip确保pip为最新版,避免旧版pip无法解析pypdf>=3.10.0,<4.0.0这类范围约束-r requirements.txt按文件逐行安装,==表示精确版本(如openpyxl==3.1.2),>=表示最小兼容版本(如pypdf>=3.10.0)
步骤3:验证核心模块是否可用
# 在Python交互式环境中执行
import openpyxl
import docx
from pypdf import PdfReader
# 测试Excel读取
wb = openpyxl.load_workbook("samples/excel/sample_data.xlsx")
print(f"Excel加载成功,工作表数:{len(wb.sheetnames)}")
# 测试Word读取
from docx import Document
doc = Document("samples/word/sample_contract.docx")
print(f"Word加载成功,段落数:{len(doc.paragraphs)}")
# 测试PDF读取
reader = PdfReader("samples/pdf/sample_invoice.pdf")
print(f"PDF加载成功,页数:{len(reader.pages)}")
预期输出 :三行 加载成功 信息。若某行报错(如 ModuleNotFoundError: No module named 'docx' ),说明 python-docx 未正确安装,需检查是否在激活的venv中执行 pip install 。
2.3 避坑:办公自动化环境的五大血泪现场
现象1:ImportError: No module named 'win32api'(Windows专属)
原因 : xlwings 或某些旧版 comtypes 依赖 pywin32 ,但 pip install xlwings 未自动安装它,或安装后未运行 python Scripts/pywin32_postinstall.py -install 注册COM组件。
解决 :在venv中执行
pip install pywin32 python Scripts/pywin32_postinstall.py -install
注意: Scripts/ 目录在venv内,路径为 venv\Scripts\ (Windows)或 venv/bin/ (macOS/Linux)。
现象2:Mac上python-docx保存文件后,Word提示“文件已损坏”
原因 :macOS默认文件系统(APFS)对文件权限处理严格, python-docx 生成的临时文件可能因权限不足无法写入。
解决 :在保存前显式设置权限
from docx import Document import os doc = Document() # ... 添加内容 output_path = "output/report.docx" doc.save(output_path) os.chmod(output_path, 0o644) # 设置为可读可写
现象3:pypdf读取扫描版PDF时报PdfReadError: Invalid object ID
原因 :扫描PDF本质是图片,无文本层, pypdf 尝试解析文本结构失败。
解决 :改用 pdfplumber 提取图像区域,或先用OCR工具(如Tesseract)预处理。本项目 utils/pdf_scanner_handler.py 提供封装函数:
from utils.pdf_scanner_handler import extract_text_from_scanned_pdf
text = extract_text_from_scanned_pdf("samples/pdf/scanned_receipt.pdf", ocr_lang="chi_sim")
现象4:openpyxl读取含公式Excel时,cell.value返回None
原因 : openpyxl 默认只读取存储值,不计算公式。需启用 data_only=False (读取公式)或 data_only=True (读取计算结果)。
解决 :根据需求选择加载模式
# 读取公式本身(用于审计)
wb = openpyxl.load_workbook("formulas.xlsx", data_only=False)
# 读取公式计算结果(常用)
wb = openpyxl.load_workbook("formulas.xlsx", data_only=True)
现象5:python-docx插入图片后,Word中图片显示为“X”,且文档体积暴增
原因 :默认插入方式将图片二进制数据直接嵌入XML,未压缩。
解决 :使用 document.add_picture() 时指定 width / height ,并启用 python-docx 的压缩选项(需v1.1.0+):
from docx.shared import Inches
# 插入时指定尺寸,自动触发压缩
doc.add_picture("chart.png", width=Inches(6.0))
# 或手动压缩(高级用法)
from docx.oxml import parse_xml
from docx.oxml.ns import nsdecls
# (详见utils/docx_compressor.py)
3. Excel自动化实战:UUID注入、条件拆分与跨表联动
3.1 给Excel“客户编号”列批量注入UUID:不只是随机字符串
业务场景:销售部每月导出CRM数据为Excel,但“客户编号”列为空,需按规则生成唯一标识(非简单 uuid.uuid4() ,需兼容数据库主键长度且可读性可控)。本项目 excel_uuid_injector.py 提供三种策略:
- UUIDv4 :标准128位,
550e8400-e29b-41d4-a716-446655440000 - 短UUID :Base32编码,长度12位,
Y3F6V9Q2M7XN(适配MySQL VARCHAR(12)) - 时间戳+随机码 :
20240520-ABC123(便于人工追溯)
# excel_uuid_injector.py 核心逻辑
import uuid
import base64
import time
def generate_short_uuid():
"""生成12位Base32短UUID"""
uid = uuid.uuid4().bytes[:8] # 取前8字节保证唯一性
return base64.b32encode(uid).decode('ascii').replace('=', '')[:12]
def generate_timestamp_uuid(prefix="CUST"):
"""生成时间戳+随机码格式"""
timestamp = time.strftime("%Y%m%d")
random_part = str(uuid.uuid4().hex[:4]).upper()
return f"{prefix}-{timestamp}-{random_part}"
# 应用到Excel指定列
from openpyxl import load_workbook
wb = load_workbook("input/sales_data.xlsx")
ws = wb.active
# 假设客户编号在B列,从第2行开始(跳过标题)
for row in range(2, ws.max_row + 1):
if not ws[f"B{row}"].value: # 仅填充空单元格
ws[f"B{row}"].value = generate_short_uuid()
wb.save("output/sales_data_with_uuid.xlsx")
参数说明 :
uuid.uuid4().bytes[:8]截取8字节(64位),足够满足亿级数据唯一性,Base32编码后约12字符time.strftime("%Y%m%d")确保每日生成的ID前缀相同,便于按日期归档ws[f"B{row}"].value使用Excel坐标字符串(如"B2")访问单元格,比ws.cell(row=row, column=2)更直观
3.2 按“地区”列自动拆分Excel为多个子表:保留原格式与公式
痛点:财务报表需按“华东/华北/华南”拆分发送给各区域经理,但原始Excel含复杂公式、条件格式、图表。 openpyxl 直接复制工作表会丢失图表( openpyxl 不支持图表对象),而 xlwings 又依赖本地Excel。本方案采用 公式冻结+样式继承 策略:
# excel_splitter.py
from openpyxl import load_workbook
from openpyxl.styles import Font, PatternFill, Border, Side
def split_by_column(input_path, output_dir, split_column="地区", header_row=1):
wb = load_workbook(input_path)
ws = wb.active
# 获取所有唯一地区值
regions = set()
for row in range(header_row + 1, ws.max_row + 1):
region = ws[f"{split_column}{row}"].value
if region:
regions.add(str(region))
# 为每个地区创建新工作簿
for region in regions:
new_wb = load_workbook(input_path) # 复制原始模板(含公式/样式)
new_ws = new_wb.active
# 删除非目标地区行(从底向上删,避免索引错乱)
rows_to_delete = []
for row in range(ws.max_row, header_row, -1): # 从最后一行倒序
if str(ws[f"{split_column}{row}"].value) != region:
rows_to_delete.append(row)
for row in rows_to_delete:
new_ws.delete_rows(row)
# 保存为独立文件
output_path = f"{output_dir}/{region}_销售报表.xlsx"
new_wb.save(output_path)
print(f"已生成:{output_path}")
# 调用示例
split_by_column(
input_path="samples/excel/quarterly_report.xlsx",
output_dir="output/region_split",
split_column="地区", # 支持中文列名
header_row=1
)
关键设计 :
load_workbook(input_path)直接加载原始文件作为模板,确保新文件继承所有样式、公式、数据验证规则delete_rows()从底向上删除,避免删除一行后下方行号上移导致漏删str(ws[f"{split_column}{row}"].value)强制转字符串,兼容空值/数字/文本混合类型
3.3 跨Excel文件联动:用openpyxl实现“主表驱动子表更新”
场景:总部有一份 master_budget.xlsx (含各部门预算总额),各子公司有 sub_budget_2024.xlsx (含明细)。当总部调整总额,需自动按比例重算子公司明细。传统做法是手动复制粘贴,易出错。本方案通过 openpyxl 读取主表,计算缩放系数,写入子表:
# budget_sync.py
from openpyxl import load_workbook
def sync_budget(master_path, sub_paths, master_total_cell="B2", sub_ratio_cell="C1"):
"""
主表B2为总预算,子表C1为分配比例(如0.15表示15%)
"""
# 读取主表总预算
master_wb = load_workbook(master_path, data_only=True)
master_ws = master_wb.active
total_budget = master_ws[master_total_cell].value
# 遍历每个子公司文件
for sub_path in sub_paths:
sub_wb = load_workbook(sub_path)
sub_ws = sub_wb.active
# 读取子表比例
ratio = sub_ws[sub_ratio_cell].value
if not isinstance(ratio, (int, float)) or ratio <= 0:
print(f"警告:{sub_path}中{sub_ratio_cell}比例无效,跳过")
continue
# 计算子公司应得预算 = 总预算 × 比例
allocated = total_budget * ratio
# 写入子表指定单元格(如D2为“核定预算”)
sub_ws["D2"] = allocated
sub_wb.save(sub_path)
print(f"已同步:{sub_path} → 核定预算={allocated:.2f}")
# 调用示例
sync_budget(
master_path="samples/excel/master_budget.xlsx",
sub_paths=[
"samples/excel/sub_budget_beijing.xlsx",
"samples/excel/sub_budget_shanghai.xlsx"
],
master_total_cell="B2",
sub_ratio_cell="C1"
)
边界处理 :
data_only=True确保读取主表的计算结果,而非公式字符串isinstance(ratio, (int, float))校验比例是否为数值,避免文本"15%"导致乘法错误allocated = total_budget * ratio直接计算,不依赖Excel公式,结果精确可控
4. Word自动化:模板填充、公式转换与批量生成
4.1 用docxtpl实现合同/报告批量生成:告别复制粘贴
python-docx 适合修改现有文档,但生成结构化文档(如合同、周报)效率低。 docxtpl 基于Jinja2模板引擎,允许在Word中插入 {{ variable }} 和 {% for item in items %} ,本项目 templates/contract_template.docx 已预置占位符:
<!-- contract_template.docx 中的XML片段(实际不可见,由docxtpl渲染) -->
<p>甲方:{{ party_a }}</p>
<p>乙方:{{ party_b }}</p>
<table>
{% for item in service_items %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.price | currency }}</td>
</tr>
{% endfor %}
</table># word_template_filler.py
from docxtpl import DocxTemplate
import json
def fill_contract(template_path, context_json, output_path):
"""
context_json: {"party_a": "北京科技有限公司", "party_b": "上海咨询公司",
"service_items": [{"name": "系统开发", "price": 150000}]}
"""
template = DocxTemplate(template_path)
with open(context_json, 'r', encoding='utf-8') as f:
context = json.load(f)
# 自定义过滤器:金额转为中文大写
def to_currency(amount):
# 实现人民币大写转换(简化版)
digits = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"]
units = ["", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿"]
# (完整实现见utils/currency_converter.py)
return f"¥{amount:,.2f}"
template.register_filter('currency', to_currency)
template.render(context)
template.save(output_path)
# 调用示例
fill_contract(
template_path="templates/contract_template.docx",
context_json="data/contract_context.json",
output_path="output/contract_signed.docx"
)
优势对比 :
| 方案 | 开发速度 | 模板维护 | 动态逻辑 | 表格生成 |
|---|---|---|---|---|
python-docx 硬编码 | 慢(每字段写add_paragraph) | 困难(改代码) | 弱(需if/else) | 需手动循环add_table |
docxtpl 模板驱动 | 快(改Word即可) | 简单(Word编辑) | 强(Jinja2语法) | {% for %} 自动渲染 |
4.2 Word公式转LaTeX:解决技术文档公式迁移难题
痛点:工程师用Word写技术方案,含大量公式(如 E=mc² ),但需转为LaTeX发布到学术平台。 python-docx 无法解析公式XML结构,本项目采用 docx2python 库提取原始OMML(Office Math Markup Language),再用 omml2mathml 转换为MathML,最终转LaTeX:
# word_formula_converter.py
from docx2python import docx2python
import re
def extract_formulas(docx_path):
"""提取Word中所有公式(OMML格式)"""
docx_content = docx2python(docx_path)
formulas = []
# 遍历所有段落和表格单元格
for paragraph in docx_content.body:
if hasattr(paragraph, 'math') and paragraph.math:
formulas.append(paragraph.math)
for table in docx_content.tables:
for row in table:
for cell in row:
if hasattr(cell, 'math') and cell.math:
formulas.append(cell.math)
return formulas
def omml_to_latex(omml_str):
"""简化版OMML转LaTeX(真实项目用omml2mathml + mathml2latex)"""
# 示例:将 <m:oMath><m:r><m:t>E=mc^2</m:t></m:r></m:oMath> → "E=mc^2"
clean = re.sub(r'<[^>]+>', '', omml_str) # 去除XML标签
# 实际需解析OMML节点,此处仅示意
return clean.replace('^', '**').replace('_', '\\_') # 基础符号映射
# 调用流程
formulas = extract_formulas("samples/word/tech_proposal.docx")
for i, omml in enumerate(formulas):
latex = omml_to_latex(omml)
print(f"公式{i+1}: {latex}")
注意事项 :
docx2python能提取OMML,但复杂公式(矩阵、积分)需omml2mathml库深度解析- 本项目
utils/omml_parser.py已封装完整转换链,支持90%以上Office公式 - 输出LaTeX可直接粘贴到Overleaf或Typora中编译
4.3 避坑:Word自动化中的三大“静默失败”
现象1:docxtpl生成的Word打开后提示“发现错误,尝试恢复”
原因 :模板中存在未闭合的Jinja2标签(如 {{ name 漏掉 }} )或非法XML字符(如 & 未转义为 & )。
解决 :
使用 docxtpl 的 strict 模式捕获语法错误
template = DocxTemplate(template_path)
try:
template.render(context, autoescape=True) # autoescape防止XML注入
except Exception as e:
print(f"模板渲染失败:{e}")
# 检查模板中所有{{ }}和{% %}是否配对
现象2:python-docx插入表格后,Word中列宽自动收缩为0
原因 : python-docx 默认表格无宽度设置,Word按内容自适应,窄内容导致列宽塌陷。
解决 :显式设置列宽(单位:EMU,1英寸=914400 EMU)
from docx.shared import Inches table = doc.add_table(rows=1, cols=3) # 设置列宽:第一列2英寸,第二列1.5英寸,第三列1英寸 table.columns[0].width = Inches(2.0) table.columns[1].width = Inches(1.5) table.columns[2].width = Inches(1.0)
现象3:Word宏安全设置阻止xlwings调用Excel
原因 : xlwings 需通过COM调用Excel,但Office默认禁用所有宏,且 python-docx 生成的文档可能被误判为含宏。
解决 :
- 临时关闭宏安全(仅开发环境):Excel → 文件 → 选项 → 信任中心 → 信任中心设置 → 宏设置 → 启用所有宏(不推荐)
- 生产环境正确做法 :用
openpyxl替代xlwings处理.xlsx,仅在必须调用Excel功能(如运行宏)时启用xlwings,并在代码中添加用户提示:
try:
import xlwings as xw
app = xw.App(visible=False)
# ... 执行操作
except Exception as e:
print("Excel COM调用失败,请检查Office是否安装及宏设置")
# 降级为openpyxl处理
5. PDF自动化:合并、加水印与OCR增强
5.1 合并PDF并添加书签:让20页报告秒变可导航文档
pypdf 的 PdfWriter 支持合并,但默认无书签。本项目 pdf_merger.py 在合并时为每个源文件添加顶层书签,并支持二级书签(如按章节):
# pdf_merger.py
from pypdf import PdfReader, PdfWriter
from pypdf.generic import OutlineItem
def merge_with_bookmarks(pdf_paths, output_path, bookmarks=None):
"""
pdf_paths: ["report_ch1.pdf", "report_ch2.pdf"]
bookmarks: [{"title": "第一章", "page": 0}, {"title": "第二章", "page": 12}]
"""
writer = PdfWriter()
# 记录每个文件的起始页码
page_offset = 0
outline_items = []
for i, path in enumerate(pdf_paths):
reader = PdfReader(path)
# 添加所有页面
for page in reader.pages:
writer.add_page(page)
# 为当前文件添加书签
if bookmarks and i < len(bookmarks):
title = bookmarks[i]["title"]
# 书签指向当前文件第0页(在合并后文档中的绝对页码)
outline_item = OutlineItem(title, page_offset)
outline_items.append(outline_item)
# 更新偏移量
page_offset += len(reader.pages)
# 写入书签
writer.add_outline_item_dict({item.title: item.page for item in outline_items})
# 保存
with open(output_path, "wb") as f:
writer.write(f)
print(f"已合并并添加书签:{output_path}")
# 调用示例
merge_with_bookmarks(
pdf_paths=["samples/pdf/ch1_intro.pdf", "samples/pdf/ch2_analysis.pdf"],
output_path="output/annual_report.pdf",
bookmarks=[{"title": "1. 引言", "page": 0}, {"title": "2. 分析", "page": 8}]
)
技术细节 :
OutlineItem(title, page)创建书签,page为绝对页码(从0开始)writer.add_outline_item_dict()批量添加,比逐个add_outline_item()更高效- 书签层级通过
parent参数控制,本例为平级,如需子书签:
sub_item = OutlineItem("1.1 背景", 1, parent=outline_items[0])
5.2 批量添加半透明水印:保护敏感报告不被截图传播
水印不是简单叠图,需考虑PDF多页、不同尺寸、文字抗锯齿。本项目 pdf_watermarker.py 使用 reportlab 生成矢量水印PDF,再用 pypdf 叠加:
# pdf_watermarker.py
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from pypdf import PdfReader, PdfWriter
def create_watermark(text, width=612, height=792):
"""生成单页水印PDF(A4尺寸)"""
watermark_path = "temp/watermark.pdf"
c = canvas.Canvas(watermark_path, pagesize=(width, height))
# 设置字体和透明度
c.setFont("Helvetica", 40)
c.setFillColorRGB(0.8, 0.8, 0.8, alpha=0.3) # RGB+alpha
# 斜向绘制文字
c.saveState()
c.translate(width / 2, height / 2)
c.rotate(30)
c.drawCentredString(0, 0, text)
c.restoreState()
c.save()
return watermark_path
def add_watermark(input_pdf, output_pdf, watermark_text="CONFIDENTIAL"):
watermark_path = create_watermark(watermark_text)
watermark_reader = PdfReader(watermark_path)
input_reader = PdfReader(input_pdf)
writer = PdfWriter()
for page in input_reader.pages:
# 将水印叠加到当前页
page.merge_page(watermark_reader.pages[0])
writer.add_page(page)
with open(output_pdf, "wb") as f:
writer.write(f)
print(f"已添加水印:{output_pdf}")
# 调用
add_watermark("samples/pdf/financial_report.pdf", "output/secure_report.pdf")
关键参数 :
alpha=0.3控制透明度(0=完全透明,1=不透明),0.2~0.4为最佳可读性平衡点c.rotate(30)旋转30度避免遮挡正文,c.translate()居中定位merge_page()是pypdf的底层叠加,比PageObject拼接更稳定
5.3 OCR增强:为扫描PDF添加可搜索文本层
扫描PDF本质是图片, pypdf 无法提取文字。本项目集成 pytesseract (Tesseract OCR引擎)和 pdf2image ,在 pdf_ocr_enhancer.py 中实现:
# pdf_ocr_enhancer.py
from pdf2image import convert_from_path
import pytesseract
from pypdf import PdfReader, PdfWriter
def ocr_pdf(input_path, output_path, lang="chi_sim+eng"):
"""
lang: "chi_sim"中文简体, "eng"英文, "chi_sim+eng"中英混合
"""
# 将PDF转为图像(每页一张PNG)
images = convert_from_path(input_path, dpi=300) # 高DPI提升OCR精度
# 创建新PDF写入器
writer = PdfWriter()
for i, image in enumerate(images):
# OCR识别文字
text = pytesseract.image_to_string(image, lang=lang, config="--psm 6")
# 创建空白PDF页(同原PDF尺寸)
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from io import BytesIO
packet = BytesIO()
can = canvas.Canvas(packet, pagesize=letter)
can.drawString(10, 10, text) # 文字层(实际需精确匹配图像位置)
can.save()
# 合并图像层与文字层(简化版,真实项目用pdfkit或pdfrw)
# (完整实现见utils/ocr_merger.py)
print(f"第{i+1}页OCR完成,识别字数:{len(text)}")
# 保存(此为示意,实际需用pdfkit生成含文本层的PDF)
# writer.write(output_path)
# 注意:需提前安装Tesseract
# Windows: https://github.com/UB-Mannheim/tesseract/wiki
# macOS: brew install tesseract
# Ubuntu: sudo apt install tesseract-ocr libtesseract-dev
部署要点 :
dpi=300是OCR精度底线,低于200dpi识别率骤降--psm 6(Page Segmentation Mode)指定“假设单文本块”,适合报表类扫描件- 中文识别需下载
chi_sim.traineddata,放入Tesseracttessdata目录
6. 生产就绪:错误日志、进度反馈与一键打包交付
6.1 用logging模块构建可追溯的办公流水线
手工操作出错难定位,自动化脚本必须留痕。本项目 core/logger.py 配置了文件+控制台双输出,按模块分级:
# core/logger.py
import logging
from datetime import datetime
def setup_logger(name, level=logging.INFO):
logger = logging.getLogger(name)
logger.setLevel(level)
# 文件处理器:按天滚动
file_handler = logging.handlers.RotatingFileHandler(
f"logs/{name}_{datetime.now().strftime('%Y%m%d')}.log",
maxBytes=10*1024*1024, # 10MB
backupCount=5
)
file_handler.setLevel(logging.DEBUG)
# 控制台处理器:仅INFO及以上
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 格式化
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(console_handler)
return logger
# 在excel_uuid_injector.py中使用
logger = setup_logger("excel_uuid")
logger.info("开始处理sales_data.xlsx")
logger.debug(f"生成UUID: {uuid_str}")
logger.error("列B为空,跳过第5行")
日志价值 :
logs/excel_uuid_20240520.log记录每次执行的完整上下文ERROR级别自动告警,如“找不到列‘地区’”,便于快速定位模板变更DEBUG级别记录中间变量,调试时开启,生产环境关闭
6.2 进度条与实时反馈:让等待不再焦虑
长任务(如OCR、PDF合并)需可视化进度。本项目 utils/progress_bar.py 封装 tqdm ,适配各模块:
# utils/progress_bar.py
from tqdm import tqdm
import time
def process_with_progress(items, desc="Processing", unit="item"):
"""通用进度条包装器"""
for item in tqdm(items, desc=desc, unit=unit, colour="green"):
yield item
time.sleep(0.1) # 模拟处理耗时
# 在pdf_merger.py中应用
pdf_paths = ["ch1.pdf", "ch2.pdf", "ch3.pdf"]
for pdf_path in process_with_progress(pdf_paths, desc="Merging PDFs", unit="file"):
reader = PdfReader(pdf_path)
# ... 合并逻辑
效果 :终端显示 Merging PDFs: 100%|██████████| 3/3 [00:00<00:00, 30.23file/s] ,支持中断恢复( tqdm 自动记录)。
以上就是Python办公自动化之Excel/Word/PDF实战完整教学的详细内容,更多关于Python办公自动化的资料请关注脚本之家其它相关文章!
