PDFをテキストに変換するバッチ

一見すると、昨年、データベースにエクスポートするデータを含む12列のテーブルを含むファイルのバッチ処理システムを作成するために、単純な作業が命じられました。 すべては問題ありませんが、ファイルはPDFのドキュメントであることが判明し、顧客は処理用の別の形式を提供できないと主張しました。



画像

同じPDFのサンプル-構造はファイルに保存されますが、すべてのデータは消去されます。



まあ、知識のある人々の警告にもかかわらず、彼らは驚くべきことを警告しました-私は仕事に行き、この冒険を経験しました:







PDFファイルのバッチ処理用ソフトウェアの検索が開始されました。 作業はLinuxで行われました-最初の申請者はpopplerパッケージのプログラム-pdftotextであったため、この目的で最もよく使用されます。



pdftotext



この関数はコマンドラインから簡単に呼び出され、次の形式になります。



$ pdftotext .pdf .txt









しかし、変換結果は非常に奇妙であることが判明しました。



レジストリから抽出する

お得



オークションに続いて

CJSCサンクトペテルブルク

インターナショナル

商品交換



SET-VRSフォーム



入札日:1900年1月1日

セクション:SPbMTSB CJSCの石油製品セクション

メンバー:LLC

メンバーコード:000000000000

クライアントの名前とコード:OJSC / 000000000000

ツールコード:0000000001

ツールの説明:Gasoline Premium Euro-95 type II class B、



お得



時間

お得



申込番号



購入/取引価格(数量ごと

セール¹

1トン)

たくさん



01-01



02-02



01-03



S



01-05



5



02-01



02-02



02-03



S



02-05



1



0000000001の合計



などなど...



それだけでなく、出力はファイルごとに変化します-もちろん、この形式では、パーサーを作成してテーブルからデータをプルすることはできませんでした。



そのため、今度は独自の候補がもうすぐ登場します。Linux用のAdobe Acrobat Readerです。



Acrobat Reader



この場合、まず、コマンドラインを詳しく調べることなく、グラフィカルモードで「ファイル-テキストとして保存」の機能をテストすることにしました。 後で判明したように、私は正しいことをしました-私のpdfとこのプログラムでの変換の結果は楽観主義を刺激しませんでした:



メンバーID:

セクション:

ツールコード:

ツールコード:

000000000000

LLC

0000000001

0000000002

00,000,000.11 00,000.12

0,000,000.21 0,000.22

01-12

02-12

03-12

04-12

CJSCサンクトペテルブルク

インターナショナル

商品交換

レジストリから抽出する

お得

オークションに続いて

入札日:1900年1月1日

SET-VRSフォーム

クライアントの名前とコード:OJSC / 000000000000

メンバー:

SPbMTSB CJSCのオイル製品セクション

ツールの説明:Gasoline Premium Euro-95 type II class B、

コード

トレーダー

時間

トランザクショントランザクション量



お得

申込番号

0000000001の合計

ツールの説明:冬のディーゼル燃料Z-0.2-35。

コード

トレーダー

時間

トランザクショントランザクション量



お得

申込番号

0000000002の合計



などなど...



このような結論を解析するために、私も本当にしたくありませんでした。



最後に、最後の候補はpdfeditでした



pdfedit



すべてのリポジトリで、コマンドラインからスクリプトを実行できるグラフィカルプログラムで表されます。 PDFをグラフィカル環境「ファイル-テキストとして保存」から生成されたテキストに変換する最初の開始であるAcrobat Readerと同様に、結果は非常に満足しています。



 
  CJSC「サンクトペテルブルクの登録SET-VRSフォームからの抜粋 
  国際取引 
  商品と原料の交換」入札の結果をフォロー 
                               入札日:1900年1月1日 
  セクション:CJSC「SPbMTSB」のセクション「石油製品」 
  メンバー:LLC 
  メンバーコード:000000000000 
  クライアントの名前とコード:OJSC / 000000000000 
  ツールコード:0000000001 
  ツールの説明:Gasoline Premium Euro-95 type II class B、 
    ルームタイムオーダー番号 
                      購入/取引価格(数量ごと 
                                                    NDS Exchange名 
                                                                                  コード 
                                  CRCトランザクション量 
   取引取引セール¹ 
                        1トン) 
                               ロット(18%)カウンターパーティコレクション 
                                                                               トレーダー 
  01-01 01-02 01-03 S 01-05 5 01-07 01-08 01-09 01-10 PeSee 
                                                                             01-12 
  02-01 02-02 02-03 S 02-05 1 02-07 02-08 02-09 02-10 PbSE 
                                                                             02-12 
   0000000001 00,000,000.11 00,000.12の合計 
  ツールコード:0000000002 
  ツールの説明:冬のディーゼル燃料Z-0.2-35。 
    ルームタイムオーダー番号 
                      購入/取引価格(数量ごと 
                                                    NDS Exchange名 
                                                                                  コード 
                                  CRCトランザクション量 
   取引取引セール¹ 
                        1トン) 
                               ロット(18%)カウンターパーティコレクション 
                                                                               トレーダー 
  03-01 03-02 03-03 S 03-05 1 03-07 03-08 03-09 03-10 PuSee 
                                                                             03-12 
  04-01 04-02 04-03 S 04-05 1 04-07 04-08 04-09 04-10 PgSee 
                                                                             04-12 
   0000000002の合計0.000.000.21 0.000.22 
  ブローカーSPbMTSB電子文書のコピー 
        ¹B-購入、S-販売。  1/3 
 






