最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

項目效果預(yù)覽

運行腳本后:

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

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

技術(shù)棧簡介

技術(shù)作用
python-docx讀取 .docx 文件內(nèi)容
difflib計算文本差異(增刪改)
webbrowser自動打開瀏覽器預(yù)覽結(jié)果
os / datetime文件路徑處理與時間戳記錄
原生 HTML + CSS生成結(jié)構(gòu)清晰、樣式現(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 標(biāo)簽高亮。

例如:

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

生成精美 HTML 報告

我們構(gòu)建了一個完整的 HTML 頁面,包含:

響應(yīng)式設(shè)計 + 現(xiàn)代化 UI 風(fēng)格

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

對比概覽區(qū)

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

詳細(xì)對比表格

段落文檔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)默認(rèn)瀏覽器打開,用戶體驗極佳!

使用方法(超簡單)

步驟 1:安裝依賴

pip install python-docx

注意:difflib 是標(biāo)準(zhǔn)庫,無需安裝。

步驟 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'
?? 報告已自動在默認(rèn)瀏覽器中打開。

報告截圖展示

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

完整代碼下載

你可以將本文提供的完整代碼保存為 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ù)對比結(jié)果生成 HTML 報告。
    """
    # 構(gòu)建 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>?? 詳細(xì)對比結(jié)果</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

        # 生成差異標(biāo)記文本
        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標(biāo)簽
    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)
        # 構(gòu)造 file:// URL
        url = f"file://{abs_path}"
        # 自動打開瀏覽器
        try:
            webbrowser.open(url)
            print(f"?? 報告已自動在默認(rèn)瀏覽器中打開。")
        except Exception as e:
            print(f"??  自動打開瀏覽器失敗,您可以手動打開文件:\n   {abs_path}")
    else:
        print("? 報告生成失敗。")

if __name__ == "__main__":
    main()

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

相關(guān)文章

  • Python Pandas describe()函數(shù)的使用詳解

    Python Pandas describe()函數(shù)的使用詳解

    pandas庫中的describe()函數(shù)為我們提供了這樣的功能,它可以快速生成數(shù)據(jù)集的描述性統(tǒng)計信息,這篇文章主要介紹了Python Pandas describe()函數(shù)的使用介紹,需要的朋友可以參考下
    2024-05-05
  • 快速解決pyqt5窗體關(guān)閉后子線程不同時退出的問題

    快速解決pyqt5窗體關(guān)閉后子線程不同時退出的問題

    今天小編就為大家分享一篇快速解決pyqt5窗體關(guān)閉后子線程不同時退出的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-06-06
  • Pycharm中切換pytorch的環(huán)境和配置的教程詳解

    Pycharm中切換pytorch的環(huán)境和配置的教程詳解

    這篇文章主要介紹了Pycharm中切換pytorch的環(huán)境和配置,本文給大家介紹的非常詳細(xì),對大家的工作或?qū)W習(xí)具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • Pandas中八個常用option設(shè)置的示例詳解

    Pandas中八個常用option設(shè)置的示例詳解

    通過pandas的使用,我們經(jīng)常要交互式地展示表格(dataframe)、分析表格。本文整理了8個常用的配置選項,使用可以提高很多效率,需要的可以參考一下
    2022-06-06
  • python中的np.round()函數(shù)示例詳解

    python中的np.round()函數(shù)示例詳解

    np.round()是NumPy庫中的一個函數(shù),用于對數(shù)組或單個數(shù)值進行四舍五入,該函數(shù)返回一個與輸入類型相同的數(shù)組或數(shù)值,并可以通過可選的參數(shù)來指定保留的小數(shù)位數(shù),這篇文章主要介紹了python中的np.round()函數(shù),需要的朋友可以參考下
    2024-06-06
  • python執(zhí)行數(shù)據(jù)庫的查詢操作實例講解

    python執(zhí)行數(shù)據(jù)庫的查詢操作實例講解

    在本篇文章里小編給大家整理了一篇關(guān)于python執(zhí)行數(shù)據(jù)庫的查詢操作實例講解內(nèi)容,有需要的朋友們可以參考學(xué)習(xí)下。
    2021-10-10
  • Python實現(xiàn)基于HTTP文件傳輸實例

    Python實現(xiàn)基于HTTP文件傳輸實例

    這篇文章主要介紹了Python實現(xiàn)基于HTTP文件傳輸?shù)姆椒?以實例形式詳細(xì)講述了server端與client端的實現(xiàn)代碼,非常具有實用價值,需要的朋友可以參考下
    2014-11-11
  • Python利用matplotlib模塊數(shù)據(jù)可視化繪制3D圖

    Python利用matplotlib模塊數(shù)據(jù)可視化繪制3D圖

    matplotlib是python最著名的繪圖庫,它提供了一整套和matlab相似的命令A(yù)PI,十分適合交互式地行制圖,下面這篇文章主要給大家介紹了關(guān)于Python利用matplotlib模塊數(shù)據(jù)可視化實現(xiàn)3D圖的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • python文件編寫好后如何實踐

    python文件編寫好后如何實踐

    在本篇文章里小編給大家分享了關(guān)于python文件編寫好后如何實踐的相關(guān)內(nèi)容,需要的朋友們可以參考下。
    2020-07-07
  • Python調(diào)用接口合并Excel表代碼實例

    Python調(diào)用接口合并Excel表代碼實例

    這篇文章主要介紹了Python調(diào)用接口合并Excel表代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03

最新評論

夏河县| 尚志市| 建湖县| 当雄县| 安顺市| 宁明县| 九江市| 贵定县| 阿坝| 垦利县| 工布江达县| 静宁县| 阿拉善左旗| 莲花县| 木兰县| 穆棱市| 东莞市| 汝南县| 钟山县| 那坡县| 江门市| 新巴尔虎左旗| 马尔康县| 右玉县| 固镇县| 白山市| 彭泽县| 合阳县| 安龙县| 五峰| 通榆县| 麟游县| 沭阳县| 涿鹿县| 青河县| 中卫市| 兴业县| 永修县| 宁津县| 青冈县| 南靖县|