当前位置: 首页 > news >正文

【Word】用 Python 轻松实现 Word 文档对比并生成可视化 HTML 报告

在日常工作和学习中,我们经常需要对两个版本的文档进行比对,比如合同修改、论文修订、报告更新等。手动逐字检查不仅耗时费力,还容易遗漏细节。

今天,我将带你使用 Python + python-docx + difflib 实现一个自动化 Word 文档对比工具,不仅能精准识别段落增删改,还能生成美观的 HTML 可视化报告,并自动在浏览器中打开查看!


🚀 项目效果预览

运行脚本后:

  • 自动读取两个 .docx 文件
  • 按段落逐一对比内容差异
  • 生成一份 高亮标注差异 的 HTML 报告
  • 支持浏览器自动打开,无需手动查找文件

完全自动化 | ✅ 差异高亮显示 | ✅ 支持中文 | ✅ 界面美观专业


🛠️ 技术栈简介

技术作用
python-docx读取 .docx 文件内容
difflib计算文本差异(增删改)
webbrowser自动打开浏览器预览结果
os / datetime文件路径处理与时间戳记录
原生 HTML + CSS生成结构清晰、样式现代化的报告页面

📂 核心功能解析

1️⃣ 读取 .docx 文件内容

from docx import Documentdef read_docx(file_path):"""读取 .docx 文件,返回段落列表"""try:doc = Document(file_path)paragraphs = [para.text.strip() for para in doc.paragraphs if para.text.strip()]return paragraphsexcept Exception as e:print(f"❌ 读取文件 {file_path} 时出错: {e}")return []

📌 说明:

  • 使用 Document 加载 Word 文件
  • 提取所有非空段落,并去除首尾空格
  • 异常捕获确保程序健壮性

2️⃣ 利用 difflib 实现文本差异分析

matcher = difflib.SequenceMatcher(None, p1, p2)
opcodes = matcher.get_opcodes()

difflib.SequenceMatcher 是 Python 内置的强大工具,可以分析两个字符串之间的差异操作(equal, insert, delete, replace),我们据此为每个字符添加 HTML 标签高亮。

例如:

<span class='diff-delete'>[删除: 这句话被删了]</span>
<span class='diff-add'>[新增: 这是新内容]</span>

3️⃣ 生成精美 HTML 报告

我们构建了一个完整的 HTML 页面,包含:

✅ 响应式设计 + 现代化 UI 风格
  • 渐变标题栏
  • 圆角卡片式表格
  • 悬停交互效果
  • 适配中文字体
✅ 对比概览区

显示文件名、段落数量、生成时间等元信息。

✅ 详细对比表格
段落文档1内容文档2内容差异状态
第1段✅ 相同✅ 相同✅ 完全相同
第2段❌ 被删除➕ 新增内容⚠️ 内容有差异

每一段都用颜色区分:

  • 🟢 绿色:相同内容
  • 🔴 红色:删除或缺失
  • 🔵 蓝色:新增内容
  • 🟡 黄色背景:整段新增/删除

4️⃣ 自动生成并打开报告

abs_path = os.path.abspath(report_path)
url = f"file://{abs_path}"
webbrowser.open(url)

一键生成报告后,自动调用系统默认浏览器打开,用户体验极佳!


💡 使用方法(超简单)

步骤 1:安装依赖

pip install python-docx

⚠️ 注意:difflib 是标准库,无需安装。

步骤 2:修改主函数中的文件路径

file1_path = r'C:\Users\Administrator\Desktop\11.docx'
file2_path = r'C:\Users\Administrator\Desktop\22docx.docx'file1_name = "11.docx (原文版)"
file2_name = "22docx.docx (对比版)"
output_html_file = "荷塘月色_对比报告.html"

📌 支持任意 .docx 文件,建议使用绝对路径避免出错。

步骤 3:运行脚本

python docx_compare.py

输出示例:

🚀 正在启动文档对比程序...
============================================================
✅ 成功读取文档!• 11.docx (原文版) 共 15 段• 22docx.docx (对比版) 共 17 段
✅ HTML 报告已成功生成: '荷塘月色_对比报告.html'
🌐 报告已自动在默认浏览器中打开。

🖼️ 报告截图展示

在这里插入图片描述
在这里插入图片描述

  • 顶部标题:带有时间戳和渐变背景
  • 对比表格:左右并列展示,差异高亮
  • 状态标识:图标+颜色提示,一目了然

