Статья Получаем общедоступные данные по номеру телефона с помощью Python

Можно ли по номеру телефона узнать местоположение абонента? Безусловно, да. Тут нужно правильно задать вопрос: «Кому это можно сделать?» К сожалению, ответ для нас с вами не особо утешителен.

- Есть варианты за деньги, то есть оплачиваешь тарифный план и пользуешься. Как правило, такие сервисы предоставляют данные на основе HLR-запросов.
- Есть вариант хакнуть сеть сигнализации SS7. Но, тут уж как звезды сойдутся. Да и не получиться это сделать у любого человека с улицы. У вас должен быть выход в эту сеть, плюс к тому возможность формировать любые сообщения сигнализации, а также в сети не должно быть фильтрации некорректных или подозрительных сообщений SS7.
- И как вариант, запрос правоохранительных органов.

Если вы не нашли своего состояния в данных описаниях, то скорее всего просто так получить данные у вас не получиться.

000.png



Получение местонахождения мобильного телефона

Первый – это получение примерного местонахождения с помощью HLR-запроса отправленного в СМС-центр. Подробнее о данном способе можно поискать информацию в интернете, да и наверняка вы видели рекламу сервисов предоставляющих эту услугу. Здесь есть подводные камни. Не всегда можно получить данные с высокой точностью. Вернее даже, о точности тут речь не ведется. Если город достаточно крупный, то возможно у вас получиться улучшить результаты. Если же нет, тут уж как повезет. У многих операторов коммутаторы расположены не в тех городах, где находиться абонент, а где-нибудь в другом городе, откуда данный коммутатор и обслуживает всех абонентов. Ведь вспомните, когда вы разрешаете сервисам геолокации определить ваше местонахождение, то есть без использования GPS, то ваше местоположение зачастую определяется неправильно. У меня, например, всегда разные результаты.

А вот в Европе с этим получше. Там коммутаторы установлены в каждом областном центре и крупном городе. А потому, информация, полученная с данных коммутаторов будет намного выше и позволит даже отследить перемещение телефона из соты в соту.

Второй способ – каким-то чудесным образом получить IP-адрес сотового телефона. В этом может помочь сниффер. Но такой способ тоже полон недостатков. Для начала, этот способ поможет получить город, но не точное местоположение. Ну и потом, те сервисы, что предоставляют информацию, не всегда обладают достаточно полной базой, чтобы определить геопозицию по IP.

Еще один способ, получить ваше местоположение с помощью технологии HTML5 Geolocation. Тут уже точность повыше. Так как используется как вычисление до положения на основе близости от вышки оператора, так и получение GPS-координат. Так же возможно получение местоположения, если вы подключены к какому-либо из публичных Wi-Fi. Тут все зависит от того, есть ли Wi-Fi на общедоступной карте размещения роутеров. Ну и используется также получение местоположения по IP. То есть, некая совокупность способов. Однако, это доступно для телефона. А не для человека, который просто запросил данные по номеру.

Лучше всего вас могут найти сотовые операторы, которые вычисляют ваше местоположение методом триангуляции. Здесь уже точность обнаружения может варьироваться до 50-ти метров. Этими же данными пользуются правоохранительные органы, которые запрашивают их у операторов.

Ну и еще один способ – банальный обман пользователя. Если вы зададитесь целью и поищете, то найдете массу сервисов подобного толка. Здесь вам будет предлагаться ввести номер телефона и протестировать данную услугу. Вот только не думайте, что это можно проделать несколько раз. Если бы все было так просто, то этими сервисами пользовались бы все. И нужды в особых услугах не было бы. Но, тут, специально для вас изобразят бурный поиск данных, после чего определят примерное местонахождение, которое в лучшем случае покажет область регистрации телефона. Все остальные данные будут якобы доступны после регистрации и оплаты тарифного плана. Но, увы, это не так. Главное здесь, заставить вас заплатить. А все остальное – это уже ваши проблемы.

А что же с питоном? Можно ли с его помощью установить местонахождение? Тут все довольно просто. Конечно же, если вы ОпСоС, то вам возможно все. В пределах вашей сети, конечно. А то и дальше. Но, нам, простым смертным доступно не так много опций. Давайте напишем небольшой скрипт, который будет получать те данные, которые есть в общем доступе. А вот что для этого понадобиться, об этом немного ниже.

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


Что понадобиться?

Установить библиотеку phonenumbers. Делается это просто. Запустите терминал и введите команду:

pip install phonenumbers

В принципе, эта библиотека не особо нужна. Но, для обработки номеров отличных от российских она вполне пригодиться. Далее нужно скачать справочник Роснумерации. Лежит он в открытом доступе, но на момент написания статьи был недоступен. . Написано было, что проводятся технические работы. Поэтому я еще немного поискал и нашел данный справочник . На данной странице нас интересует «Выписка по диапазону 9xx», то есть, мобильных операторов связи. Предоставляется она в формате csv, а потому, я ее даже не стал переименовывать, а работал с тем, что скачалось. Ну и небольшой файлик в формате json, который я уже скомпоновал сам, из того, что было. В нем содержаться регионы и их часовые пояса. Для совместимости со справочником Роснумерации названия регионов такие же, как в нем. Я его выложу в прикрепленных файлах. А если не позволит размер, то размещу на Яндекс.Диске и дам ссылку на загрузку.


