使用Python-docx突出显示DOCX文件中的单词会产生不正确的结果



我想在MS Word文档中突出显示特定的单词(此处为Negativelist),并像以前一样将其余的文档留下。我试图从此中采用,但无法按照应有的方式运行:

from docx.enum.text import WD_COLOR_INDEX
from docx import Document
import pandas as pd
import copy
import re
doc = Document(docxFileName)
negativList = ["king", "children", "lived", "fire"]  # some examples
for paragraph in doc.paragraphs:
    for target in negativList:
        if target in paragraph.text:  # it is worth checking in detail ...
            currRuns = copy.copy(paragraph.runs)   # deep copy as we delete/clear the object
            paragraph.runs.clear()
            for run in currRuns:
                if target in run.text:
                    words = re.split('(W)', run.text)  # split into words in order to be able to color only one
                    for word in words:
                        if word == target:
                            newRun = paragraph.add_run(word)
                            newRun.font.highlight_color = WD_COLOR_INDEX.PINK
                        else:
                            newRun = paragraph.add_run(word)
                            newRun.font.highlight_color = None
                else: # our target is not in it so we add it unchanged
                    paragraph.runs.append(run)
doc.save('output.docx')

例如,我正在使用此文本(在Word Docx文件中):

第1章

几个世纪以前的生活 -

"国王!"我的小读者会立即说。

不,孩子们,你错了。从前有一块 木头。这不是一块昂贵的木头。离得很远。只是一个 普通的柴火块,其中一个厚实的固体原木之一 冬天在大火上使寒冷的房间舒适和温暖。

我的代码有多个问题:

1)第一个句子有效,但第二句话是两次。为什么?

2)格式在我突出显示的部分中以某种方式丢失。我可能需要将原始运行的属性复制到新创建的属性中,但是我该怎么做?

3)我松开终端" - "

4)在突出显示的最后一段中,"舒适和温暖"缺少...

我需要的是解决这些问题的解决方案,或者我对此进行了过度思考,并且有一种更简单的方法来进行突出显示?(诸如Doc.highlight之类的东西({" king":" pink"},但我在文档中没有发现任何东西)?

您不是要过度思考它,这是一个具有挑战性的问题;这是搜索和替代问题的一种形式。

通过搜索Paragraph.text可以很容易地找到目标文本,但是在保留其他格式的同时替换它(或在您的情况下添加格式)需要在Run级别上进行访问,这两个级别都可以找到。

有些并发症,这是使它具有挑战性的原因:

  • 不能保证您的"查找"目标字符串完全位于单个运行中。因此,您需要找到目标字符串的 start 的运行,以及包含目标字符串的 end eND 的运行,以及中间的任何内在。p>这可以通过使用角色偏移来帮助,例如"国王"出现在"国王"中的"偏移3"中。...',长度为4,然后识别哪个运行包含字符3,哪个包含字符(3 4)。

  • 与第一个复杂性有关,无法保证所有目标字符串部分出现的运行都相同。例如,如果您的目标字符串为" A BOLD Word",则更新的版本(添加突出显示后)至少需要 3 运行,一个用于" A",一个对于"粗体",一个用于" word"(顺便说一句,运行两个空间字符中的每个字符都不会改变它们的出现)。

    如果您接受了目标字符串始终是一个单词的简化,则可以考虑简化替换运行所找到的目标运行的第一个字符(第一个运行)的格式,这可能是通常的方法。

因此,我想有几种可能的方法,但其中一种是"正常化"包含目标字符串的每个段落的运行,以便目标字符串出现在独特的运行中。然后,您可以将突出显示到该运行中,然后得到想要的结果。

要获得更多帮助,您需要缩小问题区域并提供特定的输入和输出。我将从第一个开始(也许输掉" - ")(在一个单独的问题中,也许是从这里链接的),然后再一次进行,直到一切都起作用。要让受访者生产自己的测试案件太多:)

然后,您会有一个问题:"我运行字符串:'几个世纪以前... - '通过此代码和尾随" - 消失",这对人们来说要容易得多。通过。

下一步可能是打印出每次运行的文本,这样您就可以了解它们如何分解。这可能会使您深入了解它不起作用的地方。

我知道它不是同一库,但是使用wincom32库,您可以一次在特定范围内突出显示该单词的所有实例。下面的代码将获得所有亮点所有命中。

import win32com.client as win32
word = win32.gencache.EnsureDispatch('Word.Application');word.Visible = True
word = word.Documents.Open("test.docx")
strage = word.Range(Start=0, End=0) #change this range to shorten the replace
strage.Find.Replacement.Highlight = True
strage.Find.Execute(FindText="the",Replace=2,Format=True)

我遇到了一个类似的问题,我应该在文档中突出显示一组单词。我修改了OP代码的某些部分,现在我能够正确强调选定的单词。

正如OP在评论中所说的:paragraph.runs.clear()更改为paragraph.clear()。我在代码的以下一部分中添加了几行:

 else:
    paragraph.runs.append(run)

得到这个:

 else:
    oldRun = paragraph.add_run(run.text)
    if oldRun.text in spell_errors:
        oldRun.font.highlight_color = WD_COLOR_INDEX.YELLOW

在通过Currruns迭代时,我们提取运行的文本内容并将其添加到段落中,因此我们需要再次强调这些单词。

最新更新