📎 完整代码下载

你可以将本文提供的完整代码保存为 docx_compare.py,稍作配置即可使用。

import difflib
from docx import Document
import webbrowser
import os
from datetime import datetimedef read_docx(file_path):"""读取 .docx 文件,返回段落列表"""try:doc = Document(file_path)paragraphs = [para.text.strip() for para in doc.paragraphs if para.text.strip()]return paragraphsexcept Exception as e:print(f"❌ 读取文件 {file_path} 时出错: {e}")return []def generate_html_report(paras1, paras2, file1_name, file2_name, output_html="对比报告.html"):"""根据对比结果生成 HTML 报告。"""# 构建 HTML 内容html_content = f"""<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><title>文档对比报告</title><style>body {{font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;line-height: 1.8;color: #333;max-width: 1200px;margin: 0 auto;padding: 20px;background-color: #f9f9f9;}}.header {{text-align: center;background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);color: white;padding: 30px 20px;border-radius: 10px;margin-bottom: 30px;box-shadow: 0 4px 6px rgba(0,0,0,0.1);}}.header h1 {{margin: 0;font-size: 2.5em;}}.header p {{margin: 10px 0 0;opacity: 0.9;}}.comparison-table {{width: 100%;border-collapse: collapse;margin: 20px 0;box-shadow: 0 2px 10px rgba(0,0,0,0.1);background-color: white;border-radius: 8px;overflow: hidden;}}.comparison-table th {{background-color: #4a5568;color: white;text-align: left;padding: 15px;font-weight: 600;}}.comparison-table td {{padding: 15px;border-bottom: 1px solid #e2e8f0;vertical-align: top;}}.comparison-table tr:nth-child(even) {{background-color: #f7fafc;}}.comparison-table tr:hover {{background-color: #ebf8ff;}}.diff-equal {{color: #22c55e;font-weight: 600;}}.diff-delete {{color: #e53e3e;font-weight: 600;}}.diff-add {{color: #3182ce;font-weight: 600;}}.context {{font-family: 'Courier New', monospace;background-color: #f1f5f9;padding: 10px;border-radius: 5px;white-space: pre-wrap;word-wrap: break-word;font-size: 0.95em;}}.footer {{text-align: center;margin-top: 40px;color: #718096;font-size: 0.9em;}}.highlight {{background-color: #fff3cd;padding: 2px 4px;border-radius: 3px;}}</style></head><body><div class="header"><h1>📄 文档对比报告</h1><p>生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p></div><h2>📊 对比概览</h2><p><strong>文档 1:</strong> {file1_name}</p><p><strong>文档 2:</strong> {file2_name}</p><p><strong>段落数量:</strong> 文档1: {len(paras1)} 段, 文档2: {len(paras2)} 段</p><h2>🔍 详细对比结果</h2><table class="comparison-table"><thead><tr><th>段落</th><th>{file1_name}</th><th>{file2_name}</th><th>差异状态</th></tr></thead><tbody>"""max_len = max(len(paras1), len(paras2))for i in range(max_len):p1 = paras1[i] if i < len(paras1) else Nonep2 = paras2[i] if i < len(paras2) else None# 生成差异标记文本if p1 is not None and p2 is not None:matcher = difflib.SequenceMatcher(None, p1, p2)opcodes = matcher.get_opcodes()result1 = []result2 = []for tag, i1, i2, j1, j2 in opcodes:if tag == 'equal':result1.append(p1[i1:i2])result2.append(p2[j1:j2])elif tag == 'delete':result1.append(f"<span class='diff-delete'>[删除: {p1[i1:i2]}]</span>")result2.append(f"<span class='diff-add'>[缺失]</span>")elif tag == 'insert':result1.append(f"<span class='diff-add'>[缺失]</span>")result2.append(f"<span class='diff-delete'>[新增: {p2[j1:j2]}]</span>")elif tag == 'replace':result1.append(f"<span class='diff-delete'>[删除: {p1[i1:i2]}]</span>")result2.append(f"<span class='diff-add'>[新增: {p2[j1:j2]}]</span>")marked_p1 = ''.join(result1)marked_p2 = ''.join(result2)else:marked_p1 = p1 or "<span class='diff-add'>[该段落不存在]</span>"marked_p2 = p2 or "<span class='diff-add'>[该段落不存在]</span>"# 确定差异状态if p1 is None:status = f"<span class='diff-add'>➕ 新增段落</span>"elif p2 is None:status = f"<span class='diff-delete'>➖ 删除段落</span>"elif p1 == p2:status = f"<span class='diff-equal'>✅ 完全相同</span>"else:status = f"<span class='diff-delete'>⚠️ 内容有差异</span>"# 添加到HTML表格中paragraph_num = f"第 {i+1} 段"html_content += f"""<tr><td><strong>{paragraph_num}</strong></td><td class="context">{marked_p1}</td><td class="context">{marked_p2}</td><td>{status}</td></tr>"""# 闭合HTML标签html_content += f"""</tbody></table><div class="footer"><p>此报告由 Python 文档对比工具自动生成</p></div></body></html>"""# 写入文件try:with open(output_html, 'w', encoding='utf-8') as f:f.write(html_content)print(f"✅ HTML 报告已成功生成: '{output_html}'")return output_htmlexcept Exception as e:print(f"❌ 生成 HTML 文件时出错: {e}")return Nonedef main():# 🔧 请修改为您的实际文件路径file1_path = r'C:\Users\Administrator\Desktop\11.docx'file2_path = r'C:\Users\Administrator\Desktop\22docx.docx'# 自定义显示名称file1_name = "11.docx (原文版)"file2_name = "22docx.docx (对比版)"output_html_file = "荷塘月色_对比报告.html"print("🚀 正在启动文档对比程序...")print("=" * 60)# 读取文档paras1 = read_docx(file1_path)paras2 = read_docx(file2_path)if not paras1 or not paras2:print("⛔ 文档读取失败,请检查文件。")returnprint(f"✅ 成功读取文档!")print(f"   • {file1_name} 共 {len(paras1)} 段")print(f"   • {file2_name} 共 {len(paras2)} 段")# 生成 HTML 报告report_path = generate_html_report(paras1, paras2, file1_name, file2_name, output_html_file)if report_path:# 获取文件的绝对路径abs_path = os.path.abspath(report_path)# 构造 file:// URLurl = f"file://{abs_path}"# 自动打开浏览器try:webbrowser.open(url)print(f"🌐 报告已自动在默认浏览器中打开。")except Exception as e:print(f"⚠️  自动打开浏览器失败,您可以手动打开文件:\n   {abs_path}")else:print("❌ 报告生成失败。")if __name__ == "__main__":main()
http://www.dtcms.com/a/355108.html

