Часто приходятся работать с полнотекстовым поиском, распознаванием и нормализаций телефонных номеров в длинном тексте. Часто эти номера имеют различный вид. Порой, в тексте номера могут быть в разных форматах с разными разделителями, с и без кода страны. В этой статье рассказываю о том, как действовать в таком случае.
Для начала, определимся с рамками задачи. Во-первых, телефоны должны быть одной страны. В нашем случае — российские номера (код России +7). Это правило сильно упростит жизнь. Также, номера могут иметь совершенно разные разделители и быть в разных форматах:
- Без плюса: 79001234567
- Без семерки: 9001234567
- Через восьмерку: 89001234567
- Скобки: 8(900)1234567, +7 (900) 123-45-67
- Пробелы: 8 900 123 45 67, +7 (900) 123 45 67
- Дефисы: 8-900-123-45-67, +7-900-123-45-67
- Точки: 8.900.123.45.67, 900.123.45.67
+ возможны сочетания любых этих типов друг с другом по нескольку раз за один номер.
Сразу скажу, что все эти случае покрывает библиотека libphonenumber от Google. У библиотеки есть порты для многих языков (PHP, C#, Go, Swift, Python, Ruby аж 3 штуки, Rust и других), ссылки на них есть на странице проекта в GitHub. Проблема решения от Google в том, что мы не может из коробки искать номера по тексту. Да, без сомнения, если пользователь указывает номер в специальном поле, библиотека от Google становится очень полезной. Но если пользователь указывает телефон в тексте или задача вообще состоит из парсинга номеров с сайта, то решение Google нам не подойдёт.
Тем не менее, подойдёт более быстрая и простая (по утверждению автора) реализация для JavaScript libphonenumber-js. В прекрасном демо этой библиотеки можно поиграться с различными типами номеров и проверить работоспособность:
Как видите, библиотека отлично справляется с поиском и распознаванием номеров. Она даже сможет подсказать вам некоторые особенности. Такие как различные форматы, удобные жителям той страны, в которой выпущен номер. Тип номера (мобильный, домашний, бесплатный, он же TOLL_FREE), а так же длину номера и его валидность. Например, не бывает номеров российских, начинающихся с +710.
Собственно, пример кода:
import { findPhoneNumbersInText } from 'libphonenumber-js' const phones = findPhoneNumbersInText(`Тест с номерами 8(900)1234567, а так же 900.123.45.67`, 'RU') console.log(phones)
//phones будет содержать: const phones = [ { startsAt: 16, endsAt: 29, number: PhoneNumber { country: 'RU', countryCallingCode: '7', nationalNumber: '9001234567', number: '+79001234567' } }, { startsAt: 40, endsAt: 53, number: PhoneNumber { country: 'RU', countryCallingCode: '7', nationalNumber: '9001234567', number: '+79001234567' } } ]
Тем не менее, советую прочитать документацию именно на предмет особенностей для вашего кейса использования. Так, например, библиотека умеет работать с дополнительными номерами, форматировать номера в нужный формат, сравнивать номера, проверять принадлежность к указанной стране, генерировать удобный форматтер для пошагового ввода (актуально для фронтенда) и много другое.