А теперь давайте писать код

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

Python:
import csv
import json

from phonenumbers.phonenumberutil import NumberParseException
from phonenumbers import parse
from phonenumbers import geocoder
from phonenumbers import timezone
from phonenumbers import carrier

Из нестандартного тут только библиотека phonenumbers, из которой пришлось импортировать модули по отдельности, но только лишь исключительно ради удобства. Давайте сегодня начнем с функции main(). В ней происходит начало действа с номерами телефонов.

Для начала печатается строка в которой говориться, что тут вообще происходит. Далее запрашивается номер телефона пользователя, который приводиться в нужный вид путем замещения всяких «лишних» символов. Впрочем, все предусмотреть невозможно. Если только поместить в список всю клавиатуру и заменять все, что не соответствует номеру телефона ))

Затем проверяется первый символ. Если это плюс, то смотрим дальше второй символ. И если это 7, то тогда вызываем функцию обработки российских номеров. Ну и так же для первого символа 8. Если же это не так, работу с номером передаем в цепкие лапы phonenumbers.

Python:
def main():
    print('\n* ИНФОРМАЦИЯ О НОМЕРЕ ТЕЛЕФОНА. РЕГИОН, ОПЕРАТОР И ЧАСОВОЙ ПОЯС *\n')
    phone = input('Введите номер >>> ').replace("-", "").replace("(", "").replace(")", "").replace(" ", "")
    if phone[0:1] == "+":
        if phone[1:2] == "7":
            russia_num(phone)
        else:
            phnum_parse(phone)
    elif phone[0:1] == "8":
        russia_num(phone)
    else:
        phnum_parse(phone)

Следующей будет функция обработки российских номеров. Я назвал ее russia_num(phone) и на вход она принимает номер телефона. Тут идет проверка первого и третьего символа в случае с плюсом и первого и второго в случае с восьмеркой. Нужно это для того, чтобы разделить номер телефона на части, которые и будут участвовать в проверке.

Дело в том, что номер телефона, после +7 или 8, что является кодом страны, содержит в себе еще и зону нумерации, которая состоит из трех цифр. Как раз таки вот эти вот 913, 905 и прочие. А дальше идет собственно сам номер телефона. Вот их то и будет проверять.

Структура загруженного справочника такова, что в нем содержится в первом столбце зона нумерации, во втором и третьем диапазон номеров для данной зоны. Дальше идет емкость, которая нам не нужна, а после оператор, регион и ИНН оператора. Вот оператора и регион мы будем забирать. Итак, из данного справочника необходимо забрать зону нумерации, диапазон, оператора и регион.

screenshot5.png

Вернемся к коду. На основании плюса или восьмерки забираем зону нумерации. Здесь еще делается проверка на то, идет после 7-ки или 8-ки девятка. Так как в Казахстане, к примеру, номера так же могут начинаться на +7. Что приведет к ошибке. И если все в порядке, и девятка обнаружена, вызывается функция распарсивания csv. Если же нет, номер телефона передается библиотеке phonenumbers.

Python:
def russia_num(phone):
    if phone[0:1] == "+" and phone[2:3] == "9":
        num_one = phone[2:5]
        two_num = phone[5:]
        csv_read(num_one, two_num, phone)
    elif phone[0:1] == "8" and phone[1:2] == "9":
        num_one = phone[1:4]
        two_num = phone[4:]
        csv_read(num_one, two_num, phone)
    else:
        phnum_parse(phone)

Теперь код функции обработки номера с помощью библиотеки phonenumbers. Назвал функцию phnum_parse(phone). На вход она принимает номер телефона. Уж, почему у функции такое странное название не помню. Наверняка, на момент, когда я ее обзывал, оно что-то значило.

Для начала с помощью функции parse распарсиваем номер телефона. Справиться она может далеко не со всеми номерами. К примеру, вообще не работает с номерами Армении и еще какой-то страны, код которых начинается с 0. Но это частности. Тем не менее, функция падает в осадок, а потому надо этот осадок поймать. Заключаем распарсивание номера в блок try-except. Ну и если что-то не так, возвращаем принт о неправильном регионе и катапультируемся из функции вообще. Если же все в порядке, идем дальше. А дальше определяем часовой пояс с помощью timezone.time_zones_for_number, в которую передаем распарсенный номер телефона. Затем определяем регион или страну. Тут уже по-разному. В geocoder.description_for_number передаем номер телефона и указываем обязательный параметр – язык вывода результата. У меня стоит русский.

