Начало работы с PDF Oxide (Ruby)
PDF Oxide — самая быстрая библиотека для работы с PDF в Ruby: среднее время извлечения текста 0,8 мс и 100% успешных обработок на 3830 PDF. Один gem для извлечения, поиска, конвертации, создания и редактирования (с удалением данных) PDF, построенный на том же ядре на Rust, что и привязки для Python, Java, Node, Go, C# и PHP.
Установка
gem install pdf_oxide
Или добавьте в Gemfile:
gem 'pdf_oxide', '~> 0.3'
Готовая нативная библиотека libpdf_oxide поставляется внутри gem с тегом платформы — компилятор и установка в систему не нужны. Готовые сборки покрывают Ruby 3.1–3.4 на x86_64-linux, aarch64-linux, macOS на Intel и Apple Silicon, а также Windows (x64-mingw-ucrt).
Открытие PDF
Чтобы загрузить файл, используйте PdfDocument.open. В блочной форме документ автоматически закрывается по завершении блока; метод #close тоже доступен и идемпотентен.
require 'pdf_oxide'
PdfOxide::PdfDocument.open('research-paper.pdf') do |doc|
puts "Pages: #{doc.page_count}"
puts "PDF version: #{doc.pdf_version}"
puts "Encrypted: #{doc.encrypted?}"
end
Для зашифрованных документов передайте password::
PdfOxide::PdfDocument.open('confidential.pdf', password: 'secret') do |doc|
puts doc.extract_text(0)
end
Можно также открыть документ из байтов в памяти — удобно при потоковой передаче из S3, HTTP или базы данных. PdfDocument.open автоматически распознаёт сырые байты PDF по магической сигнатуре %PDF-:
bytes = File.binread('report.pdf')
PdfOxide::PdfDocument.open(bytes) do |doc|
puts doc.extract_text(0)
end
Извлечение текста
Одна страница
Извлеките обычный текст с любой страницы по её индексу (нумерация с нуля).
PdfOxide::PdfDocument.open('report.pdf') do |doc|
text = doc.extract_text(0)
puts text
end
Все страницы
PdfOxide::PdfDocument.open('book.pdf') do |doc|
doc.page_count.times do |i|
puts "--- Page #{i + 1} ---"
puts doc.extract_text(i)
end
end
Вспомогательный метод за один вызов
Когда нужен текст лишь одной страницы, PdfDocument.extract_text открывает документ, извлекает текст и закрывает его — всё за один вызов:
text = PdfOxide::PdfDocument.extract_text('report.pdf', page: 0)
puts text
Извлечение с автоматической маршрутизацией
extract_text_auto использует авто-маршрутизатор из v0.3.51, чтобы для каждой страницы выбрать нативный текст или OCR. В сборке без feature ocr метод корректно откатывается к нативному текстовому слою — он никогда не вызывает ошибку «OCR недоступен».
PdfOxide::PdfDocument.open('scan.pdf') do |doc|
puts doc.extract_text_auto(0)
end
Чтобы получить типизированную причину, описывающую качество извлечения, используйте AutoExtractor:
PdfOxide::PdfDocument.open('scan.pdf') do |doc|
ax = doc.auto_extractor
result = ax.extract_page(0)
puts result[:text]
warn "degraded: #{result[:reason]}" unless ax.ok?(result[:reason])
end
Работа со страницами
PdfDocument#page возвращает облегчённое представление PdfPage, заимствующее данные у документа. #pages возвращает по одному такому представлению на каждую страницу.
PdfOxide::PdfDocument.open('paper.pdf') do |doc|
page = doc.page(0)
puts "Index: #{page.index}"
puts page.text # same as doc.extract_text(0)
doc.pages.each do |p|
puts "Page #{p.index}: #{p.text.length} chars"
end
end
Конвертация в Markdown и HTML
Конвертируйте отдельную страницу (передав её индекс) или весь документ (опустив индекс) в Markdown или HTML.
PdfOxide::PdfDocument.open('paper.pdf') do |doc|
puts doc.to_markdown(0) # first page to Markdown
puts doc.to_html(0) # first page to HTML
puts doc.to_markdown # entire document to Markdown
end
Структурированное извлечение
extract_structured возвращает разобранную раскладку страницы в виде Hash — размеры страницы и типизированные регионы с текстом, ограничивающими рамками и индексами колонок.
PdfOxide::PdfDocument.open('paper.pdf') do |doc|
page = doc.extract_structured(0)
puts "Size: #{page['page_width']} x #{page['page_height']}"
page['regions'].each do |region|
puts "#{region['kind']}: #{region['text']}"
end
end
Поиск
search сканирует весь документ и возвращает массив хешей-совпадений, у каждого из которых есть :page, :text и хеш :bbox с ключами :x, :y, :width, :height.
PdfOxide::PdfDocument.open('manual.pdf') do |doc|
matches = doc.search('configuration', case_sensitive: false)
matches.each do |m|
bbox = m[:bbox]
puts "Page #{m[:page]}: '#{m[:text]}' at (#{bbox[:x].round}, #{bbox[:y].round})"
end
end
Рендеринг
Отрендерите страницу в байты PNG с заданным DPI:
PdfOxide::PdfDocument.open('poster.pdf') do |doc|
png = doc.render(0, dpi: 150)
File.binwrite('page-0.png', png)
end
Создание PDF
Класс Pdf создаёт PDF из Markdown, HTML или обычного текста. Экземпляры владеют нативным дескриптором; используйте блочную форму (закрывает автоматически) или вызывайте #close самостоятельно.
PdfOxide::Pdf.from_markdown("# Hello World\n\nThis is a PDF.") do |pdf|
pdf.save('output.pdf')
end
PdfOxide::Pdf.from_html('<h1>Invoice</h1><p>Amount due: $42.00</p>') do |pdf|
pdf.save('invoice.pdf')
end
PdfOxide::Pdf.from_text("Plain text document.\n\nSecond paragraph.") do |pdf|
pdf.save('notes.pdf')
end
Получите байты вместо сохранения на диск с помощью #to_bytes:
pdf_bytes = PdfOxide::Pdf.from_markdown('# Report').to_bytes
# upload pdf_bytes, attach to an email, etc.
Удаление конфиденциальных данных (redaction)
DocumentEditor открывает существующий PDF для необратимого удаления данных. apply_redactions! навсегда удаляет закрытое содержимое и за тот же проход может очистить метаданные документа.
PdfOxide::DocumentEditor.open('source.pdf') do |ed|
ed.add_redaction(page: 0, rect: [100, 200, 300, 250])
ed.apply_redactions!(scrub_metadata: true)
ed.save_to('redacted.pdf')
end
Обработка ошибок
PDF Oxide возбуждает типизированные подклассы PdfOxide::Error для специфичных для PDF сбоев.
begin
PdfOxide::PdfDocument.open('document.pdf') do |doc|
puts doc.extract_text(0)
end
rescue PdfOxide::FileNotFoundError
warn 'File not found'
rescue PdfOxide::EncryptedError
warn 'Wrong or missing password'
rescue PdfOxide::ParseError => e
warn "Malformed PDF: #{e.message}"
rescue PdfOxide::Error => e
warn "PDF error: #{e.message}"
end
Дальнейшие шаги
- Начало работы с Python — использование PDF Oxide из Python
- Начало работы с Rust — использование PDF Oxide из Rust
- Извлечение текста — подробные параметры и рецепты извлечения
- Создание PDF — продвинутое создание, шифрование и метаданные
- Редактирование — изменение существующих PDF, аннотации и поля форм