結果は非常に正しい結論でした-解析は簡単で快適です。 しかし、それはそこにありませんでした、叙事詩を完了するための道は厄介でした。 標準のpdfeditアセンブリのコマンドラインから「テキストとして保存」関数を呼び出すことはできませんでした。



 
  $ pdfedit -console 
  PDFedit 0.4.5 
  使用法: 
   pdfedit -console [関数名] [関数パラメーター(複数可)] 
  最初のパラメーターは、呼び出す関数の名前(大文字と小文字を区別しない)またはその明確な部分です。 
  残りのパラメーターは、呼び出された関数に渡されます。 
  利用可能な機能: 
   デリニアライザ 
    説明:入力ファイルの非線形化 
    パラメーター:[入力ファイル] [出力ファイル] 
   フラットナー 
    説明:入力ファイルを統合(最後のリビジョンを除くすべてのリビジョンを削除) 
    パラメーター:[入力ファイル] [出力ファイル]  
 






コンソールヘルプの出力は、テキストへの変換とは関係のない2つのユーティリティを提供しました。 wikiのドキュメントをさらに調査すると、既製の変換スクリプトsavealltext.qsが作成されましたが、問題は、グラフィカルメニューから実行する必要があることです。 その結果、材料を詳細に調査する必要がありました。



pdfeditスクリプトAPIの説明

pdfeditスクリプト作成wiki

既製のスクリプトの例



この素材の「喫煙」はすでに+標準アセンブリで提示されているコンソールスクリプト/usr/share/pdfedit/delinearize.qsの段階的な分析-私は自分でsavealltext.qsを作成することになりました。



 /** Print help for savealltext */ function savealltext_help() { print(tr("Usage:")); print("savealltext ["+tr("input file")+"] ["+tr("output file")+"]"); print(" "+tr("Input file must exist")); print(" "+tr("Output file must not exist")); exit(1); } function savealltext_fail(err) { print(tr("savealltext failed!")); print(err); exit(2); } function saveAsText_save(p,f) { document=loadPdf(p) qs=""; pages=document.getPageCount(); for (i=1;i<=pages;i++) { pg=document.getPage(i); text=pg.getText(); qs+=text; qs+="\n"; } saveFile(f,qs); } p=parameters(); if (p.length!=2) { savealltext_help("savealltext "+tr("is expecting two parameters")); } inFile=p[0]; outFile=p[1]; if (!exists(inFile)) savealltext_fail(tr("Input file '%1' does not exist").arg(inFile)); if (exists(outFile)) savealltext_fail(tr("Output file '%1' already exist").arg(outFile)); if (inFile==outFile) savealltext_fail(tr("Input and output files must be different")); if (saveAsText_save(inFile,outFile)) { } else { print(tr("savealltext")+" :"+inFile+" -> "+outFile); } 
      





/** Print help for savealltext */ function savealltext_help() { print(tr("Usage:")); print("savealltext ["+tr("input file")+"] ["+tr("output file")+"]"); print(" "+tr("Input file must exist")); print(" "+tr("Output file must not exist")); exit(1); } function savealltext_fail(err) { print(tr("savealltext failed!")); print(err); exit(2); } function saveAsText_save(p,f) { document=loadPdf(p) qs=""; pages=document.getPageCount(); for (i=1;i<=pages;i++) { pg=document.getPage(i); text=pg.getText(); qs+=text; qs+="\n"; } saveFile(f,qs); } p=parameters(); if (p.length!=2) { savealltext_help("savealltext "+tr("is expecting two parameters")); } inFile=p[0]; outFile=p[1]; if (!exists(inFile)) savealltext_fail(tr("Input file '%1' does not exist").arg(inFile)); if (exists(outFile)) savealltext_fail(tr("Output file '%1' already exist").arg(outFile)); if (inFile==outFile) savealltext_fail(tr("Input and output files must be different")); if (saveAsText_save(inFile,outFile)) { } else { print(tr("savealltext")+" :"+inFile+" -> "+outFile); }







/ usr / share / pdfedit /ディレクトリに配置されると、スクリプトはコマンドラインから呼び出され、必要な変換を実行します。



 
  $ pdfedit -console 
  PDFedit 0.4.5-20111014140242 
  使用法: 
   pdfedit -console [関数名] [関数パラメーター(複数可)] 
  最初のパラメーターは、呼び出す関数の名前(大文字と小文字を区別しない)またはその明確な部分です。 
  残りのパラメーターは、呼び出された関数に渡されます。 
  利用可能な機能: 
   デリニアライザ 
    説明:入力ファイルの非線形化 
    パラメーター:[入力ファイル] [出力ファイル] 
   フラットナー 
    説明:入力ファイルを統合(最後のリビジョンを除くすべてのリビジョンを削除) 
    パラメーター:[入力ファイル] [出力ファイル] 
   savealltext 
    説明:savealltext入力ファイル 
    パラメーター:[入力ファイル] [出力ファイル] 
 






