Web開発
なぜ金額がすべてマイナス値になるのか?
Why are all the amounts values negative? (bankstatementconverter.com)
要約
PDFから金額を変換する際に、すべての値がマイナスになる問題が発生しました。これは、PDFのエンコーディングで、マイナス記号が背景色と同じ色で描画され、見えなくなっていることが原因でした。この問題は、PDFの右揃えを調整するために、見えないマイナス記号が使用されたために発生したと考えられます。解決策として、OCR処理や、黒以外の色のテキストを無視する方法が提案されています。
全文翻訳
数日前、顧客からこのようなメールを受け取りました。金額がすべてマイナスで表示されるとのことです。PDFを変換してみました。PDFサンプル 変換後サンプル 顧客の言う通り、すべての金額がマイナスとして表示されていました。非常に奇妙です。興味深いことに、列ヘッダーはマイナス記号で終わっています。
次に、PDFSnakeでPDFを開き、テキストがどのようにエンコードされているかを確認しました。値「$110.00-」と「$1,527.57-」がどのようにエンコードされているかを見てみましょう。
$110.00-
PDFは一連のコマンドで構成されています。このセグメントに現れるコマンドを順に見ていきましょう。
BT: Begin Text。PDFレンダラーにテキストレンダリングモードに入り、前のグラフィックス状態を保存するように指示します。Begin TextとEnd Textブロック内では、テキストオペレーターのみが許可されます。
ET: End Text。PDFにテキストレンダリングモードを終了し、BTコマンド前のグラフィックス状態を復元するように指示します。
Tf: テキストフォントとサイズを設定します。
Td: テキスト位置を移動します。
Tj: テキストを表示します。
g: 非ストローク操作のグレースケールを設定します。
G: ストローク操作のグレースケールを設定します。
上記のPDFコマンドは、「テキスト($110.00)を描画する。グレースケールを0に設定する。テキスト(-)を描画する」と要約できます。
$1,527.57-
これらのコマンドはすべて以前にも見たことがあり、構造も似ています。しかし、一つ重要な違いがあります。マイナス記号を描画する際に、グレースケールが0.878に設定されています。マイナス記号のグレースケールは、背景色と同じグレースケールです。これにより、マイナス記号が見えなくなります。文字は存在しますが、表示されないため、私のコードがこのPDFを処理する際に検出されるのです。
なぜ彼らはこのPDFをこのようにエンコードしたのでしょうか?私にはわかりませんが、推測できます。彼らはこのPDFで末尾のマイナス記号を使用しました。末尾のマイナス記号は、右揃えを少し難しくします。なぜなら、彼らは単純な右揃えを求めたのではなく、マイナス記号を無視した数値要素の右揃えを求めたからです。これを実現する一つの方法は、常にマイナス記号のためのスペースを空けておくことです。しかし、マイナス記号の幅はどれくらいでしょうか?フォントサイズによりますが、予測が難しいかもしれません。そこで彼らは、正の値に対して見えないマイナス記号を配置しました。PDFは見た目が良くても、そこからデータを抽出するのは大変です。
彼らは先頭にマイナス記号を使用すれば、このような事態を避けられたかもしれませんが、何らかの理由で末尾にマイナス記号を使用したかったのです。
さて、この問題が発生する理由がわかったところで、このPDFを正しく変換するにはどうすればよいでしょうか。2つの解決策が考えられます。
解決策1 - PDFをOCR処理する
PDF内のテキスト要素を読み取る代わりに、PDFをPNGファイルのシリーズに変換し、OCRソフトウェアを実行することができます。これはうまくいくはずですが、いくつかの欠点があります。OCR処理は100%正確ではありません。かなりうまく機能しますが、文字が誤って認識される可能性は常にあります。OCR処理は大幅に遅くなります。
解決策2 - 黒以外のテキストを削除する
この明細書のタイプでは、黒色のテキストのみが関連します。他の色に設定されたテキスト要素は、見えないものとして扱われます。これはうまくいくはずですが、一つ問題があります。Bank Statement Converterでテキストを抽出する際、テキストの色を保存していません。そのため、この機能を追加するコードが必要になります。ただし、それほど難しくはないはずです。