市面上有多个可识别PDF内容的库,我选的是PyPDF2,可通过pip直接安装,但是在使用过程中,有一些PDF文件就会报出一个无法找到EOF标记的错误。
1. 安装
2. 报错 1 PdfReaderError: EOF marker not found
这个错误一般都是在创建PdfReader
实例时出来的,想要抽取文件里的内容,就必须先生成这个实例,这个实例会提供一系列操作PDF文件的方法,包括读取页数、抽取文字内容,等等。
3. 原因 一般来说,PDF文件最后3行是固定的,如下,注意,每行末尾都有个\n
的换行符号:
这个是PDF文件结构决定的,这里不展开说了,EOF表示结束,中间的数字是startxref
的值,每个文件会不同。但是有的PDF文件并不是按照这个格式来的,会在EOF的后面再加上一些东西,导致PdfReader找不到EOF这个标记,对于这种情况,处理方式就是把EOF后面的行都删掉即可。
此外,还会有一种情况,如下,同样末尾有个\n
:
这三个东西在同一行上,PdfReader在找到EOF后,就会去这一行的上面找startxref,所以如果在同一行的话,还是会找不到,然后就报错。对于这种情况,就需要把这三个东西分开,放到3行即可。
4. 代码 思路就是,输入一个PDF文件的路径,然后依次判断上述的2种情况,有则处理,最后把处理好的结果输出到一个新文件,将该文件的路径返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import os.pathimport PyPDF2def fix_pdf_eof (file_path: str ) -> str : if not os.path.exists(file_path): return '' file_name = os.path.basename(file_path) file_dir = file_path.replace(file_name, '' ) fix_file_name = 'fix_%s' % file_name fix_file_path = '%s%s' % (file_dir, fix_file_name) if os.path.exists(fix_file_path): return fix_file_path with open (file_path, 'rb' ) as input_stream: lines = input_stream.readlines() length = len (lines) eof_index = get_eof_index(lines) if eof_index == -1 : return '' if eof_index != length - 1 : lines = lines[:eof_index + 1 ] last_line = lines[-1 ] if last_line.startswith(b'startxref' ): xref = last_line.replace(b'startxref' , b'' ).replace(b'%%EOF\n' , b'' ).replace(b' ' , b'' ) lines[-1 ] = b'startxref\n' lines.append(xref + b'\n' ) lines.append(b'%%EOF\n' ) with open (fix_file_path, 'wb' ) as fix_output: fix_output.writelines(lines) return fix_file_path def get_eof_index (lines: list ): length = len (lines) for i, line in enumerate (lines[::-1 ]): if line.endswith(b'%%EOF\n' ) or line.endswith(b'%%EOF\r\n' ): return length - 1 - i return -1