pdfminerでpdfから文字情報の取り出し

pdfminer で pdf から文字情報を取り出す。

インストール

pip install pdfminer.six
pip install chardet

sixにしないと日本語が認識されないので注意

参考: https://techacademy.jp/magazine/22374

  • 例1
#coding: utf-8
import io
import os
from pdfminer.pdfparser import PDFParser # (from pdfminer.pdfparser import PDFParserみたいです)
from pdfminer.pdfdocument import PDFDocument # (from pdfminer.pdfdocument import PDFDocumentみたいです)
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.pdfpage import PDFPage

os.chdir("F:\\\\dir\\python_test")
print(os.getcwd())   




retstr = io.StringIO()

parser = PDFParser(open("outfile/test2.pdf",'rb'))

try:
    doc = PDFDocument(parser)
except Exception as e:
    print('is not a readable pdf')
parser.set_document(doc)

rsrcmgr = PDFResourceManager()
device = TextConverter(rsrcmgr, retstr)
interpreter = PDFPageInterpreter(rsrcmgr, device)

# doc.get_pages()はバージョンが古くて、PDFPage.create_pages(doc)とするべきみたいです。
for page in PDFPage.create_pages(doc):
#for page in PDFPage.get_pages(doc):
    interpreter.process_page(page)

device.close()

str = retstr.getvalue()
print(str)
retstr.close()

str
  • 例2


