2016-07-05 10 views
0

私は定期的にインボイスpdfsを流入しています。 これらのpdfsからさまざまな操作と保存のためにデータを抽出します。不正な構造OCRを使用してPDFからデータを抽出する

ここでは例のセクションです:enter image description here

最初のステップは、Adobe社のOCRを使用することですが。 次に、tikaを使ってpdfを解析します。 Pythonで :

from tika import parser 
parsedPDF = parser.from_file("the_file.pdf") 

これは予想される出力である:

... 
001 6 0 6 EA FSC450-WBKR FUTSAL, ADULT, WHT/BLK/RED BULK \n\n 
002 6 0 6 EA SS50-P SOCCER PURPLE/BLUE/WHITE BULK \n\n 
... 

行は改行で区切られており、あなたがPDFに表示行が(下記参照)の完全な行として解析されます。

これは実際の出力です:

001 6 0 6 \n\n 
002 6 0 6 \n\n 
003 13 0 13 \n\n 
004 3 0 3 \n\n 
EA FSC450-WBKR FUTSAL, ADULT, WHT/BLK/RED BULK \n\n 
EA SS50-P SOCCER PURPLE/BLUE/WHITE BULK \n\n 
... 

OCRは、あなたがPDFファイルでご覧行は二つのセクション[*注]に分割された構造を作成しました。この分割は、 "Shipped"と "Unit"見出しの間で行われます。 enter image description here

項目002の場合、「#」見出しから「Packaging」見出しにドラッグすると、まず最初のセクションのデータが選択され、次に2番目のセクションの先頭にジャンプします。

この問題を解決する方法はありますか? OCRのための構造を定義する方法がある(例えば、それは、単一の行として行を読み込み?)

[*注]:それはだ、実際にテキストが包ま垂直(水平テキストと比較されていることラップは通常見られる)。

答えて

1

データを再作成するのではなく、自分が所有しているもので作業してください。 2つのグループのグループが得られます。最初のグループは、データの行の左半分を含み、2番目のグループは、右半分を含みます。 itertools.groupbyは、いくつかのグループ化基準で行を分割するのに最適です。この場合、左半分の行はすべて数字で始まり、右半分の行は数字で始まることがわかります。

これらを2つの等しいサイズのグループに分けたら、Pythonの組み込みメソッドzipを使ってそれらを一緒に戻します。その後split()秒の連続は、各ラインの内容を解析することができます - 以下のコード内のコメントを参照してください。

from itertools import groupby 

lines = """ 
001 6 0 6 


002 6 0 6 


003 13 0 13 


004 3 0 3 


EA FSC450-WBKR FUTSAL, ADULT, WHT/BLK/RED BULK 


EA SS50-P SOCCER PURPLE/BLUE/WHITE BULK 


EA SS30-G SOCCER BALL GREEN/WHITE #3 BULK 


EA VQ2000-RGW COMPOSITE VB ROYAL/GOLD/WHITE BULK 


""".splitlines() 

# filter out empty lines 
lines = filter(None, lines) 

# use groupby to walk the list, and get the lines that start with 
# numbers vs those that don't - from your description, there should be 
# two groups 
groups = [] 
for _, grouplines in groupby(lines, key=lambda ll : ll[0].isdigit()): 
    groups.append(list(grouplines)) 

# validate the input - should be two groups of line, each the same length 
assert len(groups) == 2 
assert len(groups[0]) == len(groups[1]) 

# use zip to walk the two groups together, and create list of consolidated data 
consolidated = [left + right for left,right in zip(groups[0], groups[1])] 

# now break these strings up into their various pieces, using a succession of split()s 
parsed_lines = [] 
for cons_line in consolidated: 
    left_items = cons_line.split(None, 4) 
    right_items = left_items.pop(-1).rsplit(None,1) 
    right_items, qty_type = right_items 
    um, desc = right_items.split(None, 1) 
    parsed_lines.append(list(map(int,left_items) + [um, desc, qty_type])) 

# dump out the parsed lines 
for data in parsed_lines: 
    print(data) 

は与える:問題を見ての新しい方法を提供するための

[1, 6, 0, 6, 'EA', 'FSC450-WBKR FUTSAL, ADULT, WHT/BLK/RED', 'BULK'] 
[2, 6, 0, 6, 'EA', 'SS50-P SOCCER PURPLE/BLUE/WHITE', 'BULK'] 
[3, 13, 0, 13, 'EA', 'SS30-G SOCCER BALL GREEN/WHITE #3', 'BULK'] 
[4, 3, 0, 3, 'EA', 'VQ2000-RGW COMPOSITE VB ROYAL/GOLD/WHITE', 'BULK'] 
+0

感謝を。 –

関連する問題