Экспорт друзей VK в Google Contacts

После покупки андроид-фона, появилась необходимо перебросить всех друзей ВК с нормальными номерами телефона в Гугл контакты. В интернете ничего подходящего не нашел, поэтому пришлось написать свой скрипт на Python.

Возможности скрипта


В Гугл контактах создается группа VK( можно поменять название группы, строка 13 в скрипте), в которую заносятся все пользователи из ВК. Работает с синхронизацией по полному имени (имя + фамилия). Если контакт уже существует, то в нем обновляются все данные, и контакт добавляетсяв группу VK. Если в Гугл контактах у Вас более 1000 контактов, то увеличьте переменную numberOfContacts = '1000' до необходимого значения.

Переносится фотография профиля из ВК, день рожения, правдивые номера телефонов.
Если в основном номера украинские, сделайте переменную ukraine = 1.

Запуск скрипта


Для работы скрипта необходим Python, Vkontakte api for Python, gdata (Google Api for Python).

Авторизация ВК происходит с помощью токена, его необходимо указать в скрипте(строка 18). Получить токен можно здесь. Для авторизации в Google надо в скрипте указать логин и пароль gmail(строки 11, 12).

Можно запускать.

Скрипт


# -*- coding: utf-8 -*-
import vkontakte

import gdata.data
import gdata.gauth
import gdata.contacts.client
import gdata.contacts.data
import atom

#Google
email = ''
password = ''
groupName = 'VK'
numberOfContacts = '1000'

#VK
#URL for getting token http://oauth.vk.com/authorize?client_id=2859200&scope=friends&response_type=token
tokenVK = ''

#If Ukraine, make it 1
ukraine = 0


def TransformPhone(phone):
    if len(phone) < 5:
        return 0
    phone.replace('-', '')
    phone.replace('(', '')
    phone.replace(')', '')
    phone.replace(' ', '')
    if phone[1:].isdigit():
        if not ukraine:
            return phone
        else:
            if len(phone) == 7:
                return '+38044' + phone
            elif phone[0] == '+':
                return phone
            elif phone[0:3] == '380':
                return '+' + phone
            elif phone[0:2] == '80':
                return '+3' + phone
            elif phone[0] == '0':
                return '+38' + phone
            else:
                return 0
    else:
        return 0


def TransformBirthday(date):
    if len(date) > 5:
        year = date[date.rfind('.') + 1:]
        month = date[date.find('.') + 1:date.rfind('.')]
        if len(month) == 1:
            month = '0' + month
        day = date[0:date.find('.')]
        if len(day) == 1:
            day = '0' + day
        gDate = year + '-' + month + '-' + day
    else:
        month = date[date.rfind('.') + 1:]
        if len(month) == 1:
            month = '0' + month
        day = date[0:date.find('.')]
        if len(day) == 1:
            day = '0' + day
        gDate = '--' + month + '-' + day

    return gDate


def makeStr(data):
    return data.encode('utf-8')


def GetIndex(seq, attribute, value):
    return next(index for (index, d) in enumerate(seq) if d[attribute] == value)


def CheckVkGroup(gd_client):
    feed = gd_client.GetGroups()
    for entry in feed.entry:
        if makeStr(entry.title.text) == groupName:
            return entry.id.text
    return 0


def CreateVkGroup(gd_client):
    new_group = gdata.contacts.data.GroupEntry(title=atom.data.Title(text=groupName))
    created_group = gd_client.CreateGroup(new_group)
    return created_group


def GetAllContacts(gd_client):
    query = gdata.contacts.client.ContactsQuery()
    query.max_results = numberOfContacts
    feed = gd_client.GetContacts(q=query)
    return feed.entry


def downloadPhoto(url, file_name):
    from urllib2 import Request, urlopen

    #Create the request
    req = Request(url)

    # Open the url
    f = urlopen(req)

    # Open our local file for writing
    local_file = open(file_name, "wb")
    #Write to our local file
    local_file.write(f.read())
    local_file.close()


def removeLocalPhoto(file_name):
    from os import remove

    remove(file_name)


