代码之家  ›  专栏  ›  技术社区  ›  jason

python pdf直接阅读pdf中的外观

  •  6
  • jason  · 技术社区  · 6 年前

    如果我在这里使用答案中的代码: 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())
    
    4 回复  |  直到 6 年前
        1
  •  1
  •   Adarsh Chavakula    6 年前

    您可以使用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])
    

    给定页面(第6页对应于文档中的第7页)的输出如下所示。它不是完美的,但是表的所有数字部分都与文本在同一行中捕获。

    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 
    
        2
  •  2
  •   JosephA    6 年前

    很难说为什么pdfminer会提供它所提供的文本提取结果。也许算法出了问题。

    我工作的公司有pdf库的示例代码,我使用 TextExtract C(我这样做是为了测试是否有可能实现您正在寻找的结果)文档样本(说明如何编写代码来提取PDF文档的文本),并从第7页提取了以下内容:

    合并利润表 人民币百万元,除非另有说明 未经审计 未经审计 2018年第1季度 2017年第1季度 2018年第1季度 2017年第4季度 收入 73528个 49552个 73528个 66392个 增值税 46877个 35108个 46877个 39947个 网络广告 一万零六百八十九 6888个 10689个 12361个 其他 15962个 7556个 15962个 14084个 收入成本 (36486) (24109个) (36486) (34897) 毛利润 37042个 25443个 37042个 31495个 毛利率 50% 51% 50% 47% 利息收入 1065年 808个 1065年 1156年 其他净收益 7585个 3191个 7585个 7906个 销售和营销费用 (5570个) (3158) (5570个) (6022) 一般及管理费用 (9430) (7012) (9430) (8811) 营业利润 30692个 19272年 30692个 25724个 营业利润率 42% 39% 42% 39% 净财务成本 (654个) (691) (654个) (859) 联营企业和合营企业的利润/(亏损)份额 (319) (375个) (319) (120个) 所得税前利润 29719个 18206年 29719个 24745个 所得税费用 (5746) (3658) (5746) (3123) 本期利润 23973个 14548个 23973个 21622个 净利润 33% 29% 33% 33% 归因于: 公司股东 23290个 14476个 23290个 20797个 非控股权益 683个 72个 683个 825个 归属于股东的非公认会计原则利润 单位 18313年 一万四千二百一十一 18313年 17454年 每股收益 公司股东 (每股人民币) -基本 2.470个 一点五四零 2.470个 2.206条 -稀释的 二点四三五 1.522个 2.435条 2.177条

    正如你所看到的,它会按照你的要求返回结果。

        3
  •  1
  •   Tim    6 年前

    您的问题更多的是如何构建PDF文件,而不是pyPDF2的问题在解析PDF以重新构造页面布局时,我遇到了许多相同的问题。

    生成pdf时,每个文本块都位于页面上,并根据应用的字体规则进行呈现(类似于只使用绝对定位和css构建html文档)。一个简单的pdf库只需按照文件中定义的顺序返回每个块的文本(当页面反向生成时,我已经有了文档,最后一段是首先定义的)。

    要么您需要使用一个更高级的PDF库(可能是在简单库的基础上构建的库),它将获取每个文本块的X、Y位置及其字体信息,以确定垂直位置,要么您自己开发这个库看起来这个软件 约瑟法 正在谈论的正是这样做的。

        4
  •  1
  •   Benehiko    6 年前

    我先查了一下 extractText function of PyPDF2 并试图从输出中“剥离”任何新行,以使您“跨过”页面一行。

    结果不太理想… output

    而且,从你的产出来看,它似乎并不可靠。 从PyPDF2文档中: 不要依赖于此函数中文本的顺序,因为如果使此函数更复杂,它将发生变化。

    所以我去探索使用tesseract的方法。因此,这与使用“pdf提取库”有点不同,它基本上是“构建自己的提取脚本”。

    一旦你掌握了特塞拉克,就不难了。我花了大约一小时的时间研究现有的知识。

    以下是我自己的代码逐页提取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文件保存在名为“pages”的单独目录中Pytesseract读取每个文件,然后返回文本,然后使用“.replace”进行格式化,该命令删除所有行并将文本格式化为一行。

    开始的地方: Tesseract install

    在python中使用tesseract: pytesseract

    使用的培训数据: eng.traineddata

    额外来源: pdf to tiff

    玻璃陶瓷: documentation

    我希望这对你有帮助。不确定这是不是你要找的东西。