Как извлечь аннотации из PDF файла
Эта статья-руководство отражает пройденный мною путь от постановки вопроса "как извлечь выделенный текст (highlight) из PDF книги" до найденного решения. Времени на поиск решения я потратил немало, из-за чего не решился удалить описание тех программ и способов получения аннотаций, которые меня не устроили, либо работали не корректно.
Зачем это нужно?
Я читаю книги.. Когда я читаю печатное издание, то всегда оставляю липкие закладки на полях, отмечая тем самым интересную и важную для меня информацию. Через некоторое время после прочтения книги, я перелистываю эти закладки и сохраняю, либо анализирую отмеченную информацию. И такое ощущение, что так никто не делает.. По крайней мере, при чтении электронных книг. Ни один линуксовый PDF ридер (Foxit, Okular) не умеет экспортировать аннотации! Лишь немногие могут более-менее сносно показывать их в меню. Тем не менее, я обнаружил платный сервис, который умеет извлекать примечания из PDF - sumnotes.net. Импорт 50 примечаний (или страниц) бесплатный, а за 500 просят $7 в год.
Извлечение аннотаций на сервисе sumnotes, есть экспорт в TXT
Я задался целью найти именно консольную утилиту, которая умела бы извлекать аннотации. Сразу приведу работающее решение, а после него те, которые обнаружил в процессе.
Все действия проводились в Ubuntu 14.04.
Извлечение аннотаций из PDF с помощью poppler
Poppler - это python библиотека для работы с PDF файлами, которая умеет извлекать аннотации.
Ставим библиотеку python-poppler
: (предполагается, что python
уже установлен в системе)
sudo apt-get install python-poppler
Скрипт pdf_extract_annotations.py
, который будет извлекать заметки/аннотации с помощью poppler:
import poppler
import sys
import urllib
import os
def main():
input_filename = sys.argv[1]
# http://blog.hartwork.org/?p=612
document = poppler.document_new_from_file('file://%s' % \
urllib.pathname2url(os.path.abspath(input_filename)), None)
n_pages = document.get_n_pages()
all_annots = 0
for i in range(n_pages):
page = document.get_page(i)
annot_mappings = page.get_annot_mapping ()
num_annots = len(annot_mappings)
if num_annots > 0:
for annot_mapping in annot_mappings:
if annot_mapping.annot.get_annot_type().value_name != 'POPPLER_ANNOT_LINK':
all_annots += 1
print 'page: {0:3}, {1:10}, type: {2:10}, content: {3}'.format(i+1, annot_mapping.annot.get_modified(), annot_mapping.annot.get_annot_type().value_nick, annot_mapping.annot.get_contents())
if all_annots > 0:
print str(all_annots) + " annotation(s) found"
else:
print "no annotations found"
if __name__ == "__main__":
main()
Извлекаем аннотации из PDF файла:
python pdf_extract_annotations.py book.pdf
Пример вывода аннотаций:
page: 6, D:20160204112641Z00'00, type: text , content: Тестовая заметка Adobe PDF Reader
page: 8, D:20160204113002+02'00', type: highlight , content: good practices
Leela PDF Annotation Extractor
Это C библиотека, которая предоставляет консольную утилиту leela
(неужели та самая, из футурамы). Импортирует аннотации в XML формате, но структура не валидная. В общем использовать можно, но с костылями.
Установка зависимостей и компиляция:
git clone git@github.com:TrilbyWhite/Leela.git
sudo aptitude install libpoppler-glib-dev
cd Leela
make
Извлечь аннотации:
./leela annots book.pdf
Обработанный формат вывода:
<annot page="7" index="5" type="text">
<rect x1="315.000000" y1="731.000000" x2="333.000000" y2="749.000000"/>
<name>c9ff65f3-0caf-480b-9833-71c73f71c500</name>
<color r="65535" g="65535" b="0"/>
<label>Stanislav</label>
</markup>
<text>Тестовая заметка Adobe PDF Reader</text>
</annot>
<annot page="7" index="6" type="highlight">
<rect x1="128.919000" y1="682.944000" x2="211.297000" y2="700.228000"/>
<name>f4c04f7f-da60-4653-ac3e-343825a667fd</name>
<color r="65535" g="65535" b="0"/>
<text>good practices</text>
</annot>
Для получения нормальной разметки я набросал скрипт pdf_annotate_extract.sh
:
annotations=$(./leela annots "$1" \
| sed -r 's/\s<\/markup>//g' \
| sed '/^\s*$/d' \
| pcregrep -iM '<annot.*? type="(text|highlight)">(.|\n)+?</annot>')
xml=$(echo $annotations | xml_wrap.sh)
echo $xml
Формирование валидного XML (xml_wrap.sh
):
echo '<?xml version="1.0"?><container>' $(cat) '</container>'
Другие утилиты для извлечения аннотаций
Изначально, я пытался получить аннотации с помощью таких утилит, как pdftotext
, pdftohtml
и pdfgrep
. Забудьте! Все они извлекают лишь "сырой" текст, никаких аннотаций.
PDF Xchange Viewer
Также, я нашел упоминание про хорошую поддержку аннотаций в виндовой программе pdf-xchange-viewer. Скачал портативную версию, запустил под wine. Есть функция экспорта аннотаций, называется "сводка комментариев", но только в PDF.
Панель экспорта сводки комментариев и аннотаций
Сказано, что DEMO версия оставляет водяные знаки, но я их не обнаружил, м.б. где-то внизу листа.
Пример сводки комментариев
В общем, это не совсем то, что мне было нужно, идем дальше...
Mendeley
Это система обмена документами. Для моей задачи это избыточно, но я все же зарегистрировался и установил десктопную версию.
Интерфейс приятный, создание примечаний простое, но.. Утилита не от отображает список аннотаций, которые я добавил через Adobe и Foxit, хотя видит посдсвеченный текст и примечания. Дают 2GB места под документы, интегрируется с Zotero.
Клиентское приложение сервиса mendeley.com
pdfannotextractor.pl
Вот с этой штуковиной я изрядно повозился, но ничего толкового у меня не вышло - примеяания не удалось извлечь из-за ошибки "java.lang.Exception: Unsupported annotation subtype".
Нам понадобятся утилиты pax
и texlive-latex-extra
(весит не мало):
sudo apt-get install texlive-latex-extra pax
Установим зависимость PDFBox:
pdfannotextractor --install
* будет установлен PDFBox в ~/.texmf-var/scripts/pax/PDFBox-0.7.3.zip
.
Извлекаем аннотации:
pdfannotextractor book.pdf
И в итоге я получил:
* Processing file `modern_php.pdf' ...
!!! Warning: Annotation on page 8 not recognized!
java.lang.Exception: Unsupported annotation subtype: Text
!!! Warning: Annotation on page 8 not recognized!
java.lang.Exception: Unsupported annotation subtype: Popup
!!! Warning: Annotation on page 8 not recognized!
java.lang.Exception: Unsupported annotation subtype: Highlight
Копать дальше не хватило терпения.. Да и жавовский PDFBox довольно медленная штука.
Утилиты, которые я не проверил:
- marginalia - https://github.com/nichtich/marginalia
- PDFMiner - http://www.unixuser.org/~euske/python/pdfminer/
#extract annotations, #linux pdf highlight extractor