问题描述
如何从 PDF 中的文本中提取字体颜色?
我已经尝试使用 PDFminer 探索 LTText
或 LTChar
对象,但该模块似乎只允许提取字体大小和样式,而不允许提取颜色。
解决方法
(免责声明:我是本示例中使用的库 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_color
、font_size
等
您可以通过 GitHub 或使用 PyPi 获取 pText 还有很多examples,请查看它们以了解有关处理图像的更多信息。
,我查看了 PDFMiner(未维护)和 PDFMiner.Sixth(fork)的所有源代码。 Python 模块都不允许您提取颜色。在两个模块的问题部分中,提取字体颜色是一个常见问题。
我还查看了使用 PDFMiner.Sixth 的 PDFPlumber。该模块提取字体颜色。提取的颜色元素包括 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.Sixth 和 PDFPlumber 来提取各种元素,例如文本、字体名称、字体大小、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')
更新 03-09-2021
我仍在对这些功能进行网格划分和同步。我检查了它们,它们似乎输出了正确的元素。
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)