Вступление
Проверка телефонных номеров может быть очень сложной задачей. Формат
номера телефона может отличаться от страны к стране. Черт возьми, это
может также отличаться в пределах одной страны! Некоторые страны
используют один и тот же код страны, в то время как некоторые другие
страны используют более одного кода страны. Согласно примеру из
репозитория Google
libphonenumber
GitHub, США, Канада и Карибские острова имеют один и тот же код страны (
+1
). С другой стороны, на телефонные номера из Косово можно звонить
по сербскому, словенскому и марокканскому кодам стран.
Это лишь некоторые из проблем, связанных с идентификацией или проверкой телефонных номеров. На первый взгляд, можно хотя бы проверить код страны телефонного номера с помощью RegEx . Однако это означает, что вам нужно будет написать собственное правило RegEx для каждой страны мира, просто чтобы проверить код страны. Кроме того, у некоторых операторов мобильной связи есть свои правила (например, для определенных цифр можно использовать только определенный диапазон номеров). Вы можете видеть, что ситуация может быстро выйти из-под контроля и сделать для нас практически невозможным проверку ввода номера телефона самостоятельно.
К счастью, есть библиотека Python, которая может помочь нам легко и
эффективно пройти процесс проверки. Библиотека Python Phonenumbers
является производным от библиотеки Google libphonenumber
, которая
также доступна для других языков программирования, таких как C ++, Java
и JavaScript.
В этом руководстве мы узнаем, как анализировать, проверять и извлекать телефонные номера, а также как извлекать дополнительную информацию из телефонных номеров, таких как данные оператора связи, часового пояса или геокодера.
Использовать библиотеку очень просто, и обычно она используется следующим образом:
import phonenumbers
from phonenumbers import carrier, timezone, geocoder
my_number = phonenumbers.parse("+447986123456", "GB")
print(phonenumbers.is_valid_number(my_number))
print(carrier.name_for_number(my_number, "en"))
print(timezone.time_zones_for_number(my_number))
print(geocoder.description_for_number(my_number, 'en'))
И вот результат:
True
EE
('Europe/Guernsey', 'Europe/Isle_of_Man', 'Europe/Jersey', 'Europe/London')
United Kingdom
Начнем с настройки нашей среды и установки библиотеки.
Установка телефонных номеров
Сначала давайте создадим и активируем нашу виртуальную среду:
$ mkdir phonenumbers && cd phonenumbers
$ python3 -m venv venv
$ . venv/bin/active # venv\Scripts\activate.bat on Windows
Затем устанавливаем библиотеку Python Phonenumbers:
$ pip3 install Phonenumbers
В этом руководстве будет использоваться библиотека Phonenumbers версии
8.12.19
.
Теперь мы готовы начать знакомство с библиотекой Phonenumbers.
Разбор номера телефонов номера телефонов Python
Независимо от того, получаете ли вы ввод пользователя из веб-формы или
из других источников, например извлекаете из некоторого текста
(подробнее об этом позже в этом руководстве), входящий номер телефона,
скорее всего, будет строкой. В качестве первого шага, мы должны
разобрать его , используя phonenumbers
, и превратить его в
PhoneNumber
, например , так , что мы можем использовать его для
проверки и других функций.
Мы можем разобрать номер телефона с помощью метода parse()
import phonenumbers
my_string_number = "+40721234567"
my_number = phonenumbers.parse(my_string_number)
Метод phonenumbers.parse()
принимает строку номера телефона в качестве
обязательного аргумента. Вы также можете передать информацию о стране в
формате ISO Alpha-2 в качестве необязательного аргумента. Рассмотрим,
например, следующий код:
my_number = phonenumbers.parse(my_string_number, "RO")
«RO» означает Румынию в формате ISO Alpha-2. Вы можете проверить другие коды стран Alpha-2 и цифровые коды на этом веб-сайте . В этом руководстве для простоты я буду опускать код страны ISO Alpha-2 для большинства случаев и включать его только тогда, когда это строго необходимо.
В phonenumbers.parse()
уже есть некоторые встроенные базовые правила
проверки, такие как длина числовой строки, проверка нуля в начале или
знак +
Обратите внимание, что этот метод вызовет исключение, если
какое-либо из необходимых правил не выполнено. Поэтому не забудьте
использовать его в блоке try / catch в своем приложении .
Теперь, когда мы правильно проанализировали номер телефона, приступим к проверке.
Подтверждение телефонных номеров с помощью телефонных номеров Python
Phonenumbers имеет два метода проверки действительности телефонного номера. Основное отличие этих методов - скорость и точность.
Чтобы уточнить, начнем с is_possible_number()
:
import phonenumbers
my_string_number = "+40021234567"
my_number = phonenumbers.parse(my_string_number)
print(phonenumbers.is_possible_number(my_number))
И результат будет:
True
Теперь давайте воспользуемся тем же числом, но на этот раз с методом
is_valid_number()
import phonenumbers
my_string_number = "+40021234567"
my_number = phonenumbers.parse(my_string_number)
print(phonenumbers.is_valid_number(my_number))
Несмотря на то, что ввод был таким же, результат был бы другим:
False
Причина в том, что метод is_possible_number()
быстро угадывает
действительность телефонного номера, проверяя длину проанализированного
номера, в то время как метод is_valid_number()
выполняет полную
проверку, проверяя длину, префикс телефонного номера и регион.
При переборе большого списка телефонных номеров использование
phonenumbers.is_possible_number()
обеспечит более быстрые результаты
по сравнению с phonenumbers.is_valid_number()
. Но, как мы видим
здесь, эти результаты не всегда могут быть точными. Это может быть
полезно для быстрого удаления телефонных номеров, не соответствующих
длине. Так что используйте это на свой страх и риск.
Извлечение и форматирование телефонных номеров с помощью телефонных номеров Python
Пользовательский ввод - не единственный способ получить или собрать
телефонные номера. Например, у вас может быть паук / краулер, который
будет читать определенные страницы с веб-сайта или документа и извлекать
номера телефонов из текстовых блоков. Это звучит как сложная проблема,
но, к счастью, библиотека Phonenumbers предоставляет нам только
необходимые функции с помощью PhoneNumberMatcher(text, region)
.
PhoneNumberMatcher
принимает текстовый блок и область в качестве
аргумента, а затем выполняет PhoneNumberMatch
чтобы вернуть
соответствующие результаты в виде объектов PhoneNumberMatch.
Давайте использовать PhoneNumberMatcher
со случайным текстом:
import phonenumbers
text_block = "Our services will cost about 2,200 USD and we will deliver the product by the 10.10.2021. For more information, you can call us at +44 7986 123456 or send an e-mail to [email protected] "
for match in phonenumbers.PhoneNumberMatcher(text_block, "GB"):
print(match)
Это напечатает совпадающие телефонные номера вместе с их индексом в строке:
PhoneNumberMatch [131,146) +44 7986 123456
Возможно, вы заметили, что наш номер отформатирован в стандартизованном международном формате и разделен пробелами. Это может быть не всегда так в реальных сценариях. Вы можете получить свой номер в других форматах, например, разделенный тире или отформатированный в национальном (вместо международного) формате.
Давайте PhoneNumberMatcher()
с другими форматами телефонных номеров:
import phonenumbers
text_block = "Our services will cost about 2,200 USD and we will deliver the product by the 10.10.2021. For more information you can call us at +44-7986-123456 or 020 8366 1177 send an e-mail to [email protected] "
for match in phonenumbers.PhoneNumberMatcher(text_block, "GB"):
print(match)
Это выведет:
PhoneNumberMatch [130,145) +44-7986-123456
PhoneNumberMatch [149,162) 020 8366 1177
Несмотря на то, что номера телефонов встроены глубоко в текст с
различными форматами с другими номерами, PhoneNumberMatcher
успешно
возвращает номера телефонов с большой точностью.
Помимо извлечения данных из текста, мы также можем захотеть получить
цифры по одной от пользователя. Представьте, что пользовательский
интерфейс вашего приложения работает аналогично современным мобильным
телефонам и форматирует номера телефонов по мере ввода. Например, на
своей веб-странице вы можете передавать данные в свой API с каждым
onkeyup
и использовать AsYouTypeFormatter()
для форматируйте
телефонный номер с каждой входящей цифрой.
Поскольку часть пользовательского интерфейса выходит за рамки этой
статьи, мы будем использовать базовый пример для AsYouTypeFormatter
.
Чтобы смоделировать форматирование на лету, давайте перейдем к
интерпретатору Python:
>>> import phonenumbers
>>> formatter = phonenumbers.AsYouTypeFormatter("TR")
>>> formatter.input_digit("3")
'3'
>>> formatter.input_digit("9")
'39'
>>> formatter.input_digit("2")
'392'
>>> formatter.input_digit("2")
'392 2'
>>> formatter.input_digit("2")
'392 22'
>>> formatter.input_digit("1")
'392 221'
>>> formatter.input_digit("2")
'392 221 2'
>>> formatter.input_digit("3")
'392 221 23'
>>> formatter.input_digit("4")
'392 221 23 4'
>>> formatter.input_digit("5")
'392 221 23 45'
Не весь пользовательский ввод происходит по мере ввода. В некоторых формах есть простые поля для ввода текста для телефонных номеров. Однако это не обязательно означает, что мы будем вводить данные в стандартном формате.
Библиотека Phonenumbers также предоставила нам format_number()
. Этот
метод позволяет нам преобразовать телефонные номера в три хорошо
известных стандартизованных формата. Национальный, Международный и E164.
Национальные и международные форматы говорят сами за себя, в то время
как формат E164 - это международный формат телефонных номеров, который
гарантирует, что номера телефонов ограничены 15 цифрами и имеют формат
{+} {код страны} {номер с кодом города} . Для получения дополнительной
информации о E164 вы можете проверить эту страницу в
Википедии .
Начнем с национального форматирования:
import phonenumbers
my_number = phonenumbers.parse("+40721234567")
national_f = phonenumbers.format_number(my_number, phonenumbers.PhoneNumberFormat.NATIONAL)
print(national_f)
Это вернет строку номера телефона с красивым интервалом в национальном формате:
0721 234 567
Теперь попробуем отформатировать национальный номер как международный:
import phonenumbers
my_number = phonenumbers.parse("0721234567", "RO") # "RO" is ISO Alpha-2 code for Romania
international_f = phonenumbers.format_number(my_number, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
print(international_f)
Приведенный выше код вернет строку с номером телефона с аккуратным интервалом:
+40 721 234 567
Обратите внимание, что мы передали "RO"
в качестве второго параметра в
метод parse()
. Поскольку введенный номер является национальным
номером, он не имеет префикса кода страны, который указывал бы на
страну. В этих случаях нам нужно указать страну с ее кодом ISO Alpha-2,
чтобы получить точный результат. Исключение числового кода страны и кода
страны ISO Alpha-2 вызовет исключение
NumberParseException: (0) Missing or invalid default region.
.
Теперь попробуем E164
форматирования E164. В качестве входных данных
мы передадим национальную строку:
import phonenumbers
my_number = phonenumbers.parse("0721234567", "RO")
e164_f=phonenumbers.format_number(my_number, phonenumbers.PhoneNumberFormat.E164)
print(e164_f)
Результат будет очень похож на PhoneNumberFormat.INTERNATIONAL
, за
исключением пробелов:
+40721234567
Это очень полезно, если вы хотите передать число в фоновый API. API-интерфейсы нередко ожидают, что телефонные номера будут строками без пробелов.
Получить дополнительную информацию о номере телефона
В телефонный номер загружены данные о пользователе, который может вас заинтересовать. Вы можете использовать разные API или конечные точки API в зависимости от оператора связи с конкретным номером телефона, поскольку это играет роль в стоимости продукта. Возможно, вы захотите отправить свои рекламные уведомления в зависимости от часового пояса вашего клиента (номера телефона), чтобы вы не отправляли им сообщение посреди ночи. Или вы можете захотеть получить информацию о местонахождении номера телефона, чтобы вы могли предоставить соответствующую информацию. Библиотека Phonenumbers предоставляет необходимые инструменты для удовлетворения этих потребностей.
Для начала воспользуемся методом description_for_number()
из класса
geocoder
Этот метод принимает в качестве параметров проанализированный
номер телефона и короткое название языка.
Давайте попробуем это с нашим предыдущим фальшивым номером:
import phonenumbers
from phonenumbers import geocoder
my_number = phonenumbers.parse("+447986123456")
print(geocoder.description_for_number(my_number, "en"))
Это распечатает страну происхождения телефонного номера:
United Kingdom
Краткие названия языков довольно интуитивно понятны. Попробуем получить вывод на русском языке:
import phonenumbers
from phonenumbers import geocoder
my_number = phonenumbers.parse("+447986123456")
print(geocoder.description_for_number(my_number, "ru"))
А вот результат, в котором по-русски написано Великобритания:
Соединенное Королевство
Вы можете попробовать его с другими языками по вашему выбору, такими как «de», «fr», «zh» и т. Д.
Как упоминалось ранее, вы можете сгруппировать свои телефонные номера по их операторам связи, поскольку в большинстве случаев это повлияет на стоимость. Чтобы уточнить, библиотека Phonenumbers, вероятно, предоставит большинство имен операторов точно, но не на 100%.
Сегодня в большинстве стран можно получить свой номер у одного оператора связи, а затем перенести тот же номер на другого оператора, оставив при этом номер телефона неизменным. Поскольку Phonenumbers - это просто автономная библиотека Python, эти изменения невозможно обнаружить. Поэтому лучше рассматривать названия операторов как справку, а не как факт.
Мы будем использовать метод name_for_number()
из класса carrier
import phonenumbers
from phonenumbers import carrier
my_number = phonenumbers.parse("+40721234567")
print(carrier.name_for_number(my_number, "en"))
Если возможно, отобразится исходный оператор телефонного номера:
Vodafone
Примечание . Как указано в исходных документах Python Phonenumbers, информация о операторах связи доступна для мобильных номеров в некоторых странах, а не во всех.
Еще одна важная информация о номере телефона - это часовой пояс. Метод
time_zones_for_number()
вернет список часовых поясов, которым
принадлежит номер. Мы импортируем его из phonenumbers.timezone
:
import phonenumbers
from phonenumbers import timezone
my_number = phonenumbers.parse("+447986123456")
print(timezone.time_zones_for_number(my_number))
Это напечатает следующие часовые пояса:
('Europe/Guernsey', 'Europe/Isle_of_Man', 'Europe/Jersey', 'Europe/London')
На этом мы завершаем наше руководство по телефонным номерам Python.
Заключение
Мы узнали, как анализировать телефонные номера с помощью parse()
,
извлекать числа из текстовых блоков с помощью PhoneNumberMatcher()
,
получать номера телефонов по цифрам и форматировать их с помощью
AsYouTypeFormatter()
, использовать различные методы проверки с
is_possible_number()
и is_possible_number()
, форматируйте числа с
помощью NATIONAL
, INTERNATIONAL
и E164
и извлекайте
дополнительную информацию из номеров телефонов с помощью классов
geocoder
, carrier
и timezone
Не забудьте проверить исходный репозиторий библиотеки Phonenumbers на GitHub . Также, если у вас есть какие-либо вопросы, не стесняйтесь комментировать ниже.