Python,使用pdfplumber、pdfminer包从pdf中提取文本,粗体字符重复

问题描述 投票:0回答:2

目标:提取中文财务报告文本

实现:Python pdfplumber/pdfminer 包将PDF文本提取到txt

问题:对于 PDF 粗体文本,相应提取的 txt 中的文本重复

示例如下:

如以下PDF文本: pdf text Python 提取到 txt 如下: pdfplumber result

而且我不需要重复文本,只需普通文本即可。

我该怎么做,我应该更改封装还是添加新功能?

请参阅下面的代码和原始 pdf 文本。

附加:pdf管道工代码:

import pdfplumber
 
def pdf2txt(filename, delLinebreaker=True):
    pageContent = ''
    showplace = ''
    try:    
        with pdfplumber.open(  filename  ) as pdf:
            page_count = len(pdf.pages)
            for page in pdf.pages:
                if delLinebreaker==True:
                    pageContent += page.extract_text().replace('\n', "")   
                else:
                    pageContent += page.extract_text()  
    except Exception as e:
        print( "file: ", filename, ', reason: ', repr(e) )
    return pageContent
 
pdf2txt(r"report.pdf", delLinebreaker=False)

pdfminer代码:

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.pdfpage import PDFPage
 
rsrcmgr = PDFResourceManager()
outfp = open(r"report.txt", 'w', encoding='utf-8')
device = TextConverter(rsrcmgr, outfp)
with open(r"Report.pdf", 'rb') as fp:
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    for page in PDFPage.get_pages(fp):
        interpreter.process_page(page)
device.close()
outfp.close()

pdfminer的结果是: pdfminer result

pdf文件可在深圳证券交易所官网下载 http://www.szse.cn/disclosure/listed/bulletinDetail/index.html?9324ce3c-6072-499d-8798-b25d641b52ec

pdf nlp extract cjk pdfplumber
2个回答
1
投票

使用 PyMuPDF,您可以抑制伪粗体文本,如下所示:

import fitz  # import PyMuPDF

doc = fitz.open("input.pdf")
page = doc[0]  # example first page

# extract text including its coordinates
blocks = page.get_text("dict", sort=True, flags=fitz.TEXTFLAGS_TEXT)["blocks"]
old_bbox = fitz.EMPTY_RECT()  # store previous bbox here
old_text = ""  # store previous text here
for b in blocks:  # loop over text blocks
    for l in b["lines"]:  # lines in current block
        bbox = fitz.Rect(l["bbox"])  # line boundary box
        # text in line - remove leading trailing spaces where possible
        text = " ".join([s["text"].strip() for s in l["spans"]]).strip()
        # check if new bbox overlaps old bbox
        isect = abs(bbox & old_bbox) / abs(bbox)  # overlap ratio
        if text != old_text or isect < 0.5:  # text unequal or no overlap
            print(text)  # print text
        old_text = text  # store for next
        old_bbox = +bbox  # store for next

之前的代码提供了这个:

浙江精功科技股份有限公司 2017 年年度报告全文

浙江精功科技股份有限公司
2017 年年度报告
年年度报告
2018 年
年
年 04 月
月
1

而不是这个:

浙江精功科技股份有限公司 2017 年年度报告全文

浙江精功科技股份有限公司
浙江精功科技股份有限公司
浙江精功科技股份有限公司
浙江精功科技股份有限公司
2017 年年度报告
年年度报告
年年度报告
年年度报告
2018 年
年
年
年 04 月
月
月
月
1

正如您所看到的,即使有纠正逻辑,仍然存在一些重复:

2017 年年度报告
之后是
年年度报告
,这可能与前面的中文部分重复。因此,为了也捕获这些情况,您的逻辑需要更加智能,并且还要检查部分 bbox 重叠和尾随文本相等性,例如
if old_text.endswith(text) ...
。这样做会带来更好的结果:

浙江精功科技股份有限公司 2017 年年度报告全文

浙江精功科技股份有限公司
2017 年年度报告
2018 年
年 04 月
1

但是,字符“年”在“2018”和“04”之间重复。我想你明白了。


0
投票

对于

pdfplumber
,这是一个已知错误,自版本 0.5.242020 年 10 月 4 日起已修复

问题出在

pdfminer.six
,它是
pdfminer
pdfplumber
的核心模块。

更新您的 pdfplumber,然后使用

page.dedupe_chars().extract_text()

而不是
page.extract_text()

© www.soinside.com 2019 - 2024. All rights reserved.