web-dev-qa-db-ja.com

この圧縮PDF / Aからテキストを抽出するにはどうすればよいですか?

機械学習の目的で( sckit-learn )、たくさんのPDFファイルから生のテキストを抽出する必要があります。最初に、私は xpdf pdftotext このタスクを実行するには:

exe = r'"'+os.path.join(xpdf_path,"pdftotext.exe")+'"'
cmd = exe+" "+"\""+pdf+"\""+" "+"\""+pdf+".txt"+"\""
subprocess.check_output(cmd)
with open(pdf+".txt") as f:
    texto_converted = f.read()

しかし、残念ながら、一部のユーザーにとっては、PDFソースで「ストリーム」を使用しているため、テキストを取得できませんでした this one のように。

結果は次のようになります。

59!"#$%&'()*+,-.#/#01"21"" 345667.0*(879:4$;<;4=<6>4?$@"12!/ 21#$@A$3A$>@>BCDCEFGCHIJKIJLMNIJILOCNPQRDS QPFTRPUCTCVQWBCTTQXFPYTO"21 "#/!"#(Z[12\&A+],$3^_3;9`Z &a# .2"#.b#"(#c#A(87*95d$d4?$d3e#Z"f#\"#2b?2"#`Z 2"!eb2"#H1TBRgF JhiO
jFK# 2"k#`Z !#212##"elf/e21m#*c!n2!!#/bZ!#2#`Z "eo ]$5<$@;A533> "/\ko/f\#e#e#p

私はzlib + regexを使用しようとしています:

import re
import zlib

pdf = open("pdfa.pdf", "rb").read()
stream = re.compile(b'.*?FlateDecode.*?stream(.*?)endstream', re.S)

for s in re.findall(stream,pdf):
    s = s.strip(b'\r\n')
    try:
        print(zlib.decompress(s).decode('UTF-8'))
        print("")
    except:
        pass

結果は次のようなものでした:

1 0 -10 -10 10 10 d1
0.01 0 0 0.01 0 0 cm
1 0 -10 -10 10 10 d1
0.01 0 0 0.01 0 0 cm

私はpdftopng(xpdf)を試し、成功せずにtesseractを試しました、それで、PDFからPythonまたはサードパーティのアプリ?

3
celsowm

PDFファイル内のストリームを解凍する場合は、qdpfを使用することをお勧めしますが、このファイルでは

_ qpdf --decrypt --stream-data=uncompress document.pdf out.pdf
_

どちらも役に立ちません。

なぜxpdftesseractを使った努力がうまくいかなかったのかはわかりませんが、image-magickのconvertを使用して一時ディレクトリとtesseractにPNGファイルを作成すると、次のことができます。

_import os
from pathlib import Path
from tempfile import TemporaryDirectory
import subprocess

DPI=600

def call(*args):
    cmd = [str(x) for x in args]
    return subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode('utf-8')

def ocr(docpath, lang):
    result = []
    abs_path = Path(docpath).expanduser().resolve()
    old_dir = os.getcwd()
    out = Path('out.txt')
    with TemporaryDirectory() as tmpdir:
         os.chdir(tmpdir)
         call('convert', '-density', DPI, abs_path, 'out.png')
         index = -1
         while True:
             # names have no leading zeros on the digits, would be difficult to sort glob() output
             # so just count them
             index += 1
             png = Path(f'out-{index}.png')
             if not png.exists():
                 break
             call('tesseract', '--dpi', DPI, png, out.stem, '-l', lang)
             result.append(out.read_text())
         os.chdir(old_dir)
    return result

pages = ocr('~/Downloads/document.pdf', 'por')
print('\n'.join(pages[1].splitlines()[21:24]))
_

それは与える:

_DA NÃO REALIZAÇÃO DE AUDIÊNCIA DE AUTOCOMPOSIÇÃO NO CASO EM CONCRETO

Com Vista a obter maior celeridade processual, assim como da impossibilidade de conciliação entre
_

Windowsを使用している場合は、PDFファイルが別のプロセス(PDFビューア)など)で開かれていないことを確認してください。そのように。

出力全体が非常に大きいため、最後のprintは制限されます。

この変換とOCR処理にはしばらく時間がかかるため、call()printのコメントを解除して、進行状況を把握することをお勧めします。

1
Anthon

使用できるかなり単純な手法が2つあります。

1)Googleの「Tessaract」オープンソースOCR(光学式文字認識)。これをすべてのPDFに均等に適用できますが、そのすべてのデータをピクセルに変換してからそれらを処理する魔法は、計算コストが高くなります。エンジニア時間とCPU時間のどちらがより重要ですか? pytesseract モジュールがあります。このツールは画像形式で機能するため、GhostScript(別のオープンソースプロジェクト)などを使用してPDFのすべてのページを画像に変換し、それらの画像に対して[py] tessaractを実行する必要があります。

2) pyPDF は、各ページを取得し、ページに描画された順序でプログラムでテキスト描画操作を抽出できます。これは、ページの論理的な読み取り順序のようなものではないかもしれません... a PDFcouldwhile all draw the ' aとすべての 'b'(以下同様)、「font a」ですべてを描画し、次に「font b」ですべてを描画する方が実際にはより効率的です。「font b」は、イタリックバージョンの"font a"。これは、描画コマンドのより短い/より効率的なストリームを生成しますが、そうすることは、ビジネス上適切な決定となるほどで​​はありません。

ここでのキッカーは、PDFファイルのランダムな山がいくつかのOCRの実行を必要とする可能性があるということです。不完全に組み立てられたPDF( 「ユニコードへ」のデータ)は、テキストの描画操作しかありませんが、テキストに対して適切にマイニングすることはできません。グリフは「グリフ」です。これは、グリフが使用された順序だからです。

一方、自家製のPDFを持っている場合、またはすべてのPDFが既知のソース(WordのPDFコンバーターなど)からのものである場合は、事前に何を期待するかがわかります。

上記で私が実際に使用した唯一のものはGhostscriptであることに注意してください。オンラインで画像を生成するために使用した堅固なコマンドラインインターフェイスがあることを覚えていますPDFビューア何年も前。

0
Mark Storer