Эта программа для чтения PDF не дает больших возможностей для взаимодействия со структурой возвращаемых данных. Тем не менее, можно добавить новую функцию, которая возвращает каждый элемент как другой элемент в списке. Тогда вы, по крайней мере, сможете извлечь данные между двумя элементами. Подход по-прежнему не является надежным, поскольку вам все еще нужно определиться с возможными случаями прекращения:
import PyPDF2
import itertools
def extractTextList(self):
text_list = []
content = self["/Contents"].getObject()
if not isinstance(content, ContentStream):
content = ContentStream(content, self.pdf)
for operands, operator in content.operations:
if operator == b_("Tj"):
_text = operands[0]
if isinstance(_text, TextStringObject) and len(_text.strip()):
text_list.append(_text.strip())
elif operator == b_("T*"):
pass
elif operator == b_("'"):
pass
_text = operands[0]
if isinstance(_text, TextStringObject) and len(operands[0]):
text_list.append(operands[0])
elif operator == b_('"'):
_text = operands[2]
if isinstance(_text, TextStringObject) and len(_text):
text_list.append(_text)
elif operator == b_("TJ"):
for i in operands[0]:
if isinstance(i, TextStringObject) and len(i):
text_list.append(i)
return text_list
from PyPDF2.pdf import PageObject, u_, ContentStream, b_, TextStringObject
PageObject.extractTextList = extractTextList
def between(text_elements, drop_while, take_while):
return list(itertools.takewhile(take_while, itertools.dropwhile(drop_while, text_elements)))[1:]
pdfFileObj = open('SPE7M518T446E.pdf', 'rb')
pdfReader = PyPDF2.PdfFileReader(pdfFileObj)
page0 = pdfReader.getPage(0)
text_elements = page0.extractTextList()
lines = between(text_elements, lambda x: x != 'RATING', lambda x: 'DAYS' not in x)
print('\n'.join(lines))
Это даст вам нужные строки, которые затем будут объединены в один вывод следующим образом:
DLA LAND AND MARITIME
ACTIVE DEVICES DIVISION
PO BOX 3990
COLUMBUS OH 43218-3990
USA
Name: Desmond Forshey Buyer Code:PMCMTA9 Tel: 614-692-6154 Fax: 614-692-6930
Email: Desmond.Forshey@dla.mil
Поскольку новая функция extractTextList()
возвращает список текстовых элементов, найденных на странице, я использую itertools.dropwhile()
и itertools.takewhile()
для обработки возвращенного списка.
Функция between()
работает в два этапа: сначала она читает список строк по одной за раз и отбрасывает их до тех пор, пока не будет соответствовать этому первому тесту (который должен найти RATING
). Затем он начинает возвращать элементы в функцию takewhile()
. Это продолжает принимать элементы, пока не обнаружит слово DAYS
в одном из элементов. list()
используется для создания отфильтрованного списка. Затем я опускаю первый элемент (как это слово RATING
).
По сути это итеративный способ создания фрагмента в списке.
Примечание: lambda
- это просто еще один способ определения функции. В этом случае он принимает текстовый элемент с именем x
и возвращает True
, если это определенное значение, или для такта, если слово DAYS
находится где-то внутри него. Две функции itertool вызывают эти лямбда-функции для каждого элемента в списке.