Определяем оператора carrier.name_for_number, в которого так же передаем распарсенный номер телефона и язык вывода. А дальше проверяем, не является ли одна из переменных с пустым значением, так как иногда оператор не определяется или другой параметр. Вместо них подставляем Unknown. Исключение пришлось сделать только для часового пояса, так как это значение заменить не получалось. Потому пришлось указать полный принт. После этого принта функция завершается. Если же нет, то переходит к принту уже с полными или замененными параметрами.

Python:
def phnum_parse(phone):
    try:
        ph_parse = parse(phone)
    except NumberParseException:
        print('[-] Неправильный регион')
        return
    ph_timezone = timezone.time_zones_for_number(ph_parse)
    ph_region = geocoder.description_for_number(ph_parse, 'ru')
    ph_prov = carrier.name_for_number(ph_parse, 'ru')
    if ph_prov == "":
        ph_prov = "Unknown"
    elif ph_region == "":
        ph_region = "Unknown"
    elif ph_timezone[0] == "":
        print(f'\n[+] Информация о номере: {phone}:\n    - Провайдер (ОпСоС): {ph_prov}\n    '
              f'- Регион: {ph_region}\n    - Часовой пояс: Unknown')
        return
    print(f'\n[+] Информация о номере: {phone}:\n    - Провайдер (ОпСоС): {ph_prov}\n    '
          f'- Регион: {ph_region}\n    - Часовой пояс: {ph_timezone[0]}')

Ну и, собственно, распарсивание csv. Я так эту функцию и назвал csv_read(zone, number, phone). В нее передается зона нумерации, номер телефона и полный номер, который мы получили после ввода. Сначала я его передавать не хотел, а хотел собрать из того, что есть. А потом подумал, что так будет при печати покрасивее ))

Итак, поехали. Открываем и читаем файл json с часовыми поясами. Затем отрываем справочник Роснумерации и тоже читаем. В цикле пробегаемся по нему, где делаем проверки. Первая проверка это на нулевую строку. В ней содержаться заголовки. А они нам совершенно не нужны, потому мы их просто пропускаем. Затем пилим полученную строку по точке с запятой и забираем нулевой элемент. Если вы помните, то в справочнике здесь лежит зона нумерации. Сравниваем ее с той, что в номере телефона. Если не она, идем дальше. Ах, да, чуть не забыл. Здесь еще и проверяется одновременным условием and, входит ли номер в диапазон, если все же зона нумерации совпадает. Ну и так до самого совпадения. После чего в цикле забирается информация о часовом поясе, если она есть в json и все это добро печатается в терминал. С или без часового пояса.

Python:
def csv_read(zone, number, phone):
    with open('zone.json', 'r', encoding='utf-8') as f:
        zone_t = json.load(f)
    with open("DEF-9xx.csv", "r", encoding='utf-8') as f:
        reader = csv.reader(f, delimiter="\t")
        for i, line in enumerate(reader):
            if i != 0:
                if line[0].split(";")[0] == zone and \
                        [k for k in range(int(line[0].split(";")[1]), int(line[0].split(";")[2])) if int(number) == k]:
                    prov = line[0].split(";")[4]
                    region = line[0].split(";")[5].strip()
                    try:
                        for z in zone_t:
                            if region in z:
                                time_zone = z[region]
                        print(f'\n[+] Информация о номере: {phone}:\n    - Провайдер (ОпСоС): {prov}\n    '
                              f'- Регион: {region}\n    - Часовой пояс: {time_zone}')
                        return
                    except KeyError:
                        print(f'\n[+] Информация о номере: {phone}:\n    - Провайдер (ОпСоС): {prov}\n    '
                              f'- Регион: {region}')
                        return

Вот, в принципе и все. Как видите, информации не густо. И это то, что можно получить, не прибегая ни к каким уловкам. Все остальное, это уже проверки в базах утечек или в гетконтактах. Это немного не то. А вот именно та информация, которая общедоступная, по большей части вся. Ну да, тут еще можно было выкорчевать ИНН оператора. Но он, наверное, не нужен.

Понятно дело, что я мог что-то упустить или недоглядеть, так как не претендую на полноту информации. Если да, то подскажите. С удовольствием покопаю в этом направлении.

Python:
# pip install phonenumbers

import csv
import json

from phonenumbers.phonenumberutil import NumberParseException
from phonenumbers import parse
from phonenumbers import geocoder
from phonenumbers import timezone
from phonenumbers import carrier


def russia_num(phone):
    if phone[0:1] == "+" and phone[2:3] == "9":
        num_one = phone[2:5]
        two_num = phone[5:]
        csv_read(num_one, two_num, phone)
    elif phone[0:1] == "8" and phone[1:2] == "9":
        num_one = phone[1:4]
        two_num = phone[4:]
        csv_read(num_one, two_num, phone)
    else:
        phnum_parse(phone)


