Предыстория и анонс
Мы в далеком 2022 году писали статью про анализ групп Вконтакте, она обрела популярность, разлетелась по многим статьям популярных сайтов. Сейчас когда Вконтакте возвращает себе былую мощь и аудиторию, статья снова становится актуальной.
Мы обновили парсер ВК групп, восстановили его работоспособность, а так же добавили новый функционал. Помимо анализа группы по активности ее пользователей за заданный интервал времени, который был реализован еще в прошлый раз, мы добавили сохранение в excel файл результата парсинга подписчиков группы Вконтакте, который содержит поля:
- id — идентификатор пользователя (по желанию можно добавить имя/фамилию, но мы это не делаем);
- activity — активен профиль пользователя или нет (активен/удален/заблокирован);
- last_seen — дата последнего посещения пользователя (можно с точностью до секунды);
- city — город, который указан у пользователя;
- bdate — год рождения, который указан у пользователя;
- sex — пол пользователя (муж/жен, третьего у нас не дано ;-D )
- platform — идентификатор платформы с которой сидит пользователь (мобильная версия, десктоп и тд. Расшифровки нигде на нашел, если поможете буду благодарен)
- is_closed — указывает закрытая страница у пользователя или нет.
Новая функция: save_excel Сохранение в excel
Для данный функции надо установить и добавить импорт библиотеки pandas, а так же установить вспомогательные библиотеки openpyxl и XlsxWriter
Вот так выглядит новая функция:
def save_excel(data: list, filename: str):
"""сохранение результата в excel файл"""
df = pandas.DataFrame(data)
writer = pandas.ExcelWriter(f'{filename}.xlsx')
df.to_excel(writer, sheet_name='data', index=False)
writer.sheets['data'].set_column(0, 1, width=10)
writer.sheets['data'].set_column(1, 2, width=12)
writer.sheets['data'].set_column(2, 3, width=14)
writer.sheets['data'].set_column(3, 4, width=23)
writer.sheets['data'].set_column(4, 5, width=10)
writer.sheets['data'].set_column(5, 6, width=8)
writer.sheets['data'].set_column(6, 7, width=12)
writer.close()
print(f'Все сохранено в {filename}.xlsx\n')
На входе получаем data, который является списком с данными, которые мы собрали благодаря парсеру ВК, и название файла filename, типа string, который получаем из списка указанных групп для анализа.
writer.sheets[‘data’].set_column(0, 1, width=10) и последующие похожие строки строки, для того чтобы указывать ширину каждого столбца в конечном файле excel.
Модифицируем функцию get_users Добавляем поля для парсинга из Вконтакте.
Добавим в params ‘fields’: ‘last_seen, city, bdate, sex’.
last_seen — последнее посещение пользователя, предоставляется в формате timestamp и platform — с какого устройства последний раз заходил пользователь, city — город пользователя, bdate — дата рождения, sex — пол пользователя (1 или 2)
С полным списком всех полей можете ознакомится тут: Официальная документация Вконтакте. Так же прошу вашей помощи, найти расшифровку идентификаторов поля platform, я так понимаю каждая цифра это web, android и ios, но это не точно)))
В начале функции создаем списки:
- data_list — в нем будем аккумулировать собранные данные о собранных пользователях;
- active_list — для активных пользователей (которые не удалены или забанены);
- active_list_by_time — для активных пользователей за отведенное время;
- un_active_list — для всех не активных пользователей группы Вконтакте;
- banned_list — для забаненных и удаленных пользователей группы Вконтакте.
Используя метод API VK groups.getMembers получим json с данными о пользователях и распарсим его, распределяя пользователей по нашим спискам.
Многие поля из json нечитабельны, преобразуем каждый из них в визуально понятный. Например параметр sex мы получаем 1 и 2, а мы сразу укажем что 1 это жен, а 2 — муж. Параметр last_seen в формате timestamp, переведем его в дд.мм.гггг. используя стандартную библиотеку python datetime: datetime.datetime.utcfromtimestamp(user.get(‘last_seen’).get(‘time’)).strftime(‘%d.%m.%Y’). Единственное, что я не знаю, это значения 1, 2, 4, 7 из platform, пишите мне или в комментарии если вы знаете, что за что отвечает.
def get_users(group_id: str, from_data: str) -> list:
"""Получаем данные о всех пользователях в группе и сортируем их по спискам"""
data_list = [] # лист для сохранения данных о пользователях
active_list = [] # активные пользователи
active_list_by_time = [] # активные пользователи за отведенное время
un_active_list = [] # неактивные пользователи
banned_list = [] # удаленные и забаненные пользователи
total_users = ''
for offset in range(0, get_offset(group_id) + 1):
params = {'access_token': token,
'v': 5.131,
'group_id': group_id,
'offset': offset * 1000,
'fields': 'last_seen, city, bdate, sex'}
users = requests.get('https://api.vk.com/method/groups.getMembers', params=params).json()
for user in users['response']['items']:
total_users = users['response']['count']
user_id = user.get('id')
if user.get('deactivated'):
activity = user.get('deactivated')
banned_list.append(user_id)
else:
activity = 'active'
active_list.append(user_id)
try:
last_seen = datetime.datetime.utcfromtimestamp(user.get('last_seen').get('time')).strftime('%d.%m.%Y')
except AttributeError:
last_seen = None
if user.get('city'):
city = user['city'].get('title')
else:
city = None
bdate = user.get('bdate')
if user.get('sex') == 2:
sex = 'муж'
else:
sex = 'жен'
try:
platform = user.get('last_seen').get('platform')
except AttributeError:
platform = None
if user.get('is_closed'):
is_closed = 'закрытй профиль'
else:
is_closed = 'открытый профиль'
data_list.append({
'id': user_id,
'activity': activity,
'last_seen': last_seen,
'city': city,
'bdate': bdate,
'sex': sex,
'platform': platform,
'is_closed': is_closed,
})
# проверка последнего посещения, не ранее указанной даты from_data преобразованной в timestamp
start_point_data = datetime.datetime.strptime(from_data, '%d.%m.%Y').timestamp()
try:
if user['last_seen']['time'] >= start_point_data:
active_list_by_time.append(user['id'])
else:
un_active_list.append(user['id'])
except: # если дата посещения скрыта (раньше можно было скрыть, сейчас такой функции нет)
un_active_list.append(user['id'])
print(f"Количество подписчиков всего: {total_users}")
print(f"Активных подписчиков: {len(active_list)} ({round(len(active_list) / total_users * 100, 2)}%)")
print(f"Уделенных/забаненных: {len(banned_list)} ({round(len(banned_list) / total_users * 100, 2)}%)")
print(f'Активные за отведенное время: {len(active_list_by_time)} ({round(len(active_list_by_time) / total_users * 100, 2)}%)')
print(f'Неактивные за отведенное время: {len(un_active_list)} ({round(len(un_active_list) / total_users * 100, 2)}%)\n')
return data_list
В конце функции выведем на печать наши статистические данные о группе, я их переработал в отличии от прошлой версии парсера ВК, которые представлены в старой статье и сделал более информативными и удобными, плюс там были неточности в подсчетах. Все суммы и проценты результатов сходятся с реалиями и соответствуют действительности.
print(f"Количество подписчиков всего: {total_users}")
print(f"Активных подписчиков: {len(active_list)} ({round(len(active_list) / total_users * 100, 2)}%)")
print(f"Уделенных/забаненных: {len(banned_list)} ({round(len(banned_list) / total_users * 100, 2)}%)")
print(f'Активные за отведенное время: {len(active_list_by_time)} ({round(len(active_list_by_time) / total_users * 100, 2)}%)')
print(f'Неактивные за отведенное время: {len(un_active_list)} ({round(len(un_active_list) / total_users * 100, 2)}%)\n')
Изменения в основной функции parser
И последний штрих, подредактируем основную функцию нашего парсера Вконтакте
def parser(group_list):
from_data = input('Введите дату, с которой хотите отслеживать активность\nв формате: дд.мм.гггг: ')
print(f'Анализируем с {from_data}\n')
for group in group_list:
print(f'Группа: {group}')
try:
users = get_users(group_id=group, from_data=from_data)
save_excel(users, filename=f"users_of_{group}")
except Exception as ex:
print(f'{group} - не предвиденная ошибка: {ex}\n')
continue
Добавив в нее функцию сохранения. Проходя по каждой заданной группы из списка, результат будет сохраняться в excel по 1 группе отдельно. И так время тестирования, запустим наш обновленный парсер vk.com
Запуск парсера Вконтакте и сравнение с прошлой версией
Запускаем наш парсер. Я его запускаю на момент написания статьи 05.09.2024, буду анализировать свою группу за последние два месяца, то есть с 05.07.2024 (интервал в 2 месяца выбран потому что, в прошлой статье было так же)
А вот такой вывод был в старой статье:
Приятно видеть, что количество подписчиков выросло вдвое, но и удаленных/забаненных подписчиков не мало, целых 228 человек. Процент активности ~80% результат приемлемый, радует.
Смотрим excel с результатами парсинга группы ВКонтакте
Самая вишенка на торте, это наши собранные данные по подписчикам, которые мы можем анализировать и делать выводы, кто с какого города, с какой площадки сидел, какого пола, возраста и сколько их всего
Итоги парсинга пользователей в группе Вконтакте
Проанализировав группы мы понимаем, стоит ли иметь с ней дело, покупать ее, размещать там рекламу или сотрудничать, цифры не врут в отличии от людей, которые заинтересованы в навязывании своей группы.
Дополнительно, если дописать пару моментов, можно сделать чистку группы ВК от удаленных/забаненные пользователей, через специальные методы VK API, но это уже совсем другая история.
Вступайте в нашу группу ВКонтакте: HappyPython
Телеграм канал: Happy Python | Парсинг Фриланс Обучение🐍
Партнерский телеграм канал: Backend development 💻
Ссылка на код GitHub
Ссылка на нашу самую популярную статью: Парсер Wildberries (а так же запустили бота в телеграм для парсинга Вайлдберриз, канал парсера Тимур и его блог )