【问题标题】:How do I merge items from a list avoiding repeated content inside the items?如何合并列表中的项目以避免项目内的重复内容?
【发布时间】:2021-10-17 09:02:55
【问题描述】:

编辑 4:

我想做的更简单的例子:

我有一个这样的列表:

sentences = ['Hello, how are','how are you','you doing?']

我想把它变成这样的字符串:

sentence = 'Hello, how are you doing?'

感谢任何帮助!

原帖:

我正在尝试从 .pdf 文件中提取突出显示的文本并将其放入具有相同名称的 .docx 文件中。

这是它的代码:

    from typing import List, Tuple

import fitz  # install with 'pip install pymupdf'
import os
from docx import Document


def _parse_highlight(annot: fitz.Annot, wordlist: List[Tuple[float, float, float, float, str, int, int, int]]) -> str:
    points = annot.vertices
    quad_count = int(len(points) / 4)
    sentences = []
    for i in range(quad_count):
        # where the highlighted part is
        r = fitz.Quad(points[i * 4: i * 4 + 4]).rect

        words = [w for w in wordlist if fitz.Rect(w[:4]).intersects(r)]
        sentences.append(" ".join(w[4] for w in words))
    sentence = " ".join(sentences)
    return sentence


def handle_page(page):
    wordlist = page.getText("words")  # list of words on page
    wordlist.sort(key=lambda w: (w[3], w[0]))  # ascending y, then x
    separator = "PÁGINA NÚMERO " + str(page.number) + ": "

    highlights = []
    annot = page.firstAnnot
    while annot:
        if annot.type[0] == 8:
            highlights.append(separator)
            highlights.append(_parse_highlight(annot, wordlist))
            document.add_paragraph(highlights)
        annot = annot.next

    return highlights


def main(filepath: str) -> List:
    doc = fitz.open(filepath)

    highlights = []
    for page in doc:
        highlights += handle_page(page)

    return highlights

dir_files = [f for f in os.listdir(".") if os.path.isfile(os.path.join(".", f))]
print(dir_files)
document = Document()
for file in dir_files:  # look at every file in the current directory
    if file.endswith('.pdf'):  # if it is a PDF, use it
        print('Working on converting: ' + file)

        main(file)
        document.save(file.replace(".pdf",".docx"))

我不得不说我没有写出让文本脱离亮点的部分。我知道了here

问题是它创建的列表中有重复的项目。以下是 .docx 文件的输出示例:

PÁGINA NÚMERO 0: En los primeros tiempos de la microscopia electronica los bi-logos pensaban que los organulos de una célula eucarionte primeos tiempos de la microscopia electronica los bi-logos pensaban que losorganulos de una célula eucarionte flotaban libremente en醇。 Pero los progresos realizados pensaban que losorganulos de una célula eucarionte flota-ban libremente en el citosol。 Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia en el citosol。 Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras que se extiende a traves del citosqueleto (图 6-20)。 El citoesqueleto, revelado la presencia del citoesqueleto, una red de fibras que se extiende a través del citoplasma(图 6-20)。 El citoesqueleto, que desempena un papel importante en la Organizacion a través del citoplasma(图 6-20)。 que desempena un papel importante en la Organizacion estructuras y las actividades de la célula, PÁGINA NÚMERO 0: En los primeros tiempos de la microscopia electronica los bi-logos pensaban que losorganulos de una célula eucarionte primeos tiempos de la microscopia electronica los bi-logos pensaban que losorganulos de una célula eucarionte flotaban libremente en el citosol。 Pero los progresos realizados pensaban que losorganulos de una célula eucarionte flota-ban libremente en el citosol。 Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia en el citosol。 Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras que se extiende a traves del citosqueleto (图 6-20)。 El citoesqueleto, revelado la presencia del citoesqueleto, una red de

如您所见,它不止一次地重复同一件事。

我认为这是因为我的 pdf 像这样分成两部分:

但是将每一页分成两半并创建更长的 pdf 会很不方便。另一个问题可能是我对这个 pdf 进行了 OCR 处理,这可能会导致问题(这就是为什么文本输出与 pdf 略有不同,但我对此很好)。

所以我正在寻找一种方法来检查“亮点”列表是否有重复的项目并删除它们。或者也许在它们被添加到列表之前检查而不添加它们。但是我在编程方面没有那么经验,所以我请求您的帮助!

感谢任何帮助!

抱歉,英语不好!

编辑 1:

我现在已经尝试过这样做:

...
def main(filepath: str) -> List:
    doc = fitz.open(filepath)

    highlights = []
    for page in doc:
        highlights += handle_page(page)
        highlights = set(highlights)
        highlights = list(highlights)
        document.add_paragraph(highlights)

    return highlights
...

但它不起作用。它甚至会更改项目的顺序,因为它会删除最先添加的内容,而我不希望这样做。

编辑 2:

我想我找到了困扰我的地方。

在他们加入“句子”之前我做了print(sentences),这就是我得到的:

