Код для обновления фотографии профиля Вконтакте с помощью VK API. Рассмотрим работу с капчей и загрузим код на сервер для автоматического обновления фотографии.

image

Необходимые библиотеки


Устанавливаем библиотеку vk_api для работы с VK API для Python: pip install vk_api

Пример работы vk_api
import vk_api

#Логин (номер телефона) и пароль от профиля ВК 
vk_session = vk_api.VkApi('login', 'password')
vk_session.auth()

vk = vk_session.get_api()

#Опубликовать пост на своей странице с текстом 'Hello world!'
vk.wall.post(message='Hello world!') 


Импортируем необходимые библиотеки

import os
import time
import random
import requests

import vk_api

from vk_api.utils import get_random_id
from urllib import urlretrieve

Авторизация


Авторизация в ВК с помощью API

vk_session = vk_api.VkApi('+7999132****', '*********')
vk_session.auth()

vk = vk_session.get_api()

Загрузка изображений


Загружаем изображения на сервер ВКонтакте.
photos.getOwnerPhotoUploadServer() возвращает адрес сервера для загрузки главной фотографии на страницу пользователя.

url = vk.photos.getOwnerPhotoUploadServer()['upload_url']

Для загрузки изображения на сервер ВКонтакте надо передать файл на адрес upload_url, полученный в предыдущем пункте, сформировав POST-запрос с полем photo.

#Изображения находятся в папке images
images = os.listdir("images")

photo = []
for image in images:
    request = requests.post(url, files={'photo': open('images/'+image, 'rb')}).json()
    photo.append(request['photo'])

Сохраним значения сервера и хеша. Они понадобятся для обновления фотографии профиля.

server = request['server'] 
hash = request['hash']

Обновление фотографии профиля


photos.saveOwnerPhoto() сохраняет фотографию пользователя.

#Выбираем рандомную фотографию и меняем фотографию профиля 
x = random.randint(0, len(photo)-1)
vk.photos.saveOwnerPhoto(server = server, hash = hash, photo = photo[x])

После обновления фотографии на стену добавляется пост с этой фотографией. Если не удалить эти посты, то лента друзей будет забита постами про ваше обновление аватарки.

posts = vk.wall.get()
post_id = posts["items"][0]["id"]
vk.wall.delete(post_id = post_id)

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

y = 0
while(True):
    x = random.randint(0, len(photo)-1)
    while(x == y):
        x = random.randint(0, len(photo)-1)
    y = x
    #x и y используется для того, чтобы одна фотография не повторялась 2 раза подряд
    
    vk.photos.saveOwnerPhoto(server = server, hash = hash, photo = photo[x])

    posts = vk.wall.get()
    post_id = posts["items"][0]["id"]
    vk.wall.delete(post_id = post_id)
     
    #Удаляем предыдущую фотографию 
    photos = vk.photos.getAll()
    if (photos['count']>1):
        photo_id = photos["items"][1]["id"]
        vk.photos.delete(photo_id = photo_id)
    
    time.sleep(60) #Задержка 60 сек.

Полный код
import os
import time
import random
import requests

import vk_api

from vk_api.utils import get_random_id
from urllib import urlretrieve

vk_session = vk_api.VkApi('+7999132****', '***********')
vk_session.auth()

vk = vk_session.get_api()

images = os.listdir("images")

url = vk.photos.getOwnerPhotoUploadServer()['upload_url']

photo = []
for image in images:
    request = requests.post(url, files={'photo': open('images/'+image, 'rb')}).json()
    photo.append(request['photo'])

server = request['server'] 
hash = request['hash']

y = 0
while(True):
    x = random.randint(0, len(photo)-1)
    while(x == y):
        x = random.randint(0, len(photo)-1)
    y = x
               
    vk.photos.saveOwnerPhoto(server = server, hash = hash, photo = photo[x])

    posts = vk.wall.get()
    post_id = posts["items"][0]["id"]
    vk.wall.delete(post_id = post_id)
      
    photos = vk.photos.getAll()
    if (photos['count']>1):
        photo_id = photos["items"][1]["id"]
        vk.photos.delete(photo_id = photo_id)
        
    time.sleep(60)


Но после несколькольких десятков обновлений фотографии профиля выйдет ошибка
Captcha: Captcha needed

Давайте разберемся как работать с капчей в VK API.

Работа с captcha


В методе vk_api.VkApi() уже реализована работа с капчей. Необходимо кроме логина и пароля передать функцию обработки капчи captcha_handler.

Изменяем vk_session

vk_session = vk_api.VkApi('+7999132****', '**********', captcha_handler=captcha_handler)

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

def captcha_handler(captcha):
    
    #Получаем адрес капчи
    captcha_url = captcha.get_url() 
    
    #Сохраняем изображение капчи на компьютер
    urlretrieve(captcha_url, "captcha.jpg")
    
    #Получаем ключ (send_captcha() см. далее)
    key = send_captcha(captcha_url)
    
    #Отправляем ключ (текст) капчи
    return captcha.try_again(key)

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

