Я работаю над проектом, где мне приходится читать отсканированные изображения финансовых отчетов. Я использовал 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()
где кто-то пытается использовать re.match()
для .groups()
чтобы найти шаблон: как разбить строки на текст и число?
Я просто знаком с регулярным выражением, и я стараюсь правильно понять синтаксис и документацию. На данный момент я пытаюсь использовать чит-лист, но мне сложно определить, как это сделать, пожалуйста, помогите.
Я написал это регулярное выражение, наблюдая за вашим первым ожидаемым выходом. Но я не уверен, что ваш желаемый результат с вашим третьим предложением.
([A-Za-z ]+)(?=\d|\S)
сопоставить имя, пока не найдем номер или символ..*?
для строки, которая нам не нужна([\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', '')]
'Business taxes 999 -
?» так что в основном я хочу получить следующий результат [[налоги на бизнес], [999], [-]] .... где дефис является пустым числом
Regexes являются излишними для этой проблемы, как вы заявили об этом.
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]
и обработать их на основе слов и цифр.
Чтобы обнаружить строку
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')
Пусть распакует эту большую ол-строку.
[AZ]
означает искать все буквы от до A
Z
, в то время как [0-9,]
означает искать цифры 0
через 9
, а также характер ,
. -
вот оператор используется внутри квадратные скобки для обозначения диапазона символов, которые мы хотим.+
означает поиск по крайней мере одного события того, что непосредственно предшествует ему. Например, выражение [AZ]+
означает поиск хотя бы одного вхождения любой буквы A
в Z
Вы также можете использовать оператор *
, чтобы искать по крайней мере нулевые вхождения того, что предшествует ему.([A-Z+])
означает искать хотя бы одно вхождение любой буквы A
Z
, а затем сохранять все, что окажется. Мы x.groups()
доступ к этому, выполняя x.groups()
после присвоения результата соответствия регулярному выражению переменной x
.[[TEXT], [NUMBER], [NUMBER]]
. Квадратные скобки экранируются символом \
, потому что мы хотим интерпретировать их буквально, а не как набор символов.re.match()
будет искать rev_str
для любых мест, где данный шаблон соответствует, отслеживать группы в этом совпадении и возвращать эти группы при вызове x.groups()
.Это довольно простой пример, но вы должны что-то начать, верно? Вы должны использовать это как отправную точку для создания более сложного выражения регулярного выражения для обработки большего количества вашего кода.
r"([A-Za-z ]+)(?=\d|\S).*?([\d,]+)\s([\d,]+)"
. вам нужно использоватьre.findall()