['En los primeros tiempos de la microscopia electronica los bio-logos pensaban que losorganulos de una célula eucarionte', 'primeros tiempos de la microscopia electronica los bio-logos pensaban que losorganulos de una célula eucarionte flotaban libremente en el citosol。 Pero los progresos realizados', 'pensaban que losorganulos de una célula eucarionte flota-ban libremente en el citosol。 Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia', 'en el citosol。 Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras', 'microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras que se extiende a través del citoplasma(图 6-20)。 El citoesqueleto,', 'revelado la presencia del citoesqueleto, una red de fibras que se extiende a través del citoplasma(图 6-20)。 El citoesqueleto, que desempena un papel importante en la organizacion', 'a través del citoplasma(图 6-20)。 que desempena un papel importante en la Organizacion estructuras y las actividades de la célula,']

正如您所见,“句子”中的项目相互包含,因此即使我使用 set(sentences) 它也不起作用。我很确定 OCR 与此有关。

所以现在我认为我需要将注意力转移到交叉引用“句子”中的每个项目上。

就像做 A+B-(A∩B)=C 时一样。这意味着 C 不会有重复项,并且如果顺序正确,它将构成一个易于理解的句子。但是如果有办法做到这一点,我完全是空白。

我也学会了这个以消除欺骗并保持列表的顺序:list(dict.fromkeys())

编辑 3:

仅运行此代码:

def _parse_highlight(annot: fitz.Annot, wordlist: List[Tuple[float, float, float, float, str, int, int, int]]) -> str:
    points = annot.vertices
    quad_count = int(len(points) / 4)
    sentences = []
    for i in range(quad_count):
        # where the highlighted part is
        r = fitz.Quad(points[i * 4: i * 4 + 4]).rect

        words = [w for w in wordlist if fitz.Rect(w[:4]).intersects(r)]
        sentences.append(" ".join(w[4] for w in words))
    print(sentences)
    sentence = " ".join(sentences)
    print(sentence)
    return sentence


def handle_page(page):
    wordlist = page.getText("words")  # list of words on page
    wordlist.sort(key=lambda w: (w[3], w[0])) 
    separator = "PÁGINA NÚMERO " + str(page.number) + ": "

    highlights = []
    annot = page.firstAnnot
    while annot:
        if annot.type[0] == 8:
            highlights.append(separator)
            highlights.append(_parse_highlight(annot, wordlist))
        annot = annot.next
    return highlights


def main(filepath: str) -> List:
    doc = fitz.open(filepath)

    highlights = []
    for page in doc:
        highlights += handle_page(page)
    print(highlights)
    return highlights

main(example.pdf)

这是我唯一强调的:

终端是这样说的:

['El citoesqueleto es una red de fibras que Organiza las estructuras', 'citoesqueleto es una red de que Organiza las estructuras y las actividades', 'las estructuras y las actividades de la célula', 'En los primeos tiempos de la microscopia electronica los bio-logos pensaban que los organulos de una célula eucarionte', 'primeros tiempos de la microscopia electronica los bio-logos pensaban que losorganulos de una célula eucarionte flotaban libremente en el citosol。 Pero los progresos realizados', 'pensaban que losorganulos de una célula eucarionte flota-ban libremente en el citosol。 Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia', 'en el citosol。 Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras', 'microscopia 6ptica como en la microscopia revelado la presencia del citoesqueleto, extiende a traves del citoplasma']

El citoesqueleto es una red de fibras que Organiza las estructuras citoesqueleto es una red de que Organiza de una célula eucarionte primeos tiempos de la microscopia electronica los bio-logos pensaban que losorganulos de una célula eucarionte flotaban libremente en el citosol。 Pero los progresos realizados pensaban que losorganulos de una célula eucarionte flota-ban libremente en el citosol。 Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia en el citosol。 Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras microscopia 6ptica como en la microscopia revelado la presencia del citoesqueleto, extiende a traves del citoplasma

['PÁGINA NÚMERO 0: ', 'El citoesqueleto es una red de fibras que Organiza las estructuras citoesqueleto es una red de que Organiza las estructuras y las actividades las estructuras y las actividades de la célula En los primeos tiempos de la microscopia electronica los bio-logos pensaban que losorganulos de una célula eucarionte primeos tiempos de la microscopia Pero los progresos realizados pensaban que losorganulos de una célula eucarionte flota-ban libremente en el citosol。 Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia en el citosol。 Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras microscopia 6ptica como en la microscopia revelado la presencia del citoesqueleto, extiende a través del citosqueleto']

现在我看到一些我没有突出显示的文本也被变成了“句子”项目。同样,我认为这是 OCR 的错误,或者我可以更好地调整 pymupdf idk。

