Начало работы с PDF Oxide ®
PDF Oxide поставляется с идиоматичными биндингами для R, обеспечивающими быстрое извлечение текста, Markdown и HTML из PDF — среднее время извлечения текста 0,8 мс, 100% успешных прогонов на 3830 PDF — на основе того же ядра на Rust, что и все остальные биндинги. Пакет для R оборачивает C ABI библиотеки pdf_oxide через интерфейс .Call языка R; дескрипторы документов представлены внешними указателями R, которые освобождает сборщик мусора, а индексация страниц начинается с 0, в соответствии с базовым движком.
Установка
Пакет для R линкуется с cdylib, собранной с набором функций по умолчанию. Соберите нативную библиотеку, а затем установите пакет, указав ему путь к заголовочному файлу и cdylib:
# 1. собираем нативную библиотеку (набор функций для биндингов)
cargo build --release --lib \
--features ocr,rendering,signatures,barcodes,tsa-client,system-fonts
# 2. устанавливаем пакет для R
PDF_OXIDE_INCLUDE_DIR="$PWD/include" PDF_OXIDE_LIB_DIR="$PWD/target/release" \
R CMD INSTALL r/
Во время выполнения сделайте cdylib доступной для компоновщика:
LD_LIBRARY_PATH="$PWD/target/release" Rscript your_script.R
Открытие PDF
Откройте файл с помощью pdf_open(), а затем изучите его метаданные. pdf_version() возвращает именованный список с полями major и minor.
library(pdfoxide)
doc <- pdf_open("research-paper.pdf")
pdf_page_count(doc) # количество страниц
v <- pdf_version(doc)
cat("PDF version:", paste(v$major, v$minor, sep = "."), "\n")
pdf_is_encrypted(doc) # логическое значение
Извлечение текста
Извлеките текст в порядке чтения для отдельной страницы (индексация с 0) с помощью pdf_extract_text().
library(pdfoxide)
doc <- pdf_open("report.pdf")
text <- pdf_extract_text(doc, 0) # индекс страницы с отсчётом от 0
cat(text)
Пройдитесь по всем страницам, используя pdf_page_count():
doc <- pdf_open("book.pdf")
for (page in seq_len(pdf_page_count(doc)) - 1L) { # индексы с отсчётом от 0
cat("--- Page", page + 1L, "---\n")
cat(pdf_extract_text(doc, page), "\n")
}
Markdown и HTML
Преобразуйте отдельную страницу в Markdown или HTML, либо конвертируйте весь документ целиком.
library(pdfoxide)
doc <- pdf_open("paper.pdf")
md <- pdf_to_markdown(doc, 0) # одна страница в Markdown
html <- pdf_to_html(doc, 0) # одна страница в HTML
all_md <- pdf_to_markdown_all(doc) # весь документ
all_text <- pdf_to_plain_text_all(doc) # весь документ, обычный текст
cat(all_md)
Слова, символы и строки
Извлечение элементов возвращает списки записей с позиционными ограничивающими прямоугольниками. Каждый bbox — это именованный список с полями x, y, width и height.
library(pdfoxide)
doc <- pdf_open("paper.pdf")
# Позиционированные слова — у каждого есть $text, $bbox, $font_name, $font_size, $bold
words <- pdf_extract_words(doc, 0)
for (w in head(words, 10)) {
cat(sprintf("'%s' at (%.1f, %.1f) font=%s bold=%s\n",
w$text, w$bbox$x, w$bbox$y, w$font_name, w$bold))
}
# Строки в порядке чтения — у каждой есть $text, $bbox, $word_count
lines <- pdf_extract_text_lines(doc, 0)
for (ln in head(lines, 5)) {
cat(sprintf("[%d words] %s\n", ln$word_count, ln$text))
}
# Позиционированные символы — $character это кодовая точка Unicode (целое число)
chars <- pdf_extract_chars(doc, 0)
for (ch in head(chars, 10)) {
cat(sprintf("'%s' at (%.1f, %.1f) size=%.1f\n",
intToUtf8(ch$character), ch$bbox$x, ch$bbox$y, ch$font_size))
}
Таблицы
pdf_extract_tables() возвращает обнаруженные таблицы. Каждая запись таблицы содержит row_count, col_count, has_header и символьную матрицу cells с индексацией от 1: tbl$cells[row, col].
library(pdfoxide)
doc <- pdf_open("statement.pdf")
tables <- pdf_extract_tables(doc, 0)
for (tbl in tables) {
cat(sprintf("Table: %d rows x %d cols (header=%s)\n",
tbl$row_count, tbl$col_count, tbl$has_header))
for (r in seq_len(tbl$row_count)) {
cat(paste(tbl$cells[r, ], collapse = " | "), "\n")
}
}
Поиск
Ищите по отдельной странице с помощью pdf_search() или по всему документу с помощью pdf_search_all(). Обе функции принимают необязательный флаг case_sensitive (по умолчанию FALSE) и возвращают записи с полями text, page и bbox.
library(pdfoxide)
doc <- pdf_open("manual.pdf")
# Весь документ
hits <- pdf_search_all(doc, "configuration")
for (h in hits) {
cat(sprintf("Page %d: '%s' at (%.0f, %.0f)\n",
h$page, h$text, h$bbox$x, h$bbox$y))
}
# Отдельная страница, с учётом регистра
page_hits <- pdf_search(doc, 0, "Configuration", case_sensitive = TRUE)
Открытие из байтов
Откройте PDF, находящийся в памяти, — это удобно при чтении из S3, по HTTP или из базы данных — с помощью pdf_open_from_bytes(), которая принимает вектор raw.
library(pdfoxide)
bytes <- readBin("report.pdf", "raw", file.info("report.pdf")$size)
doc <- pdf_open_from_bytes(bytes)
cat(pdf_extract_text(doc, 0))
PDF, защищённые паролем
Откройте зашифрованный документ с помощью pdf_open_with_password() или вызовите pdf_authenticate() после открытия (она возвращает TRUE при успехе и FALSE при неверном пароле).
library(pdfoxide)
doc <- pdf_open_with_password("confidential.pdf", "secret")
cat(pdf_extract_text(doc, 0))
Создание PDF
Функции-строители создают объект pdfoxide_pdf из Markdown, HTML или обычного текста. Сохраните его в файл с помощью pdf_save() или сериализуйте в вектор raw с помощью pdf_to_bytes() (который можно снова открыть через pdf_open_from_bytes()).
library(pdfoxide)
pdf <- pdf_from_markdown("# Hello World\n\nThis is a PDF.\n")
pdf_save(pdf, "output.pdf")
pdf_from_html("<h1>Invoice</h1><p>Amount due: $42.00</p>") |>
pdf_save("invoice.pdf")
pdf_from_text("Plain text document.\n\nSecond paragraph.") |>
pdf_save("notes.pdf")
# Полный цикл через байты
bytes <- pdf_to_bytes(pdf_from_markdown("# In memory\n\nbody\n"))
doc <- pdf_open_from_bytes(bytes)
cat(pdf_extract_text(doc, 0))
Дальнейшие шаги
- Начало работы с Python – использование PDF Oxide из Python
- Начало работы с Rust – базовый крейт на Rust
- Извлечение текста – подробные опции и рецепты извлечения
- Создание PDF – продвинутое создание с помощью строителей, шифрования и метаданных