Методы messages не доступны для пользователя с сервера, поэтому надо создать группу и получить token.

  1. Создаём группу/публичную страницу
  2. Управление => Работа с API => Создать ключ
  3. Выбираем:
    • Разрешить приложению доступ к сообщениям сообщества
    • Разрешить приложению доступ к фотографиям сообщества
  4. Копируем ключ
    Так же надо включить Сообщения в настройках группы (Управление => Сообщения) и разрешить сообщения (в меню группы)

    def send_captcha(captcha_url):
        #token (ключ) группы
        token = "КЛЮЧ"
        
        vk_session = vk_api.VkApi(token = token)
        vk = vk_session.get_api()
        
        #Получаем адрес капчи
        url = vk.photos.getMessagesUploadServer()['upload_url']
        
        #Загружаем изображение на сервер ВКонтакте 
        request = requests.post(url, files={'photo': open("captcha.jpg", 'rb')}).json()
        
        #Сохраняем фотографию
        photo = vk.photos.saveMessagesPhoto(server=request['server'],
                                            photo = request['photo'],
                                            hash = request['hash'])
        
        attachment = 'photo{}_{}'.format(photo[0]['owner_id'], photo[0]['id'])
        
        #Отправляем сообщение
        vk.messages.send(
            user_id = ВАШ_ID,
            attachment = attachment,
            random_id=get_random_id())
        
        #Удаляем капчу
        os.remove("captcha.jpg")
        
        #Ждем ответа
        key = ''
        while (key == ''):
            #Получаем первый в списке диалог
            messages = vk.messages.getDialogs()['items'][0]
            
            #Если к сообщению не прикреплено изображение, то значит это ключ 
            if 'attachments' not in messages['message'].keys():
                key = messages['message']['body']
        return key
    

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

    Полный код
    import os
    import time
    import random
    import requests
    
    import vk_api
    
    from vk_api.utils import get_random_id
    from urllib import urlretrieve
    
    def captcha_handler(captcha):
        
        captcha_url = captcha.get_url()
        
        urlretrieve(captcha_url, "captcha.jpg")
        
        key = send_captcha(captcha_url)
        
        print(key)
        return captcha.try_again(key)
    
    def send_captcha(captcha_url):
        token = "КЛЮЧ"
        
        vk_session = vk_api.VkApi(token = token)
        vk = vk_session.get_api()
        
        url = vk.photos.getMessagesUploadServer()['upload_url']
        
        request = requests.post(url, files={'photo': open("captcha.jpg", 'rb')}).json()
        
        photo = vk.photos.saveMessagesPhoto(server=request['server'],
                                            photo = request['photo'],
                                            hash = request['hash'])
        
        attachment = 'photo{}_{}'.format(photo[0]['owner_id'], photo[0]['id'])
        
        vk.messages.send(
            user_id=ВАШ_ID,
            attachment = attachment,
            random_id=get_random_id())
        
        os.remove("captcha.jpg")
        
        key = ''
        while (key == ''):
            messages = vk.messages.getDialogs()['items'][0]
            if 'attachments' not in messages['message'].keys():
                key = messages['message']['body']
        return key
    
    vk_session = vk_api.VkApi('+7999132****', '*********', captcha_handler=captcha_handler)
    vk_session.auth()
    
    vk = vk_session.get_api()
    
    images = os.listdir("images")
    
    url = vk.photos.getOwnerPhotoUploadServer()['upload_url']
    
    photo = []
    for image in images:
        request = requests.post(url, files={'photo': open('images/'+image, 'rb')}).json()
        photo.append(request['photo'])
    
    server = request['server'] 
    hash = request['hash']
    
    y = 0
    while(True):
        x = random.randint(0, len(photo)-1)
        while(x == y):
            x = random.randint(0, len(photo)-1)
        y = x
                   
        vk.photos.saveOwnerPhoto(server = server, hash = hash, photo = photo[x])
    
        posts = vk.wall.get()
        post_id = posts["items"][0]["id"]
        vk.wall.delete(post_id = post_id)
          
        photos = vk.photos.getAll()
        if (photos['count']>1):
            photo_id = photos["items"][1]["id"]
            vk.photos.delete(photo_id = photo_id)
            
        print("Successfully", x)
        time.sleep(60)
    


    Для круглосуточного выполнения кода я использую VPS хостинг. Загружаю изображения и выполняю код на сервере.

    Код на github

    Если есть вопросы, пишите в коментариях или в ЛС.

Комментарии (3)


  1. algotrader2013
    20.08.2019 21:48
    +1

    Дочитав до слова капча, и помня, что в заголовке указана автоматизация, а в тегах значится Python, подумал, что тут то и начнется самое интересное… Но нет(


  1. shifttstas
    21.08.2019 09:36

    Вконтакте в 2019? Но зачем?


  1. zoldaten
    22.08.2019 17:18

    Отличная возможность попрактиковаться!