Быстрый в изучении - мощный в программировании
>> Telegram ЧАТ для Python Программистов

Свободное общение и помощь советом и решением проблем с кодом! Заходите в наш TELEGRAM ЧАТ!

>> Python Форум Помощи!

Мы создали форум где отвечаем на все вопросы связанные с языком программирования Python. Ждем вас там!

>> Python Канал в Telegram

Обучающие статьи, видео и новости из мира Python. Подпишитесь на наш TELEGRAM КАНАЛ!

Отбор валидных мобильных номеров друзей «Вконтакте» на Python

Отбор валидных мобильных номеров друзей «Вконтакте» на Python

Многие, изучающие Python интересуются его использованием в связке с API Вконтакте. В VK имеется телефонная книга, она в более-менее нормальном формате отображает мобильные номера ваших друзей. А учитывая то, что далеко не каждый человек охотно оставляет там свой валидный (полный) номер телефона, будет весьма интересно и полезно написать скрипт, который будет отбирать исключительно валидные мобильные номера и выводить их в отдельную таблицу. Наша телефонная книга будет создавать CSV-файл, который впоследствии можно будет открывать, к примеру, в Excel.

Бесплатная почта для вашего домена!

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

Чтобы воспользоваться API Вконтакте на Python можно воспользоваться неплохой библиотекой vk. Оригинальное название, не так ли? Итак, нужно импортировать нужные нам модули:

import vk
from time import sleep
from re import sub, findall
from getpass import getpass
from csv import writer, QUOTE_ALL

Дале создаем класс User с методами, которые нам необходимы:

class User(object):
    """VK User"""
    def __init__(self, login, password):
        self.login = login
        self.password = password
        self.id = ''
    
    def auth(self):
        session = vk.AuthSession(app_id='5340228', user_login=self.login, user_password=self.password)
        api = vk.API(session)
        return api
    
    def friends(self, api):
        user_friends = api.friends.get(user_id=self.id, order='hints')
        return user_friends
    
    def friends_count(self, api):
        user_friends = User.friends(self, api)
        friends_count = len(user_friends)
        return friends_count
    
    def info(self, api):
        user = api.users.get(user_id=self.id)
        return user[0]

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

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

def norm_mob(str):
    if len(str) != '':
        norm_mob = sub(r'(\s+)?[+]?[-]?', '', str)
        right_mob = findall(r'[\d]', norm_mob)
        
        if (len(right_mob) == len(norm_mob)) and (len(norm_mob) >= 10):
            rev_norm_mob = norm_mob[::-1]
            norm_mob = rev_norm_mob[0:10]
            if norm_mob[::-1][0] == '0':
                return norm_mob[::-1]
    else:
        return False

Затем пройдем по друзьям, отобрав тех, которые оставили свои контактные данные, и если оставили, то мы их валидируем и записываем в массив. У сервера ВК есть одна особенность – он не любит большое количество запросов, соответственно нужно сделать так, чтобы наш скрипт «спал» определенное время между ними. Были перепробованы различные значение, и определены оптимальные.

def find_correct_phone_numbers(api, friends, friends_count):
    users_phones = []
    for i in range(0, friends_count):
        cur_user_id = int(friends[i])
        cur_user = api.users.get(user_id=cur_user_id, fields='contacts')
        try:
            cur_mob = cur_user[0]['mobile_phone']
        except KeyError:
            sleep(0.3)
            continue
        mob = norm_mob(cur_mob)
        if mob:
            users_phones.append({
                'user_name': '{} {}'.format(cur_user[0]['first_name'], cur_user[0]['last_name']),
                'user_phone': '8{}'.format(mob)
                })
        sleep(0.4)
    return users_phones

Теперь сохраним полученный результат.

def saveCSV(data, path):
    with open(path, 'w') as csvfile:
        my_writer = writer(csvfile, delimiter='    ', quotechar='"', quoting=QUOTE_ALL)
        my_writer.writerow(('Имя пользователя', 'Номер моб. телефона'))
        for item in data:
            try:
                my_writer.writerow((item['user_name'], item['user_phone']))
            except Exception:
                my_writer.writerow(('(Ошибка в кодировке)', item['user_phone']))

Далее нужно добавить функцию, подсчитывающую затраченное время.

class Timer(object):
    def __enter__(self):
        self._startTime = time()
 
    def __exit__(self, type, value, traceback):
        howLong = time() - self._startTime
        print("Операция заняла: {:.2f} минут".format(howLong/60))

И в конце нужно реализовать вызов созданных функций.

def main():
    while True:
        login = input('E-mail: ')
        password = getpass('Password: ')
        try:
            vk_user = User(login, password)
            api = vk_user.auth()
            print('Авторизация выполнена успешно!')
            break
        except Exception:
            print('Вы ввели неверные данные, пожалуйста, повторите попытку.')
 
    friends = vk_user.friends(api)
    friends_count = vk_user.friends_count(api)
 
    print('Найдено {} друзей.'.format(friends_count))
    print('Идет выборка мобильных номеров...')
 
    with Timer() as p:
        users_phones = find_correct_phone_numbers(api, friends, friends_count)
 
    print('Выборка окончена. Сохранение...')
    saveCSV(users_phones, 'vk_mob.csv')
    print('Данные успешно сохранены.')
 
if __name__ == '__main__':
    main()

В результате мы получаем csv-файл, который в виде удобной таблицы можно открывать в Excel.