def csv_read(zone, number, phone):
    with open('zone.json', 'r', encoding='utf-8') as f:
        zone_t = json.load(f)
    with open("DEF-9xx.csv", "r", encoding='utf-8') as f:
        reader = csv.reader(f, delimiter="\t")
        for i, line in enumerate(reader):
            if i != 0:
                if line[0].split(";")[0] == zone and \
                        [k for k in range(int(line[0].split(";")[1]), int(line[0].split(";")[2])) if int(number) == k]:
                    prov = line[0].split(";")[4]
                    region = line[0].split(";")[5].strip()
                    try:
                        for z in zone_t:
                            if region in z:
                                time_zone = z[region]
                        print(f'\n[+] Информация о номере: {phone}:\n    - Провайдер (ОпСоС): {prov}\n    '
                              f'- Регион: {region}\n    - Часовой пояс: {time_zone}')
                        return
                    except KeyError:
                        print(f'\n[+] Информация о номере: {phone}:\n    - Провайдер (ОпСоС): {prov}\n    '
                              f'- Регион: {region}')
                        return


def phnum_parse(phone):
    try:
        ph_parse = parse(phone)
    except NumberParseException:
        print('[-] Неправильный регион')
        return
    ph_timezone = timezone.time_zones_for_number(ph_parse)
    ph_region = geocoder.description_for_number(ph_parse, 'ru')
    ph_prov = carrier.name_for_number(ph_parse, 'ru')
    if ph_prov == "":
        ph_prov = "Uncnown"
    elif ph_region == "":
        ph_region = "Uncnown"
    elif ph_timezone[0] == "":
        print(f'\n[+] Информация о номере: {phone}:\n    - Провайдер (ОпСоС): {ph_prov}\n    '
              f'- Регион: {ph_region}\n    - Часовой пояс: Uncnown')
        return
    print(f'\n[+] Информация о номере: {phone}:\n    - Провайдер (ОпСоС): {ph_prov}\n    '
          f'- Регион: {ph_region}\n    - Часовой пояс: {ph_timezone[0]}')
  

def main():
    print('\n* ИНФОРМАЦИЯ О НОМЕРЕ ТЕЛЕФОНА. РЕГИОН, ОПЕРАТОР И ЧАСОВОЙ ПОЯС *\n')
    phone = input('Введите номер >>> ').replace("-", "").replace("(", "").replace(")", "").replace(" ", "")
    if phone[0:1] == "+":
        if phone[1:2] == "7":
            russia_num(phone)
        else:
            phnum_parse(phone)
    elif phone[0:1] == "8":
        russia_num(phone)
    else:
        phnum_parse(phone)
  

if __name__ == "__main__":
    main()

P.S.: Одно время ездил по вахтам и у меня много накопилось номеров телефонов. Да и так, самых разных, со временем. Когда сделал скрипт, сидел, баловался, определял регион и оператора :LOL:

Спасибо за внимание. Надеюсь, что данная информация будет кому-нибудь полезной
 

Вложения

  • zone.zip
    1,7 КБ · Просмотры: 1 434

Johan Van

Green Team
13.06.2020
363
691
BIT
395
Спасибо. Это будет благородно с вашей стороны.
Думаю, я многому у вас научусь.

В общем, я тут немного посидел, подумал, и вот, что у меня получилось...

Во вложении к ответу будут три версии файла:
- Первая версия - это собственно вчерашняя, то есть, практически оригинальная;
- Вторая версия - это переделанная логика без потоков;
- Третья версия - то же самое, что и вторая, но с использованием потоков.

У меня нет большого количества номеров, а фейкер заводить неохота. В общем, тестировал на том, что нашел.
Нашел я порядка 130 номеров. Конечно, для полноценного теста маловато, но да ладно.
Тестировал на одном и том же файле все три версии.

Скрины:

Первая версия (время проверки номеров):

01_orig_time.png


Вторая версия (время проверки номеров):

02_without_threads.png


Третья версия (время проверки номеров):

03_with_threads.png


Как видно, здесь по скорости третья версия, с потоками не особо выделилась. Но, думаю,
что если у вас будет большой массив номеров, то скорость будет различаться.

Такие вот дела. Код во вложении.

Ну и да, фоннамберс можете выпилить. Я его оставил, так, на всякий случай. Потому как если вы его совсем выпилите, вам нужно
будет написать обработку ошибок для тех номеров, которые не попадут под российские.
 

Вложения

  • zone_03.zip
    100,8 КБ · Просмотры: 121
  • zone_02.zip
    100,7 КБ · Просмотры: 114
  • zone_01.zip
    100,2 КБ · Просмотры: 113
Последнее редактирование:
  • Нравится
Реакции: UnnamedUser и bigsky

Johan Van

Green Team
13.06.2020
363
691
BIT
395
Спасибо. Это будет благородно с вашей стороны.
Думаю, я многому у вас научусь.

Сделал версии без фоннамбера. Добавил список, куда будут складываться нераспознанные номера, а потом сохраняться в текстовый документ.
 

Вложения

  • zone_02_no_ph.zip
    100,6 КБ · Просмотры: 123
  • zone_03_no_ph_thread.zip
    100,8 КБ · Просмотры: 149
  • Нравится
Реакции: bigsky

bigsky

