关于python:PDFminer:提取带有字体信息的文本

PDFminer: extract text with its font information

我找到了这个问题,但是它使用命令行,并且我不想使用子进程在命令行中调用Python脚本并解析HTML文件以获取字体信息。

我想将PDFminer用作库,但我发现了这个问题,但它们仅涉及提取纯文本,而没有诸如字体名称,字体大小等其他信息。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#!/usr/bin/env python
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfpage import PDFPage
from pdfminer.pdfinterp import PDFResourceManager
from pdfminer.pdfinterp import PDFPageInterpreter
from pdfminer.layout import LAParams
from pdfminer.converter import PDFPageAggregator
import pdfminer


def createPDFDoc(fpath):
    fp = open(fpath, 'rb')
    parser = PDFParser(fp)
    document = PDFDocument(parser, password='')
    # Check if the document allows text extraction. If not, abort.
    if not document.is_extractable:
        raise"Not extractable"
    else:
        return document


def createDeviceInterpreter():
    rsrcmgr = PDFResourceManager()
    laparams = LAParams()
    device = PDFPageAggregator(rsrcmgr, laparams=laparams)
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    return device, interpreter


def parse_obj(objs):
    for obj in objs:
        if isinstance(obj, pdfminer.layout.LTTextBox):
            for o in obj._objs:
                if isinstance(o,pdfminer.layout.LTTextLine):
                    text=o.get_text()
                    if text.strip():
                        for c in  o._objs:
                            if isinstance(c, pdfminer.layout.LTChar):
                                print"fontname %s"%c.fontname
        # if it's a container, recurse
        elif isinstance(obj, pdfminer.layout.LTFigure):
            parse_obj(obj._objs)
        else:
            pass


document=createPDFDoc("/tmp/simple.pdf")
device,interpreter=createDeviceInterpreter()
pages=PDFPage.create_pages(document)
interpreter.process_page(pages.next())
layout = device.get_result()


parse_obj(layout._objs)


这种方法不使用PDFMiner,但是可以解决问题。

首先,将PDF文档转换为docx。然后,您可以使用python-docx检索字体信息。这是获取所有粗体文本的示例

1
2
3
4
5
6
7
8
from docx import *

document = Document('/path/to/file.docx')

for para in document.paragraphs:
    for run in para.runs:
        if run.bold:
            print run.text

如果您真的想使用PDFMiner,可以尝试一下。传递" -t"会将PDF转换为带有所有字体信息的HTML。


看看PDFlib,它可以根据需要提取字体信息,并具有一个Python库,您可以将其导入脚本并使用它。


我希望这可以对您有所帮助:)

获取字体系列:

1
2
if isinstance(c, pdfminer.layout.LTChar):
    print (c.fontname)

获取字体大小:

1
2
if isinstance(c, pdfminer.layout.LTChar):
    print (c.size)

获取字体位置:

1
2
if isinstance(c, pdfminer.layout.LTChar):
    print (c.bbox)

获取图像信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
if isinstance(obj, pdfminer.layout.LTImage):
outputImg ="<Image>\
"

outputImg += ("name: %s," % obj.name)
outputImg += ("x: %f," % obj.bbox[0])
outputImg += ("y: %f\
"
% obj.bbox[1])
outputImg += ("width1: %f," % obj.width)
outputImg += ("height1: %f," % obj.height)
outputImg += ("width2: %f," % obj.stream.attrs['Width'])
outputImg += ("height2: %f\
"
% obj.stream.attrs['Height'])
print (outputImg)

如果要使用PDF Miner库从PDF文件中获取字体大小或字体名称,则必须解释整个pdf页面。您应该确定要为哪个单词,短语获取字体大小和字体名称(如在页面上,您可以拥有多个具有不同字体大小的单词)。使用PDF Miner的页面结构:
PDFPageInterpreter-> LTTextBox-> LTChar
一旦找到要获取哪个字体的字号,就可以致电:
字体大小的size方法(实际上是高度),字体的字体名。
代码应如下所示,您传递pdf文件路径,要获取其字体大小的单词和页码(在该页面上搜索到的单词):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def get_fontsize_and_fontname_for_word(self, pdf_path, word, page_number):
    resource_manager = PDFResourceManager()
    layout_params = LAParams()
    device = PDFPageAggregator(resource_manager, laparams=layout_params)
    pdf_file = file(pdf_path, 'rb')
    pdf_page_interpreter = PDFPageInterpreter(resource_manager, device)
    global actual_font_size_pt, actual_font_name

    for current_page_number, page in enumerate(PDFPage.get_pages(pdf_file)):
        if current_page_number == int(page_number) - 1:
            pdf_page_interpreter.process_page(page)
            layout = device.get_result()
            for textbox_element in layout:
                if isinstance(textbox_element, LTTextBox):
                    for line in textbox_element:
                        word_from_textbox = line.get_text().strip()
                        if word in word_from_textbox:
                            for char in line:
                                if isinstance(char, LTChar):
                                    # convert pixels to points
                                    actual_font_size_pt = int(char.size) * 72 / 96
                                    # remove prefixed font name, such as QTBAAA+
                                    actual_font_name = char.fontname[7:]
    pdf_file.close()
    device.close()
    return actual_font_size_pt, actual_font_name

您可以检查LTChar类还支持哪些其他属性。


LTChar类中的某些信息处于较低级别。这似乎是合理的,因为可以将字体大小,斜体,粗体等应用于单个字符。

更多信息在这里:https://github.com/euske/pdfminer/blob/master/pdfminer/layout.py#L222

但是我仍然对不在这堂课的字体颜色感到困惑