14

PDFMiner pythonバインディングを使用して、多数のPDFからテキストを抽出しようとしています。私が書いたモジュールは多くのPDFで機能しますが、PDFのサブセットでこのやや不可解なエラーが発生します。

ipythonスタックトレース:

/usr/lib/python2.7/dist-packages/pdfminer/pdfparser.pyc in set_parser(self, parser)
    331                 break
    332         else:
--> 333             raise PDFSyntaxError('No /Root object! - Is this really a PDF?')
    334         if self.catalog.get('Type') is not LITERAL_CATALOG:
    335             if STRICT:

PDFSyntaxError: No /Root object! - Is this really a PDF?

もちろん、すぐにこれらのPDFが破損していないかどうかを確認しましたが、問題なく読み取ることができます。

ルートオブジェクトがないにもかかわらず、これらのPDFを読み取る方法はありますか?ここからどこへ行けばいいのかよくわかりません。

どうもありがとう!

編集:

私はいくつかの鑑別診断を得るためにPyPDFを使ってみました。スタックトレースは次のとおりです。

In [50]: pdf = pyPdf.PdfFileReader(file(fail, "rb"))
---------------------------------------------------------------------------
PdfReadError                              Traceback (most recent call last)
/home/louist/Desktop/pdfs/indir/<ipython-input-50-b7171105c81f> in <module>()
----> 1 pdf = pyPdf.PdfFileReader(file(fail, "rb"))

/usr/lib/pymodules/python2.7/pyPdf/pdf.pyc in __init__(self, stream)
    372         self.flattenedPages = None
    373         self.resolvedObjects = {}
--> 374         self.read(stream)
    375         self.stream = stream
    376         self._override_encryption = False

/usr/lib/pymodules/python2.7/pyPdf/pdf.pyc in read(self, stream)
    708             line = self.readNextEndLine(stream)
    709         if line[:5] != "%%EOF":
--> 710             raise utils.PdfReadError, "EOF marker not found"
    711 
    712         # find startxref entry - the location of the xref table


PdfReadError: EOF marker not found

Quonuxは、おそらくPDFMinerが最初のEOF文字に達した後に解析を停止したことを示唆しました。これは別のことを示唆しているように見えますが、私は非常に無知です。何かご意見は?

4

5 に答える 5

6

スレート pdf での解決策は、「rb」を使用することです --> バイナリ モードを読み取ります。

スレート pdf は PDFMiner に依存しており、私も同じ問題を抱えているため、これで問題が解決するはずです。

fp = open('C:\Users\USER\workspace\slate_minner\document1.pdf','rb')
doc = slate.PDF(fp)
print doc
于 2013-08-15T22:03:59.293 に答える
5

興味深い問題。私はある種の研究を行っていました:

pdfを解析した関数(マイナーソースコードから):

def set_parser(self, parser):
        "Set the document to use a given PDFParser object."
        if self._parser: return
        self._parser = parser
        # Retrieve the information of each header that was appended
        # (maybe multiple times) at the end of the document.
        self.xrefs = parser.read_xref()
        for xref in self.xrefs:
            trailer = xref.get_trailer()
            if not trailer: continue
            # If there's an encryption info, remember it.
            if 'Encrypt' in trailer:
                #assert not self.encryption
                self.encryption = (list_value(trailer['ID']),
                                   dict_value(trailer['Encrypt']))
            if 'Info' in trailer:
                self.info.append(dict_value(trailer['Info']))
            if 'Root' in trailer:
                #  Every PDF file must have exactly one /Root dictionary.
                self.catalog = dict_value(trailer['Root'])
                break
        else:
            raise PDFSyntaxError('No /Root object! - Is this really a PDF?')
        if self.catalog.get('Type') is not LITERAL_CATALOG:
            if STRICT:
                raise PDFSyntaxError('Catalog not found!')
        return

EOF に問題がある場合は、別の例外が発生します: '''ソースからの別の関数'''

def load(self, parser, debug=0):
        while 1:
            try:
                (pos, line) = parser.nextline()
                if not line.strip(): continue
            except PSEOF:
                raise PDFNoValidXRef('Unexpected EOF - file corrupted?')
            if not line:
                raise PDFNoValidXRef('Premature eof: %r' % parser)
            if line.startswith('trailer'):
                parser.seek(pos)
                break
            f = line.strip().split(' ')
            if len(f) != 2:
                raise PDFNoValidXRef('Trailer not found: %r: line=%r' % (parser, line))
            try:
                (start, nobjs) = map(long, f)
            except ValueError:
                raise PDFNoValidXRef('Invalid line: %r: line=%r' % (parser, line))
            for objid in xrange(start, start+nobjs):
                try:
                    (_, line) = parser.nextline()
                except PSEOF:
                    raise PDFNoValidXRef('Unexpected EOF - file corrupted?')
                f = line.strip().split(' ')
                if len(f) != 3:
                    raise PDFNoValidXRef('Invalid XRef format: %r, line=%r' % (parser, line))
                (pos, genno, use) = f
                if use != 'n': continue
                self.offsets[objid] = (int(genno), long(pos))
        if 1 <= debug:
            print >>sys.stderr, 'xref objects:', self.offsets
        self.load_trailer(parser)
        return

ウィキから(pdf仕様):PDFファイルは主にオブジェクトで構成されており、そのうち8つのタイプがあります:

Boolean values, representing true or false
Numbers
Strings
Names
Arrays, ordered collections of objects
Dictionaries, collections of objects indexed by Names
Streams, usually containing large amounts of data
The null object

オブジェクトは、直接的 (別のオブジェクトに埋め込まれている) または間接的のいずれかです。間接オブジェクトには、オブジェクト番号と世代番号が付けられます。xref テーブルと呼ばれるインデックス テーブルは、ファイルの先頭からの各間接オブジェクトのバイト オフセットを示します。この設計により、ファイル内のオブジェクトへの効率的なランダム アクセスが可能になり、ファイル全体を書き換えずに小さな変更を加えることができます (増分更新)。PDF バージョン 1.5 から、間接オブジェクトもオブジェクト ストリームと呼ばれる特別なストリームに配置される場合があります。この手法は、多数の小さな間接オブジェクトを含むファイルのサイズを縮小し、特にタグ付き PDF に役立ちます。

問題は、「破損した pdf」のページに「ルート要素」がいくつかあることだと思います。

Possible solution:

ソースをダウンロードして、xref オブジェクトが取得され、パーサーがこのオブジェクトを解析しようとした各場所に「印刷関数」を書き込むことができます。エラーの完全なスタックを特定することが可能になります (このエラーが表示される前)。

ps: 製品の何らかのバグだと思います。

于 2012-07-11T17:55:32.557 に答える
0

私もこのエラーを受け取り、 fp = open('example','rb') を試し続けました

ただし、まだOPが示すエラーが表示されます。私が見つけたのは、PDFがまだ別の関数によって開かれているコードにバグがあったことです。
そのため、他の場所でも PDF をメモリ内で開いていないことを確認してください。

于 2018-04-03T20:28:36.093 に答える