Member
09.12.2020
8
0
BIT
0
@Johan Van, Большое спасибо за Ваш труд 🤝
Обязательно предоставлю обратную связь о коде.
 

bigsky

Member
09.12.2020
8
0
BIT
0
@Johan Van, Здравствуйте.
Код из архива zone_03_no_ph_thread.zip работает потрясающе – высокая скорость. Спасибо за Ваш труд.

@Johan Van, как будет выглядеть код файла phone_no_ph_thread.py из архива zone_03_no_ph_thread.zip для работы только с номерами российских операторов если:
1. номера в файле numbers.txt будут только такого формата/вида:
79230041595
79230910795
79237860404
79230542647
79231751758
79232679465
79239556508
79235545728
79236188444
79233044905
2. от кода файла phone_no_ph_thread.py нужно только определение оператора связи.
3. в файл numbers_find.txt нужен вывод только операторов связи каждого номера, а если определение оператора номера не возможно, то вместо него была строка "– – –"
ПАО "МегаФон"
ПАО "МегаФон"
ПАО "МегаФон"
– – –
ПАО "МегаФон"
ПАО "МегаФон"
– – –
ПАО "МегаФон"
4. вывод нераспознанных номеров в файл unknown_number.txt не нужен, потому как они будут в файле numbers_find.txt в виде "– – –"
 

Johan Van

Green Team
13.06.2020
363
691
BIT
395
@Johan Van, Здравствуйте.
Код из архива zone_03_no_ph_thread.zip работает потрясающе – высокая скорость. Спасибо за Ваш труд.

@Johan Van, как будет выглядеть код файла phone_no_ph_thread.py из архива zone_03_no_ph_thread.zip для работы только с номерами российских операторов если:
1. номера в файле numbers.txt будут только такого формата/вида:
79230041595
79230910795
79237860404
79230542647
79231751758
79232679465
79239556508
79235545728
79236188444
79233044905
2. от кода файла phone_no_ph_thread.py нужно только определение оператора связи.
3. в файл numbers_find.txt нужен вывод только операторов связи каждого номера, а если определение оператора номера не возможно, то вместо него была строка "– – –"
ПАО "МегаФон"
ПАО "МегаФон"
ПАО "МегаФон"
– – –
ПАО "МегаФон"
ПАО "МегаФон"
– – –
ПАО "МегаФон"
4. вывод нераспознанных номеров в файл unknown_number.txt не нужен, потому как они будут в файле numbers_find.txt в виде "– – –"

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

Если вам данный код нужен для выполнения какой-то работы, то рекомендую разобраться в его работе, чтобы иметь возможность самому исправлять возникающие неполадки или вносить изменения в код по мере необходимости. Тем более, что данный код не выглядит довольно сложным.

Я конечно же могу сделать то, что вы здесь написали, но вы только представьте, если я буду делать все то, что меня просят просто так, то все мое время будет уходить на выполнение, как вам кажется, небольших, но отнимающих определенное время заданий. Вопрос в том, а зачем это мне? Я же не настолько "добрый самаритянин". Да, я могу что-то подсказать, но выполнять все, так, как вам этого захотелось в данный момент, просто потому, что один раз вам пошли навстречу... без обид, мне не особо нужно.

Цель статьи не в том, чтобы дать вам готовое решение. Хотя, кому-то оно будет достаточным в том виде, в котором есть. А в том, чтобы натолкнуть вас на мысль о том, что можно сделать так-то и так-то. Переделка кода под ваши нужны - это уже задача только ваша.

Я понимаю ваше желание сделать код. Но поймите и меня. У меня есть другие дела и постоянно решать задачи не всегда представляется возможным. Как-то так. Извините, если обидел.
 
  • Нравится
Реакции: f22, UnnamedUser и bigsky

Johan Van

Green Team
13.06.2020
363
691
BIT
395
@Johan Van, Здравствуйте.
Код из архива zone_03_no_ph_thread.zip работает потрясающе – высокая скорость. Спасибо за Ваш труд.

@Johan Van, как будет выглядеть код файла phone_no_ph_thread.py из архива zone_03_no_ph_thread.zip для работы только с номерами российских операторов если:
1. номера в файле numbers.txt будут только такого формата/вида:
79230041595
79230910795
79237860404
79230542647
79231751758
79232679465
79239556508
79235545728
79236188444
79233044905
2. от кода файла phone_no_ph_thread.py нужно только определение оператора связи.
3. в файл numbers_find.txt нужен вывод только операторов связи каждого номера, а если определение оператора номера не возможно, то вместо него была строка "– – –"
ПАО "МегаФон"
ПАО "МегаФон"
ПАО "МегаФон"
– – –
ПАО "МегаФон"
ПАО "МегаФон"
– – –
ПАО "МегаФон"
4. вывод нераспознанных номеров в файл unknown_number.txt не нужен, потому как они будут в файле numbers_find.txt в виде "– – –"

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

001.png


002.png



Python:
import csv
import json
import sys
import time
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path

def_9xx = dict()
zone_t = dict()
number_info = []


