iText7 RegexBasedLocationExtractionStrategy не находит все совпадения регулярных выражений - PullRequest
0 голосов
/ 17 июня 2020

Итак, я использовал iText7 на C# для извлечения и выделения данных PDF. Раньше я использовал iTextSharp 5, и он хорошо справлялся с тем, что мне было нужно, я перенес некоторые функции, но решил начать использовать RegexBasedLocationExtractionStrategy для поиска прямоугольников, которые мне нужно выделить, а не модифицированную версию TextLocationExtractionStrategy . Проблема, с которой я сталкиваюсь, заключается в том, что у меня есть PDF-файл (к сожалению, не могу поделиться, но я пытаюсь создать тот, который может воспроизвести проблему), который содержит словосочетание «Кровяное давление», и у меня есть следующий оператор регулярного выражения @"\b\.blood\spressure\b" . Я проверил, что этот оператор регулярного выражения находит совпадение текста в PDF-документе, когда я извлекаю весь текст страницы, но когда я запускаю его с помощью стратегии Regex, он не возвращает результат совпадения для той же самой страницы. Ниже приведен код, который я использую

            foreach (string searchTerm in Model.SearchTerms)
            {
                if (searchTerm.Contains(" "))
                {
                    var split = searchTerm.Split(" ");
                    foreach (string item in split)
                    {
                        term += item + @"\s";
                    }
                    char[] trim = new char[2] { 's', '\\' };
                    term = term.Trim(trim);
                }
                else
                {
                    term = searchTerm;
                }
                regexList.Add(@"\b" + term + @"\b");
                regexList.Add(@"\b\." + term + @"\b");
                regexList.Add(@"\.\b" + term + @"\b");
                regexList.Add(@"\b" + term + @"s\b");
                regexList.Add(@"\b" + term + @"\.\b");
                regexList.Add(@"\b" + term + @"\s\b");
            }

            searchRegex = new Regex(string.Join('|', regexList), RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
            for (int i = Model.BlankPages + 1; i <= pdfDocument.GetNumberOfPages(); i++)
            {
                extractionStrategy = new RegexBasedLocationExtractionStrategy(searchRegex);
                canvasProcessor = new PdfCanvasProcessor(extractionStrategy);
                canvasProcessor.ProcessPageContent(pdfDocument.GetPage(i));
                page = pdfDocument.GetPage(i);
                pageRectangles.Add(new KeyValuePair<PdfPage, List<Rectangle>>(page, extractionStrategy.GetResultantLocations().Select(x => x.GetRectangle()).ToList()));
            }

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

            for (int page = 1; page <= numberOfPages; page++)
            {
                strategy = new LocationTextExtractionStrategy();
                pageText = PdfTextExtractor.GetTextFromPage(pdfDocument.GetPage(page), strategy);
                pageValuePairs.Add(page, pageText);
            }
            // code break to seperate helper method where searchString is the pageText from the above code
        public static KeyValuePair<Regex, bool> FindString(string searchTerm, string searchString)
        {
            List<string> regexList = new List<string>();
            string term = "";
            if (searchTerm.Contains(" "))
            {
                var split = searchTerm.Split(" ");
                foreach (string item in split)
                {
                    term += item + @"\s";
                }
                char[] trim = new char[2] { 's', '\\' };
                term = term.Trim(trim);
            }
            else
            {
                term = searchTerm;
            }
            regexList.Add(@"\b" + term + @"\b");
            regexList.Add(@"\b\." + term + @"\b");
            regexList.Add(@"\.\b" + term + @"\b");
            regexList.Add(@"\b" + term + @"s\b");
            regexList.Add(@"\b" + term + @"\.\b");
            regexList.Add(@"\b" + term + @"\s\b");
            Regex searchRegex = new Regex(string.Join('|', regexList), RegexOptions.IgnoreCase);
            if (searchRegex.IsMatch(searchString))
            {
                return new KeyValuePair<Regex, bool>(searchRegex, true);
            }
            return new KeyValuePair<Regex, bool>(null, false);
        }

Это фрагмент текста, который содержит указанный термин "\nPulse 1: 100 bpm \nBlood Pressure 1:" после осмотра я не нашел причин для несоответствия, нет нечетных символов пробела, я пробовал с RegexOptions.SingleLine и без него, но изменений не было. Я действительно не понимаю, в какой строке он ищет, если она отличается от той, которую я ищу (и почему), и как я могу исправить эту проблему.

Примечание: я знаю, что это не так. Выглядит не очень хорошо, это все еще PO C, но этот код, в частности, действительно находит прямоугольники примерно для 150 поисковых запросов и работает безумно быстро по сравнению с моей предыдущей версией iTextSharp 5, 200-страничного документа со 150 поисковыми запросами и 5000 совпадений в старой версии занимали ~ 45-60 секунд, вышеупомянутая версия с более высокой точностью (за исключением этого одного случая "кровяного давления") занимает менее 5 секунд и в среднем по всем документам менее секунды.

РЕДАКТИРОВАТЬ Я , возможно, пришел к выводу, что это проблема в RegexBasedLocationExtractionStrategy в том смысле, что он ищет по одному слову за раз, а не целую строку сразу, что делает невозможным найти фразу через ее logi c. Я верю в это, поскольку обнаружил, что другие результаты при поиске по регулярным выражениям из нескольких слов совпадают в других документах. Если у кого-то есть дополнительные знания по этому поводу, обновите и сообщите по мере необходимости

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

...