def ch_pdf2txt(input_filename="test2.pdf",output_filename="test2.txt",output_dir="outfile"):
    def find_textboxes_recursively(layout_obj):
        print(layout_obj)
        #"""
        #再帰的にテキストボックス(LTTextBox)を探して、テキストボックスのリストを取得する。
        #"""
        # LTTextBoxを継承するオブジェクトの場合は1要素のリストを返す。
        if isinstance(layout_obj, LTTextBox):
        #if isinstance(layout_obj, LTRect):
            return [layout_obj]

        # LTContainerを継承するオブジェクトは子要素を含むので、再帰的に探す。
        if isinstance(layout_obj, LTContainer):
            boxes = []
            for child in layout_obj:
                boxes.extend(find_textboxes_recursively(child))

            return boxes

        return []  # その他の場合は空リストを返す。

    # Layout Analysisのパラメーターを設定。縦書きの検出を無効にする。
    # line_margin :行間幅が大きすぎて誤検出されたので小さくする。
    laparams = LAParams(detect_vertical=False,line_margin=0.000000000,char_margin=0.2)

    # 共有のリソースを管理するリソースマネージャーを作成。
    resource_manager = PDFResourceManager()

    # ページを集めるPageAggregatorオブジェクトを作成。
    device = PDFPageAggregator(resource_manager, laparams=laparams)

    # Interpreterオブジェクトを作成。
    interpreter = PDFPageInterpreter(resource_manager, device)

    # 出力用のテキストファイル
    #output_txt = open('outfile/output.txt', 'w')
    output_filename2="outfile\\"+output_filename
    output_txt = open(output_filename2, 'w')


    #入力用ファイル
    #input_pdf=sys.argv[1]
    #input_pdf="outfile/test2.pdf"
    input_pdf="outfile\\"+input_filename
    input_txt = open(input_pdf)


    def print_and_write(txt):
        print(txt,end="")
        #print(txt)
        output_txt.write(txt)
        #output_txt.write('\n')

    syasin_x=10000000000
    hyouzu_x=10000000000
    renban_x=10000000000
    keisaibi_x=10000000000
    wareki_x=10000000000
    sisi_x=10000000000
    page_x=10000000000                               
    dansuu_x=10000000000        
    midasi_x=10000000000                  


    syasin_flg=True
    hyouzu_flg=True
    syasin_flg=True
    hyouzu_flg=True
    renban_flg=True
    keisaibi_flg=True
    wareki_flg=True
    sisi_flg=True
    page_flg=True                             
    dansuu_flg=True       
    midasi_flg=True
    kiji_title_flg=True
    
    header_flg=True
    header_flg2=False
    print(input_pdf)
    with open(input_pdf, 'rb') as f:
        # PDFPage.get_pages()にファイルオブジェクトを指定して、PDFPageオブジェクトを順に取得する。
        # 時間がかかるファイルは、キーワード引数pagenosで処理するページ番号(0始まり)のリストを指定するとよい。
        for page in PDFPage.get_pages(f):
            #print(f)
            print_and_write('\n====== ページ区切り ======\n')
            interpreter.process_page(page)  # ページを処理する。
            layout = device.get_result()  # LTPageオブジェクトを取得。
            print(layout)
            # ページ内のテキストボックスのリストを取得する。
            boxes = find_textboxes_recursively(layout)
            print(boxes)
            # テキストボックスの左上の座標の順でテキストボックスをソートする。
            # y1(Y座標の値)は上に行くほど大きくなるので、正負を反転させている。
            boxes.sort(key=lambda b: (-b.y1, b.x0))
            old_y=-100
            #print(boxes)
            for box in boxes:
                #print(box.get_text())
                #print_and_write('-' * 10)  # 読みやすいよう区切り線を表示する。
                #print_and_write(box.get_text().strip())  # テキストボックス内のテキストを表示する。
                #print(box.y1)
               # print(type(box.get_text()))
               # print(type("写真"))
               # print(box)
                if round(1*box.y1)!=round(1*old_y):
                    #print_and_write("aaa"+str(box.x0)+"aaa")
                    print_and_write("\n")
                    syasin_flg=True
                    hyouzu_flg=True
                    renban_flg=True
                    keisaibi_flg=True
                    wareki_flg=True
                    sisi_flg=True
                    page_flg=True                             
                    dansuu_flg=True       
                    midasi_flg=True
                    kiji_title_flg=True
                    if header_flg2:
                        header_flg=False

                if "連番" in str(box.get_text()):
                    renban_x=box.x1
                    
                    print_and_write(box.get_text().replace("\n",""))
                    print_and_write(",") 
                    header_flg=True

                if header_flg:    
                    
                    if "掲載日" in str(box.get_text()):
                        keisaibi_x=box.x1
                       # keisaibi0_x=box.x0
                        print_and_write(box.get_text().replace("\n","")) 
                        print_and_write(",") 

                    if "和暦" in str(box.get_text()):
                        wareki_x=box.x1
                        print_and_write(box.get_text().replace("\n","")) 
                        print_and_write(",") 

                    if "紙誌" in str(box.get_text()):
                        sisi_x=box.x1
                        print_and_write(box.get_text().replace("\n","")) 
                        print_and_write(",")    

                    if "ページ" in str(box.get_text()):
                        page_x=box.x1
                        print_and_write(box.get_text().replace("\n","")) 
                        print_and_write(",") 

                    if "段数" in str(box.get_text()):
                        dansuu_x=box.x1
                        print_and_write(box.get_text().replace("\n","")) 
                        print_and_write(",")  

                    if "見出し" in str(box.get_text()):
                        midasi_x=box.x1
                        print_and_write(box.get_text().replace("\n","")) 
                        print_and_write(",")          


                    if "写真" in str(box.get_text()):
                        #   print("syasin",str(box.x0),"syasin")
                        syasin_x=box.x1
                        print_and_write(box.get_text().replace("\n","")) 
                        print_and_write(",") 

                    if "表図" in str(box.get_text()):
                     #   print("syasin",str(box.x0),"syasin")
                        hyouzu_x=box.x1;
                        print_and_write(box.get_text().replace("\n","")) 
                        print_and_write(",")

                    if "記事タイトル" in str(box.get_text()):
                     #   print("syasin",str(box.x0),"syasin")
                        kiji_title_x=box.x1;
                        print_and_write(box.get_text().replace("\n","")) 
                        #print_and_write(",") 
                        header_flg2=True


                if not header_flg:    
              


                    if (1*box.x1)>=renban_x and int(renban_flg)<=2:
                        #print_and_write("aaa"+str(box.x0)+"aaa")
                    
                        renban_flg=int(renban_flg)+1
                        if renban_flg == 3:
                            print_and_write(",")
                        

                    if (1*box.x0)>=keisaibi_x and keisaibi_flg:
                        #print_and_write("aaa"+str(box.x0)+"aaa")
                        print_and_write(",")    
                        keisaibi_flg=False

                    if (1*box.x0)>=wareki_x and wareki_flg:
                        #print_and_write("aaa"+str(box.x0)+"aaa")
                        print_and_write(",")    
                        wareki_flg=False

                    if (1*box.x0)>=sisi_x and sisi_flg:
                        #print_and_write("aaa"+str(box.x0)+"aaa")
                        print_and_write(",")    
                        sisi_flg=False
                    if (1*box.x0)>=page_x and page_flg:
                        #print_and_write("aaa"+str(box.x0)+"aaa")
                        print_and_write(",")    
                        page_flg=False

                    if (1*box.x0)>=dansuu_x and dansuu_flg:
                        #print_and_write("aaa"+str(box.x0)+"aaa")
                        print_and_write(",")    
                        dansuu_flg=False

                    if (1*box.x0)>=midasi_x and midasi_flg:
                        #print_and_write("aaa"+str(box.x0)+"aaa")
                        #print("\n midasi:"+box.get_text()+"\n")
                        print_and_write(",")    
                        midasi_flg=False

                    
                    #print("syasin_flg"+str(syasin_flg)+"\n")   
                    if (1*box.x0)>=syasin_x and syasin_flg:
                        #print_and_write("aaa"+str(box.x0)+"aaa")
                        #print("test:"+box.get_text())
                        #print("\n syasin:"+box.get_text()+"\n")
                        print_and_write(",")  
                        
                        syasin_flg=False

                    if (1*box.x0)>=hyouzu_x and hyouzu_flg:
                        #print_and_write("aaa"+str(box.x0)+"aaa")
                        #print("\n hyouzu:"+box.get_text()+"\n")
                        print_and_write(",")    
                        hyouzu_flg=False
                        
                    if (1*box.x0)>=kiji_title_x and kiji_title_flg:
                        #print_and_write("aaa"+str(box.x0)+"aaa")
                        #print("\n kiji:"+box.get_text()+"\n")
                        print_and_write(",")    
                        kiji_title_flg=False

                    print_and_write(box.get_text().replace("\n","")) 
                #print_and_write(",")
                #print_and_write(str((box.y1))+box.get_text().strip()) 
                old_y=box.y1

    output_txt.close()
    
#ch_pdf2txt(input_filename="outfile\\test2.pdf",output_filename="outfile\\test2.txt")