def russia_num(phone: str):
    # Делаем проверку: если номера начинаются на 7 или 8, а следующая цифра 9,
    # будем считать, что это российский номер. Запускаем функцию поиска оператора.
    if phone[0:1] in ["8", "7"] and phone[1:2] == "9":
        zone_find(phone[1:4], phone[4:], phone)
    # Здесь проверяем те номера, которые начинаются на +, так как порядок цифр,
    # за счет добавления "+" немного другой. То есть, если обратите внимание,
    # в функцию поиска оператора передаются несколько другие срезы.
    elif phone[0:1] == "+" and phone[2:3] == "9":
        zone_find(phone[2:5], phone[5:], phone)
    # Добавляем те номера, которые не прошли проверку на российские в список,
    # как неопределенные.
    else:
        number_info.append(f'{phone}: "---"')


def zone_find(zone: str, number: str, phone: str):
    global def_9xx, zone_t, number_info
    # Итерируемся по словарю из csv. Проверяем, не равна ли переданная в функцию зона
    # текущему значению в словаре. Если равна, итерируемся по значениям, которые представляют собой также словарь,
    # ключами в котором являются диапазоны операторов, так как это уникальные значения, а значениями оператор
    # и регион.
    for zn in def_9xx:
        if zone == zn:
            for rng in def_9xx[zn]:
                # Проверяем, входит ли номер телефона в диапазон оператора. Если нет, двигаемся дальше.
                # Если входит, забираем оператора (провайдера), получаем из него регион, забираем из словаря
                # временную зону и выводим все это в терминал. Также добавляем номер телефона и оператора
                # в список с определенными операторами.
                if int(number) in range(int(rng.split(",")[0]), int(rng.split(",")[1])):
                    try:
                        print(f'\n[+] Информация о номере: {phone}:\n    - Провайдер (ОпСоС): '
                              f'{def_9xx[zn][rng].split(",")[0].strip()}\n    '
                              f'- Регион: {def_9xx[zn][rng].split(",")[1].strip()}\n    - Часовой пояс: '
                              f'{zone_t[def_9xx[zn][rng].split(",")[1].strip()]}')
                        number_info.append(f'{phone}: {def_9xx[zn][rng].split(",")[0].strip()}')
                        return
                    except KeyError:
                        print(f'\n[+] Информация о номере: {phone}:\n    - Провайдер (ОпСоС): '
                              f'{def_9xx[zn][rng].split(",")[0].strip()}\n    '
                              f'- Регион: {def_9xx[zn][rng].split(",")[1].strip()}')
                        number_info.append(f'{phone}: {def_9xx[zn][rng].split(",")[0].strip()}')
                        return
    number_info.append(f'{phone}: "---"')


def conv():
    # Здесь открываем файл csv, перебираем его построчно, делим каждую строку
    # и добавляем в словарь, ключом к каждому разделу будет зона, то есть, 900 и т.д.
    global def_9xx
    with open(Path.cwd() / 'guides' / 'DEF-9xx.csv', "r", encoding='utf-8') as f:
        readers = csv.reader(f, delimiter="\t")
        for num, line in enumerate(readers):
            if num != 0:
                ln = line[0].split(";")
                if ln[0] not in def_9xx:
                    def_9xx[ln[0]] = dict()
                opsos = f'{ln[4]}, {ln[5]}'
                rng = f'{ln[1]},{ln[2]}'
                def_9xx[ln[0]].update({rng: opsos})


