はしくれエンジニアもどきのメモ

情報系技術・哲学・デザインなどの勉強メモ・備忘録です。

PythonでPDFを処理できるpdfminer3kの使い方メモ

PythonでPDFを処理できるpdfminer3kの使い方メモ

pdfminerを使うとpdfをパース・解析(情報を取得)できる(pdfのスクレイピング的なことができる).

環境

  • Windows10

    • python 3.5.3

    • pdfminer3k 1.3.1

pdfminerのモジュールの種類

オリジナルのpdfminerはpython2系デノミ使える.

種類 pythonのversion 更新
pdfminer(オリジナル) 2系 最新版2014年
pdfminer.six 2・3系対応 2017年の今も更新されている
pdfminer3k 3系 最新版2015年

注意点:どのモジュールもimportするときのnameはpdfminerなので競合注意.

これからpdfminerを始める人は,「pdfminer.six」がよさげ(今も更新されているので).

install

上記の3つはpip からインストールできる.


> pip search pdfminer3k
pdfminer3k (1.3.1)  - PDF parser and analyzer

> pip install pdfminer3k

pdfminerの処理の流れ

必要なオブジェクトがけっこうあるので,最初とっつきにくい. が,オブジェクトごとに役割がある.

  1. PDFファイルを開き,PDFのファイルオブジェクトを作成

  2. PDFParserオブジェクトを作って,1.のファイルオブジェクトを投げる,`PDFParser`はファイルからデータをfetchする.

  3. PDFDocument オブジェクトにパーサーから読まれたデータが保存される(まだ各ページの内容(page content)の処理はしていない).

  4. PDFPageInterpreterオブジェクトを作成.PDFDocumentから任意のページのオブジェクトPagePDF を投げると,page contentが処理される.

  5. PDFDeviceオブジェクトに,そのページのテキストなどのデータが保存される.

PDFResourceManagerオブジェクトは,シェアされるリソース( fonts や imageなど)を保存するのにつかわれる.

pdfminer3kのサブモジュールとクラスの位置

pdfminer(2系オリジナル)とpdfminer 3kのクラスの位置が異なるので注意.


# pdfminer3kの場合
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfparser import PDFDocument
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfparser import PDFPage
from pdfminer.pdfparser import PDFException
from pdfminer.pdfdevice import PDFDevice
from pdfminer.converter import PDFPageAggregator
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams

example1:PDFファイルの各ページのPDFPageオブジェクトの取得

この例では,PDFPageInterpreterPDFDeviceは使わない.


  # 一括処理
  from pdfminer.pdfparser import PDFParser
  from pdfminer.pdfparser import PDFDocument
  from pdfminer.pdfparser import PDFPage
  from pdfminer.pdfparser import PDFException
  from pdfminer.pdfinterp import PDFResourceManager
  from pdfminer.pdfinterp import PDFPageInterpreter
  from pdfminer.pdfdevice import PDFDevice

  # Open a PDF file.
  fp = open('.pdf', 'rb')

  # Create a PDF parser object associated with the file object.
  parser = PDFParser(fp)
  document = PDFDocument()
  parser.set_document(document) # set document to parser

  # Create a PDF document object that stores the document structure.
  # Supply the password for initialization.
  password="" # pdfを開くときのパスワード
  document.set_parser(parser) # set parser to document
  document.initialize(password)

  # Check if the document allows text extraction. If not, abort.
  if not document.is_extractable:
      raise PDFException

  # Process each page contained in the document.
  for page in document.get_pages():
      print(page)

> , 'ExtGState': , 'ProcSet': [/PDF, /Text]}, MediaBox=[0, 0, 595.28, 841.89]>

PDFPageprintすると, FontやMediaBoxなどの情報が見れる.

注意:Encryption Errorが出る場合

document.initialize()Encryption Errorが出る場合,PDFに保護がかかっている可能がある.なので保護をqpdfなどで解除する必要がある.

cartman0.hatenablog.com


参考

example2: レイアウト解析

Webスクレイピングでいうところのhtmlのタグ構造を見るのと同じように, PDFのそのページの構造が見れる.

今回の例は,PDF中の1ページ目中の複数ある LTTextBoxHorizontalから文字列を抽出する.


# 一括処理
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfparser import PDFDocument
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfparser import PDFPage
from pdfminer.pdfdevice import PDFDevice
from pdfminer.converter import PDFPageAggregator
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.layout import LTTextBoxHorizontal

# Open a PDF file.
fp = open('epack_shipping_dec.pdf', 'rb')

# Create a PDF parser object associated with the file object.
parser = PDFParser(fp)
document = PDFDocument()
parser.set_document(document)

# Create a PDF document object that stores the document structure.
# Supply the password for initialization.
password=""
document.set_parser(parser)
document.initialize(password)

# Create a PDF resource manager object that stores shared resources.
rsrcmgr = PDFResourceManager()

# Set parameters for analysis.
laparams = LAParams()

# Create a PDF page aggregator object.
device = PDFPageAggregator(rsrcmgr, laparams=laparams)
interpreter = PDFPageInterpreter(rsrcmgr, device)

pages = list(document.get_pages())
page_1 = pages[0] # 1st page
page_1

# interpreter page1
interpreter.process_page(page_1)

# receive the LTPage object for the page.
# layoutの中にページを構成する要素(LTTextBoxHorizontalなど)が入っている
layout = device.get_result()
# print(layout)

for l in layout:
#     print(l) # l is object
    if isinstance(l, LTTextBoxHorizontal):
        print(l.get_text()) # オブジェクト中のtextのみ抽出