Начало работы с PDF Oxide (Clojure)
PDF Oxide — самый быстрый PDF-инструментарий со встроенным извлечением текста: 0.8 мс в среднем и 100% успешных разборов на 3830 PDF. Биндинг для Clojure — это идиоматичная тонкая обёртка над зрелым Java-биндингом fyi.oxide:pdf-oxide, которому принадлежит единственный нативный мост через JNI. Он не добавляет ни строчки нативного кода: вызывает Java-классы через interop и возвращает удобные для Clojure значения (java.util.List → вектор, java.util.Optional → значение или nil).
Установка
Добавьте Java-биндинг в свой deps.edn. Пространство имён Clojure (pdf_oxide.core) лежит в вашем дереве исходников и оборачивает его:
{:deps {fyi.oxide/pdf-oxide {:mvn/version "0.3.69"}}}
Типы дескрипторов (Pdf, PdfDocument, DocumentEditor) реализуют AutoCloseable, поэтому используйте with-open для детерминированной очистки ресурсов.
Быстрый старт
Соберите PDF из Markdown, откройте его обратно и извлеките текст. Каждый шаг возвращает обычные значения Clojure.
(require '[pdf-oxide.core :as pdf])
(with-open [p (pdf/from-markdown "# Hello\n\nbody\n")
d (pdf/open (pdf/save p))]
(println "pages: " (pdf/page-count d))
(println "producer:" (or (pdf/producer d) "(none)"))
(println (pdf/extract-text d 0)))
Открытие PDF
pdf/open принимает либо массив байтов, либо строку с путём к файлу, а также необязательный пароль для зашифрованных документов.
(require '[pdf-oxide.core :as pdf])
;; Из пути
(with-open [d (pdf/open "research-paper.pdf")]
(println "pages:" (pdf/page-count d)))
;; Из байтов (например, скачанных из S3 или по HTTP)
(with-open [d (pdf/open pdf-bytes)]
(println (pdf/extract-text d 0)))
;; Зашифрованный документ
(with-open [d (pdf/open "confidential.pdf" "secret")]
(println (pdf/extract-text d 0)))
Можно также пройти аутентификацию уже после открытия:
(with-open [d (pdf/open "confidential.pdf")]
(when (pdf/authenticate d "secret")
(println (pdf/extract-text d 0))))
Извлечение текста
Извлекайте обычный текст с любой страницы по её индексу, отсчитываемому от нуля.
(require '[pdf-oxide.core :as pdf])
(with-open [d (pdf/open "report.pdf")]
;; Одна страница
(println (pdf/extract-text d 0))
;; Все страницы
(doseq [i (range (pdf/page-count d))]
(println "--- Page" (inc i) "---")
(println (pdf/extract-text d i))))
Элементы страницы
pdf/page возвращает PdfPage. Из неё можно извлечь слова, строки, символы, таблицы, изображения и аннотации — каждый набор как вектор Clojure. Объекты слов, строк и символов предоставляют .text и .bbox через interop.
(require '[pdf-oxide.core :as pdf])
(with-open [d (pdf/open "paper.pdf")]
(let [pg (pdf/page d 0)]
(println "page width:" (.width pg))
;; Слова вместе с их ограничивающими рамками
(doseq [w (take 8 (pdf/words pg))]
(println " " (.text w) "@" (.bbox w)))
;; Остальные векторы элементов
(println "lines: " (count (pdf/lines pg)))
(println "chars: " (count (pdf/chars pg)))
(println "tables: " (count (pdf/tables pg)))
(println "images: " (count (pdf/images pg)))
(println "annotations:" (count (pdf/annotations pg)))
;; Обычный текст всей страницы или вырезанной области (BBox)
(println (pdf/page-text pg))))
Чтобы ограничить извлечение областью, передайте fyi.oxide.pdf.geometry.BBox:
(import '[fyi.oxide.pdf.geometry BBox])
(with-open [d (pdf/open "paper.pdf")]
(let [pg (pdf/page d 0)]
(println (pdf/page-text pg (BBox. 0.0 0.0 1000.0 1000.0)))))
Конвертация в Markdown и HTML
Конвертируйте весь документ или отдельную страницу в Markdown или HTML.
(require '[pdf-oxide.core :as pdf])
(with-open [d (pdf/open "paper.pdf")]
;; Весь документ
(println (pdf/to-markdown d))
(println (pdf/to-html d))
;; Отдельная страница (индекс от нуля)
(println (pdf/to-markdown d 0))
(println (pdf/to-html d 0)))
Для более богатой структуры pdf/extract-structured возвращает дерево структурированных элементов страницы:
(with-open [d (pdf/open "paper.pdf")]
(println (pdf/extract-structured d 0)))
Поиск
pdf/search сканирует весь документ и возвращает вектор объектов-совпадений. Каждое совпадение предоставляет .text через interop.
(require '[pdf-oxide.core :as pdf])
(with-open [d (pdf/open "manual.pdf")]
(doseq [m (pdf/search d "configuration")]
(println (.text m))))
Рендеринг
Отрендерите страницу в массив байтов PNG, при желании с заданным DPI.
(require '[pdf-oxide.core :as pdf]
'[clojure.java.io :as io])
(with-open [d (pdf/open "paper.pdf")]
;; DPI по умолчанию
(io/copy (pdf/render d 0) (io/file "page-0.png"))
;; Явный DPI
(io/copy (pdf/render d 0 150) (io/file "page-0@150.png")))
Создание
Тип Pdf предоставляет фабричные функции. pdf/save сериализует собранный Pdf в массив байтов.
(require '[pdf-oxide.core :as pdf]
'[clojure.java.io :as io])
;; Из Markdown
(with-open [p (pdf/from-markdown "# Hello World\n\nThis is a PDF.")]
(io/copy (pdf/save p) (io/file "output.pdf")))
;; Из HTML
(with-open [p (pdf/from-html "<h1>Invoice</h1><p>Amount: $42</p>")]
(io/copy (pdf/save p) (io/file "invoice.pdf")))
Редактирование и редактирование с затиранием
pdf/editor открывает DocumentEditor (из массива байтов или пути) для структурных правок. Очистите метаданные, отметьте области для затирания и примените их необратимо, затем сериализуйте результат через pdf/editor-save.
(require '[pdf-oxide.core :as pdf]
'[clojure.java.io :as io])
(import '[fyi.oxide.pdf.geometry BBox])
(with-open [ed (pdf/editor "form.pdf")]
(pdf/scrub-metadata ed)
(pdf/add-redaction ed 0 (BBox. 10.0 10.0 50.0 20.0))
(pdf/apply-redactions ed)
(io/copy (pdf/editor-save ed) (io/file "redacted.pdf")))
Метаданные и жизненный цикл
pdf/producer и pdf/creator возвращают метаданные документа как значение или nil, если они отсутствуют (java.util.Optional разворачивается за вас). Предпочитайте with-open; pdf/close и pdf/open? — это запасные средства для ручного управления жизненным циклом.
(require '[pdf-oxide.core :as pdf])
(let [d (pdf/open "paper.pdf")]
(println "open? " (pdf/open? d))
(println "producer:" (or (pdf/producer d) "(none)"))
(println "creator: " (or (pdf/creator d) "(none)"))
(pdf/close d)
(println "open? " (pdf/open? d)))
Дальнейшие шаги
- Начало работы с Java — Java-биндинг, на котором построена эта обёртка
- Извлечение текста — подробные параметры и рецепты извлечения
- Создание PDF — продвинутое создание с метаданными и стилизацией
- Редактирование — изменение существующих PDF, аннотации и затирание