Синтаксический анализ PDF на C++ (PoDoFo)
Привет, поэтому я пытаюсь разобрать текст из некоторых PDF-файлов, и я хотел бы использовать PoDoFo, теперь я попытался найти примеры того, как использовать PoDoFo для разбора pdf, однако все, что я могу придумать, это примеры того, как создавать и писать pdf-файл, который не то, что мне действительно нужно.
Если у кого-нибудь есть учебник или пример разбора PDF-файла с PoDoFo или есть предложения для другой библиотеки, которую я могу использовать, пожалуйста, дайте мне знать. Также я знаю, что есть pdftotext на linux, однако я не только не могу использовать это, но я бы предпочел сделать все, что мне нужно, внутри и не полагаться на внешние программы, устанавливаемые.
2 ответов
PoDoFo не предоставляет средства для легкого извлечения текста из документа, но это не трудно сделать.
загрузить документ PdfMemDocument
:
PoDoFo::PdfMemDocument pdf("mydoc.pdf");
повторите каждую страницу:
for (int pn = 0; pn < pdf.GetPageCount(); ++pn) {
PoDoFo::PdfPage* page = pdf.GetPage(pn);
повторите все команды PDF на этой странице:
PoDoFo::PdfContentsTokenizer tok(page);
const char* token = nullptr;
PoDoFo::PdfVariant var;
PoDoFo::EPdfContentsType type;
while (tok.ReadNext(type, token, var)) {
switch (type) {
case PoDoFo::ePdfContentsType_Keyword:
// process token: it contains the current command
// pop from var stack as necessary
break;
case PoDoFo::ePdfContentsType_Variant:
// process var: push it onto a stack
break;
default:
// should not happen!
break;
}
}
}
комментарии "маркер процесса" и "process var" - это то, где он становится немного сложнее. Вам предоставляются необработанные команды PDF для обработки. К счастью, если вы на самом деле не представляя страницы и все, что вам нужно, это текст, вы можете игнорировать большинство из них. Команды, которые вам нужно обработать:
BT
, ET
, Td
, TD
, Ts
, T
, Tm
, Tf
, "
, '
, Tj
и TJ
на BT
и ET
команды отмечают начало и конец текстового потока, поэтому вы хотите игнорировать все, что не находится между BT
/ET
пара.
язык PDF основан на RPN. Поток команд состоит из значения, которые помещаются в стек, и команды, которые выводят значения из стека и обрабатывают их.
на "
, '
, Tj
и TJ
команды являются единственными, которые фактически генерируют текст. "
, '
и Tj
возвращает одну строку. Использовать var.IsString()
и var.GetString()
для ее обработки.
TJ
возвращает массив строк. Вы можете извлечь каждый из них с:
if (var.isArray()) {
PoDoFo::PdfArray& a = var.GetArray();
for (size_t i = 0; i < a.GetSize(); ++i)
if (a[i].IsString())
// do something with a[i].GetString()
другие команды используются, чтобы определить, когда ввести строку. "
и '
также ввести разрывы строк. Лучше всего загрузить спецификацию PDF из Adobe и посмотреть раздел обработки текста. Он объясняет, что каждая команда делает более подробно.
я нашел очень полезным написать небольшую программу, которая берет PDF-файл и сбрасывает поток команд для каждой страницы.
Примечание: Если все, что вы делаете извлечение сырого текста без информации о местоположении, вы на самом деле не нужно поддерживать стек var
значения. Все команды отрисовки текста имеют не более одного параметра. Вы можете просто предположить, что последнее значение в var
содержит параметр для текущей команды.
Я не использовал PoDoFo, но быстрый просмотр иерархии классов на их веб-странице API показывает:
void PoDoFo::PdfMemDocument::Load( const char * pszFilename )
поэтому я бы просто рискнул предположить здесь, что вы делаете:
PoDoFo::PdfMemDocument doc;
doc.Load( "somefile.pdf" );
тогда я представляю, что вы перемещаетесь по дереву документов, вызывая doc.GetObjects()
и пройдя через этот массив (см. pdfdocument class)