$pdfedit -console savealltext .pdf .txt







すべてがうまくいくように見えましたが、落とし穴は浮かび上がりました:コンソールモードで、pdfeditが612x792ピクセルのデフォルト領域からテキストを選択することが判明しました-これは、72 dpiの解像度でA4横向きシートに対応します。 パッチrotate_text_fix.patchからの対応する命令のコード内に存在するにもかかわらず、プログラムはスキャン領域を回転させたくありませんでした

このトリッキーな「デフォルトエリア」の定義を検索すると、プロジェクトソースコード 、ファイルsrc / kernel / displayparams.hに移動しました。結局のところ、どこに配置するかがわかりました。



static const int DEFAULT_PAGE_RX = 612; /**< Default A4 width on a device with 72 horizontal dpi. */

static const int DEFAULT_PAGE_RY = 792; /**< Default A4 height on a device with 72 vertical dpi. */







両方の値を1584ポイント(同じ解像度のwhatmanの半分に相当)に置き換え、プロジェクトを再変換しました。



これについては、苦痛は終わったと言うことができます-PDFは、A4thランドスケープアルバムランドスケープのすべてで、ターミナルから処理されました。

彼の苦痛の結果に基づいて、彼はArchLinuxのsavealltextでpdfeditパッケージを構築するルールを作成し、それをAURに入れました:

pdfeditリリース

csvからのpdfeditバージョン



PS:



おとぎ話はすぐに影響を及ぼしますが、すぐには完了しません。コンソールモードであっても、システムでqt3が必要なpdfeditの実行は本当に好きではありませんでした。



$ pdfedit -console

pdfedit:共有ライブラリのロード中にエラーが発生しました:libqt-mt.so.3:共有オブジェクトファイルを開けません:そのようなファイルまたはディレクトリはありません



これにより、ソースからビルドするときにプログラムの構成キーが考慮され、次のレシピが見つかりました。



configure --disable-gui --enable-pdfedit-core-dev --enable-tools







その結果、グラフィックpdfeditバイナリはまったく構築されませんが、savealltext.qsスクリプトと同じアルゴリズムを使用して、pdf_to_text-必要な変換を実行する有用なユーティリティ全体が作成されます。



$pdf_to_txt -file .pdf >.txt







このようなプロジェクトアセンブリの結果は、ArchLinuxのPKGBUILDに変換され、 AURに投稿されました。



upd1:



ご相談ありがとうございました! 議論のおかげで、pdfをテキストに変換するさらに興味深い方法がいくつか明らかになりました。

zelibobaはpdftotextに-layoutオプションを適用することを提案しました

$ pdftotext -layout .pdf .txt







誇張することなく、記事のプロジェクトファイルはpdfeditよりもこの方法をより良く変換すると言うことができます。



 
  CJSC「サンクトペテルブルクの登録SET-VRSフォームからの抜粋 
  国際取引 
  商品と原料の交換」入札の結果をフォロー 

                                                                          入札日:1900年1月1日 

  セクション:CJSC「SPbMTSB」のセクション「石油製品」 
  メンバー:LLC 
  メンバーコード:000000000000 
  クライアントの名前とコード:OJSC / 000000000000 

  ツールコード:0000000001 
  ツールの説明:Gasoline Premium Euro-95 type II class B、 

   番号時間注文番号購入/取引価格(付加価値税の額)取引所名コード 
                                                                                   CRCトランザクション量 
   取引取引販売¹1トン)のロット(18%)トレーダーのカウンターパーティのコレクション 

  01-01 01-02 01-03 S 01-05 5 01-07 01-08 01-09 01-10 PeSee 01-12 
  02-01 02-02 02-03 S 02-05 1 02-07 02-08 02-09 02-10 PbSee 02-12 

   0000000001 00,000,000.11 00,000.12の合計 
 






一方、すべてのPDFでこのルールが機能するわけではありません。

「今日、さまざまなpdfファイルを試しましたが、pdfeditとpdftotextの間にはまだ絶対的なチャンピオンが存在しないことがわかりました。

Pdftotext-一連の水平方向に細長いテーブルと単一列のマガジンをより適切に変換しました。

Pdfedit-複数列のログ(例:linuxformat)と垂直方向のテーブルでよりよく機能しました。

どちらのプログラムも同じ結果を示しました(例:Zeinghaus誌)。」



kornerzは、inkscapeを使用してpdfをsvgに変換することを提案しました-以前はpdfファイルをシートに分割していました(pdftkを使用するオプションとして)



$pdftk file.pdf burst







$inkscape -z -f pg_0001.pdf -l output_page1.svg








All Articles