在PDFrw for Python中使用流?

在PDFrw for Python中使用流?,python,pdf,pdfrw,Python,Pdf,Pdfrw,我试图阅读一个带有PDFrw的PDF示例。PDF在左下角坐标(100100)处包含短语Hello Matthew。当我试图输出文本时(如果我可以的话),我会得到一个数据流。我似乎不知道如何把它作为文本 >>> import pdfrw >>> file_object = pdfrw.PdfReader("Hello.pdf") >>> file_object {'/ID': ['<f643bc0910dfb67725d53e11054

我试图阅读一个带有PDFrw的PDF示例。PDF在左下角坐标
(100100)
处包含短语
Hello Matthew
。当我试图输出文本时(如果我可以的话),我会得到一个数据流。我似乎不知道如何把它作为文本

>>> import pdfrw

>>> file_object = pdfrw.PdfReader("Hello.pdf")
>>> file_object
{'/ID': ['<f643bc0910dfb67725d53e11054f4609>', '<f643bc0910dfb67725d53e11054f4609>'], '/Info': (5, 0), '/Root': {'/Outl
ines': (8, 0), '/PageMode': '/UseNone', '/Pages': {'/Count': '1', '/Kids': [{'/Contents': (7, 0), '/MediaBox': ['0', '0
', '595.2756', '841.8898'], '/Parent': {...}, '/Resources': {'/Font': (1, 0), '/ProcSet': ['/PDF', '/Text', '/ImageB',
'/ImageC', '/ImageI']}, '/Rotate': '0', '/Trans': {}, '/Type': '/Page'}], '/Type': '/Pages'}, '/Type': '/Catalog'}, '/S
ize': '9'}

>>> file_object.pages[0]
{'/Contents': (7, 0), '/MediaBox': ['0', '0', '595.2756', '841.8898'], '/Parent': {'/Count': '1', '/Kids': [{...}], '/T
ype': '/Pages'}, '/Resources': {'/Font': (1, 0), '/ProcSet': ['/PDF', '/Text', '/ImageB', '/ImageC', '/ImageI']}, '/Rot
ate': '0', '/Trans': {}, '/Type': '/Page'}

>>> file_object.pages[0].keys()
['/Contents', '/MediaBox', '/Parent', '/Resources', '/Rotate', '/Trans', '/Type']

>>> file_object.pages[0].Contents
{'/Filter': ['/ASCII85Decode', '/FlateDecode'], '/Length': '102'}

>>> file_object.pages[0].Contents.stream
'GapQh0E=F,0U\\H3T\\pNYT^QKk?tc>IP,;W#U1^23ihPEM_?CW4KISi90EC-p>QkRte=<%V"lI7]P)Rn29neZ[Kb,htEWn&q7Q2"V~>'
导入pdfrw >>>file_object=pdfrw.PdfReader(“Hello.pdf”) >>>文件对象 {'/ID':['','','/Info':(5,0),'/Root':{'/Outl ines':(8,0),'/PageMode':'/UseNone','/Pages':{'/Count':'1','/Kids':[{'/Contents':(7,0),'/MediaBox':['0','0',' “,”595.2756“,”841.8898“],“/Parent':{…},“/Resources':{'/Font':(1,0),“/ProcSet':['/PDF','/Text','/ImageB', “/ImageC',“/ImageI']},/Rotate':“0',“/Trans':{},/Type':'/Page'}],“/Type':'/Pages'},/Type':'/Catalog'},”/S ize':'9'} >>>文件\u对象页[0] {'/Contents':(7,0),'/MediaBox':['0','0','595.2756','841.8898'],'/Parent':{'/Count':'1','/Kids':[{…}],'/T 键入“:”/Pages'},/Resources':{“/Font':(1,0),“/ProcSet':[”/PDF',“/Text',“/ImageB',“/ImageC',”/ImageI']},/Rot ate':'0','/Trans':{},/Type':'/Page'} >>>文件\对象。页面[0]。键() ['/Contents'、'/MediaBox'、'/Parent'、'/Resources'、'/Rotate'、'/Trans'、'/Type'] >>>文件\u对象。页面[0]。内容 {'/Filter':['/ASCII85Decode','/FlateDecode'],'/Length':'102'} >>>文件\u object.pages[0]。Contents.stream 'GapQh0E=F,0U\\H3T\\pNYT^QKk?tc>IP,;W#U1^23ihPEM_2;cw4kis90ec-p>QkRte=
该流被压缩。通过dictionary/Filter参数可以看出这一点

不幸的是,pdfrw还不知道如何使用这种类型的过滤器进行解压缩。如果您先通过pdftk之类的东西来解压缩pdf,您可能会看到更合理的内容

免责声明:我是pdfrw的主要作者

但是

即使如此,特别是对于非ASCII字体,PDF中的字符到字形映射也很复杂,所以您不会总是看到看起来合理的东西


如果你真的想深入检查文本PDF文件,pdfminer可能更有用——pdfrw还没有真正开发出足够的工具来完成这项工作。

如果你的过滤器只是/flateCode,或者你可以先找到一个ASCII85Decode过滤器来运行(它们必须按顺序运行)。我一直在使用pdfrw.uncompress.uncompress(page.Contents)对/flatedCode流进行解码(与PdfReader.uncompress()不同,该方法不将流传递给处理函数,而是为其提供所有间接对象)

pdf=pdfrw.PdfReader('foo.pdf') >>>pages=pdf.Root.pages.Kids >>>p1=页数[0] >>>p1.内容 {'/Filter':'/FlateCode','/Length':'13679'} >>>p1.内容流[:30] ‘x\x9cÕÕÕÝ\x92æÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ213 >>>pdfrw.uncompress.uncompress([p1.Contents])#列表中的内容对象。 True#即使流未解码,也会返回True。 >>>p1.内容流[:30]
“/Artifact当我注意到它被压缩时,我才得出这个结论!我完全同意,非ASCII字体可能会很混乱。我的最终结果是我试图修改PDF的标记,并将它们从
h1
更改为
h4
或添加注释。我不认为这可能是在我仔细阅读了你的
pdfrw
源代码之后t?Patrick,你有什么建议?(顺便说一句,我看到你30分钟前还在网上,非常感谢你的快速回复和透彻的解释!)事实上,注释不在内容流中,因此你可以在不修改(甚至解压缩)的情况下对注释进行大量修改content stream.pdfrw对此很有用,但我还没有编写任何特定于注释的代码。嗯。明天早上我会更多地使用它,看看如果不太难的话,我是否可以在GH上的PR中构建对注释的支持。这将是非常棒的,但很难弄清楚什么是足够小和通用的。例如PRs程序总是受欢迎的,但我正试图管理核心库,以防止它像pyPdf2那样在自身重量下崩溃。我花了数年时间才添加页面合并模块……您是否成功演示了如何添加或编辑批注?(在压缩内容流之外听起来非常有用)。
>>> pdf = pdfrw.PdfReader('foo.pdf')
>>> pages = pdf.Root.Pages.Kids
>>> p1 = pages[0]
>>> p1.Contents
{'/Filter': '/FlateDecode', '/Length': '13679'}
>>> p1.Contents.stream[:30]
'x\x9cÕ}Ý\x92æ¶\x91å½"ô\x0eu5Q߬ëk\x02üßP8BRwË'
>>> pdfrw.uncompress.uncompress([p1.Contents]) # Contents object/s in a list.
True # it returns True even if the stream is not decoded.
>>> p1.Contents.stream[:30]
'/Artifact <</Attached [/Top]/T' # ready for parsing