25
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PDF】日本語PDFの文字化けに怒ってRustでPDFパーサーを書いた

25
Posted at

自分のPythonプロジェクトでPDFのテキスト抽出が必要になった

仕事でPDFからテキストを抽出する処理を書いていて、英語のPDFはうまくいくのに日本語のPDFで文字化けが頻発しました。

# よくある光景
import pymupdf
doc = pymupdf.open("契約書.pdf")
text = doc[0].get_text()
print(text)

ライブラリを切り替えてみても同じ。pdfminer、pypdf、pypdfium2…どれも日本語CIDフォントのPDFで程度の差はあれ化けます。

原因を調べていくうちにPDF仕様そのものに興味が湧いて、1,000ページ超のPDF Reference(ISO 32000)を章ごとに読み始めました。数ヶ月かかりましたが、読み終わった頃には「これは自分で実装するしかない」と思っていました。

それで作ったのがPDF Oxideです。Rustで書いて、PyO3でPythonバインディングを付けています。

なぜ日本語で文字化けするのか

PDFはテキストを直接保存していません。グリフID(字形番号)を保存して、フォントエンコーディング経由でUnicodeに変換する仕組みです。

英語フォントはこの変換が比較的単純なのですが、日本語フォント(CIDフォント)は別の経路を通ります。Adobe-Japan1というレジストリのCID-to-Unicodeマッピングが必要で、これが15,000エントリ以上あります。

多くのライブラリがこのマッピングを持っていないか、不完全にしか実装していません。さらにShift-JIS/RKSJデコーディングやIdentity-H CMapの伝搬処理も必要で、どれか一つ抜けると化けます。

初期バージョンでは日本語CIDフォントの処理にバグがあって、ある種のPDFで一部の文字だけ化ける(残りは正しい)という厄介な状態になりました。原因はCID-to-Unicodeマッピングの優先順位の問題で、ToUnicode CMがある場合とない場合で処理を分岐させる必要がありました。

PDF Oxideの対応

PDF Oxideでは80,000以上のCID-to-Unicodeマッピングを内蔵しています(Adobe-Japan1, GB1, CNS1, Korea1)。Shift-JIS/RKSJデコーディングとCFFフォントエンコーディングパーサーも実装済みです。

pip install pdf_oxide

from pdf_oxide import PdfDocument

doc = PdfDocument("日本語文書.pdf")
text = doc.extract_text(0)   # 正しい日本語テキスト
md = doc.to_markdown(0, detect_headings=True)  # Markdown変換

ベンチマーク

3,830の実PDFファイル(veraPDF 2,907、Mozilla pdf.js 897、DARPA SafeDocs 26)でテスト。テストコーパスもベンチマークコードもリポジトリで公開しています。

ライブラリ 平均 p99 パス率 ライセンス
PDF Oxide 0.8ms 9ms 100% MIT
PyMuPDF 4.6ms 28ms 99.3% AGPL-3.0
pypdfium2 4.1ms 42ms 99.2% Apache-2.0
pdfminer 16.8ms 124ms 98.8% MIT
pdfplumber 23.2ms 189ms 98.8% MIT
pypdf 12.1ms 97ms 98.4% BSD-3

v0.3.5で平均23.3msだったのが、プロファイリングを繰り返してv0.3.8で0.8msまで下がりました。一番効いたのはページツリーのO(n^2)探索をO(1)バルクキャッシュに変えたこと(168倍高速化)です。

テキスト抽出以外にもPDF作成(Markdown/HTML/画像から)、OCR(PaddleOCR + ONNX Runtime)、暗号化(AES-256)などに対応しています。MITライセンスです。

リンク

日本語PDFでテストしていただけると助かります。文字化けやバグを見つけたらGitHub issueで教えてください。

25
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?