Анализ данных, Обработка документов

Паттерны в “розыскном” деле

Время прочтения: 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/ для проверки полученных знаний. Помните о том, что регулярные выражения это достаточно простой в освоении и удобный инструмент, который сократит Вам много часов работы.

Советуем почитать