tutorial python pdf stream pypdf

tutorial - pypdf2 python 3



pyPdf para la extracción de IndirectObject (3)

Un IndirectObject se refiere a un objeto real (es como un enlace o alias para que el tamaño total del PDF se pueda reducir cuando el mismo contenido aparece en varios lugares). El método getObject te dará el objeto real.

Si el objeto es un objeto de texto, simplemente haciendo un str () o unicode () en el objeto debería obtener los datos dentro de él.

Alternativamente, pyPdf almacena los objetos en el atributo resolvedObjects. Por ejemplo, un PDF que contiene este objeto:

13 0 obj << /Type /Catalog /Pages 3 0 R >> endobj

Se puede leer con esto:

>>> import pyPdf >>> pdf = pyPdf.PdfFileReader(open("pdffile.pdf")) >>> pages = list(pdf.pages) >>> pdf.resolvedObjects {0: {2: {''/Parent'': IndirectObject(3, 0), ''/Contents'': IndirectObject(4, 0), ''/Type'': ''/Page'', ''/Resources'': IndirectObject(6, 0), ''/MediaBox'': [0, 0, 595.2756, 841.8898]}, 3: {''/Kids'': [IndirectObject(2, 0)], ''/Count'': 1, ''/Type'': ''/Pages'', ''/MediaBox'': [0, 0, 595.2756, 841.8898]}, 4: {''/Filter'': ''/FlateDecode''}, 5: 147, 6: {''/ColorSpace'': {''/Cs1'': IndirectObject(7, 0)}, ''/ExtGState'': {''/Gs2'': IndirectObject(9, 0), ''/Gs1'': IndirectObject(10, 0)}, ''/ProcSet'': [''/PDF'', ''/Text''], ''/Font'': {''/F1.0'': IndirectObject(8, 0)}}, 13: {''/Type'': ''/Catalog'', ''/Pages'': IndirectObject(3, 0)}}} >>> pdf.resolvedObjects[0][13] {''/Type'': ''/Catalog'', ''/Pages'': IndirectObject(3, 0)}

Siguiendo este ejemplo, puedo enumerar todos los elementos en un archivo pdf

import pyPdf pdf = pyPdf.PdfFileReader(open("pdffile.pdf")) list(pdf.pages) # Process all the objects. print pdf.resolvedObjects

ahora, necesito extraer un objeto no estándar del archivo pdf.

Mi objeto es el llamado MYOBJECT y es una cadena.

La pieza impresa por el script python que me concierne es:

{''/MYOBJECT'': IndirectObject(584, 0)}

El archivo pdf es esto:

558 0 obj <</Contents 583 0 R/CropBox[0 0 595.22 842]/MediaBox[0 0 595.22 842]/Parent 29 0 R/Resources <</ColorSpace <</CS0 563 0 R>> /ExtGState <</GS0 568 0 R>> /Font<</TT0 559 0 R/TT1 560 0 R/TT2 561 0 R/TT3 562 0 R>> /ProcSet[/PDF/Text/ImageC] /Properties<</MC0<</MYOBJECT 584 0 R>>/MC1<</SubKey 582 0 R>> >> /XObject<</Im0 578 0 R>>>> /Rotate 0/StructParents 0/Type/Page>> endobj ... ... ... 584 0 obj <</Length 8>>stream 1_22_4_1 --->>>> this is the string I need to extract from the object endstream endobj

¿Cómo puedo seguir el valor 584 para referirme a mi cadena (en pyPdf, por supuesto)?


cada elemento en pdf.pages es un diccionario, por lo tanto, suponiendo que esté en la página 1, pdf.pages[0][''/MYOBJECT''] debería ser el elemento que desee.

Puede tratar de imprimirlo individualmente o tocarlo con help y dir en un aviso de Python para obtener más información sobre cómo obtener la cadena que desea

Editar:

después de recibir una copia del pdf, encontré el objeto en pdf.resolvedObjects[0][558][''/Resources''][''/Properties''][''/MC0''][''/MYOBJECT''] y el valor puede ser recuperado a través de getData ()

la siguiente función ofrece una forma más genérica de resolver esto mediante la búsqueda recursiva de la clave en cuestión

import types import pyPdf pdf = pyPdf.PdfFileReader(open(''file.pdf'')) pages = list(pdf.pages) def findInDict(needle,haystack): for key in haystack.keys(): try: value = haystack[key] except: continue if key == needle: return value if type(value) == types.DictType or isinstance(value,pyPdf.generic.DictionaryObject): x = findInDict(needle,value) if x is not None: return x answer = findInDict(''/MYOBJECT'',pdf.resolvedObjects).getData()


El método de Jehiah es bueno si buscamos el objeto en todas partes. Mi suposición (mirando el PDF) es que siempre está en el mismo lugar (la primera página, en la propiedad ''MC0''), por lo que un método mucho más simple para encontrar la cadena sería:

import pyPdf pdf = pyPdf.PdfFileReader(open("file.pdf")) pdf.getPage(0)[''/Resources''][''/Properties''][''/MC0''][''/MYOBJECT''].getData()