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")