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

使用python-docx生成的Word文檔打開時彈出“無法讀取內(nèi)容“警告的解決方案

 更新時間:2026年05月06日 08:37:27   作者:岫珩  
這篇文章主要介紹了使用python-docx基于WPS模板生成.docx報告文件時,用Microsoft Word打開會彈出“無法讀取內(nèi)容”警告的問題及其解決方案,需要的朋友可以參考下

背景:使用 python-docx 基于 WPS 創(chuàng)建的模板生成 .docx 報告文件,用 Microsoft Word 打開時彈出以下警告:

“Word 在 report_xxx.docx 中發(fā)現(xiàn)無法讀取的內(nèi)容。是否恢復(fù)此文檔的內(nèi)容?如果您信任此文檔的來源,請單擊"是”。"

一、問題現(xiàn)象

程序運行正常,生成的 .docx 文件內(nèi)容完整,但每次用 Microsoft Word 打開都會彈出"無法讀取內(nèi)容"警告彈窗。點擊"是"之后文檔可以正常顯示,但這個警告嚴(yán)重影響用戶體驗,并暗示文件存在潛在的格式問題。

二、排查過程

第一步:常規(guī) XML 結(jié)構(gòu)檢查

首先懷疑是 python-docx 生成的 XML 本身存在格式問題,逐一檢查:

  • word/document.xml 的 body 結(jié)構(gòu)
  • 顏色值格式(#000000 vs 000000
  • 圖片關(guān)系引用
  • 樣式引用完整性
  • 書簽配對完整性
  • 表格 XML 結(jié)構(gòu)(tblPr/tblGrid/tblW

結(jié)果:全部通過,未發(fā)現(xiàn)異常。

插曲:檢查過程中確實發(fā)現(xiàn)了一個 #000000 顏色值格式問題——python-docx 要求顏色值不含 # 前綴(應(yīng)為 000000),修復(fù)后警告依然存在,說明這不是根本原因。

第二步:檢查customXml目錄

.docx 文件作為 ZIP 包解壓,進入 customXml/ 目錄檢查:

customXml/
├── item1.xml
├── item2.xml
├── _rels/
│   ├── item1.xml.rels
│   └── item2.xml.rels
├── itemProps1.xml   ← 關(guān)鍵文件
└── itemProps2.xml

打開 customXml/itemProps1.xml,發(fā)現(xiàn)了問題所在:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ds:datastoreItem ds:itemID="{B1977F7D-...}" xmlns:ds="...">
  <ds:schemaRefs>
    <ds:schemaRef ds:uri="http://www.wps.cn/officeDocument/2013/wpsCustomData"/>
  </ds:schemaRefs>
</ds:datastoreItem>

以及 customXml/item1.xml 中的私有數(shù)據(jù):

<s:customData xmlns="http://www.wps.cn/officeDocument/2013/wpsCustomData">
  <!-- WPS 私有擴展信息:形狀、段落屬性等 -->
</s:customData>

第三步:確認(rèn)完整關(guān)系鏈

word/_rels/document.xml.rels
  └─ rId12 → ../customXml/item1.xml   (WPS 私有數(shù)據(jù))
  └─ rId14 → ../customXml/item2.xml   (APA 書目,正常)
[Content_Types].xml
  └─ <Override PartName="/customXml/itemProps1.xml" ContentType="...customXmlProperties+xml"/>

三、根本原因

模板文件由 WPS(金山 Office)創(chuàng)建,WPS 會在 .docx 文件中嵌入私有的 wpsCustomData XML 數(shù)據(jù),其 schema URI 為:

http://www.wps.cn/officeDocument/2013/wpsCustomData

當(dāng) python-docx 加載該模板并保存新文檔時,這份 WPS 私有 customXml 數(shù)據(jù)會被完整保留到輸出文件中。

Microsoft Word 打開文檔時會嘗試驗證所有 customXml 的 schema 引用。由于 wpsCustomData 是 WPS 的私有 schema,Microsoft Word 無法找到或識別它,因此觸發(fā)"無法讀取內(nèi)容"警告。

四、解決方案

doc.save() 之后,直接對生成的 ZIP 包(即 .docx 文件)進行處理,移除 WPS 私有數(shù)據(jù)。

實現(xiàn)代碼

def clean_wps_custom_data(docx_path):
    """
    從生成的 docx 文件中移除 WPS 私有 customXml 數(shù)據(jù)。
    模板由 WPS 創(chuàng)建時會嵌入 wpsCustomData 私有 XML,其 schema URI 為
    http://www.wps.cn/officeDocument/2013/wpsCustomData,Microsoft Word
    無法識別此私有 schema,導(dǎo)致打開時彈出"無法讀取內(nèi)容"警告。
    此函數(shù)在 doc.save() 之后運行,直接對 ZIP 包進行手術(shù),移除該私有數(shù)據(jù)。
    """
    import zipfile, re, io
    buffer = io.BytesIO()
    try:
        with zipfile.ZipFile(docx_path, 'r') as z_in:
            with zipfile.ZipFile(buffer, 'w', compression=zipfile.ZIP_DEFLATED) as z_out:
                file_list = z_in.namelist()
                # 第一步:找出含有 WPS schema 引用的 itemProps 文件編號
                wps_item_nums = set()
                for fname in file_list:
                    if fname.startswith('customXml/itemProps') and fname.endswith('.xml'):
                        with z_in.open(fname) as f:
                            content = f.read().decode('utf-8', errors='replace')
                        if 'wps.cn' in content or 'wpsCustomData' in content:
                            m = re.search(r'itemProps(\d+)\.xml', fname)
                            if m:
                                wps_item_nums.add(m.group(1))
                # 第二步:構(gòu)建需要整體刪除的文件集合
                files_to_delete = set()
                for num in wps_item_nums:
                    files_to_delete.add(f'customXml/item{num}.xml')
                    files_to_delete.add(f'customXml/itemProps{num}.xml')
                    files_to_delete.add(f'customXml/_rels/item{num}.xml.rels')
                if not wps_item_nums:
                    print('clean_wps_custom_data: 未發(fā)現(xiàn) WPS 私有數(shù)據(jù),無需清理')
                    return
                print(f'clean_wps_custom_data: 發(fā)現(xiàn) WPS 私有數(shù)據(jù)(item 編號 {wps_item_nums}),正在清理...')
                # 第三步:逐文件處理,重新打包 ZIP
                for fname in file_list:
                    if fname in files_to_delete:
                        continue  # 跳過 WPS 私有文件,不寫入新 zip
                    with z_in.open(fname) as f:
                        data = f.read()
                    if fname == '[Content_Types].xml':
                        # 刪除 WPS itemProps 的 Override 聲明
                        content = data.decode('utf-8')
                        for num in wps_item_nums:
                            content = re.sub(
                                r'<Override[^>]*PartName="/customXml/itemProps' + num + r'\.xml"[^>]*/>', '',
                                content
                            )
                        z_out.writestr(fname, content.encode('utf-8'))
                    elif fname == 'word/_rels/document.xml.rels':
                        # 刪除指向 WPS item 文件的 Relationship 條目
                        content = data.decode('utf-8')
                        for num in wps_item_nums:
                            content = re.sub(
                                r'<Relationship[^>]*Target="\.\./customXml/item' + num + r'\.xml"[^>]*/>', '',
                                content
                            )
                        z_out.writestr(fname, content.encode('utf-8'))
                    else:
                        z_out.writestr(fname, data)
        # 將處理后的內(nèi)容寫回原文件
        buffer.seek(0)
        with open(docx_path, 'wb') as f:
            f.write(buffer.read())
        print('clean_wps_custom_data: WPS 私有數(shù)據(jù)清理完成')
    except Exception as e:
        print(f'clean_wps_custom_data: 清理失?。ú挥绊懳臋n內(nèi)容): {e}')

調(diào)用方式

doc = Document(template_path)
# ... 填充內(nèi)容 ...
doc.save(output_path)
clean_wps_custom_data(output_path)   # ← 緊接在 save 之后調(diào)用

五、方案要點說明

為什么不直接修改模板文件?

可以手動用 Microsoft Word 打開模板并重新保存,以去除 WPS 私有數(shù)據(jù)。但這種方式存在風(fēng)險:

  • 每次模板更新后都需要手動處理
  • 在自動化流水線中無法保證

因此選擇在代碼層面自動清理,更加健壯。

ZIP 重打包的注意事項

.docx 本質(zhì)上是一個 ZIP 文件。修改其內(nèi)容的正確方式是:

  1. 讀取原 ZIP 到內(nèi)存(io.BytesIO
  2. 創(chuàng)建新 ZIP,逐文件寫入(跳過或修改目標(biāo)文件)
  3. 將新 ZIP 的內(nèi)容寫回原路徑

不要直接在原 ZIP 上增刪文件(Python 的 zipfile 模塊不支持原地刪除),否則會損壞文件結(jié)構(gòu)。

正則表達式中[^>]*的選擇

處理 [Content_Types].xmldocument.xml.rels 時,需要匹配完整的 XML 元素標(biāo)簽。注意:

# ? 錯誤:[^/]* 會在 ContentType 屬性值中的 / 處提前停止
r'<Override[^>]*PartName="..."[^/]*/>'

# ? 正確:[^>]* 只排除 >,允許屬性值中包含 /
r'<Override[^>]*PartName="..."[^>]*/>'

ContentType="application/vnd.openxmlformats-officedocument.customXmlProperties+xml" 中包含 /,必須使用 [^>]* 才能正確匹配到 />。

只清理 WPS 私有項,保留其他 customXml

文檔中可能存在合法的 customXml 數(shù)據(jù)(如 APA 書目數(shù)據(jù)),清理時通過檢測 wps.cn 域名精確定位,只刪除 WPS 私有項,不影響其他數(shù)據(jù)。

六、驗證方法

用 Python 對清理前后的文件進行驗證:

import zipfile

def verify_clean(docx_path):
    with zipfile.ZipFile(docx_path, 'r') as z:
        file_list = z.namelist()

        # 1. 檢查是否還有 WPS schema 引用
        for fname in file_list:
            if fname.startswith('customXml/itemProps') and fname.endswith('.xml'):
                with z.open(fname) as f:
                    content = f.read().decode('utf-8', errors='replace')
                if 'wps.cn' in content or 'wpsCustomData' in content:
                    print(f"? 仍有 WPS schema: {fname}")
                    return False

        # 2. 檢查 document.xml.rels
        with z.open('word/_rels/document.xml.rels') as f:
            rels = f.read().decode('utf-8')
        if 'wpsCustomData' in rels or ('customXml' in rels and 'wps.cn' in rels):
            print("? document.xml.rels 中仍有 WPS 引用")
            return False

        print("? 清理驗證通過,無 WPS 私有數(shù)據(jù)殘留")
        return True

七、總結(jié)

項目內(nèi)容
問題根因WPS 創(chuàng)建的模板內(nèi)嵌私有 wpsCustomData schema,Microsoft Word 無法識別
觸發(fā)條件用 python-docx 加載 WPS 模板并保存,私有數(shù)據(jù)被保留到輸出文件
修復(fù)方式doc.save() 后對 ZIP 包進行后處理,刪除 WPS 私有文件并清理引用
清理范圍customXml/item{n}.xml、customXml/itemProps{n}.xml、customXml/_rels/item{n}.xml.rels[Content_Types].xml 中的 Override 聲明、word/_rels/document.xml.rels 中的 Relationship 條目
副作用無,不影響文檔內(nèi)容和其他合法 customXml 數(shù)據(jù)

適用場景:所有使用 python-docx 基于 WPS 創(chuàng)建的模板生成 Word 文檔的場景,均可能遇到此問題,使用本文的清理方案可徹底解決。

以上就是使用python-docx生成的Word文檔打開時彈出“無法讀取內(nèi)容“警告的解決方案的詳細(xì)內(nèi)容,更多關(guān)于python-docx生成的Word無法讀取內(nèi)容的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python 按字典dict的鍵排序,并取出相應(yīng)的鍵值放于list中的實例

    Python 按字典dict的鍵排序,并取出相應(yīng)的鍵值放于list中的實例

    今天小編就為大家分享一篇Python 按字典dict的鍵排序,并取出相應(yīng)的鍵值放于list中的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-02-02
  • PyCharm代碼回滾,恢復(fù)歷史版本的解決方法

    PyCharm代碼回滾,恢復(fù)歷史版本的解決方法

    今天小編就為大家分享一篇PyCharm代碼回滾,恢復(fù)歷史版本的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-10-10
  • 使用celery執(zhí)行Django串行異步任務(wù)的方法步驟

    使用celery執(zhí)行Django串行異步任務(wù)的方法步驟

    這篇文章主要介紹了使用celery執(zhí)行Django串行異步任務(wù),文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Django具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • Python導(dǎo)入其他路徑下的文件報錯的問題及解決

    Python導(dǎo)入其他路徑下的文件報錯的問題及解決

    文章主要討論了Python模塊導(dǎo)入的路徑問題,并提供了幾種解決方案,包括使用絕對路徑和修改sys.path等,通過這些方法,可以解決在導(dǎo)入模塊時出現(xiàn)的ModuleNotFoundError問題,特別是在使用打包工具如pyinstaller時
    2026-01-01
  • Python面向?qū)ο笾鄳B(tài)原理與用法案例分析

    Python面向?qū)ο笾鄳B(tài)原理與用法案例分析

    這篇文章主要介紹了Python面向?qū)ο笾鄳B(tài)原理與用法,結(jié)合具體案例形式分析了Python多態(tài)的具體功能、原理、使用方法與操作注意事項,需要的朋友可以參考下
    2019-12-12
  • Python3使用tesserocr識別字母數(shù)字驗證碼的實現(xiàn)

    Python3使用tesserocr識別字母數(shù)字驗證碼的實現(xiàn)

    這篇文章主要介紹了Python3使用tesserocr識別字母數(shù)字驗證碼的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Python爬蟲基礎(chǔ)初探selenium

    Python爬蟲基礎(chǔ)初探selenium

    selenium最初是一個自動化測試工具,而爬蟲中使用它主要是為了解決requests無法執(zhí)行javaScript代碼的問題。本文給大家分享Python爬蟲基礎(chǔ)selenium知識,包括selenium工作原理,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • Appium+python+unittest搭建UI自動化框架的實現(xiàn)

    Appium+python+unittest搭建UI自動化框架的實現(xiàn)

    本文主要介紹了Appium+python+unittest搭建UI自動化框架的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-03-03
  • Python基于opencv實現(xiàn)的人臉識別(適合初學(xué)者)

    Python基于opencv實現(xiàn)的人臉識別(適合初學(xué)者)

    OpenCV是一個基于BSD許可開源發(fā)行的跨平臺計算機視覺庫,下面這篇文章主要給大家介紹了關(guān)于Python基于opencv實現(xiàn)的人臉識別,文中通過實例代碼介紹的非常詳細(xì),本文的教程非常適合初學(xué)者,需要的朋友可以參考下
    2022-03-03
  • Python3.9新特性詳解

    Python3.9新特性詳解

    這篇文章主要介紹了Python3.9新特性詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10

最新評論

沙坪坝区| 呼玛县| 慈利县| 当涂县| 赣州市| 广元市| 绥化市| 峨眉山市| 晋宁县| 乌拉特后旗| 孝感市| 邯郸市| 白沙| 巨野县| 伊春市| 蓬莱市| 新田县| 礼泉县| 科技| 扎赉特旗| 三穗县| 扶绥县| 双桥区| 合作市| 通渭县| 贡嘎县| 台东县| 翁牛特旗| 怀仁县| 临沭县| 盐山县| 深水埗区| 玛纳斯县| 兴城市| 龙井市| 扎兰屯市| 婺源县| 克东县| 红桥区| 尼玛县| 双流县|