pyPdf для извлечения IndirectObject - PullRequest
10 голосов
/ 12 января 2009

Следуя этому примеру, я могу перечислить все элементы в PDF-файл

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

Теперь мне нужно извлечь нестандартный объект из файла PDF.

Мой объект называется MYOBJECT, и это строка.

Фрагмент, напечатанный скриптом python, который меня интересует:

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

PDF-файл выглядит так:

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

Как я могу следовать значению 584, чтобы ссылаться на мою строку (под pyPdf, конечно) ??

Ответы [ 3 ]

8 голосов
/ 14 января 2009

каждый элемент в pdf.pages - это словарь, поэтому, если он находится на странице 1, pdf.pages[0]['/MYOBJECT'] должен быть желаемым элементом.

Вы можете попробовать распечатать это по отдельности или ткнуть в него с помощью help и dir в приглашении Python для получения дополнительной информации о том, как получить желаемую строку

Edit:

после получения копии pdf я нашел объект в pdf.resolvedObjects[0][558]['/Resources']['/Properties']['/MC0']['/MYOBJECT'], и значение можно получить с помощью getData ()

следующая функция дает более общий способ решения этой проблемы путем рекурсивного поиска рассматриваемого ключа

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()
3 голосов
/ 14 января 2009

IndirectObject относится к реальному объекту (это как ссылка или псевдоним, так что общий размер PDF может быть уменьшен, когда один и тот же контент появляется в нескольких местах). Метод getObject даст вам реальный объект.

Если объект является текстовым объектом, то просто выполнение str () или unicode () над объектом должно получить данные внутри него.

Кроме того, pyPdf сохраняет объекты в атрибуте resolvedObjects. Например, PDF, содержащий этот объект:

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

Может быть прочитано с этим:

>>> 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)}
2 голосов
/ 15 января 2009

Метод Джехии хорош, если везде искать объект. Я предполагаю (глядя на PDF), что он всегда находится в одном и том же месте (первая страница, в свойстве 'MC0'), и поэтому гораздо более простой метод поиска строки будет выглядеть так:

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