如果我在此处使用答案中的代码: Extracting text from a PDF file using PDFMiner in python?
应用于此pdf文件时,我可以提取文字:https://www.tencent.com/en-us/articles/15000691526464720.pdf
但是,您在“合并收入声明”下看到了它的内容,即... Revenues VAS Online advertising
,然后再读取数字...我希望将其读出,即:
Revenues 73,528 49,552 73,528 66,392 VAS 46,877 35,108
等...有办法吗?
寻找pdfminer
以外的其他可能解决方案。
如果我尝试将这段代码用于PyPDF2
,则并非所有文字都显示出来:
# importing required modules
import PyPDF2
# creating a pdf file object
pdfFileObj = open(file, 'rb')
# creating a pdf reader object
pdfReader = PyPDF2.PdfFileReader(pdfFileObj)
# printing number of pages in pdf file
a=(pdfReader.numPages)
# creating a page object
for i in range(0,a):
pageObj = pdfReader.getPage(i)
print(pageObj.extractText())
答案 0 :(得分:2)
很难说为什么pdfminer会给您它提取文本的结果。也许它的算法有些问题。
我工作的公司有用于PDF库的示例代码,我使用了TextExtract C#(在测试是否有可能获得所需结果的过程中,这是我的练习)您的文档(说明了如何编写代码来提取PDF文档的文本),并从第7页中提取了以下内容:
合并收益表 百万元,除非另有说明 未经审核 未经审核 2018年第一季度 2017年第一季度 2018年第一季度 2017年第四季度 营业额 73,528 49,552 73,528 66,392 增值服务 46,877 35,108 46,877 39,947 在线广告 10,689 6,888 10,689 12,361 其他 15,962 7,556 15,962 14,084 收益成本 (36,486) (24,109) (36,486) (34,897) 毛利 37,042 25,443 37,042 31,495 毛利率 50% 51% 50% 47% 利息收入 1,065 808 1,065 1,156 其他收益净额 7,585 3,191 7,585 7,906 营销费用 (5,570) (3,158) (5,570) (6,022) 一般及行政开支 (9,430) (7,012) (9,430) (8,811) 营业利润 30,692 19,272 30,692 25,724 营业利润率 42% 39% 42% 39% 财务费用净额 (654) (691) (654) (859) 应占联营公司及合营企业的损益 (319) (375) (319) (120) 除所得税前溢利 29,719 18,206 29,719 24,745 所得税费用 (5,746) (3,658) (5,746) (3,123) 本期利润 23,973 14,548 23,973 21,622 净利润 33% 29% 33% 33% 归因于: 公司股权持有人 23,290 14,476 23,290 20,797 非控制性权益 683 72 683 825 非GAAP归属于股东的权益 公司 18,313 14,211 18,313 17,454 归属于母公司股东的每股收益 公司股权持有人 (每股人民币) -基本 2.470 1.540 2.470 2.206 -稀释 2.435 1.522 2.435 2.177
您可以看到,它正在“请求”返回整个页面。
答案 1 :(得分:1)
与pyPDF2的问题相比,您的问题更多地与PDF文件的结构有关。在解析PDF以重新构建页面布局时,我遇到了许多相同的问题。
生成PDF时,每个文本块都将在页面上定位并根据所应用的字体规则进行呈现(类似于使用绝对位置定位和CSS来构造HTML文档)。一个简单的PDF库将简单地按照文件中定义的顺序从每个块中返回文本(当反向生成页面时,我已经有了文档,最后一段首先定义)。
您要么需要使用更高级的PDF库(可能会在简单库的基础上构建),该库将利用每个文本块的X,Y位置及其字体信息来确定垂直位置,或自己开发。看来 JosephA 正在谈论的软件正是在这样做。
答案 2 :(得分:1)
我首先查找extractText function of PyPDF2,并尝试从输出中“剥离”任何新行,以使您“跨过”页面。
输出不是很理想... output
此外,就您的输出而言,它似乎也不可靠。 从PyPDF2文档中: “请勿依赖此功能产生的文本顺序,因为如果此功能变得更复杂,它将改变。”
因此,我去探索了使用Tesseract的选项。因此,使用“ pdf提取库”有点偏离,它基本上是“构建自己的提取脚本”。
一旦掌握了Tesseract,这并不太困难。我花了大约一个小时的时间对tesseract的现有知识进行研究。
这是我自己的代码逐页提取pdf的结果:https://gist.github.com/Benehiko/60862a6be13b3b652b7d506121b95811
请注意,我的代码有一个缺点。它不会按顺序提取页面。
以防万一链接消失:
from PIL import Image
import pytesseract
import subprocess
import pathlib
import glob
import os
pathlib.Path("pages").mkdir(parents=False, exist_ok=True)
params = ['convert', "-density", "300", 'test.pdf', '-depth', '8',
'pages/test_%02d.tiff']
subprocess.check_call(params)
images = glob.glob("pages/*.tiff")
for image in images:
image = Image.open(image)
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
os.environ["TESSDATA_PREFIX"] = ROOT_DIR + "/tessdata"
text = pytesseract.image_to_string(image, lang='eng', nice=0,
output_type=pytesseract.Output.STRING).replace("\n", " ")
print(text)
代码说明:
这首先将pdf转换为单独的“ tiff”图像,因为出于某种原因读取带有pytesseract的多页tiff仅读取第一页。 tiff文件保存在称为“页面”的单独目录中。 Pytesseract读取每个文件,然后返回文本,然后使用“ .replace”将其格式化,该文本将删除所有行并将文本格式化为一行。
开始的地方: Tesseract install
在python中使用tesseract: pytesseract
训练数据: eng.traineddata
其他来源: pdf to tiff
Pytesseract: documentation
希望这对您有所帮助。不确定这是否是您想要的东西。
答案 3 :(得分:1)
您可以使用PDFMiner来完成这项工作,以我的经验,它比那里的其他开源Python工具更好。
关键是正确地指定laparams
参数 ,而不是将其保留为默认值。此参数用于为PDFMiner提供有关页面布局的更多信息。由于此处的文本对应于具有宽空格的表,因此我们需要指示PDFMiner使用较大的字符边距(char_margin
)。
布局的代码为here。尝试为该特定文档提供最佳结果的超参数。
这是有关pdf的示例代码。我在这里仅使用一个页面进行演示:
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from io import StringIO
def convert_pdf_to_txt(path, pages):
rsrcmgr = PDFResourceManager()
retstr = StringIO()
codec = 'utf-8'
laparams=LAParams(all_texts=True, detect_vertical=True,
line_overlap=0.5, char_margin=1000.0, #set char_margin to a large number
line_margin=0.5, word_margin=2,
boxes_flow=1)
device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
fp = open(path, 'rb')
interpreter = PDFPageInterpreter(rsrcmgr, device)
password = ""
maxpages = 0
caching = True
pagenos=set(pages)
for page in PDFPage.get_pages(fp, pagenos, maxpages=maxpages, password=password,caching=caching, check_extractable=True):
interpreter.process_page(page)
text = retstr.getvalue()
fp.close()
device.close()
retstr.close()
return text
pdf_text_page6 = convert_pdf_to_txt("15000691526464720.pdf", pages=[6])
给定页面(与文档中的第7页相对应的第6页)的输出看起来像下面的块。这不是完美的方法,但是表格的所有数字部分都与文本位于同一行。
Page 7 of 11
Unaudited Unaudited
1Q2018 1Q2017 1Q2018 4Q2017
Revenues 73,528 49,552 73,528 66,392
VAS 46,877 35,108 46,877 39,947
Online advertising 10,689 6,888 10,689 12,361
Others 15,962 7,556 15,962 14,084
Cost of revenues (36,486) (24,109) (36,486) (34,897)
Gross profit 37,042 25,443 37,042 31,495