Извлечение текста PDF в местах гиперссылок

Кто-нибудь знает о каком-то (БЕСПЛАТНОМ) SDK, который может начать извлечение текста в той точке PDF-документа, куда ведет гиперссылка (в том же PDF-документе)? Ссылки в конечном итоге ведут нас к определенным точкам на определенных страницах.

В частности, нам нужна программа, которая может анализировать pdf-документ, содержащий вопросы и ответы к тесту (а также соответствующие примечания для каждого вопроса/ответа), и экспортировать в текстовый файл только те части, которые нам нужны.

В основном документ PDF имеет тестовые вопросы в начале документа, и в каждом вопросе есть гиперссылка на его ответ и соответствующие примечания в другой части документа PDF.

P.S. - Использование одного из следующих языков: C++, Java, VB.net, C#.net, javascript P.P.S. - Только бесплатное программное обеспечение


person Evan Sevy    schedule 22.10.2010    source источник
comment
Как вы знаете, текст в PDF может быть в любом порядке, даже символы в слове могут быть сгенерированы не по порядку. Таким образом, вам понадобится SDK для извлечения текста, но сохраните достаточно информации, чтобы отметить местоположение закладки, чтобы вы могли извлечь оттуда вперед. iText и QuickPDF SDK должны быть хорошим местом для начала чтения. Кроме того, публикация образца PDF может более четко объяснить, чего вы пытаетесь достичь.   -  person Andrew Cash    schedule 22.10.2010


Ответы (3)


Это сложнее, чем кажется - возможно, вам придется переосмыслить свой вопрос. Гиперссылки внутри документа обычно создаются с помощью аннотации ссылки с назначением, установленным для действия «Перейти к просмотру». Это представление не обязательно включает границы или даже точку. Иногда это просто страница (при текущем масштабе), или страница (по ширине), или страница (вверху, определенный масштаб). И это еще сложнее, потому что место назначения ссылки может быть деревом действий, которые нужно выполнить по порядку, причем каждое действие является одним из 18 различных возможных типов действий, включая javascript, который можно использовать для побуждения зрителя перейти к определенному месту назначения.

Я думаю, у вас также будут проблемы с «в том месте, куда вас ведет ссылка».

Вы можете выполнить большую часть этой задачи на C #, используя Atalasoft dotAnnotate и надстройку извлечения текста PDF (отказ от ответственности, я работаю в Atalasoft, написал импортер PDF-> аннотаций и раньше работал в Adobe над Acrobat v 1, 2 и 3). И нет, извините, это не бесплатное программное обеспечение.

Вот как я бы это сделал (отказ от ответственности - это сразу пришло мне в голову):

class PageAnnots : KeyValuePair<int, List<PdfLinkData>> { }

public PageAnnots GetPageLinkDestinations(Stream stm)
{
    PdfAnnotationDataImporter importer = new PdfAnnotationDataImporter(stm);
    List<PageAnnots> pageAnnots = new List<PageAnnots>();

    try {
        importer.Load();
        // this gets all annotations on all pages.  On long docs, this will be time consuming
        AnnotationDataCollection allAnnots = importer.Import();
        int pageNo = 0;
        // allAnnots is a collection of LayerData, each LayerData object being a collection
        // of annots for a page.  The collection is empty if there are no annots
        foreach (AnnotationData pageOfAnnots in allAnnots) {
            List<PdfLinkData> linkAnnots = new List<PdfLinkData>();
            LayerData pageLayer = pageOfAnnots as LayerData;
            if (pageLayer != null) {
                // filter out each annot that is a link
                foreach (AnnotationData annot in pageLayer.Items) {
                    PdfLinkData link = annot as PdfLinkData;
                    if (link != null)
                        linkAnnots.Add(link);
                }
            }
            if (linkAnnots.Count > 0) {
                pageAnnots.Add(new PageAnnots(pageNo, linkAnnots));
            }
            pageNo++;
        }
    }
    catch (Exception err) {
        // keep it?  drop it?
    }

    return pageAnnots;
}

На данный момент мы сократили его до набора пар ключ-значение, где каждый ключ представляет собой номер страницы, а каждое значение представляет собой непустой список объектов PdfLinkData, представляющих ссылки на этой странице.

Оттуда вы можете перебрать эту коллекцию и попытаться определить место назначения следующим образом:

private int PageFromDestination(PdfDestination dest)
{
    PdfIndexedPageReference pageRef = dest.Page as PdfIndexedPageReference;
    return pageRef == null ? -1 : pageRef.PageIndex;
}