def main():
    global zone_t, number_info

    # Проверяем наличие словаря с временными зонами. Если его нет - завершаем работу.
    # Если словарь есть, открываем его и добавляем содержимое в словарь, который определен
    # глобально. То есть, содержимое словаря будет находиться в памяти для ускорения поиска данных.
    if not (Path.cwd() / 'guides' / 'zone.json').exists():
        print("Отсутствует справочник с временными зонами 'zone.json'")
        sys.exit(0)
    with open(Path.cwd() / 'guides' / 'zone.json', 'r', encoding='utf-8') as f:
        zone_t.update(json.load(f))

    # Производим проверку на наличие файла с диапазонами. Если его нет - завершаем работу.
    # Если файл есть, запускаем функцию для конвертации csv в словарь.
    if not (Path.cwd() / 'guides' / 'DEF-9xx.csv').exists():
        print("Отсутствует справочник с диапазонами номеров операторов 'DEF-9xx.csv'")
        sys.exit(0)
    conv()

    # Запрашиваем у пользователя путь к файлу с номерами. Если путь неверный - выходим из скрипта.
    # В переменную t присваиваем текущее время. Это нужно, чтобы определить время работы.
    path = input("Введите путь к файлу с номерами: ")
    t = time.monotonic()
    if not Path(path).exists() or not Path(path).is_file() or not path:
        print("Введенного пути не существует")
        sys.exit(0)

    # Выводим в терминал сообщение. Открываем файл с номерами телефона.
    # Итерируемся по файлу построчно. Очищаем от скобок, пустых мест и тире.
    # Проверяем первый знак. Если он +, проверяем второй - если 7, значит - Россия.
    # Запускаем поток, который запускает функцию russia_num и передает в нее номер.
    # Если номер начинается с 7 или 8, тоже считаем, что это Россия и,
    # запускаем поток, который запускает функцию russia_num и передает в нее номер.
    # Если же номер не определен, как российский и не принадлежит сотовым операторам,
    # в рамках текущего скрипта он определен не будет. Добавляем его в список с неопределенным оператором.
    print('\n* ИНФОРМАЦИЯ О НОМЕРЕ ТЕЛЕФОНА. РЕГИОН, ОПЕРАТОР И ЧАСОВОЙ ПОЯС *\n')
    with open(path, 'r', encoding='utf-8') as file:
        with ThreadPoolExecutor(max_workers=5) as executor:
            for phone in file.readlines():
                phone = phone.replace("-", "").replace("(", "").replace(")", "").replace(" ", "").strip()
                if phone[0:1] == "+":
                    if phone[1:2] == "7":
                        executor.submit(russia_num, phone=phone)
                elif phone[0:1] == "7":
                    executor.submit(russia_num, phone=phone)
                elif phone[0:1] == "8":
                    executor.submit(russia_num, phone=phone)
                else:
                    number_info.append(f'{phone}: "---"')

    # Проверяем, не пуст ли список с операторами. Если нет,
    # открываем файл на запись, итерируемся по списку с операторами
    # и добавляем в открытый файл элементы списка.
    # После выводим в терминал время работы функции.
    if number_info:
        with open('numbers_find.txt', 'w', encoding='utf-8') as fl:
            for item in number_info:
                fl.write(f'{item}\n')

    print(f'\nВремя поиска номеров: '
          f'{(int(time.monotonic() - t) // 3600) % 24:d} ч. '
          f'{(int(time.monotonic() - t) // 60) % 60:02d} м. '
          f'{int(time.monotonic() - t) % 60:02d} с.')
    print(time.monotonic() - t)


if __name__ == "__main__":
    main()

ну и да, номера начинающиеся с 7 тоже принимаются теперь нормально.
В теории, думаю, что можно было бы также проверять и номера не сотовых операторов, загрузив соответствующий файл с сайта.

003.png


Как видите, здесь широкое поле для деятельности. Нужно только добавить в код формирование словарей из csv и проверку по сформированным словарям. Алгоритм, думаю, будет похожим.
 
Последнее редактирование:
  • Нравится
Реакции: f22 и bigsky

bigsky

Member
09.12.2020
8
0
BIT
0
Я конечно извиняюсь, но вы уже мне просто техзадание какое-то даете. Что выходит за рамки простой взаимопомощи. Все, что вы сейчас описали, вы можете сделать самостоятельно, достаточно лишь подправить добавление данных в список. Ну и, собственно, если вывод не нужен, можете просто убрать эту часть.

Если вам данный код нужен для выполнения какой-то работы, то рекомендую разобраться в его работе, чтобы иметь возможность самому исправлять возникающие неполадки или вносить изменения в код по мере необходимости. Тем более, что данный код не выглядит довольно сложным.

Я конечно же могу сделать то, что вы здесь написали, но вы только представьте, если я буду делать все то, что меня просят просто так, то все мое время будет уходить на выполнение, как вам кажется, небольших, но отнимающих определенное время заданий. Вопрос в том, а зачем это мне? Я же не настолько "добрый самаритянин". Да, я могу что-то подсказать, но выполнять все, так, как вам этого захотелось в данный момент, просто потому, что один раз вам пошли навстречу... без обид, мне не особо нужно.

Цель статьи не в том, чтобы дать вам готовое решение. Хотя, кому-то оно будет достаточным в том виде, в котором есть. А в том, чтобы натолкнуть вас на мысль о том, что можно сделать так-то и так-то. Переделка кода под ваши нужны - это уже задача только ваша.

Я понимаю ваше желание сделать код. Но поймите и меня. У меня есть другие дела и постоянно решать задачи не всегда представляется возможным. Как-то так. Извините, если обидел.
@Johan Van,
приблизительно такой ответ от Вас был ожидаем, потому как я злоупотребила Вашим радушием.
Вы действительно уже сделали большой объём работы по этому вопросу. От меня Вам бесконечная благодарность за это. Как дань уважения, я постараюсь разобраться в коде и доработать его под мои задачи. Я обязательно поделюсь с Вами полученным результатом, если осилю поставленную перед собой задачу.
 

Johan Van

Green Team
13.06.2020
363
691
BIT
395
@Johan Van,
приблизительно такой ответ от Вас был ожидаем, потому как я злоупотребила Вашим радушием.
Вы действительно уже сделали большой объём работы по этому вопросу. От меня Вам бесконечная благодарность за это. Как дань уважения, я постараюсь разобраться в коде и доработать его под мои задачи. Я обязательно поделюсь с Вами полученным результатом, если осилю поставленную перед собой задачу.

