欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python輕松實現(xiàn)Word文檔對比并生成可視化HTML報告

 更新時間:2025年08月29日 08:22:18   作者:幸福清風  
在日常工作和學習中,我們經(jīng)常需要對兩個版本的文檔進行比對,本文將使用 Python + python-docx + difflib 實現(xiàn)一個自動化 Word 文檔對比工具,感興趣的可以了解下

在日常工作和學習中,我們經(jīng)常需要對兩個版本的文檔進行比對,比如合同修改、論文修訂、報告更新等。手動逐字檢查不僅耗時費力,還容易遺漏細節(jié)。

今天,我將帶你使用 Python + python-docx + difflib 實現(xiàn)一個自動化 Word 文檔對比工具,不僅能精準識別段落增刪改,還能生成美觀的 HTML 可視化報告,并自動在瀏覽器中打開查看!

項目效果預覽

運行腳本后:

  • 自動讀取兩個 .docx 文件
  • 按段落逐一對比內(nèi)容差異
  • 生成一份 高亮標注差異 的 HTML 報告
  • 支持瀏覽器自動打開,無需手動查找文件

完全自動化 | 差異高亮顯示 |  支持中文 | 界面美觀專業(yè)

技術棧簡介

技術作用
python-docx讀取 .docx 文件內(nèi)容
difflib計算文本差異(增刪改)
webbrowser自動打開瀏覽器預覽結果
os / datetime文件路徑處理與時間戳記錄
原生 HTML + CSS生成結構清晰、樣式現(xiàn)代化的報告頁面

核心功能解析

讀取.docx文件內(nèi)容

from docx import Document

def read_docx(file_path):
    """讀取 .docx 文件,返回段落列表"""
    try:
        doc = Document(file_path)
        paragraphs = [para.text.strip() for para in doc.paragraphs if para.text.strip()]
        return paragraphs
    except Exception as e:
        print(f"? 讀取文件 {file_path} 時出錯: {e}")
        return []

說明:

  • 使用 Document 加載 Word 文件
  • 提取所有非空段落,并去除首尾空格
  • 異常捕獲確保程序健壯性

利用difflib實現(xiàn)文本差異分析

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

difflib.SequenceMatcher 是 Python 內(nèi)置的強大工具,可以分析兩個字符串之間的差異操作(equal, insert, delete, replace),我們據(jù)此為每個字符添加 HTML 標簽高亮。

例如:

<span class='diff-delete'>[刪除: 這句話被刪了]</span>
<span class='diff-add'>[新增: 這是新內(nèi)容]</span>

生成精美 HTML 報告

我們構建了一個完整的 HTML 頁面,包含:

響應式設計 + 現(xiàn)代化 UI 風格

  • 漸變標題欄
  • 圓角卡片式表格
  • 懸停交互效果
  • 適配中文字體

對比概覽區(qū)

顯示文件名、段落數(shù)量、生成時間等元信息。

詳細對比表格

段落文檔1內(nèi)容文檔2內(nèi)容差異狀態(tài)
第1段相同相同完全相同
第2段被刪除新增內(nèi)容內(nèi)容有差異

每一段都用顏色區(qū)分:

  • 綠色:相同內(nèi)容
  • 紅色:刪除或缺失
  • 藍色:新增內(nèi)容
  • 黃色背景:整段新增/刪除

自動生成并打開報告

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

一鍵生成報告后,自動調(diào)用系統(tǒng)默認瀏覽器打開,用戶體驗極佳!

使用方法(超簡單)

步驟 1:安裝依賴

pip install python-docx

注意:difflib 是標準庫,無需安裝。

步驟 2:修改主函數(shù)中的文件路徑

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'
?? 報告已自動在默認瀏覽器中打開。

報告截圖展示

  • 頂部標題:帶有時間戳和漸變背景
  • 對比表格:左右并列展示,差異高亮
  • 狀態(tài)標識:圖標+顏色提示,一目了然

完整代碼下載

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

import difflib
from docx import Document
import webbrowser
import os
from datetime import datetime

def read_docx(file_path):
    """讀取 .docx 文件,返回段落列表"""
    try:
        doc = Document(file_path)
        paragraphs = [para.text.strip() for para in doc.paragraphs if para.text.strip()]
        return paragraphs
    except Exception as e:
        print(f"? 讀取文件 {file_path} 時出錯: {e}")
        return []

