Чтение финансовой отчетности с использованием REGEX - PullRequest
0 голосов
/ 07 декабря 2018

Я работаю над проектом, в котором мне нужно читать отсканированные изображения финансовой отчетности.Я использовал tesseract 4 для преобразования изображения в текстовый вывод, который выглядит так (вот фрагмент):

ВЫХОД 9 000 000 900 000

СТОИМОСТЬ ПРОДАЖ 900 000 900 000

ВАЛОВОЙ ПРИБЫЛЬ (90%; 2016 - 90%) 900 000 900 000

Я хотел бы разбить вышесказанное на список из трех записей, где первая запись - это текст, а вторая и третья -номера.Например, первая строка будет выглядеть примерно так:

[[REVENUE], [9,000,000], [9,000,000]]

Я наткнулся на этот пост переполнения стека, где кто-то пытается использовать re.match() для .groups() метода, чтобы найти шаблон: Какразбить строки на текст и число?

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

Ответы [ 3 ]

0 голосов
/ 07 декабря 2018

Чтобы обнаружить строку

rev_str = "[[REVENUE], [9,000,000], [9,000,000]]"

и извлечь значения

("REVENUE", "9,000,000", "9,000,000")

, вы должны сделать

import re
x = re.match(r"\[\[([A-Z]+)\], \[([0-9,]+)\], \[([0-9,]+)\]\]", rev_str)
x.groups()
# ('REVENUE', '9,000,000', '9,000,000')

Давайте распакуем эту большую старую строку.

  • Квадратные скобки обозначают диапазон символов.Например, [A-Z] означает поиск всех букв от A до Z, тогда как [0-9,] означает поиск цифр от 0 до 9, а также символа ,.- - это оператор, который используется в квадратных скобках для обозначения диапазона символов, который нам нужен.
  • Оператор + означает поиск хотя бы одного вхождения любогопредшествует этому.Например, выражение [A-Z]+ означает поиск хотя бы одного вхождения любой из букв от A до Z.Вместо этого вы также можете использовать оператор *, чтобы искать хотя бы ноль вхождений того, что ему предшествует.
  • Круглые скобки (т.е. круглые скобки) обозначают группу быть извлеченным из регулярного выражения.Всякий раз, когда этот шаблон сопоставляется, все, что находится внутри любого выражения в скобках, будет извлечено и возвращено как группа.Например, ([A-Z+]) означает поиск хотя бы одного вхождения любой из букв от A до Z, а затем сохраните все, что окажется .Мы получаем доступ к этому, делая x.groups() после присвоения результата соответствия регулярному выражению переменной x.
  • В остальном все просто - в соответствии с шаблоном [[TEXT], [NUMBER], [NUMBER]].Квадратные скобки экранируются символом \, потому что мы хотим интерпретировать их буквально , а не как диапазон символов.
  • В целом, функция re.match() будет искать rev_str для любых мест, где данный шаблон соответствует , отслеживайте группы в этом матче и возвращайте эти группы при вызове x.groups().

Это довольно простой пример, но ты должен с чего-то начать, верно?Вы должны быть в состоянии использовать это как отправную точку для создания более сложного выражения регулярного выражения для обработки большей части вашего кода.

0 голосов
/ 07 декабря 2018

Я написал это регулярное выражение, просмотрев ваш первый ожидаемый результат.Но я не уверен, каков ваш желаемый результат с вашим третьим предложением.

  1. ([A-Za-z ]+)(?=\d|\S) соответствует имени, пока мы не найдем число или символ.
  2. .*? для строки, котораянам все равно,
  3. ([\d,]+)\s([\d,]+|(?=-\n|-$)) сопоставлять одну или две группы чисел, если существует только одна группа чисел, эта группа должна заканчиваться новой строкой или концом текста.

Тестовый код (отредактированный):

import re

regex = r"([A-Za-z ]+)(?=\d|\S).*?([\d,]+)\s([\d,]+|(?=-\n|-$))"

text = """
REVENUE 9,000,000 900,000

COST OF SALES 900,000 900,000

GROSS PROFIT (90%; 2016 - 90%) 900,000 900,000

Business taxes 999 -
"""

print(re.findall(regex,text))
# [('REVENUE ', '9,000,000', '900,000'), ('COST OF SALES ', '900,000', '900,000'), ('GROSS PROFIT ', '900,000', '900,000'), ('Business taxes ', '999', '')]
0 голосов
/ 07 декабря 2018

Регулярные выражения излишни для этой проблемы, как вы ее заявили.

text.split() и join элементов перед двумя последними лучше подходят для этого.

lines = [ "REVENUE 9,000,000 900,000",
          "COST OF SALES 900,000 900,000",
          "GROSS PROFIT (90%; 2016 - 90%) 900,000 900,000" ]
out = []
for line in lines:
    parts = line.split()
    if len(parts) < 3:
        raise InputError
    if len(parts) == 3:
        out.append(parts)
    else:
        out.append([' '.join(parts[0:len(parts)-2]), parts[-2], parts[-1]])

out будет содержать

 [['REVENUE', '9,000,000', '900,000'], 
  ['COST OF SALES', '900,000', '900,000'], 
  ['GROSS PROFIT (90%; 2016 - 90%)', '900,000', '900,000']]

Если текст метки нуждается в дальнейшем извлечении, вы можете использовать регулярные выражения или просто посмотреть на элементы в parts[0:len(parts)-2] и обработать их на основе слов и цифресть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...