Отбираем валидные мобильные номера друзей VK на Python / Хабр
В процессе изучения Python стало интересно попробовать его в связке с API VK. В ВК есть телефонная книга, она показывает телефоны ваших друзей в более-менее удобном формате. Так как далеко не всегда люди охотно оставляют там полые(валидные) номера своих телефонов, мне показалась интересной идея написать скрипт, который отбирал бы только валидные номера моб.телефонов и выдавал бы их отдельной таблицей. Наша телефонная книга будет генерировать csv-файл, который затем можно будет открыть, например, в excel.
Для использования API VK на 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('Данные успешно сохранены.