public void FigureDestination(PdfLinkData link)
{
    PdfActionList actions = link.ClickAction;
    foreach (PdfAction action in actions) {
        PdfGoToViewAction gotoView = action as PdfGoToViewAction;
        if (action == null)
            continue;
        // this only pulls the page from the destination.  The dest
        // may also contain information about the view.  I'm assuming you
        // only want the page number
        int page = PageFromDestination(gotoView.Destination);
        if (page >= 0) {
            // here's where you step in - the click action could be
            // a long chain of things including several GoToView actions.
            // it's up to you to decide what you want to do.  Handle only
            // action lists of length 1?  Stop at first GoToView?
            // aggregate them all?
        }
    }
}

И когда вы посмотрите на этот код, вы удивитесь, зачем существует такой уровень абстракции с точки зрения ссылок на проиндексированные страницы, типов действий и списков действий? Ответ заключается в том, что действие GoToView также может ссылаться на другой документ — перекрестные ссылки на документы допустимы в PDF. Хотя dotAnnotate не поддерживает их прямо сейчас, он готов поддерживать их в будущем. Точно так же действие может означать переход к представлению во встроенном документе PDF (да, вы можете встраивать PDF в PDF).

Вы должны знать, что dotAnnotate предоставляет вам ограниченный набор объектов довольно высокого уровня и не требует от вас знания и понимания спецификации PDF (слишком много). В прошлом мы пытались выпускать очень детализированные API для таких вещей, как TIFF, и обнаружили, что наши клиенты не находят их приемлемыми. Поэтому мы попытались угадать, что, вероятно, захотят и в чем будут нуждаться наши клиенты, и создали API, которые легче усваиваются.

iText и iTextSharp обеспечивают очень точное управление API, но вам необходимо понять спецификацию PDF, чтобы получить то, что вам нужно.

Например, чтобы выполнить извлечение аннотации, вам нужно будет открыть документ, получить каталог страниц, пройтись по дереву страниц, найти все словари страниц, которые имеют ключ аннотаций, пройтись по массиву аннотаций, найти ключ в каждом словаре. /Type со значением /Annot и для ключа /SubType со значением /Link, затем извлеките значение ключа /Dest, если оно присутствует, и если оно не равно нулю, используйте его, в противном случае посмотрите на ключ /A и начните обход дерево действий, чтобы найти действие с ключом /Type, установленным на /GoTo (IIRC), а затем перейти оттуда.

Пункт назначения может быть прямым пунктом назначения или именованным пунктом назначения. Если это именованное место назначения, вам придется вернуться к каталогу документов, вытащить дерево имен и найти в нем имя в именованном месте назначения, а когда вы его найдете, извлечь оттуда информацию.

Так что да, вы можете использовать iText или другой аналогичный анализатор PDF, но вам нужно будет выполнить все эти шаги, если только один из создателей библиотеки не сделает это за вас.

person plinth    schedule 26.10.2010

Я не знаю ни одного платного или бесплатного программного обеспечения, которое из коробки могло бы делать именно то, что вам нужно. Вам, вероятно, придется написать некоторый код независимо от того, какую библиотеку вы будете использовать. В конце концов, текст в PDF может быть в любом порядке, поэтому, по крайней мере, координаты текста должны быть рассчитаны, чтобы правильно отфильтровать нежелательный текст. Кроме того, аннотации ссылок должны быть найдены в PDF-файле, и информация об их назначении должна быть получена.

Библиотека Docotic.Pdf (отказ от ответственности: я работаю в Bit Miracle) может помочь вам как с аннотациями, так и с текстовыми координатами. Существует Извлечение текста из целевой ссылки пример, который иллюстрирует, как сделать что-то похожее на вашу задачу. Я отправляю ссылку на образец в надежде, что он может оказаться полезным для вас (если вы решите обратиться к несвободным программам) или других.

person Bobrovsky    schedule 02.11.2010

iText (Java & C#) может это сделать, хотя и не "из коробки". Вам нужно будет выполнить некоторые низкоуровневые манипуляции с объектами PDF (и некоторые математические операции), чтобы определить, где начать поиск, например.

Хорошей новостью является то, что существует «стратегия» извлечения текста, которая будет извлекать текст только из заданной ограничивающей рамки. Код может выглядеть примерно так:

http://www.itextpdf.com/examples/iia.php?id=279

Получение пункта назначения по ссылке — это не то, что можно использовать в качестве удобного примера. Вам придется взглянуть на спецификацию PDF (у Adobe есть бесплатная копия ... она упоминается в нескольких других вопросах с тегами PDF, но у меня нет под рукой ссылки на этом компьютере).

person Mark Storer    schedule 22.10.2010