とある地味なブログ

プログラミングとお絵かきに関する雑記。

Xpdfで特定の文字が読めない

行政や公的機関は、各種データをPDFで公開すんな (# ゚Д゚)

JRAのPDFを読もうとした

年度別全成績(PDF) JRA

ここのPDFからテキストを抽出しようとした。

PDFをテキスト化する方法

Mac環境で、PDFからテキストを抽出するには、 Xpdf や、その派生である Poppler が使えるらしい。

他には、Mac標準でついてきたAutomatorとかいうアプリケーションでもできる。 Googleドキュメントでテキストとして書き出しもできるし、Adobe Readerでテキストとして保存することもできる。

はずだった。

どうやってもダメ

最初はRubyでPDFのテキストをさくっと読めると思ったのだが、

  1. gem i popplerをしてもインストールできないし(おそらく既知のバグ)
  2. Ruby Gemのpdf-readerもダメだったし(理由は忘れた)
  3. XpdfとPopplerは一部の数字を読み取れないし
  4. Automatorは一部の数値(金額系?)が勝手に書き換わるし、テキストのフォーマットがぐちゃぐちゃ
  5. そのへんに落ちてたpdftotextとかいうツールもダメ
  6. Adobe Readerでテキストとして保存してもフォーマットがぐちゃる
  7. Adobe Readerで全選択->コピペが最善に思われたがExcel VBA以外で自動化する方法が見つからず
  8. Google DocsでPDFファイルを編集しようとしたら文字化けの嵐

という大変な遠回りをしたのでした。

なんでダメなんだぜ?

PDFで指定されてる文字コードがおかしかった

Ruby で PDF と戯れるの巻 - Qiita

こちらの記事が大変参考になった。 ただし、Origamiのクラス構造が変わっており、ドキュメントも見つからなかったため、 gem i pdf-readerして、

require 'pdf/reader'
reader = PDF::Reader.new("2015-1sapporo1.pdf")
print reader.pages.first.raw_content

として、PDFの中身を見た。バイナリエディタでは読めなかった...

BT(Begin Text)を探すと、以下の様なコードがある。

BT
0 0 0 1 k
/GS0 gs
/C0_0 1 Tf
7.36 0 0 8 18.7159 470.918 Tm
[<2692>500<2693>500<2690>500<2690>500<2691>]TJ

[<xxxx>]の中身は16進のCIDコードらしいので(2692なら10進で9874)、

Adobe-Japan1-6 Character Collection for CID-Keyed Fonts

ここから文字を検索すると、23001であることがわかる。 これはXpdfで抽出できなかった数字である。

どうも、この数字はCID 17 - 26 の数字とは異なる文字らしい。 この特殊な数字が原因ではないかと予想できる。

XpdfはどうやってCIDからUnicode文字に変換しているのか?

xpdfを使ってPDFから日本語抽出 | akkunchoi@github

Xpdfのインストール時に、日本語パッケージを設定している。 この名前から推測してcidToUnicodeがそうだろう。

Adobe-Japan1.cidToUnicodeのフォーマット

XpdfのソースコードCharCodeToUnicode.ccを読むと、 行数がCIDコード、そこにある16進数がUnicodeだということがわかる。

Adobe-Japan1.cidToUnicodeを編集する

Adobe-Japan1.cidToUnicodeの9873行目から9882行目を見ると、 すべて0000となっており、 数字が読めていなかった理由がわかる。

したがって、9873行目から9882行目を以下のように編集する。 Unicode 0030-0039は0-9の数字に対応する。

任意の変換をしたい場合、任意のCID行目を任意のUnicodeに変更すれば良い。

0030
0031
0032
0033
0034
0035
0036
0037
0038
0039

やっとできた

$ pdftotext 2015-1sapporo1.pdf

キター

これをパースするのがまた大変そうだよ...