[pukiwiki]
”日本語”のPDFファイル300個ほどからデータを抜き出すことになりました。
で、プロテクトもかかってないし、手作業で行おうかと思ったのですが、以前から興味のあった、Pure Python なライブラリPDFMinerを使い、テキストデータを抽出してみました。
[/pukiwiki]
[pukiwiki]
なぜか、付属してきたサンプルプログラムはhtml等を出力するようになってたので、プレーンテキストを出力するサンプルスクリプトを書くことに。
*インストール
環境はVista ,Python2.5
都合により、公式サイトに書かれた手順とは少し異なります。
-こちらのサイトからダウンロード
–[[PDFMiner:http://www.unixuser.org/~euske/python/pdfminer/index.html]]
–今回使用したアーカイブ
pdfminer-dist-20090201.tar.gz
-同ページにてCMapファイルをダウンロード
CMap.tar.bz2
–解凍後、展開されたフォルダCMapを”pdflib”フォルダ内に移動
–同pdflibフォルダ内に空フォルダCDBCMapを作成
-実行スクリプトからimportできるところにpdflibフォルダを置く
–常用する場合はpdflibをPython2.5/Lib/site-package へ移動
*プレーンテキストを抽出してみる。
こちらのコードを、ファイル名 plaintext.py として保存してください
_python plaintext.py hoge.pdf
そのまま実行すると、hoge.pdfの文章のみを、hoge.pdf.txtにプレーンテキストとして保存します。(utf8)
[/pukiwiki]
#!/usr/bin/env python # -*- coding: utf-8 -*- """plaintext.py""" import pdflib #from pdflib.pdfparser import PDFDocument, PDFParser, PDFPasswordIncorrect from pdflib.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdflib.pdfdevice import PDFDevice, FigureItem, TextItem, PDFPageAggregator from pdflib.pdffont import PDFUnicodeNotDefined from pdflib.cmap import CMapDB from pdflib.pdf2txt import TextConverter,enc class PlainTextConverter(TextConverter): idx=[ [],[1,3],[0,2]] def __init__(self, rsrc, codec='ascii',\ merge=1, \ #同一行とおぼしきものは連結 # 0 None 1 Horizontal 2 Virtical joinner="\n"): TextConverter.__init__(self,rsrc,None,codec=codec) self.text="" self.lines=[] self.joinner=joinner self.merge=merge return def end_page(self, page): TextConverter.end_page(self, page) page = self.cur_item def f(item,xy=[None,]*4): item2=item if isinstance(item, TextItem): if True in [ item.bbox[i]==xy[i] for i in self.idx[self.merge]]: #バウンダリボックスから、同一行かどうかを判定 txt=enc(item.text, self.codec) self.lines[-1]+=txt else: txt=enc(item.text, self.codec) self.lines.append(txt) xy[:]=item.bbox[:] if hasattr(item,"child") : f(item,child) self.lines=[] for child in page.objs: f(child) self.text+=self.joinner.join(self.lines)+self.joinner return rsrc=PDFResourceManager() import sys stdout = sys.stdout import os #ここでこうする都合で、CMapフォルダをpdflib内に移動してます dr=os.path.split(pdflib.__file__)[0] cmapdir = os.path.abspath('%s/CMap'%dr) cdbcmapdir = os.path.abspath('%s/CDBCMap'%dr) CMapDB.initialize(cmapdir, cdbcmapdir) device= PlainTextConverter(rsrc,codec="utf-8",merge=1,joinner="\n") def convert(fname): device.text="" pdflib.pdf2txt.convert(rsrc,device,fname) return device.text if __name__ == "__main__": import sys fname=sys.argv[1] #fname="test.pdf" convert( fname) fp=open(fname+".txt","wb") fp.write(device.text) fp.close()
[pukiwiki]
上記をモジュールとして使う場合のテストスクリプト
[/pukiwiki]
from pdflib import plaintext import glob flist=glob.glob("*.pdf") for f in flist[:3]: txt=plaintext.convert(f) open(f+".txt","wb").write(txt)
[pukiwiki]
*感想
今回、私が使うPDFはきれいにプレーンテキストに変換できました。ヤッター
官報のような入り組んだレイアウトだと、なぜか本文が消えちゃうことがあります。
CMap関連をちゃんとインスコしてないからかも。
(ホントは、makeして文字コード関連のデータベースを作成するように書いてあるのですが、手元のツールが足りなかったため、行ってません。)
個人的には、いいかげん官報はRSSリーダーで読めるようになって欲しいと思うのですけれども。それはさておき。
世の中には、pdfをプレーンテキストとして出力してくれるフリーソフトがいくつかありますので、それらをsubprocessモジュール(Popen関数)を使って実行してやるのもよいかも。
ですが、今回のサンプルコードで行ったように、(改行を入れる位置など)きめ細かい操作が行えるので、PDFMinerも場合によっては便利ですー
[/pukiwiki]