目标:提取中文财务报告文本
实现:Python pdfplumber/pdfminer 包将PDF文本提取到txt
问题:对于 PDF 粗体文本,相应提取的 txt 中的文本重复
示例如下:
而且我不需要重复文本,只需普通文本即可。
我该怎么做,我应该更改封装还是添加新功能?
请参阅下面的代码和原始 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()
pdf文件可在深圳证券交易所官网下载 http://www.szse.cn/disclosure/listed/bulletinDetail/index.html?9324ce3c-6072-499d-8798-b25d641b52ec
使用 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”之间重复。我想你明白了。