我正在尝试使用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建议,在到达第一个EOF字符后,PDFMiner可能停止解析。这似乎意味着不一样,但我非常无知。有什么想法吗?
发布于 2012-07-11 17:55:32
有趣的问题。我做了一些研究:
解析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
来自wiki(pdf规范):PDF文件主要由对象组成,其中有八种类型:
布尔值,表示真假数字字符串名称数组、对象字典的有序集合、按名称流索引的对象集合,通常包含大量数据--空对象
对象可以是直接的(嵌入在另一个对象中),也可以是间接的。间接对象用对象号和生成号编号。--一个名为xref表的索引表,从文件开始时给出每个间接对象的字节偏移量。该设计允许对文件中的对象进行有效的随机访问,并且允许在不重写整个文件(增量更新)的情况下进行小的更改。从PDF版本1.5开始,间接对象也可能位于称为对象流的特殊流中。这种技术减少了具有大量小间接对象的文件的大小,并且对于标记PDF特别有用。
我认为问题是你的“损坏pdf”有一些‘根元素’在页面上。
Possible solution:
您可以在检索xref对象和解析器试图解析这些对象的每个地方下载源代码并编写“打印函数”。可以确定完整的错误堆栈(在出现此错误之前)。
ps:我认为这是产品中的某种缺陷。
发布于 2013-08-15 22:03:59
板pdf中的解决方案是使用'rb‘->读取二进制模式。
因为板pdf是依赖于PDFMiner和我有同样的问题,这应该可以解决你的问题。
fp = open('C:\Users\USER\workspace\slate_minner\document1.pdf','rb')
doc = slate.PDF(fp)
print doc
发布于 2018-12-13 02:00:06
我在Ubuntu也遇到过同样的问题。我有一个非常简单的解决方案。只需打印pdf文件作为一个pdf。如果你在Ubuntu:
如果您想要使过程自动化,例如,遵循this,即使用此脚本自动打印您的所有pdf文件。像这样的linux脚本也能工作:
for f in *.pdfx
do
lowriter --headless --convert-to pdf "$f"
done
注:我将原始(有问题的) pdf文件称为pdfx。
https://stackoverflow.com/questions/11384591
复制相似问题