def UpdateContact(gd_client, contact, friend, vkGroup):

    #Set the contact's phone numbers.
    if ('mobile_phone' in friend) and (friend['mobile_phone'] != 0):
        contact.phone_number.append(gdata.data.PhoneNumber(text=friend['mobile_phone'],
                                                           rel=gdata.data.WORK_REL, primay='true'))
    if ('home_phone' in friend) and (friend['home_phone'] != 0):
        contact.phone_number.append(gdata.data.PhoneNumber(text=friend['home_phone'],
                                                           rel=gdata.data.HOME_REL))
    if 'bdate' in friend:
        contact.birthday = gdata.contacts.data.Birthday(when=friend['bdate'])

    #Set Group for VK friends
    contact.group_membership_info.append(gdata.contacts.data.GroupMembershipInfo(href=vkGroup))

    #Push changes to Google
    gd_client.Update(contact)

    #Download photo from vk, add to google, remove from local computer
    local_image_filename = friend['photo_big'][friend['photo_big'].rfind('/') + 1:]
    downloadPhoto(friend['photo_big'], local_image_filename)
    gd_client.ChangePhoto(local_image_filename, contact, content_type='image/jpeg')
    removeLocalPhoto(local_image_filename)


def CreateContact(gd_client, friend, vkGroup):

    new_contact = gdata.contacts.data.ContactEntry()
    name = friend['full_name']
    new_contact = gdata.contacts.data.ContactEntry(name=gdata.data.Name(full_name=gdata.data.FullName(text=name)))
    contact = gd_client.CreateContact(new_contact)

    UpdateContact(gd_client, contact, friend, vkGroup)


if __name__ == '__main__':

    #Google authorization
    gd_client = gdata.contacts.client.ContactsClient(source='Export contacts to Google')
    gd_client.ClientLogin(email, password, gd_client.source)

    #Get contacts
    googleContacts = GetAllContacts(gd_client)
    print "Received Google Contacs"

    #VK authorization
    vk = vkontakte.API('2859200', 'Uq9YfuXTq8RUZbrGNnEP')
    vk = vkontakte.API(token=tokenVK)

    #Get list of VK friends
    friends = vk.friends.get(fields="first_name, last_name, bdate, contacts, photo_big", order='name')
    print "Received VK friends"

    #Create group in Google Contacs for VK if not exist
    vkGroup = CheckVkGroup(gd_client)
    if not vkGroup:
        CreateVkGroup(gd_client)
        vkGroup = CheckVkGroup(gd_client)

    #Make list of VK friends more useful
    vkFriendsName = []
    for record in friends:
        record['full_name'] = record['first_name'] + u' ' + record['last_name']

        if 'bdate' in record:
            record['bdate'] = TransformBirthday(record['bdate'])
        if 'home_phone' in record:
            record['home_phone'] = TransformPhone(record['home_phone'])
        if 'mobile_phone' in record:
            record['mobile_phone'] = TransformPhone(record['mobile_phone'])

        del record['first_name']
        del record['last_name']
        del record['uid']
        del record['online']
        vkFriendsName.append(record['full_name'])

    #Update existing contacts
    for contact in googleContacts:
        #Some magics, because of retrieving none existed Google contact
        try:
            makeStr(contact.name.full_name.text)
        except:
            pass
        else:
            if contact.name.full_name.text in vkFriendsName:
                index = GetIndex(friends, 'full_name', contact.name.full_name.text)
                friend = friends[index]
                UpdateContact(gd_client, contact, friend, vkGroup)
                print "Updated: " + makeStr(friend['full_name'])
                vkFriendsName.remove(friend['full_name'])

    #Create new contacts
    for name in vkFriendsName:
        index = GetIndex(friends, 'full_name', name)
        friend = friends[index]
        CreateContact(gd_client, friend, vkGroup)
        print "Created: " + makeStr(friend['full_name'])


