У многих есть аккаунт в социальной сети ВК. И, если вы используете данную социальную сеть не только для общения с друзьями, то список этих друзей может быть довольно внушительным. К примеру, у моего аккаунта ВК 4635 активных друзей. Вот только не все аккаунты пользователей у вас в друзьях долго живут. Со временем кто-то из них станет «собачкой». То есть, либо просто удалит свой аккаунт, либо будет заблокирован соцсетью за какую-либо «провинность». Таких вот, неактивных, пользователей из списка друзей лучше вычищать. Но делать это вручную, особенно если список друзей напоминает египетский список, довольно долго и муторно. Можно, конечно, воспользоваться уже готовыми решениями, а можно написать собственный скрипт на Python, чем я и предлагаю заняться.
Что потребуется?
Для работы данного скрипта требуется установка двух библиотек. Это vk-api и colorama. Причем установка второй вовсе не обязательно. Она служит скорее для украшения вывода в терминал и практической пользы несет не особо много. Тем не менее, для их установки пишем в терминале команду:
Импорт необходимых библиотек
Для начала импортируем в скрипт библиотеки, которые понадобятся в процессе его работы. Конечно же, это библиотека vk-api из которого импортируем модуль VkApi, а также colorama, откуда импортируются модули Fore, init. Также понадобится импортировать из модуля vk_api.exceptions ApiError для обработки исключений, которые могут возникнуть в процессе работы с библиотекой vk-api.
Из стандартны библиотек импортируем модуль Path библиотеки pathlib; ThreadPoolExecutor из библиотеки concurrent.futures; модуль sleep из библиотеки для работы со временем time.
Также понадобиться создать дополнительный файл set.py, в котором объявить две переменные: token_vk, user_vk_id. Первая переменная будет содержать токен приложения для работы с ВК, вторая – id пользователя, со списком друзей которого мы будем работать. Обратите внимание, что работать вы сможете только со своим списком друзей, так как в процессе работы будет происходить удаление деактивированных пользователей. Выглядеть содержимое данного файла будет примерно так:
Значения, которые присвоены данным переменным служат только для примера. Вам нужно будет получить собственный токен, а также узнать
Инициализация colorama, объявление глобальных переменных и активация сессии ВК
Для корректной работы библиотеки colorama ее необходимо инициализировать с помощью команды init. Также, необходимо создать сессию ВК, в которую передать ранее полученный токен. И здесь же объявить две глобальные переменные, которые будут служить счетчиками удаленных и не удаленных пользователей в процессе работы скрипта.
Получение списка друзей ВК
Создадим функцию get_friends() -> (list, bool). На вход данной функции ничего не передается. А вот возвращает функция, в случае благополучного исхода, список id друзей пользователя, или False в случае возникновения исключения или, если список друзей будет пуст.
Объявим переменную friends_list, которой присвоим в качестве значения пустой список. В него будут помещены id друзей пользователя. В переменную friends получим список друзей пользователя с помощью метода VK API friends.get. В данный метод передадим токен, id пользователя, список друзей которого нужно получить, смещение offset, с которого нужно получать друзей – в данном случае 0, так как нужно получить полный список и количество друзей count, которое в данном случае также равно 0. Также передадим сюда версию используемого API в переменной v.
Проверим, получили ли мы список друзей. Если да, пробегаемся по нему в цикле, забираем каждый id и добавляем в список friends_list. Проверяем, не является ли данный список пустым. Если нет, возвращаем его из функции. В случае же, если список пуст или мы не получили список друзей, возвращаем False.
Также, для обработки исключения, которое может возникнуть в процессе работы с VK API, заключим данный код в блок try – except и в случае возникновения исключения возвращаем из функции False.
Проверка списка друзей
Для проверки списка друзей пользователя создадим функцию get_user(user_id: str, nm: str) -> None. На входе передаем в нее id друга, а также строку, которая содержит порядковый номер из списка проверяемого пользователя и служит больше в информационных целях. На выходе данная функция ничего не возвращает.
Теперь необходимо получить базовую информацию о пользователе с помощью метода VK API users.get. В случае, если пользователь заблокирован или удален, возвращается параметр deactivated. Вот с его помощью мы и будем определять, является ли пользователь «собачкой» или нет. Создаем переменную users, в которую будет передан список со словарями, содержащими данные о пользователе. Передаем токен, id друга, данные по которому нужно получить, а также версию используемого API.
Проверяем, получен ли ключ deactivated. Если да, выводим сообщение для пользователя на экран и передаем id деактивированного друга в функцию unfollower для удаления его из списка друзей. Данную функцию мы напишем немного позднее. После чего возвращаемся из функции.
В случае же, когда данного ключа не существует, возникнет исключение KeyError. В данном случае, это означает, что аккаунт друга активен. Сохраняем id активного друга в файл. Это понадобиться нам в дальнейшем, чтобы проверять id, которые уже были использованы, так как скрипт может быть прерван, а проверять одни и те же данные не имеет смысле. Также выводим сообщение в терминал, что пользователь активен и возвращаемся из функции.
Заключим весь код в блок try – except, чтобы обработать ошибки, которые могут возникнуть в процессе работы с VK API.
Удаление деактивированного друга из списка друзей
Для удаления друга, аккаунт которого был заблокирован или удален, создадим функцию unfollower(user_id: str) -> None. На вход данная функция получает id друга, которого надо удалить из списка друзей.
В переменную deleted получим словарь, который в случае успешного удаления пользователя из списка друзей будет содержать ключ success. Удалять пользователя из списка будем с помощью метода VK API friends.delete, куда передадим токен, id пользователя, которого нужно удалить из списка друзей и версию используемого API.
Проверяем, если ли ключ success в полученных в процессе работы с API данных. Если да, проверяем его содержимое. И если оно равно 1, удаление пользователя из списка друзей произошло успешно. Выводим сообщение в терминал об успешном удалении, увеличиваем счетчик удаленных пользователей и сохраняем id удаленного пользователя в файл user_bad.txt, который понадобиться в дальнейшем, для проверки, удален ли пользователь из списка друзей ранее или нет.
Если же возникнет ошибка при работе с API или ключа success не окажется с возвращенных данных, обработаем эти исключения и запишем данные о необработанном id в файл error_deleted.txt. Функцию для записи создадим немного позднее, а также выведем сообщение в терминал, что пользователь с текущим id не удален. После этого возвращаемся из функции.
Сохранение ошибок при работе с id
Создадим простую функцию error_save(user_id: str) -> None, которая на входе принимает id пользователя, при работе с которым возникла ошибка. Данная функция ничего не возвращает. Далее, открываем файл на добавление данных, записываем id пользователя, при работе с которым возникла ошибка и увеличиваем счетчик не удаленных пользователей.
Запуск проверки
Создадим функцию main. Для того, чтобы выполнять проверять, был ли проверен текущий id ранее, создадим переменную users_check, которая будет содержать множество из id загруженных из файлов. Проверяем в цикле, существуют ли файлы с проверенными активными и деактивированными id. Если да, загружаем из них id в множество users_check.
Получаем список друзей пользователя. В случае, если список не пуст, запускаем ThreadPoolExecutor, для выполнения функции get_user в потоках. Хотя, существенного прироста в скорости при работе с VK API особо не наблюдается. Пробегаемся по полученному списку id в цикле. Забираем id, а также с помощью функции enumerate его порядковый номер. Проверяем, есть ли текущий id в множестве с уже проверенными. Если да, выводим сообщение в терминал и продолжаем цикл дальше. Если нет, запускаем поток для функции get_user, куда передаем id и строку из порядкового номера текущего id и общего количества. Делаем паузу на 0,4 секунды. Если же список друзей получен не был, выводим соответствующее сообщение в терминал.
Таким образом, при работе данной функции у меня было найдено 4 деактивированных учетных записи друзей, которые были благополучно удалены. Создано два файла, содержащие активные id друзей, а также деактивированные id.
Также, данные пользователи отобразились в самом ВК, в виде пользователей, которых необходимо удалить как подписчиков.
Таким образом, с помощью небольшого и несложного скрипта мы смогли облегчить проверку списка друзей на деактивированных пользователей – «собачек». А заодно немного попробовали работать с методами VK API. Подробнее об использованных методах можно почитать на официальной странице руководства по данным методам:
Файлы с кодом прилагаю к статье во вложении.
А на этом, пожалуй – все. Спасибо за внимание. Надеюсь, данная информация будет вам полезна
Что потребуется?
Для работы данного скрипта требуется установка двух библиотек. Это vk-api и colorama. Причем установка второй вовсе не обязательно. Она служит скорее для украшения вывода в терминал и практической пользы несет не особо много. Тем не менее, для их установки пишем в терминале команду:
pip install vk-api colorama
Импорт необходимых библиотек
Для начала импортируем в скрипт библиотеки, которые понадобятся в процессе его работы. Конечно же, это библиотека vk-api из которого импортируем модуль VkApi, а также colorama, откуда импортируются модули Fore, init. Также понадобится импортировать из модуля vk_api.exceptions ApiError для обработки исключений, которые могут возникнуть в процессе работы с библиотекой vk-api.
Из стандартны библиотек импортируем модуль Path библиотеки pathlib; ThreadPoolExecutor из библиотеки concurrent.futures; модуль sleep из библиотеки для работы со временем time.
Также понадобиться создать дополнительный файл set.py, в котором объявить две переменные: token_vk, user_vk_id. Первая переменная будет содержать токен приложения для работы с ВК, вторая – id пользователя, со списком друзей которого мы будем работать. Обратите внимание, что работать вы сможете только со своим списком друзей, так как в процессе работы будет происходить удаление деактивированных пользователей. Выглядеть содержимое данного файла будет примерно так:
Python:
token_vk = "vk1.a.kv8Q6fhsEO4VEO3v7z87R6INxYlrU9aTyeAoPrY0ObAFEOUlzHb7AgYHd21Ykt5vqcRNkoq75jIYuWtStAHLLwD78E4RPZ_L_c0EfqiVmJcYsl- "
user_vk_id = "111111111"
Значения, которые присвоены данным переменным служат только для примера. Вам нужно будет получить собственный токен, а также узнать
Ссылка скрыта от гостей
. Импортируем все необходимое в наш скрипт:
Python:
from time import sleep
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from colorama import Fore, init
from vk_api import VkApi
from vk_api.exceptions import ApiError
from set import token_vk, user_vk_id
Инициализация colorama, объявление глобальных переменных и активация сессии ВК
Для корректной работы библиотеки colorama ее необходимо инициализировать с помощью команды init. Также, необходимо создать сессию ВК, в которую передать ранее полученный токен. И здесь же объявить две глобальные переменные, которые будут служить счетчиками удаленных и не удаленных пользователей в процессе работы скрипта.
Python:
init()
session = VkApi(token=token_vk).get_api()
del_ch = 0
not_del = 0
Получение списка друзей ВК
Создадим функцию get_friends() -> (list, bool). На вход данной функции ничего не передается. А вот возвращает функция, в случае благополучного исхода, список id друзей пользователя, или False в случае возникновения исключения или, если список друзей будет пуст.
Объявим переменную friends_list, которой присвоим в качестве значения пустой список. В него будут помещены id друзей пользователя. В переменную friends получим список друзей пользователя с помощью метода VK API friends.get. В данный метод передадим токен, id пользователя, список друзей которого нужно получить, смещение offset, с которого нужно получать друзей – в данном случае 0, так как нужно получить полный список и количество друзей count, которое в данном случае также равно 0. Также передадим сюда версию используемого API в переменной v.
Проверим, получили ли мы список друзей. Если да, пробегаемся по нему в цикле, забираем каждый id и добавляем в список friends_list. Проверяем, не является ли данный список пустым. Если нет, возвращаем его из функции. В случае же, если список пуст или мы не получили список друзей, возвращаем False.
Также, для обработки исключения, которое может возникнуть в процессе работы с VK API, заключим данный код в блок try – except и в случае возникновения исключения возвращаем из функции False.
Python:
def get_friends() -> (list, bool):
"""
Получаем список друзей пользователя и забираем их id.
"""
friends_list = []
try:
friends = session.friends.get(access_token=token_vk, user_id=user_vk_id, offset=0, count=0, v=5.131)
if friends['items']:
for item in friends['items']:
friends_list.append(item)
if friends_list:
return friends_list
return False
return False
except ApiError:
return False
Проверка списка друзей
Для проверки списка друзей пользователя создадим функцию get_user(user_id: str, nm: str) -> None. На входе передаем в нее id друга, а также строку, которая содержит порядковый номер из списка проверяемого пользователя и служит больше в информационных целях. На выходе данная функция ничего не возвращает.
Теперь необходимо получить базовую информацию о пользователе с помощью метода VK API users.get. В случае, если пользователь заблокирован или удален, возвращается параметр deactivated. Вот с его помощью мы и будем определять, является ли пользователь «собачкой» или нет. Создаем переменную users, в которую будет передан список со словарями, содержащими данные о пользователе. Передаем токен, id друга, данные по которому нужно получить, а также версию используемого API.
Python:
users = session.users.get(access_token=token_vk, user_ids=user_id, v=5.131)
Проверяем, получен ли ключ deactivated. Если да, выводим сообщение для пользователя на экран и передаем id деактивированного друга в функцию unfollower для удаления его из списка друзей. Данную функцию мы напишем немного позднее. После чего возвращаемся из функции.
Python:
if users[0]['deactivated']:
print(f'{Fore.RESET}{nm}: {user_id}: {Fore.RED}Деактивирован')
unfollower(user_id)
return
В случае же, когда данного ключа не существует, возникнет исключение KeyError. В данном случае, это означает, что аккаунт друга активен. Сохраняем id активного друга в файл. Это понадобиться нам в дальнейшем, чтобы проверять id, которые уже были использованы, так как скрипт может быть прерван, а проверять одни и те же данные не имеет смысле. Также выводим сообщение в терминал, что пользователь активен и возвращаемся из функции.
Python:
with open("user_check.txt", "a", encoding="utf-8") as file:
file.write(f"{user_id}\n")
print(f'{Fore.RESET}{nm} | {users[0]["first_name"]} {users[0]["last_name"]} https://vk.com/id{user_id}: '
f'{Fore.GREEN}Активен')
return
Заключим весь код в блок try – except, чтобы обработать ошибки, которые могут возникнуть в процессе работы с VK API.
Python:
def get_user(user_id: str, nm: str) -> None:
try:
"""
Получаем основные данные о пользователе.
"""
users = session.users.get(access_token=token_vk, user_ids=user_id, v=5.131)
try:
"""
Проверяем, есть ли ключ деактивации. Если да, то добавляем
"битый" id в список. Если нет, обрабатываем исключение и
добавляем не "битый" id в список проверенных.
"""
if users[0]['deactivated']:
print(f'{Fore.RESET}{nm}: {user_id}: {Fore.RED}Деактивирован')
unfollower(user_id)
return
except KeyError:
"""
Сохраняем не "битые" id для последующей проверки.
:param us_id: id пользователя
"""
with open("user_check.txt", "a", encoding="utf-8") as file:
file.write(f"{user_id}\n")
print(f'{Fore.RESET}{nm} | {users[0]["first_name"]} {users[0]["last_name"]} https://vk.com/id{user_id}: '
f'{Fore.GREEN}Активен')
return
except ApiError:
return
Удаление деактивированного друга из списка друзей
Для удаления друга, аккаунт которого был заблокирован или удален, создадим функцию unfollower(user_id: str) -> None. На вход данная функция получает id друга, которого надо удалить из списка друзей.
В переменную deleted получим словарь, который в случае успешного удаления пользователя из списка друзей будет содержать ключ success. Удалять пользователя из списка будем с помощью метода VK API friends.delete, куда передадим токен, id пользователя, которого нужно удалить из списка друзей и версию используемого API.
Python:
deleted = session.friends.delete(access_token=token_vk, user_id=user_id, v=5.131)
Проверяем, если ли ключ success в полученных в процессе работы с API данных. Если да, проверяем его содержимое. И если оно равно 1, удаление пользователя из списка друзей произошло успешно. Выводим сообщение в терминал об успешном удалении, увеличиваем счетчик удаленных пользователей и сохраняем id удаленного пользователя в файл user_bad.txt, который понадобиться в дальнейшем, для проверки, удален ли пользователь из списка друзей ранее или нет.
Если же возникнет ошибка при работе с API или ключа success не окажется с возвращенных данных, обработаем эти исключения и запишем данные о необработанном id в файл error_deleted.txt. Функцию для записи создадим немного позднее, а также выведем сообщение в терминал, что пользователь с текущим id не удален. После этого возвращаемся из функции.
Python:
def unfollower(user_id: str) -> None:
global del_ch
try:
"""
Удаляем пользователя из списка друзей.
Если произошли ошибки, записываем id пользователя в файл.
"""
deleted = session.friends.delete(access_token=token_vk, user_id=user_id, v=5.131)
if deleted["success"] == 1:
print(f'{user_id}: удален')
del_ch += 1
"""
Сохраняем "битые" id в отдельный файл, для последующей проверки.
:param us_id: id пользователя
"""
with open("user_bad.txt", "a", encoding="utf-8") as file:
file.write(f"{user_id}\n")
except (ApiError, KeyError):
print(f'{user_id}: не удален')
error_save(user_id)
return
Сохранение ошибок при работе с id
Создадим простую функцию error_save(user_id: str) -> None, которая на входе принимает id пользователя, при работе с которым возникла ошибка. Данная функция ничего не возвращает. Далее, открываем файл на добавление данных, записываем id пользователя, при работе с которым возникла ошибка и увеличиваем счетчик не удаленных пользователей.
Python:
def error_save(user_id: str) -> None:
global not_del
with open("error_deleted.txt", "a", encoding="utf-8") as dl:
dl.write(f'{user_id}\n')
not_del += 1
Запуск проверки
Создадим функцию main. Для того, чтобы выполнять проверять, был ли проверен текущий id ранее, создадим переменную users_check, которая будет содержать множество из id загруженных из файлов. Проверяем в цикле, существуют ли файлы с проверенными активными и деактивированными id. Если да, загружаем из них id в множество users_check.
Python:
global del_ch, not_del
users_check = set()
for f_name in ["user_check.txt", "user_bad.txt"]:
if Path(f_name).exists():
with open(f_name, "r", encoding="utf-8") as fl:
for us in fl.readlines():
users_check.add(us.strip())
Получаем список друзей пользователя. В случае, если список не пуст, запускаем ThreadPoolExecutor, для выполнения функции get_user в потоках. Хотя, существенного прироста в скорости при работе с VK API особо не наблюдается. Пробегаемся по полученному списку id в цикле. Забираем id, а также с помощью функции enumerate его порядковый номер. Проверяем, есть ли текущий id в множестве с уже проверенными. Если да, выводим сообщение в терминал и продолжаем цикл дальше. Если нет, запускаем поток для функции get_user, куда передаем id и строку из порядкового номера текущего id и общего количества. Делаем паузу на 0,4 секунды. Если же список друзей получен не был, выводим соответствующее сообщение в терминал.
Python:
def main() -> None:
global del_ch, not_del
users_check = set()
"""
Проверяем существование файла с проверенными id.
Если есть, добавляем каждый id в множество.
"""
for f_name in ["user_check.txt", "user_bad.txt"]:
if Path(f_name).exists():
with open(f_name, "r", encoding="utf-8") as fl:
for us in fl.readlines():
users_check.add(us.strip())
if frd := get_friends():
with ThreadPoolExecutor(max_workers=50) as executor:
for num, us_id in enumerate(frd):
if str(us_id) in users_check:
print(f"{Fore.RESET}{num+1}/{len(frd)} | {us_id}: {Fore.YELLOW}проверен ранее")
continue
executor.submit(get_user, user_id=us_id, nm=f'{num+1}/{len(frd)}')
sleep(0.4)
else:
print(Fore.RED + f"\nУ пользователя нет друзей.")
if __name__ == "__main__":
main()
Таким образом, при работе данной функции у меня было найдено 4 деактивированных учетных записи друзей, которые были благополучно удалены. Создано два файла, содержащие активные id друзей, а также деактивированные id.
Также, данные пользователи отобразились в самом ВК, в виде пользователей, которых необходимо удалить как подписчиков.
Таким образом, с помощью небольшого и несложного скрипта мы смогли облегчить проверку списка друзей на деактивированных пользователей – «собачек». А заодно немного попробовали работать с методами VK API. Подробнее об использованных методах можно почитать на официальной странице руководства по данным методам:
Ссылка скрыта от гостей
.
Python:
"""
Скрипт для удаления "собачек" из списка друзей ВК.
Требует для установки библиотек: vk-api и colorama:
pip install vk-api colorama
"""
from time import sleep
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from colorama import Fore, init
from vk_api import VkApi
from vk_api.exceptions import ApiError
from set import token_vk, user_vk_id
init()
session = VkApi(token=token_vk).get_api()
del_ch = 0
not_del = 0
def get_friends() -> (list, bool):
"""
Получаем список друзей пользователя и забираем их id.
"""
friends_list = []
try:
friends = session.friends.get(access_token=token_vk, user_id=user_vk_id, offset=0, count=0, v=5.131)
if friends['items']:
for item in friends['items']:
friends_list.append(item)
if friends_list:
return friends_list
return False
return False
except ApiError:
return False
def get_user(user_id: str, nm: str) -> None:
try:
"""
Получаем основные данные о пользователе.
"""
users = session.users.get(access_token=token_vk, user_ids=user_id, v=5.131)
try:
"""
Проверяем, есть ли ключ деактивации. Если да, то добавляем
"битый" id в список. Если нет, обрабатываем исключение и
добавляем не "битый" id в список проверенных.
"""
if users[0]['deactivated']:
print(f'{Fore.RESET}{nm}: {user_id}: {Fore.RED}Деактивирован')
unfollower(user_id)
return
except KeyError:
"""
Сохраняем не "битые" id для последующей проверки.
:param us_id: id пользователя
"""
with open("user_check.txt", "a", encoding="utf-8") as file:
file.write(f"{user_id}\n")
print(f'{Fore.RESET}{nm} | {users[0]["first_name"]} {users[0]["last_name"]} https://vk.com/id{user_id}: '
f'{Fore.GREEN}Активен')
return
except ApiError:
return
def unfollower(user_id: str) -> None:
global del_ch
try:
"""
Удаляем пользователя из списка друзей.
Если произошли ошибки, записываем id пользователя в файл.
"""
deleted = session.friends.delete(access_token=token_vk, user_id=user_id, v=5.131)
if deleted["success"] == 1:
print(f'{user_id}: удален')
del_ch += 1
"""
Сохраняем "битые" id в отдельный файл, для последующей проверки.
:param us_id: id пользователя
"""
with open("user_bad.txt", "a", encoding="utf-8") as file:
file.write(f"{user_id}\n")
except (ApiError, KeyError):
print(f'{user_id}: не удален')
error_save(user_id)
return
def error_save(user_id: str) -> None:
global not_del
with open("error_deleted.txt", "a", encoding="utf-8") as dl:
dl.write(f'{user_id}\n')
not_del += 1
def main() -> None:
global del_ch, not_del
users_check = set()
"""
Проверяем существование файла с проверенными id.
Если есть, добавляем каждый id в множество.
"""
for f_name in ["user_check.txt", "user_bad.txt"]:
if Path(f_name).exists():
with open(f_name, "r", encoding="utf-8") as fl:
for us in fl.readlines():
users_check.add(us.strip())
if frd := get_friends():
with ThreadPoolExecutor(max_workers=50) as executor:
for num, us_id in enumerate(frd):
if str(us_id) in users_check:
print(f"{Fore.RESET}{num+1}/{len(frd)} | {us_id}: {Fore.YELLOW}проверен ранее")
continue
executor.submit(get_user, user_id=us_id, nm=f'{num+1}/{len(frd)}')
sleep(0.4)
else:
print(Fore.RED + f"\nУ пользователя нет друзей.")
if __name__ == "__main__":
main()
Файлы с кодом прилагаю к статье во вложении.
А на этом, пожалуй – все. Спасибо за внимание. Надеюсь, данная информация будет вам полезна