在Python中使用正则表达式解析PDF文件

4 投票
4 回答
6506 浏览
提问于 2025-04-16 05:22

我正在尝试使用Python的re模块从PDF文件中解析一些对象元素。我的目标是通过正则表达式来解析每个PDF对象。

1 0 obj
<<
    /Type /Catalog
    /Pages 2 0 R
>>
endobj
2 0 obj
<<
    /Type /Pages
    /Kids [ 3 0 R ]
    /Count 1
>>
endobj
...

当我使用 "\d+\s\d+\sobj[\s,\S]*endobj" 时,它没有效果(它一直解析到最后一个endobj为止)。我该如何修改正则表达式,以便单独解析每个对象(换句话说,就是从1 0 obj到endobj之间的部分)?

4 个回答

2

这不是对你问题的直接回答,但你可以看看Python中已有的一些PDF解析库,比如:pdfminer 或者 pyPdf。即使你最后不使用它们,看看它们是怎么做的也很有帮助。

2

你需要用*?这个符号,它是非贪婪模式的版本——具体可以查看这里的文档

另外,要注意PDF格式是非常复杂的,尤其是当里面有二进制流的时候。不过如果你知道你要处理的PDF比较简单,那这个方法应该是有效的。

8

如果你只用正则表达式来处理PDF文件,可能会很容易构建出一些你的程序无法处理的PDF文件。因为PDF中的字典和列表可以包含其他对象,而正则表达式无法处理递归结构,至少在Python的re模块中是这样的。

PDF文件其实是由一棵对象和流的树组成的:

  • 字典:<<(名称 值)* >>
  • 列表:[(值)* ]
  • 名称:/(普通字符)*
  • 字符串:((字符)* )
  • 十六进制字符串:<(十六进制字符)* >
  • 数字:(-)? ((数字)+ | (数字)+ . (数字)* | . (数字)+)
  • 布尔值:true | false
  • 引用: (数字)+ (空格)+ (数字)+ (空格)+ R

空格和注释在大多数地方都是被忽略的。注释以%开头,一直到行的末尾。

间接对象的表示方式是:

1 0 obj
(any object)
endobj

这个对象可以用1 0 R来引用。间接字典也可以附带一个流:

1 0 obj
<<
/Length 22
>>
stream
(22 bytes of raw data)
endstream
endobj

一个PDF文件大致长这样:

%PDF-1.4
%ÿÿÿÿ
1 0 obj
<< /Author (MizardX) >>
endobj
2 0 obj
<<
/Type /Catalog
% more required keys
>>
endobj
%lots of more indirect objects, one after another
trailer
<<
/Info 1 0 R
/Root 2 0 R
% ... more required keys
>>
xref
0 3
0000000000 65535 f
0000000015 00000 n
0000000054 00000 n
startxref
225
%%EOF

对象树的根是trailer对象。所有对象都是直接或间接从这个字典中引用的。

流中隐藏了很多复杂的内容,但这并不影响文件的结构。

完整的规范可以在Adobe的网站上找到。

撰写回答