Я код поправил. Посмотрите предыдущее сообщение. Просто, это для вас. на будущее. Для примера, скажу, что на Stack Overflow с вами бы даже не стали разговаривать, а сразу же заминусовали. Пока вы не предоставили бы код. Там не любят писать за вас решения, а именно подсказывают, если знают варианты решения проблемы. Вы же, действительно, попытались "злоупотребить", не попытавшись разобраться самостоятельно.
 
  • Нравится
Реакции: bigsky

Savlod

New member
14.08.2023
1
0
BIT
0
У меня один вопрос, поскольку я даже не знаю как это всё утроено, хоть подскажите как запустить это всё
 
27.10.2023
1
0
BIT
0
А что делать если выдает такую ошибку
Traceback (most recent call last):
File "C:\Users\никита\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Python 3.11\kod.py", line 86, in <module>
main()
File "C:\Users\никита\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Python 3.11\kod.py", line 76, in main
russia_num(phone)
File "C:\Users\никита\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Python 3.11\kod.py", line 17, in russia_num
csv_read(num_one, two_num, phone)
File "C:\Users\никита\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Python 3.11\kod.py", line 27, in csv_read
with open('zone.json', 'r', encoding='utf-8') as f:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'zone.json'
 

Johan Van

Green Team
13.06.2020
363
691
BIT
395
А что делать если выдает такую ошибку
Traceback (most recent call last):
File "C:\Users\никита\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Python 3.11\kod.py", line 86, in <module>
main()
File "C:\Users\никита\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Python 3.11\kod.py", line 76, in main
russia_num(phone)
File "C:\Users\никита\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Python 3.11\kod.py", line 17, in russia_num
csv_read(num_one, two_num, phone)
File "C:\Users\никита\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Python 3.11\kod.py", line 27, in csv_read
with open('zone.json', 'r', encoding='utf-8') as f:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'zone.json'

Скрипт просто не находит файл json. Нужно его скачать из статьи и положить в папку со скриптом. Вот ссылка на скачивание данного файла из статьи: https://codeby.net/attachments/zone-zip.60301/
 

vladka hgvnva

New member
02.01.2024
1
0
BIT
4
Отличный сервис smspoisk.ru , определял местоположение ребенка, как мне очень полезно это знать
 

bayland

One Level
13.01.2024
3
1
BIT
9
Traceback (most recent call last):
File "C:/Users/Администратор/Desktop/address.py", line 85, in <module>
main()
File "C:/Users/Администратор/Desktop/address.py", line 75, in main
russia_num(phone)
File "C:/Users/Администратор/Desktop/address.py", line 16, in russia_num
csv_read(num_one, two_num, phone)
File "C:/Users/Администратор/Desktop/address.py", line 28, in csv_read
with open("DEF-9xx.csv", "r", encoding='utf-8') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'DEF-9xx.csv'

как исправить эту ошибку?
 

Johan Van

Green Team
13.06.2020
363
691
BIT
395
Traceback (most recent call last):
File "C:/Users/Администратор/Desktop/address.py", line 85, in <module>
main()
File "C:/Users/Администратор/Desktop/address.py", line 75, in main
russia_num(phone)
File "C:/Users/Администратор/Desktop/address.py", line 16, in russia_num
csv_read(num_one, two_num, phone)
File "C:/Users/Администратор/Desktop/address.py", line 28, in csv_read
with open("DEF-9xx.csv", "r", encoding='utf-8') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'DEF-9xx.csv'

как исправить эту ошибку?
Нужно положить файл ".csv" в директорию скрипта из которого он считывается. Взять данный файл можно тут:

Для наглядности:

screenshot1.png


И не забудьте скачать файл во вложении к статье. Иначе будет еще одна ошибка с отсутствием файла.
 
  • Нравится
Реакции: bayland

bayland

One Level
13.01.2024
3
1
BIT
9
Нужно положить файл ".csv" в директорию скрипта из которого он считывается. Взять данный файл можно тут:

Для наглядности:

Посмотреть вложение 73391

И не забудьте скачать файл во вложении к статье. Иначе будет еще одна ошибка с отсутствием файла.
почему то сайт с файлом не загружается, можете его скинуть?
 

Atlas_Shruggs

New member
22.01.2024
1
0
BIT
14
Добрый день.
Даже зарегистрировался, чтобы прокомментировать)
Спасибо большое за инфу по реестру с операторами, очень круто, не знал.

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


Python:
def num_cleaner(row, col='Мобильный телефон'):
    text = str(row[col])
    
    if '+' in text:
        text = text.split('+')[1]

    if '.' in text:
        text = text.split('.')[0]
  
    try:
        text_fix = re.sub(r'\D+','', text)
        if len(text_fix) == 11:
            
            text_fix = re.sub(r'^8{1}', r'7', text_fix)
            
        if len(text_fix) == 10 and text_fix[0] == '9':
            text_fix = '7' + text_fix



    except:
        text_fix = 0
    
    return text_fix

Она не универсальна для нероссийских номеров, но работать должно)
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!