Я пишу сценарий, чтобы взять отсканированные файлы PDF и преобразовать их в строки текста для ввода в базу данных. Я использую re.findall, чтобы получить совпадения из списка регулярных выражений, чтобы получить определенные значения из извлеченных строк tesseract. У меня возникают проблемы, когда регулярное выражение не может найти совпадение. Я хочу, чтобы оно возвращало «Ошибка». Итак, я вижу, что есть проблема.

Я пробовал несколько операторов if / else, но, похоже, я не смог их заметить.

from wand.image import Image as Img
import ghostscript
from PIL import Image
import pytesseract
import re
import os

def get_text_from_pdf(pendingpdf,pendingimg):
    with Img(filename=pendingpdf, resolution=300) as img:
        img.compression_quality = 99
        img.save(filename=pendingimg)
    pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract'
    extractedtext = pytesseract.image_to_string(Image.open(pendingimg))
    os.unlink(pendingimg)
    return extractedtext

def get_results(vendor,extracted_string,results):
    for v in vendor:
        pattern = re.compile(v)
        for match in re.findall(pattern,extracted_string):
            if type(match) is str:
                results.append(match)
            else:
                results.append("Error")
    return results

pendingpdf = r'J:\TBHscan07022019090315001.pdf'
pendingimg = 'Test1.jpg'
aggind = ["^(\w+)(?:.+)\n+3600",
          "Ticket: (nonsensewordstothrowerror)",
          "Ticket: \d+\s([0-9|/]+)",
          "Product: (\w+.+)\n",
          "Quantity: ([\d\.]+)",
          "Truck (\w+)"]
vendor = aggind
extracted_string = get_text_from_pdf(pendingpdf,pendingimg)
results = []

print(get_results(vendor,get_text_from_pdf(pendingpdf,pendingimg),results))
1
Matthew Keith 2 Июл 2019 в 18:18

4 ответа

Лучший ответ

Вы можете сделать это в одной строке:

results += re.findall(pattern, extracted_string) or ["Error"]

Кстати, вы не получаете никакой выгоды от компиляции шаблона в цикле вендора, потому что вы используете его только один раз.

Ваша функция может также вернуть весь результат поиска, используя единый список:

return [m for v in vendor for m in re.findall(v, extracted_string) or ["Error"]]

Немного странно, что вы на самом деле захотите изменить И вернуть список результатов, передаваемый в качестве параметра. Это может привести к неожиданным побочным эффектам при использовании функции.

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

Если вы хотите сообщить об ошибке только в том случае, если ни один из шаблонов поставщиков не соответствует, вы можете использовать трюк or ["Error"] для всего результата:

return [m for v in vendor for m in re.findall(v, extracted_string)] or ["Error"]
1
Alain T. 2 Июл 2019 в 15:49

С таким подходом for match in re.findall(pattern,extracted_string):
если re.findall(...) не найдет совпадений - цикл for не будет даже запущен.

Заранее сохраните результат сопоставления в переменную, затем - проверьте с условием:

...
matches = re.findall(pattern, extracted_string)
if not matches:
    results.append("Error")
else:
    for match in matches:
        results.append(match)

Обратите внимание, что при выполнении итерации результатов re.findall(...) проверка if type(match) is str: не будет иметь смысла, так как каждый сопоставляемый элемент в любом случае является строкой (в противном случае более сложный анализ содержимого строки может подразумевалось).

2
RomanPerekhrest 2 Июл 2019 в 15:35

У тебя есть

for match in re.findall(pattern,extracted_string):
        if type(match) is str:
            results.append(match)
        else:
            results.append("Error")

Но re.findall() возвращает None, когда ничего не находит, поэтому

for match in re.findall(pattern,extracted_string):

Не войдет, потому что совпадение None.

Вам нужно проверить match is None вне цикла for.

0
CRotelli 2 Июл 2019 в 15:25

re.findall возвращает пустой список, если совпадений нет. Так что это должно быть так просто, как:

result = re.findall(my_pattern, my_text)
if result:
    # Successful logic here
else:
    return "Error"
1
Alex 2 Июл 2019 в 15:24