https://habr.com/ru/post/464285/Код для обновления фотографии профиля Вконтакте с помощью VK API. Рассмотрим работу с капчей и загрузим код на сервер для автоматического обновления фотографии.
Необходимые библиотеки
Устанавливаем библиотеку vk_api для работы с VK API для Python: pip install vk_api
Пример работы vk_apiimport 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.
- Создаём группу/публичную страницу
- Управление => Работа с API => Создать ключ
- Выбираем:
- Разрешить приложению доступ к сообщениям сообщества
- Разрешить приложению доступ к фотографиям сообщества
- Копируем ключ
Так же надо включить Сообщения в настройках группы (Управление => Сообщения) и разрешить сообщения (в меню группы)
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
Если есть вопросы, пишите в коментариях или в ЛС.