Найти в Дзене

[РискТехнологии] Автоматизиция. Нахождение террориста в перечне террористов. Физические лица.

В статье рассматриваться нахождения физического лица в черном списке, когда его ФИО трансформируется в несколько вариантов для более точного поиска в списках. Так как статья является продолжением статьи Парсинг (скрапинг) перечня террористов физических лиц с помощью Python, где мы в черный список сохраняли связку Имя+Фамилия, то текущая программа будет принимать на вход только 2 параметра: На схеме ниже изображено, как программа будет преобразовывать клиента: Программа делает перестановку слов Имя+Фамилия. Для каждой перестановки делает второй вариант с замененными "Ё" и "Й" на "Е" и "И". И для каждого варианта ФИО сделает еще по одному преобразованию с кириллицы на латиницу. Итого получится 8 ФИО вместо одного изначального. Не существует одного единственного верного преобразования кириллицы в латиницу, поэтому данную схему можно расширять, но текущая программа носит ознакомительный характер, поэтому остановимся на одном варианте преобразования. Дальше, согласно схеме, каждое из 8-ми
Оглавление

Введение

В статье рассматриваться нахождения физического лица в черном списке, когда его ФИО трансформируется в несколько вариантов для более точного поиска в списках.

Так как статья является продолжением статьи Парсинг (скрапинг) перечня террористов физических лиц с помощью Python, где мы в черный список сохраняли связку Имя+Фамилия, то текущая программа будет принимать на вход только 2 параметра:

  • Имя
  • Фамилия

На схеме ниже изображено, как программа будет преобразовывать клиента:

-2

Программа делает перестановку слов Имя+Фамилия.

Для каждой перестановки делает второй вариант с замененными "Ё" и "Й" на "Е" и "И".

И для каждого варианта ФИО сделает еще по одному преобразованию с кириллицы на латиницу. Итого получится 8 ФИО вместо одного изначального.

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

Дальше, согласно схеме, каждое из 8-ми ФИО будет проходить по 5 проверок:

  • намеренная ошибка, когда латинскую букву вставляют в ФИО

например: Aлександр <- тут первая буква латинская

  • нахождение одной подстроки в другой (x2)
  • полное совпадение названий
  • нахождение расстояния Левенштейна

Количество проверок может быть и больше, но мы остановимся на 5х

Всего получается, что мы вместо 1 варианта поиска создали 40 различных проверок. И это только для связки Имя+Фамилия. В более полном виде можно достичь и 200+, и 500+, и 1000+ проверок:

-3

Плюс в реальных программах можно и нужно делать проверки на дату рождения, регион и прочие параметры.

Результатом программы будет имитация REST ответа:

-4

На примере выше видно, что сработало несколько хитов:

  • полное совпадение (DIST0)
  • три частичных совпадения (DIST2)
  • включение одной подстроки в другую (INC)

За пределами статьи:

  • заранее были подготовлены файлы для работы с виртуальной средой. О том, как их подготавливать, описываю в отдельной статье: https://dzen.ru/a/aEKVHTM_GULyazKa
  • стартовые исходники для статьи лежат в GitLab. В рамках статьи не объясняется, как устанавливать и настраивать git. Всё это описываю в отдельной статье: https://dzen.ru/a/aGgSbU4TnF-_7wL_
  • должен быть установлен Excel от версии 2007 и старше

В конце статьи есть ссылка в GitLab на финальную версию программы.

Используемые технологии

ОС: Windows 10

Язык: Python 3.12

Основные библиотеки: re, pyxlsb, pydantic, numpy

Прочее: Microsoft Office 2013

План работы

  • Клонируем репозиторий с GitLab
  • Настраиваем виртуальную среду
  • Изучаем архитектуру программы
  • Создаём программу
  • Запускаем программу

Клонируем репозиторий с GitLab

Создадим папку "searcher_fl", куда будем клонировать репозиторий

mkdir searcher_fl

Клонируем репозиторий

git clone https://gitlab.com/pytechnotes1/searcher_fl searcher_fl

Заходим в папку

cd searcher_fl/

Делаем чекаут версии коммита, который я сделал специально для статьи

git checkout 902c62da760e4e54c57d269781ed0e517f41dac9

Настраиваем виртуальную среду

Открываем в cmd наш проект searcher_fl и создать виртуальную среду

py -3.12 -m venv venv

Активируем среду

venv\Scripts\activate

Производим установку библиотек из файла, который я подготовил заранее

pip install -r requirements.txt

Выходим из виртуальной среды

deactivate

Изучаем архитектуру программы

