Время прочтения: 4 мин.
Для решения проблемы поиска данных по шаблону существуют регулярные выражения. Регулярные выражения — это последовательности символов, которые используются для поиска текста.
В Python для работы с регулярными выражениями мы будем использовать модуль re. Для использования нам нужно его импортировать в коде: import re. Регулярные выражения могут использоваться для разбиения строки на подстроки и замены части строки.
Рассмотрим специальные символы и литералы, которые могут нам помочь:
Символ | Описание |
«.» | Соответствует любому символу, кроме новой строки. |
«^» | Соответствует началу строки. |
«$» | Соответствует концу строки или непосредственно перед новой строкой в конце строки. |
«*» | Соответствует 0 или более (жадным) повторениям предыдущего RE. |
«+» | Соответствует 1 или более (жадным) повторениям предыдущего RE. |
«?» | Соответствует 0 или 1 (жадный) предыдущего RE. |
*?,+?,?? | *? +?, ?? Нежадные версии предыдущих трех специальных символов. |
{m,n} | {m, n} Соответствует от m до n повторений предыдущего RE. |
{m,n}? | Не жадная версия примера выше. |
«\\» | Либо экранирует специальные символы, либо сигнализирует о специальной последовательности. |
[] | Указывает набор символов. |
«|» | A | B, создает RE, который будет соответствовать либо A, либо B. |
Жадность (greedy) соответствует как можно большему числу повторений.
Литерал | Описание |
\number | Соответствует содержимому группы с тем же номером. |
\A | Соответствует только в начале строки. |
\Z | Соответствует только в конце строки. |
\b | Соответствует пустой строке, но только в начале или конце слова. |
\B | Соответствует пустой строке, но не в начале или конце слова. |
\d | Соответствует любой десятичной цифре; эквивалентно набору [0-9]. |
\D | Соответствует любому нецифровому символу; эквивалентно [^ \ d]. |
\s | Соответствует любому символу пробела; эквивалентно [\ t \ n \ r \ f \ v]. |
\S | Соответствует любому непробельному символу, эквивалентно [^ \ s]. |
\w | Соответствует любому буквенно-цифровому символу; эквивалентно [a-zA-Z0-9_]. |
\W | Соответствует дополнению \ w. |
\\ | Соответствует буквальному обратному слешу. |
Теперь применим полученные знания. Рассмотрим пример для вывода найденных паттернов на экран из docx файла (код не претендует на правильность, но в 95% случаев отработало как надо) возьмем вот такой договор:
Мы взяли наиболее часто встречаемые данные в документах.
Для почтового адреса паттерны выглядят:
pattern_email=r»([a-zA-Z0-9][a-zA-Z0-9_.+-]+[^..+!&#&_@-]+@[a-zA-Z0-9+][a-zA-Z0-9]+\.[a-zA-Z0-9-.]+)»
[a-zA-Z0-9] — для того, чтобы не было спец символов в начале
[a-zA-Z0-9_.+-] — в самом имени почтового ящика могут спецсимволы
[^..+!&#&_@-] — последним символом в имени посты должна быть цифра или латинская буква
Благодаря паттерну мы найдем mail.mail1@mail.com.
Числовые паттерны (используется для указания точного числа)
Паттерн номера паспорта в формате 0000 000000 или 00 00 000000 будет выглядеть:
pattern_passport =r"(\b\d{4}\s\d{6}\b|\b\d{2}\s\d{2}\s\d{6}\b)"
Он определит 0000 010101, так как условие 4 числа (\d{4}) — пробел (\s) — 6 чисел (\d{6}) соблюдены.
По аналогии сделаем паттерны 16ти значного и 18ти значного номера кредитной карты:
pattern_card16=r"(\b\d{16}\b|\b\d{4}\s\d{4}\s\d{4}\s\d{4}\b|\b\d{8}\s\d{8}\b)"
В 16ти значном номере кредитной карты найдет в документе 0001000200030004.
В 18ти значном номере кредитной карты найдет в документе 0101 0101 0101 0101 01.
Ну и расчетный счет тоже не оставим без внимания:
pattern_credit_account = r»(\b\d{20}\b)»
В документе найдет 00010002000300040005.
С ФИО чуть сложнее. Во-первых, нужно не забывать про ё и Ё. Во-вторых, нужно не забывать про сдвоенные фамилии. Однако паттерн не панацея и не может 100% определить ФИО перед ним или просто слова которые совпали с паттерном. В реальности данный паттерн отрабатывает на все сочетания из трех слов (+ сдвоенная фамилия), где первая буква в слове заглавная.
pattern_fio_ru=r»([А-ЯЁ]{1}[а-яё]*-[А-ЯЁ]{1}[а-яё]*\s[А-ЯЁ]{1}[а-яё]*\s[А-ЯЁ]{1}[а-яё]*|[А-ЯЁ]{1}[а-яё]*\s[А-ЯЁ]{1}[а-яё]*\s[А-ЯЁ]{1}[а-яё]*-[А-ЯЁ]{1}[а-яё]*|[А-ЯЁ]{1}[а-яё]*\s[А-ЯЁ]{1}[а-яё]*\s[А-ЯЁ]{1}[а-яё]*)»
pattern_fio_en=r»([A-Z]{1}[a-z]*\s[A-Z]{1}[a-z]*\s[A-Z]{1}[a-z]*|[A-Z]{1}[a-z]*-[A-Z]{1}[a-z]*\s[A-Z]{1}[a-z]*\s[A-Z]{1}[a-z]*|[A-Z]{1}[a-z]*\s[A-Z]{1}[a-z]*\s[A-Z]{1}[a-z]*-[A-Z]{1}[a-z]*)»
Рассмотрим подробнее:
- [А-ЯЁ]{1}[а-яё]*-[А-ЯЁ]{1}[а-яё]*\s[А-ЯЁ]{1}[а-яё]*\s[А-ЯЁ]{1}[а-яё]*
Фаимилия1-Фамилия2 Имя Отчество
- [А-ЯЁ]{1}[а-яё]*\s[А-ЯЁ]{1}[а-яё]*\s[А-ЯЁ]{1}[а-яё]*-[А-ЯЁ]{1}[а-яё]*
Имя Отчество Фамилия1-Фамилия2
- [А-ЯЁ]{1}[а-яё]*\s[А-ЯЁ]{1}[а-яё]*\s[А-ЯЁ]{1}[а-яё]*
Фамилия Имя Отчество или Имя Отчество Фамилия
С латинскими ФИО по аналогии.
В тексте найдет:
Иванова Ивана Ивановича
Кузьма Сергеевич Петров-Водкин
Кузьма Сергеевич Петров-Водкин (т.к. 2 раза встречается в тесте)
И теперь мы рассмотрим точное совпадение словам, выражениям или предложениям:
#Паттерн Для внутреннего использования
pattern_dvi = r»(Для внутреннего использования|для внутреннего использования|ДВИ)»
В тексте найдет: Для внутреннего использования
В данной статье мы познакомились с основными инструментами для работы с регулярными выражениями, что дает нам лишь базовое представление. Существует множество литературы, посвященные регулярным выражениям, однако полезным будет сначала ознакомится с описанием библиотеки re https://docs.python.org/3/library/re.html и использовать песочницу https://regex101.com/ для проверки полученных знаний. Помните о том, что регулярные выражения это достаточно простой в освоении и удобный инструмент, который сократит Вам много часов работы.