相关文章:

  • 《Rust 深度解析:核心概念、产业应用与生态全景报告》
  • 沙箱操作指南
  • 系统设计原则
  • 【Selenium】UI自动化测试框架设计:从项目结构到Base-Page层的最佳实践
  • 1-python 自定义模板导出文档-基础实现
  • 【cursor】提示词示范
  • 瑞芯微RK3568与君正X2600e平台Linux系统CS创世SD NAND应用全解析与驱动架构详解
  • springboot Apache PDFBox 通过路径参数读取文件信息流,并转化为pdf 在网页预览
  • 云计算学习100天-第31天
  • vue table 甘特图 vxe-gantt 实现多个表格的任务互相拖拽数据
  • GitHub 热榜项目 - 日榜(2025-08-28)
  • 鸿蒙banner页实现
  • Docker从零学习系列之Docker是什么?
  • Java有几种文件拷贝方式,哪一种效率最高?
  • 【DAB收音机】DAB 信号发生器介绍
  • 从零入门:C 语言操作 MySQL 数据库的完整指南
  • 多模态大模型研究每日简报【2025-08-28】
  • Logstash数据迁移之es-to-kafka.conf详细配置
  • 5G核心网的架构和功能详解
  • 大模型微调技术
  • 自下而上的树形dp
  • Servlet 注解:简化配置的完整指南
  • 隐语Kuscia正式发布 1.0.0 版本,实现支持 Hive 数据源,支持 envoy 日志进行异常分析等功能
  • hive on tez如果是2个大表union会写几次临时文件到hdfs目录,数据量如何计算
  • hive on tez为什么写表时,要写临时文件到hdfs目录
  • 最长连续序列,leetCode热题100,C++实现
  • 解读 AUTOSAR AP R24-11 Manifest 规范 —— 从部署到安全的全流程支撑
  • 可拖拽指令
  • Xray与XPOC工具对比分析
  • 让企业资产管理高效透明——深度解析固定资产管理系统的功能、优势与价值