首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用/Root解析没有PDFMiner对象的PDF

使用/Root解析没有PDFMiner对象的PDF
EN

Stack Overflow用户
提问于 2012-07-08 16:06:40
回答 5查看 17.9K关注 0票数 14

我正在尝试使用PDFMiner python绑定从大量PDF中提取文本。我编写的模块适用于许多PDF,但对于PDF的一个子集,我得到了这个有点神秘的错误:

ipython堆栈跟踪:

代码语言:javascript
运行
复制
/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来获得一些差异诊断。堆栈跟踪如下:

代码语言:javascript
运行
复制
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建议,在到达第一个EOF字符后,PDFMiner可能停止解析。这似乎意味着不一样,但我非常无知。有什么想法吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-07-11 17:55:32

有趣的问题。我做了一些研究:

解析pdf的函数(来自矿工源代码):

代码语言:javascript
运行
复制
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有问题,将引发另一个异常:“”来自源的另一个函数“”

代码语言:javascript
运行
复制
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

来自wiki(pdf规范):PDF文件主要由对象组成,其中有八种类型:

布尔值,表示真假数字字符串名称数组、对象字典的有序集合、按名称流索引的对象集合,通常包含大量数据--空对象

对象可以是直接的(嵌入在另一个对象中),也可以是间接的。间接对象用对象号和生成号编号。--一个名为xref表的索引表,从文件开始时给出每个间接对象的字节偏移量。该设计允许对文件中的对象进行有效的随机访问,并且允许在不重写整个文件(增量更新)的情况下进行小的更改。从PDF版本1.5开始,间接对象也可能位于称为对象流的特殊流中。这种技术减少了具有大量小间接对象的文件的大小,并且对于标记PDF特别有用。

我认为问题是你的“损坏pdf”有一些‘根元素’在页面上。

Possible solution:

您可以在检索xref对象和解析器试图解析这些对象的每个地方下载源代码并编写“打印函数”。可以确定完整的错误堆栈(在出现此错误之前)。

ps:我认为这是产品中的某种缺陷。

票数 5
EN

Stack Overflow用户

发布于 2013-08-15 22:03:59

板pdf中的解决方案是使用'rb‘->读取二进制模式。

因为板pdf是依赖于PDFMiner和我有同样的问题,这应该可以解决你的问题。

代码语言:javascript
运行
复制
fp = open('C:\Users\USER\workspace\slate_minner\document1.pdf','rb')
doc = slate.PDF(fp)
print doc
票数 6
EN

Stack Overflow用户

发布于 2018-12-13 02:00:06

我在Ubuntu也遇到过同样的问题。我有一个非常简单的解决方案。只需打印pdf文件作为一个pdf。如果你在Ubuntu:

  1. 使用(ubuntu)文档查看器打开pdf文件。
  2. Goto档案
  3. 后藤印刷
  4. 选择打印作为文件并检查标记"pdf“。

如果您想要使过程自动化,例如,遵循this,即使用此脚本自动打印您的所有pdf文件。像这样的linux脚本也能工作:

代码语言:javascript
运行
复制
for f in *.pdfx
do
lowriter --headless --convert-to pdf "$f"
done

注:我将原始(有问题的) pdf文件称为pdfx。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11384591

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档