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()