UPD: Исправил код, в связи с изменениями в Google API. Заодно добавил синхронизацию.
Метки:
Поделиться публикацией
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 26
  • 0
    Обратите только внимание, что скрипт рассчитан на украинские номера.
    • 0
      Сделал для всех номеров.
    • 0
      Насколько я понял, синхронизация не поддерживается, т.е. если второй раз запустить, то будет две копии контактов.
      • +5
        Да, но можно воспользоваться функцией в гугл «Найти и объединить совпадающие контакты», которая уберет копии.
        • +1
          Добавил синхронизацию.
        • +3
          Токен, логин и пароль лучше было бы вынести в самое начало
        • +7
          Кстати, официальный клиент VK умеет синхронизацию контактов. Может добавить всех друзей, может только тех, кто есть в телефонной книге. Прописывает аккаунт в настройках синхронизации телефона. Также синхронизирует фотки.
          • 0
            Кстати, а он распознает номера с дефисами и равнозначность 8 и +7 в начале? У меня стоит неофициальный и он этим страдает. Ну и к тому же, синхронизируя через приложение контакты попадут в телефон, но не в google contacts
            • 0
              Вот, к сожалению, на этот вопрос ответить не могу. Я сам не синхронизирую, так как не хочу в телефонной книге иметь весь «фарш» из ВКонтакта, но лично видел на другом телефоне синхронизированные через это приложение контакты. По крайней мере к уже существующим в гугл-аккаунте контактам приложение добавило фотки из сети.
              • +1
                С фаршем там всё в порядке. Сам сначала боялся. Но приложение загрузило всех друзей VK в отдельную группу. Её можно держать не отображаемой и включать отображение при необходимости. Ну и подгрузило фотки и всяческие е-мейлы для существующих контактов, да.
                Порадовала функция в общем-то.
                • 0
                  в неофициальном можно было только конкретный список друзей подгружать + фотки в разы лучшего качества. но сейчас не работает)
                  • 0
                    А отдельную группу создал на телефоне или в гугл-аккаунте?
                    • +1
                      В телефоне, как люди и пишут. В принципе, я не заморачивался синхронизацией этих контактов еще и с гуглом, может и можно как-то штатными средствами сделать.
              • 0
                Официальный клиент я так и не понял как синхронизирует «существующие» контакты. А если выбрать «все» — то в телефон загружаются все контакты из «вконтакте», что неудобно.
                Плюс к тому фотографии загружаются паршивые(разрешение низкое).

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

                Пока нашел для себя выход — официальный клиент и в телефонной книге выбрал отображение только контактов с гугла.
              • +3
                Так можно же поставить официальное приложение, и при помощи него синхронизировать контакты, тем более если имеется Android-фон.
                Если нужно в Google Контакты, то делаем экспорт в файл и восстанавливаем из него.

                Не знаю правда как там с номерами телефона, но вроде у меня всё нормально(а в приложении от amberfog`а, даже галочка есть «только с номерами телефона», вроде).
                • 0
                  Официальное приложение позволяет работать с контактами вконтата, а в google они не зальются — если зайти в google contacts через браузер — нет их там.
                  • 0
                    Ну я и написал про экспорт\импорт же. Если через телефон не импортит, то можно напрямую через браузер, там вроде тоже .vcf поддерживается.
                • 0
                  Попробуйте memiana.com
                  Он может собрать контакты с разных сервисов и синхронизировать с любыми устройствами.
                  • 0
                    Хороший сервис, однако делиться своими контактами не совсем понятно с кем большого желания нет.
                  • 0
                    Я, как владелец WP7, был рад этому скрипту.
                    У нас пока хорошей синхронизатолки под контакт нету, а свой как-то лень было писать. Спасибо!
                    • 0
                      Вылетает:

                      Traceback (most recent call last):
                      File "vk2google.py", line 131, in friends = vk.friends.get(fields = "first_name, last_name, bdate, contacts, photo_big", order = 'name')
                      File "/usr/local/lib/python2.7/dist-packages/vkontakte/api.py", line 92, in __call__ return self._get(self.method_prefix + method, **params)
                      File "/usr/local/lib/python2.7/dist-packages/vkontakte/api.py", line 73, in _get
                      raise VKError(data["error"]["error_code"], data["error"]["error_msg"], data["error"]["request_params"])
                      vkontakte.api.VKError: Error(code = '5', description = 'User authorization failed: user revoke access for this token.', params = '[{u'value': u'1', u'key': u'oauth'}, {u'value': u'friends.get', u'key': u'method'}, {u'value': u'access_token=XXX', u'key': u'access_token'}, {u'value': u'first_name, last_name, bdate, contacts, photo_big', u'key': u'fields'}, {u'value': u'name', u'key': u'order'}, {u'value': u'1332411220', u'key': u'timestamp'}]')
                      • 0
                        User authorization failed: user revoke access for this token. — Вы запретили доступ по введеному токену. Сгенерируйте новый по ссылке указанной в коде.
                      • 0
                        Чтобы избежать ошибки «Missing attribute: 'href'» нужно:
                        вместо строки 137:
                        contact.group_membership_info.append(gdata.contacts.data.GroupMembershipInfo(href=vkGroup))

                        вставить 3 строчки:
                        groupinfo = gdata.contacts.data.GroupMembershipInfo(href='', deleted=False)
                        groupinfo.href = vkGroup
                        contact.group_membership_info.append(groupinfo)
                        • –1
                          Еще могу рекомендовать это приложение
                          Синхронизатор вКонтакте

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.