def generate_html_report(paras1, paras2, file1_name, file2_name, output_html="對比報告.html"):
    """
    根據(jù)對比結果生成 HTML 報告。
    """
    # 構建 HTML 內(nèi)容
    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>段落數(shù)量:</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>差異狀態(tài)</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 None
        p2 = 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>"

        # 確定差異狀態(tài)
        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'>?? 內(nèi)容有差異</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_html
    except Exception as e:
        print(f"? 生成 HTML 文件時出錯: {e}")
        return None

def 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("? 文檔讀取失敗,請檢查文件。")
        return

    print(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:// URL
        url = 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()

以上就是Python輕松實現(xiàn)Word文檔對比并生成可視化HTML報告的詳細內(nèi)容,更多關于Python對比Word文檔的資料請關注腳本之家其它相關文章!

相關文章

  • python中如何使用正則表達式的非貪婪模式示例

    python中如何使用正則表達式的非貪婪模式示例

    貪婪與非貪婪模式影響的是被量詞修飾的子表達式的匹配行為,下面這篇文章主要給大家介紹了關于python中如何使用正則表達式的非貪婪模式的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習具有一定的參考學習價值,需要的朋友們下面來一起看看吧。
    2017-10-10
  • python 根據(jù)pid殺死相應進程的方法

    python 根據(jù)pid殺死相應進程的方法

    下面小編就為大家?guī)硪黄猵ython 根據(jù)pid殺死相應進程的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • python celery beat實現(xiàn)定時任務的示例代碼

    python celery beat實現(xiàn)定時任務的示例代碼

    在日常工作中,我們常常會用到需要周期性執(zhí)行的任務,本文主要介紹了python celery beat實現(xiàn)定時任務的示例代碼,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • python刪掉重復行之drop_duplicates()用法示例

    python刪掉重復行之drop_duplicates()用法示例

    Pandas的drop_duplicates()方法用于從DataFrame中刪除重復的行,這篇文章主要給大家介紹了關于python刪掉重復行之drop_duplicates()用法的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-08-08
  • Flask創(chuàng)建并運行數(shù)據(jù)庫遷移的實現(xiàn)過程

    Flask創(chuàng)建并運行數(shù)據(jù)庫遷移的實現(xiàn)過程

    Flask創(chuàng)建并運行數(shù)據(jù)庫遷移的過程是一個涉及多個步驟的操作,旨在幫助開發(fā)者在開發(fā)過程中管理數(shù)據(jù)庫模式的變化,而不需要手動地刪除和重建數(shù)據(jù)庫表,從而避免數(shù)據(jù)丟失,以下是一個詳細的步驟說明,需要的朋友可以參考下
    2024-09-09
  • Python能干什么、Python主要應用于哪些方面

    Python能干什么、Python主要應用于哪些方面

    無論是從入門級選手到專業(yè)級選手都在做的爬蟲,還是Web程序開發(fā)、桌面程序開發(fā)還是科學計算、圖像處理, Python都可以勝任。Python為我們提供了非常完善的基礎代碼庫,覆蓋了網(wǎng)絡、文件、GUI、 數(shù)據(jù)庫、文本等大量內(nèi)容。用Python開發(fā),許多功能不必從零編寫
    2023-06-06
  • Python中dict排序的兩種方法

    Python中dict排序的兩種方法

    字典本身是無序的,所以它每次輸出都是不一樣的,順序都是亂的,那么字典如何排序,本文主要介紹了Python中dict排序的兩種方法,感興趣的可以了解一下
    2024-01-01
  • python同時替換多個字符串方法示例

    python同時替換多個字符串方法示例

    這篇文章主要介紹了python同時替換多個字符串方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • PyQt5學習之QThread類的使用詳解

    PyQt5學習之QThread類的使用詳解

    QThread是Qt線程類中最核心的底層類。要使用QThrea開始一個線程,可以創(chuàng)建它的一個子類,然后覆蓋其QThread.run()函數(shù)。這篇文章就來和大家聊聊QThread類的使用,感興趣的可以學習一下
    2022-12-12
  • pandas中std和numpy的np.std區(qū)別及說明

    pandas中std和numpy的np.std區(qū)別及說明

    這篇文章主要介紹了pandas中std和numpy的np.std區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08

最新評論