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()