ПОСЛЕДНИЕ ОБНОВЛЕННЫЕ 10-11-2019
Я не уверен, полностью ли я понимаю ваш вопрос. Приведенный ниже код можно уточнить, но он читает либо в зашифрованном или незашифрованном формате PDF и извлекает текст. Пожалуйста, дайте мне знать, если я неправильно понял ваши требования.
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from io import StringIO
def extract_encrypted_pdf_text(path, encryption_true, decryption_password):
output = StringIO()
resource_manager = PDFResourceManager()
laparams = LAParams()
device = TextConverter(resource_manager, output, codec='utf-8', laparams=laparams)
pdf_infile = open(path, 'rb')
interpreter = PDFPageInterpreter(resource_manager, device)
page_numbers = set()
if encryption_true == False:
for page in PDFPage.get_pages(pdf_infile, page_numbers, maxpages=0, caching=True, check_extractable=True):
interpreter.process_page(page)
elif encryption_true == True:
for page in PDFPage.get_pages(pdf_infile, page_numbers, maxpages=0, password=decryption_password, caching=True, check_extractable=True):
interpreter.process_page(page)
text = output.getvalue()
pdf_infile.close()
device.close()
output.close()
return text
results = extract_encrypted_pdf_text('encrypted.pdf', True, 'password')
print (results)
Я заметил, что в вашем коде pikepdf , используемом для открытия зашифрованного PDF, отсутствует пароль, который должен был выдать это сообщение об ошибке:
pikepdf._qpdf.PasswordError: encrypted.pdf: неверный пароль
import pikepdf
with pikepdf.open("encrypted.pdf", password='password') as pdf:
num_pages = len(pdf.pages)
del pdf.pages[-1]
pdf.save("decrypted.pdf")
Вы можете использовать tika для извлечения текста из расшифрованного.pdf, созданный pikepdf .
from tika import parser
parsedPDF = parser.from_file("decrypted.pdf")
pdf = parsedPDF["content"]
pdf = pdf.replace('\n\n', '\n')
Кроме того, pikepdf в настоящее время не поддерживает извлечение текста , включая последнюю версию v1.6.4.
Я решил провести пару тестов с использованием различных зашифрованных файлов PDF.
Я назвал все зашифрованные файлы «encrypted.pdf»и все они использовали один и тот же пароль шифрования и дешифрования.
Adobe Acrobat 9.0 и более поздних версий - 256-битный уровень шифрования AES
- pikepdf был в состояниичтобы расшифровать этот файл
- PyPDF2 не удалось извлечьтекст правильно
- Тика может правильно извлечь текст
Adobe Acrobat 6.0 и более поздние версии - уровень шифрования 128-битный RC4
- pikepdf смог расшифровать этот файл
- PyPDF2 не может правильно извлечь текст
- tika может правильно извлечь текст
Adobe Acrobat 3.0и позже - уровень шифрования 40-битный RC4
- pikepdf был в состоянии расшифровать этот файл
- PyPDF2 не может правильно извлечь текст
- tika может правильно извлечь текст
Adobe Acrobat 5.0 и более поздних версий - 128-битный уровень шифрования RC4
- , созданный с помощью Microsoft Word
- pikepdf смограсшифровать этот файл
- PyPDF2 может правильно извлечь текст
- Тика может правильно извлечь текст
Adobe Acrobat 9.0 и более поздние версии - уровень шифрования256-битный AES
- , созданный с использованием pdfprotectfree
- pikepdf смог расшифровать этот файл
- PyPDF2 мог правильно извлечь текст
- Тика мог правильно извлечь текст
PyPDF2 смог извлечь текст из расшифрованных файлов PDF, не созданных с помощью Adobe Acrobat.
Я бы предположил, что сбои связаны со встроенным форматированием PDF-файлов, созданных Adobe Acrobat. Для подтверждения этой гипотезы о форматировании требуется дополнительное тестирование.
Тика смогла извлечь текст из всех документов, расшифрованных с помощью pikepdf.
import pikepdf
with pikepdf.open("encrypted.pdf", password='password') as pdf:
num_pages = len(pdf.pages)
del pdf.pages[-1]
pdf.save("decrypted.pdf")
from PyPDF2 import PdfFileReader
def text_extractor(path):
with open(path, 'rb') as f:
pdf = PdfFileReader(f)
page = pdf.getPage(1)
print('Page type: {}'.format(str(type(page))))
text = page.extractText()
print(text)
text_extractor('decrypted.pdf')
PyPDF2 не может расшифровать файлы Acrobat PDF=> 6.0
Эта проблема была открыта для владельцев модулей с 15 сентября 2015 . В комментариях к этой проблеме неясно, когда эта проблема будет решена владельцами проекта. Последний коммит был 25 июня 2018 года.
PyPDF4 проблемы с расшифровкой
PyPDF4 является заменой PyPDF2. Этот модуль также имеет проблемы с расшифровкой с некоторыми алгоритмами, используемыми для шифрования файлов PDF.
тестовый файл: Adobe Acrobat 9.0 и выше - уровень шифрования 256-битный AES
Сообщение об ошибке PyPDF2: поддерживаются только коды алгоритмов 1 и 2
Сообщение об ошибке PyPDF4: толькоалгоритм кода 1 и 2 поддерживаются. В этом PDF-файле используется код 5
ОБНОВЛЕНИЕ РАЗДЕЛА 10-11-2019
Этот раздел является ответом на ваши обновления 10-07-2019 и 10-08-2019.
В своем обновлении вы указали, что можете открыть «защищенный PDF-файл с помощью Adobe Reader» и распечатать документ в другом PDF-файле, в котором отсутствует флаг «ЗАЩИЩЕНО». После некоторого тестирования, я считаю, что выяснили, что происходит в этом сценарии.
Уровень безопасности Adobe PDF
В Adobe PDF есть несколько типов элементов управления безопасностью, которые могут быть включены владельцем документа. Элементы управления могут быть применены либо с помощью пароля, либо с помощью сертификата.
Шифрование документа (обеспечивается с помощью открытого пароля документа)
- Шифрование всего содержимого документа (большинствообщие)
- Шифрование всего содержимого документа, кроме метаданных => Acrobat 6.0
- Шифрование только файловых вложений => Acrobat 7.0
Ограничительное редактирование ипечать (принудительно с паролем разрешений)
- печать разрешена
- изменения разрешены
На изображении ниже показан файл Adobe PDFзашифрованы с помощью 256-битного шифрования AES. Чтобы открыть или распечатать этот PDF-файл, необходим пароль. Когда вы открываете этот документ в Adobe Reader с паролем, в заголовке будет указано ЗАЩИЩЕНО
Этот документ требует пароль дляоткрыть с помощью модулей Python, упомянутых в этом ответе. Если вы пытаетесь открыть зашифрованный PDF с помощью Adobe Reader. Вы должны увидеть это:
Если вы не получите это предупреждение, то документ либо не имеет включенных элементов управления безопасностью, либо имеет только ограничительное редактирование ипечать включена.
На изображении ниже показано ограничение редактирования, включаемое с паролем в документе PDF. Включена печать заметок . Чтобы открыть или распечатать этот PDF-файл, пароль не требуется . Когда вы открываете этот документ в Adobe Reader без пароля, в заголовке будет указано SECURED Это то же предупреждение, что и зашифрованный PDF-файл, открытый с помощью пароля.
Когда вы распечатываете этот документ в новом PDF, предупреждение SECURED удаляется, так как было удалено ограничительное редактирование.
Все продукты Adobe применяют ограничения, установленные паролем разрешений. Однако если сторонние продукты не поддерживают эти параметры, получатели документа могут обойти некоторые или все установленные ограничения .
Поэтому я предполагаю, что документ, который выпри печати в PDF включено ограничительное редактирование, а не имеет пароля, необходимого для открытия.
Относительно нарушения шифрования PDF
Ни PyPDF2 , ни PyPDF4 не предназначены для взлома функции открытого пароля документадокумента PDF. Оба модуля выдают следующую ошибку, если они попытаются открыть зашифрованный PDF-файл, защищенный паролем.
PyPDF2.utils.PdfReadError: файл не был расшифрован
Функция открытия пароля в зашифрованном PDF-файле может быть обойдена различными способами, но один метод может не работать, а некоторые не будут приемлемы из-за нескольких факторов, включая сложность пароля.
Внутреннее шифрование PDF работает с ключами шифрования 40, 128 или 256 бит в зависимости от версии PDF. Бинарный ключ шифрования получен из пароля, предоставленного пользователем. Пароль зависит от длины и ограничений кодирования.
Например, PDF 1.7 Adobe Extension Level 3 (Acrobat 9 - AES-256) ввел символы Unicode (65 536 возможных символов) и увеличил максимальную длину до 127 байт в представлении UTF-8 пароля.
Приведенный ниже код откроет PDF с включенным ограничительным редактированием. Он сохранит этот файл в новом PDF-файле без добавления предупреждения SECURED. Код tika проанализирует содержимое нового файла.
from tika import parser
import pikepdf
# opens a PDF with restrictive editing enabled, but that still
# allows printing.
with pikepdf.open("restrictive_editing_enabled.pdf") as pdf:
pdf.save("restrictive_editing_removed.pdf")
# plain text output
parsedPDF = parser.from_file("restrictive_editing_removed.pdf")
# XHTML output
# parsedPDF = parser.from_file("restrictive_editing_removed.pdf", xmlContent=True)
pdf = parsedPDF["content"]
pdf = pdf.replace('\n\n', '\n')
print (pdf)
Этот код проверяет, требуется ли пароль для открытия файла. Этот код будет доработан и могут быть добавлены другие функции. Есть несколько других функций, которые можно добавить, но документация для pikepdf не соответствует комментариям в базе кода, поэтому для ее улучшения требуются дополнительные исследования.
# this would be removed once logging is used
############################################
import sys
sys.tracebacklimit = 0
############################################
import pikepdf
from tika import parser
def create_pdf_copy(pdf_file_name):
with pikepdf.open(pdf_file_name) as pdf:
new_filename = f'copy_{pdf_file_name}'
pdf.save(new_filename)
return new_filename
def extract_pdf_content(pdf_file_name):
# plain text output
# parsedPDF = parser.from_file("restrictive_editing_removed.pdf")
# XHTML output
parsedPDF = parser.from_file(pdf_file_name, xmlContent=True)
pdf = parsedPDF["content"]
pdf = pdf.replace('\n\n', '\n')
return pdf
def password_required(pdf_file_name):
try:
pikepdf.open(pdf_file_name)
except pikepdf.PasswordError as error:
return ('password required')
except pikepdf.PdfError as results:
return ('cannot open file')
filename = 'decrypted.pdf'
password = password_required(filename)
if password != None:
print (password)
elif password == None:
pdf_file = create_pdf_copy(filename)
results = extract_pdf_content(pdf_file)
print (results)