Как разбить поле «ФИО» на имя, фамилию и отчество в PHP

Бывают случаи, когда ФИО пользователей на сайте задавалось с помощью единственного поля «ФИО», а после какого-то времени, в ходе рефакторинга базы, решили сделать 3 поля — Фамилия, Имя, Отчество. Как же быть со старыми данными? Ведь пользователи вводят туда всё что угодно. Попадаются такие ФИО как «Иванов К.М.», «пЕтрова ивгения», «Константин пАВЛОВ директор». Как же выделить из этих «ФИО» осмысленную информацию, настоящие имя, фамилию и отчество, чтобы заполнить соответствующие поля?

Когда я столкнулся с этой проблемой, я не нашел готового решения, поэтому написал инструмент сам.

Библиотека анализа и нечёткого поиска в строке фамилии, имени, отчества.

Библиотека написана на PHP и использует базу русских имен, фамилий, и отчеств (женских и мужских), взятых из википедии, и дополненных еще несколькими десятками вручную. Если вам нужно определять также другие ФИО (например, грузинские, таджикские, казахские), нужно будет дополнить базы слов в соответствующих файлах.

Взять библиотеку можно здесь: https://github.com/MihanEntalpo/FIO-Analyzer

Установка с помощью composer:

В вашем файле composer.json нужно прописать:

{
    "require": {
        "mihanentalpo/fio-analyzer": "*"
    }
}

Установить:

composer.phar install

Для подключения достаточно написать:

<?php 
require_once("../vendor/autoload.php");
$analyzer = new \Mihanentalpo\FioAnalyzer\FioAnalyzer();

А для выполнения анализа, натравить метод break_apart на ваши входные данные:

<?php
//Намеренно добавлены лишние слова и знаки, размер букв также специально такой. 
$src = "Иванов иван Петрович главный инженер.,"; 
$fio = $analyzer->break_apart($src);
print_r($fio);

В результате будет возвращена следующая структура:

Array
(
    [first_name] => Array
        (
            [src] => иван
            [found] => иван
            [percent] => 1
        )
    [second_name] => Array
        (
            [src] => Петрович
            [found] => петрович
            [percent] => 1
        )
    [last_name] => Array
        (
            [src] => Иванов
            [found] => иванов
            [percent] => 1
        )
)

где поля «first_name», «second_name» и «last_name» — это данные соответственно о имени, отчестве, фамилии, найденных в переданной строке. Если чего-то из них найти не удалось, тогда этого поля просто не будет в возвращаемом массиве.
Поле «src» — этот тот текст в исходной строке, по которому проводилось сравнение.
Поле «found» — найденное значение из базы имен/фамилий/отчеств, в нижнем регистре.
Поле «percent» — процент соответствия между src и found. В данном примере он равен 1, но может быть и меньше, если есть отличия в буквах.

Функционал класса

Основная функция break_apart:

/**
* @param string $fio Строка с ФИО
* @param float $edge граница совпадения имени, фамилии, и отчества, число от 0 до 1
**/
function break_apart( $fio, $edge = 0.75)

Как работает алгоритм?

1. Переданная фраза, например «Иванов иван Петрович главный инженер.,», очищается от мусора, и разбивается на массив слов.
2. По каждому слову производится поиск среди всего множества имён, фамилий и отчеств, и выбирается наиболее похожее имя, фамилия и отчество, с учётом порогового значения, то есть совпадение менее заданного процента будут считаться недостоверными.
3. Поскольку имя, фамилия и отчество в строке ФИО должны встречаться только по одному разу, собираются все возможные комбинации значений слов, когда, например, строка представляет собой «имя,фамилия,отчество, шум» (где «шум» — это просто постороннее слово, не являющееся ни именем, ни фамилией, ни отчеством), «имя, шум, отчество, фамилия», «фамилия, шум, имя, шум, отчество» и так далее, и выбирается тот вариант, где суммарный процент совпадения между словами, и их найденными «именами»,»фамилиями» и «отчествами» максимален.
4. Этот набор и возвращается в качестве результата

Нечёткий поиск

Для нечёткого поиска по именам, фамилиям, отчествам используется класс FastFuzzySearch, описанный мной в другой статье.

Оптимизация инициализации

Первая инициализация класса FioAnalyzer может занять некоторое время, поскольку проводится инициализация объектов нечёткого поиска FastFuzzySearch. Каждый из них загружает массив имён, фамилий и отчеств соответственно. После инициализации будут созданы файлы first_names.php.index, second_names.php.index и last_names.php.index, из которых в следующий раз будет проводиться быстрая загрузка данных для FastFuzzySearch


Оставить комментарий

  • *