Как обнаружить выделенный текст из PDF с помощью Python в приложении Django?
У меня есть скрипт на Python, который успешно обнаруживает выделенный текст из PDF-файла с помощью библиотек xdotool и pyperclip. Вот сценарий:
import time
import os
import subprocess
import pyperclip
def get_selected_text():
subprocess.run(['xdotool', 'key', 'ctrl+c'])
time.sleep(1)
return pyperclip.paste()
if __name__ == "__main__":
pdf_filepath = 'class3english.pdf'
subprocess.Popen(['xdg-open', pdf_filepath])
while True:
selected_text = get_selected_text()
if selected_text:
print("Selected text:", selected_text)
time.sleep(2)
Однако, когда я пытаюсь интегрировать этот скрипт в свое приложение Django, он не обнаруживает выделенный текст из PDF. Вместо этого он захватывает текст из буфера обмена. Я хочу иметь возможность обнаруживать текст, который пользователь активно выделил в программе просмотра PDF.
Есть ли способ добиться этого в приложении Django? Как я могу изменить свой подход, чтобы захватить только выделенный текст из PDF при работе в среде Django?
Лучший вариант, который я нашел, это:
- Извлеките текст из PDF-файла и отобразите его в файле шаблона, возможно, немного стилизовав. В моем примере кода я использую пакет
pypdf
. - Копирование выделенного текста с помощью JavaScript. (Подробное описание см. в этом ответе.)
Вот как выглядел бы этот подход:
from pypdf import PdfReader
# Use `get_selected_text` as it is.
def get_selected_text_view(request):
# Read the PDF file
reader = PdfReader("path-to-your-file.pdf")
document_pages = reader.pages
extracted_text = []
# Loop over all the pages and append the extracted text to the
# `extracted_text` list.
for single_page in document_pages:
text = single_page.extract_text(extraction_mode="layout")
extracted_text.append(text)
while True:
selected_text = get_selected_text()
if selected_text:
print("Selected text:", selected_text)
time.sleep(2)
# Pass the extracted text as context data
return render(request, 'pyperclip.html', {"pdf_text": extracted_text})
else:
print("\nselected_text = ","NONE")
time.sleep(2)
return render(request, 'pyperclip.html', {"pdf_text": extracted_text})
Обновите свой шаблон:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PDF Viewer</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<!-- Display all text extracted from the PDF -->
<div style="width: 100%; height: 600px;">
{% for page in pdf_text %}
<!-- To try and render the text as it may have been laid out in the PDF,
we use the pre tag. -->
<pre>
{{ page }}
</pre>
{% endfor %}
</div>
<button id="readButton">Read</button>
<script>
$(document).ready(function() {
$('#readButton').click(function() {
// Get the selected text.
let selectedText = document.getSelection().toString();
navigator.clipboard.writeText(selectedText);
$.ajax({
url: '{% url 'detectingWordSentences' %}',
type: 'GET',
success: function(response) {
// console.log(response);
},
error: function(xhr, status, error) {
// console.error(error);
}
});
});
});
</script>
</body>
</html>
Сначала извлекается текст PDF, а затем отображается, поскольку текст, выделенный во встроенном PDF (через элементы embed
или iframe
), не распознается функцией getSelection()
.
Кроме того, из-за различий в движках рендеринга, используемых разными браузерами, может оказаться невозможным надежно выделить текст. (См. этот пост.)
Другой подход, который вы можете выбрать, - это использование пакета PDF.js
. По результатам моего (ограниченного) тестирования, не удается отобразить PDF как встроенный файл, даже если следовать примеру, включенному в документацию; в результате в браузере отображается картинка.
Однако, используя демо-сайт, можно получить выделенный текст в консоли с помощью getSelection()
, так что, возможно, я что-то упускаю.