【问题讨论】:

    标签: python python-docx pymupdf


    【解决方案1】:

    您可以使用 python set 来删除重复项。它应该在循环之后和return之前完成

    highlights = ['h1', 'h2', 'h1']
    no_dups_highlights = list(set(highlights))
    print(no_dups_highlights)
    

    输出

    ['h2', 'h1']
    

    【讨论】:

    • 感谢您的回复。问题是我需要最终结果是 ['h1', 'h2'] 而不是相反,因为当我创建一个新段落时,我需要“PÁGINA NÚMERO”(这是页码)在那里所以我可以从哪个页面知道我得到了那个突出显示的文本。有没有办法做到这一点?
    • 如果您有类似highlights = [('h1', 12), ('h2', 45), ('h1', 78)] 的内容(其中数字是页码) - 您想保留哪个 h1?
    • 嗯,但这与代码创建的内容不同,对吧?如果“h”是文本,则不会有另一个具有相同文本的页码。另外,我用新的东西更新了这个问题。
    • 尝试提供一个示例代码来演示列表中重复项的问题。删除所有不相关的代码行。至于现在我还不清楚。
    • 我更新了帖子。你说的是这个吗?
    【解决方案2】:

    所以set 洗牌成员;你可以使用它,但只能作为助手。

    有几种方法可以做到这一点:

    • 使用set 跟踪您已经看到的内容:
    seen = set()
    filtered = []
    for highlight in highlights:
        if highlight not in seen:
            filtered.append(highlight)
            seen.add(highlight)
    
    • 如果您使用的是足够新的 Python 版本,dict 会保持顺序:
    filtered = list({highlight: None for highlight in highlights}.keys())
    
    • 忽略理论上的慢,直接用最直接的方式编码即可;在实践中它可能会足够快:
    filtered = []
    for highlight in highlights:
        if highlight not in filtered:
            filtered.append(higwhlight)
    

    所有这些都是为了精确匹配;如果您最终需要近似匹配,则可能无论如何都必须使用最后一种方法,并使用某种相似性度量。

    【讨论】:

    • 感谢您的回复!我想我应该在这一点上改变这个问题。问题是我想将所有“句子”项目合并到一个“句子”字符串中,但避免合并重复的“句子”中的项目部分。如果我使用最后一种方法,实施相似性度量,它可能会导致最终“句子”中的错误,因为它们的重叠量不一致。暂时我要放下这段代码,因为我没有更多的空闲时间来处理它。我现在将使用 Sumnotes 提取突出显示的文本。
    • 是的,在文本之间找到(接近)重叠以将整个文本从片段拼接在一起是一个完全不同的问题。那里必须有库和技术;它用于 DNA 序列,这些序列以片段形式读取,需要组装并且很大
    • 我编辑了问题并添加了一个更简单的示例。我认为这很好地概括了我想做的事情。也许我也可以考虑改进 pymupdf 库的使用,因为这也可能是重复单词的原因,我只是假设它是 OCR。
    【解决方案3】:

    我已经实现了另一种从 pdf 中获取“句子”列表的方法,现在它可以按预期工作了。

    这是代码:

    from typing import List, Tuple
    
    import fitz
    import os
    from docx import Document
    
    _threshold_intersection = 0.9
    
    def _check_contain(r_word, points):
        r = fitz.Quad(points).rect
        r.intersect(r_word)
    
        if r.getArea() >= r_word.getArea() * _threshold_intersection:
            contain = True
        else:
            contain = False
        return contain
    
    
    def _parse_highlight(annot: fitz.Annot, wordlist: List[Tuple[float, float, float, float, str, int, int, int]]) -> str:
        quad_points = annot.vertices
        quad_count = int(len(quad_points) / 4)
        sentences = ['' for i in range(quad_count)]
    
        for i in range(quad_count):
            points = quad_points[i * 4: i * 4 + 4]
            words = [
                w for w in wordlist if
                _check_contain(fitz.Rect(w[:4]), points)
            ]
            sentences[i] = ' '.join(w[4] for w in words)
        sentence = ' '.join(sentences)
        document.add_paragraph(sentence)
        return sentence
    
    def handle_page(page):
        wordlist = page.getText("words")
        wordlist.sort(key=lambda w: (w[3], w[0]))
    
        highlights = []
        annot = page.firstAnnot
        while annot:
            if annot.type[0] == 8:
                highlights.append(_parse_highlight(annot, wordlist))
            annot = annot.next
    
        return highlights
    
    def main(filepath: str) -> List:
        doc = fitz.open(filepath)
    
        highlights = []
        for page in doc:
            document.add_paragraph("Page Number " + str(page.number+1) + ": ")
            highlights += handle_page(page)
    
        return highlights
    
    dir_files = [f for f in os.listdir(".") if os.path.isfile(os.path.join(".", f))]
    document = Document()
    for file in dir_files:
        if file.endswith('.pdf'):
            print('Working on converting: ' + file)
            main(file)
            document.save(file.replace(".pdf",".docx"))
    

    得到了这个新方法here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-09
      • 2014-04-21
      • 1970-01-01
      • 2018-12-10
      • 1970-01-01
      • 2011-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多