【问题标题】:How can I extract font color of text within a PDF in Python with PDFMiner?如何使用 PDFMiner 在 Python 中提取 PDF 中文本的字体颜色?
【发布时间】:2021-02-25 14:17:59
【问题描述】:

如何从 PDF 中的文本中提取字体颜色?

我已经尝试使用 PDFMiner 探索 LTTextLTChar 对象,但这个模块似乎只允许提取字体大小和样式,而不是颜色。

【问题讨论】:

    标签: python pdf pdfminer


    【解决方案1】:

    我查看了PDFMiner(未维护)和PDFMiner.Sixth(fork)的所有源代码。 Python 模块都不允许您提取颜色。在两个模块的问题部分中,提取字体颜色是一个常见问题。

    我还查看了PDFPlumber,它使用了 PDFMiner.Sixth。该模块提取字体颜色。提取的颜色元素包括stroking_color,,即字符的轮廓和non_stroking_color,,即字符的填充。我查看了从示例 PDF 中提取的颜色,它们与 RGB 颜色相匹配。

    import pdfplumber
    
    pdf_file = pdfplumber.open('path_to_pdf')
    for p, char in zip(pdf_file.pages, pdf_file.chars):
        words = p.extract_words(keep_blank_chars=True)
        texts = p.extract_text()
        print(f"Page Number: {p.page_number}")
        print(f"Font Name: {char['fontname']}")
        print(f"Font Size: {char['size']}")
        print(f"Stroking Color: {char['stroking_color']}")
        print(f"Non_stroking Color: {char['non_stroking_color']}")
        print(texts.strip())
        print('\n')
    

    未回答的问题是:

    如何在提取字体颜色的同时仍然使用 PDFMiner 代码?

    下面的代码允许我同时使用 PDFMiner.SixthPDFPlumber 来提取各种元素,例如文本、字体名称、字体大小、stroking_color 和 non_stroking_color源 PDF 文件。

    import pdfplumber
    
    from pdfminer.high_level import extract_pages
    from pdfminer.layout import LTTextContainer, LTChar
    
    
    with open('path_to_pdf', 'rb') as scr_file:
        with pdfplumber.PDF(scr_file) as pdf_file:
            for page_layout, char in zip(extract_pages(scr_file), pdf_file.chars):
                for element in page_layout:
                    if isinstance(element, LTTextContainer):
                        for text_line in element:
                            for character in text_line:
                                if isinstance(character, LTChar):
                                    print(element.get_text())
                                    print(f"Font Name: {character.fontname}")
                                    print(f"Font Size: {character.size}")
                                    print(f"Stroking Color: {char['stroking_color']}")
                                    print(f"Non_stroking Color: {char['non_stroking_color']}")
                                    print('\n\n')
    
    

    2021 年 3 月 9 日更新

    我仍在努力将这些功能啮合和同步在一起。我检查了它们,它们似乎输出了正确的元素。

    import pdfplumber
    from pdfminer.high_level import extract_pages
    from pdfminer.layout import LTTextContainer, LTChar, LAParams
    
    
    def extract_character_characteristics(pdf_file):
        number_of_pages = len(list(extract_pages(pdf_file)))
        for page_layout in extract_pages(pdf_file, laparams=LAParams()):
            print(f'Processing Page: {number_of_pages}')
            number_of_pages -= 1
            for element in page_layout:
                if isinstance(element, LTTextContainer):
                    for text_line in element:
                        for character in text_line:
                            if isinstance(character, LTChar):
                                if character.get_text() != ' ':
                                    print(f"Character: {character.get_text()}")
                                    print(f"Font Name: {character.fontname}")
                                    print(f"Font Size: {character.size}")
                                    print('\n')
    
    
    def extract_character_colors(pdf_file):
        with pdfplumber.PDF(pdf_file) as file:
            for char in file.chars:
                if char['text'] != ' ':
                    print(f"Page Number: {char['page_number']}")
                    print(f"Character: {char['text']}")
                    print(f"Font Name: {char['fontname']}")
                    print(f"Font Size: {char['size']}")
                    print(f"Stroking Color: {char['stroking_color']}")
                    print(f"Non_stroking Color: {char['non_stroking_color']}")
                    print('\n')
    
    
    with open('test.pdf', 'rb') as scr_file:
        extract_character_characteristics(scr_file)
    
    

    【讨论】:

    • 您的代码似乎不起作用(您总是使用 pdf_file.chars 中的第一个字符),但它对我开发一个可行的解决方案很有用
    • @VitoGentile 我以前用过 PDFMiner,但 PDFPlumber 对我来说是新的。我也将不得不研究“第一个字符”问题。一旦我做更多的研究,我会发布更新。
    • @VitoGentile 我仍在尝试将这两个函数结合在一起,但两者的数据似乎都是准确的。
    【解决方案2】:

    (免责声明:我是 pText 的作者,本示例中使用的库。)

    pText 允许您注册一个EventListener,只要处理了 PDF 渲染指令(例如渲染文本),就会收到通知。

    收到此指令后,您可以检查图形状态以确定当前的描边/填充颜色是什么。文本应使用描边颜色呈现。

    让我们看看它是如何工作的:

    with open("input.pdf", "rb") as pdf_file_handle:
        l = ColorSpectrumExtraction()
        doc = PDF.loads(pdf_file_handle, [l])
    

    上面的代码打开一个PDF文档进行(二进制)阅读,并调用PDF.loads方法。我们传递的额外参数是 EventListener 实现的数组(在本例中为 1 个元素)。

    让我们看看ColorSpectrumExtraction

    class ColorSpectrumExtraction(EventListener):
    
        def event_occurred(self, event: Event) -> None:
            if isinstance(event, ChunkOfTextRenderEvent):
                self._render_text(event)
    
        def _render_text(self, event: ChunkOfTextRenderEvent):
            assert event is not None
            c = event.font_color.to_rgb()
            // do something with the font-color
    

    如你所见,这个类有一个方法event_occurred,它会在渲染内容时被调用。在我们的例子中,我们只对ChunkOfTextRenderEvent感兴趣。

    所以我们验证(使用isinstanceof),然后将调用委托给另一个方法。

    _render_text 方法中,我们可以从刚刚渲染的文本中获取我们想要的所有信息。比如font_colorfont_size

    您可以在GitHub 或使用PyPi 获取pText 还有很多 examples,请查看它们以了解有关使用图像的更多信息。

    【讨论】:

    • 这绝对很有趣。然而,在我的项目中使用 pText 对我来说有点复杂,因为我的印象是我需要用 pText 完全替换 pdfminer。这是不可行的......有没有办法将这个监听器想法与PDFminer结合使用?如果是这样,我可能会尝试在我的答案中附加一些代码,以更好地了解如何结合基于 pText 的颜色检测和 PDFminer 文本提取
    猜你喜欢
    • 1970-01-01
    • 2014-12-17
    • 1970-01-01
    • 1970-01-01
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    相关资源
    最近更新 更多