Заранее уже готова определенная структура программы.

  • app.py - скрипт, который будет запускать нашу программу.
  • black_list.py - скрипт с нашей программой, которую мы будем реализовывать.
  • datter.py - скрипт, в задачу которого входит извлечь черный список из заранее подготовленного эксель файла
  • response_model.py - скрипт для формирования итогового JSON
  • settings.py - скрипт с конфигами, которые править нет необходимости.
  • data - папка, где лежит заранее подготовленный эксель файл с черным списком

Создаём программу

Начнем реализацию файла response_model.py

Для модели ответа будем использовать внешнюю библиотеку pydantic:

from pydantic import BaseModel

Создадим 3 класса:

  • Response - класс с финальной структурой ответа
  • BLModel - класс, который будет содержать основные поля, такие как результат проверки, кого проверяли и что нашли.
  • PersonModel - класс с подробным описанием, по кому был поиск
-5

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

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

-6

или такой:

-7

Теперь реализуем файл datter.py

Напишем генератор, который будет итеративно, по одной строке подавать информацию из XLSB файла.

-8

Укажем используемые библиотеки:

from typing import Generator
from pyxlsb import open_workbook

Начнем реализацию файла black_list.py

Реализуем конструктор __init__:

-9

Сразу подключим необходимые импорты

import re
import numpy as np
import unicodedata
from settings import Settings
from datter import BlackListData as BLD
from response_model import BLModel, Response as RM, PersonModel as PM

Приступим к реализации метода search

-10

Метод search проверяет клиентское ФИО на ошибку, если ошибки нет, то формирует list связок: Имя+Фамилия. После итерируется по черному списку в поисках совпадений и выводит ответ.

Реализуем метод _print_response

-11

Реализуем метод _set_fio

-12

Для проверки ФИО на ошибку метод _set_fio вызывает метод _check_fio_mistake, реализуем его тоже.

Если _check_fio_mistake находит ошибку. В нашем случае, ошибкой считается, когда в ФИО находим латинские символы. Такую вещь встречал на практике, когда недобросовестные сотрудники пытались обмануть систему.

Метод _check_fio_mistake вызывает другие методы: _remove_accents и _set_hits.

-13

Метод _remove_accents убирает диакритические знаки из ФИО.

Метод _set_hits сохраняет найденный хит.

Реализуем метод _set_data_to_search и связанные с ним методы

-14

Метод _set_data_to_search формирует список всех вариантов ФИО

-15

Только в нашем случае речь идет о связке Имя+Фамилия.

Метод _set_data_to_search вызывает методы _set_ru_list_to_search и_set_lat_data_to_search, которые занимаются формированием всех вариаций ФИО.

Также вызывается метод _transliterate_ru_to_lat, который занимается транслитерацией с кириллицы на латиницу.

Перейдем к реализации метода _loop_lists

-16

Метод итерирует список ФИО, подготовленный методом _set_data_to_search.

В рамках каждой вариации клиентского ФИО итерируемся по черному списку, для этого мы ранее создали класс BlackListData, который открывает эксель файл и построчно извлекает из него информацию.

Реализуем метод _search_terrorists, который сравнивает ФИО клиента и террориста из черного списка.

-17

Метод _search_terrorists подготавливает ФИО клиента и террориста для сравнения. Для этого из ФИО удаляются все лишние символы, кроме букв, плюс в ФИО террориста убираются диакритические знаки.

После всех преобразований вызываются методы _include_eq и _levenshtein_distance, которые осуществляют поиск совпадений.

-18

С помощью метода _include_eq мы ищем включения одной подстроки в другую.

В методе _levenshtein_distance представлен вариант реализации поиска расстояния Левенштейна. Одна из причин появления этой статьи - это показать работу данного метода на практике.

Расстояние Левенштейна - это сумма вставок, удалений, замен символов между двух строк. Несколько примеров:

-19

Немного другой вариант реализации расстояния Левенштейна я показываю в статье: https://dzen.ru/a/aGYUPIdNLRvkpq-T

Под конец реализуем методы, которые будут фиксировать хиты:

-20

При проверке расстояния Левенштейна, если расстояние = 0, то считаем, что террорист в списке 100% найден, и укажем хит: DIST0. Если расстояние менее 3х, то укажем хит: DIST2.

Почему менее 3х? Из моей практики это самое оптимальное число. Большее число приведет к большому количеству ложных срабатываний, меньшее не будет сильно отличаться от хита DIST0.

На этом реализацию программы заканчиваем.

Запускаем программу

Запускаем скрипт через "py", таким образом запустится интерпретатор из виртуальной среды.

py app.py

Получаем JSON ответ:

{"black_list":{"result":2,"person":{"name":"МАГüМЕД","surname":"АБДУКАРИМОВ"},"hits":{"ERR_LAT":["u"]}}}

Исходники проекта

PyTechNotes / searcher_fl · GitLab

Подписывайтесь на Дзен, а также приглашаю в мой телеграмм канал, там публикую другой, но не менее интересный контент.