парсинг стены вконтакте python
Python для создания идеального поста во «ВКонтакте»
Несколько месяцев назад работал над проектом, одной из главных задач которого был максимальный охват постов во «ВКонтакте». Для выведения формулы идеального поста написал скрипт на Python, который парсил записи группы и группировал данные по часу, количеству символов и типу поста.
Сразу скажу, скрипт написан далеко не идеально, я маркетолог, а не программист.
Для примера работы скрипта взял группу Life News. На момент написания статьи было собрано 92 207 постов, последний пост датирован 1 апреля 2017 года. 17 минут затрачено на скачивание, и 5 секунд — на обработку данных.
Для работы с API «ВКонтакта» необходимо сгенерировать сервисный токен. На эту тему написано много инструкций, поэтому буду краток.
1. Перейдите на страницу создания приложения и создайте приложение «Standalone-приложение»:
2. После создания приложения перейдите в настройки и сохраните сервисный ключ доступа.
Anaconda — это дистрибутив для работы с Python, в него входит много библиотек и инструментов. Нам для реализации данного скрипта понадобится Jupiter Notebook и библиотека Pandas.
Собирать данные можно как из своих групп, так и групп конкурентов. Количество постов для анализа устанавливается вручную. Собираются все стандартные данные: количество символов в тексте, сам текст, количество просмотров, комментариев, лайков и вложений.
Первый этап разделен на два промежуточных. В первом мы импортируем необходимые для работы библиотеки. Request — для получения данных из «ВКонтакте», Pandas — для работы с данными, DateTime — для работы с датами, библиотека Time — для создания интервалов между запросами.
На втором этапе необходимо ввести исходные данные. В поле id_group — домен группы, token — токен, полученный на предыдущем этапе, count_posts — количество постов для анализа. Для того чтобы спарсить все записи, просто введите 1 000 000, алгоритм сам возьмёт максимальное количество постов.
После ввода кода в Jupiter Notebook нажимаем Ctrl+Enter и переходим на следующую строку для ввода второй части кода.
Для подключения к API мы использовали метод wall.get, более подробное описание методов API в официальной справке.
Вторая часть кода с помощью get-запроса инициирует обращение к API. Не буду подробно останавливаться на get-запросе, просто скажу, что он состоит из двух параметров: URL — ссылка для запроса, и Params — параметр запроса. В словаре params, в зависимости от ваших нужд, можно поменять переменную filter на owner — посты только от владельца, all — все посты, others — гостевые посты.
Подробное описание всех параметров доступно в справке.
Ответ получаем в JSON-формате и записываем его в переменную r. Из-за ограничений API за одно обращение мы можем забрать только 100 постов. Поэтому за каждую итерацию цикла 100 постов добавляются в массив данных data_posts. Также для обхода ограничения по количеству запросов в секунду я добавил time.sleep(0.5), что позволяет сделать паузу в полсекунды между запросами.
Для работы с данными нам понадобится библиотека Pandas. Pandas — одна из самых популярных библиотек для анализа и обработки данных. Работа с библиотекой строится через объект Data Frame, внешне он напоминает таблицу, но это не совсем так. Для начала работы с DF нам необходимо преобразовать и обработать данные из JSON-формата.
Для начала создадим пустой массив, где будут храниться данные stats = []. Как вы помните, мы записывали все данные поступающие из «ВКонтакте» в массив data_posts. Теперь наша задача вытащить из него только нужное. Для обхода всего массива мы создаём цикл For, такая конструкция for record in data_posts: позволит работать с одним постом за один обход цикла.
За название поста я брал первую строчку и ограничил длину 80 символами. Это подходило исключительно для моего проекта, вы переделайте алгоритм под ваш проект. Для того чтобы записать в переменную title текст, достаточно title = record[‘text’]. Далее я замерил длину текста и разделил на 100, взяв только целое число для удобной группировки.
Переменные Date и Hour — это дата в формате «гггг-мм-дд» и час выхода поста соответственно. Следующий блок кода — это поиск и подсчёт количества вложений. Все они перечислены в словаре attachments.
Последнее условие проверяет, есть ли в данных о посте количество просмотров. «ВКонтакте» относительно недавно ввела количество просмотров в записи, и поэтому при получении постов, опубликованных раньше 2017 года, скрипт выдавал ошибку, так как ключ Views отсутствовал. По этой причине я записывал в такие посты 0;
В этой части кода мы подсчитываем сумму активностей и добавляем в наш массив данные, которые нам интересны.
В последнем фрагменте третьей части мы записываем наши данные в Data Frame. Сначала необходимо задать название столбцов, я задал их через массив columns. После чего мы создаём объект Data Frame и в качестве аргументов передаём в него массив данных stats и название заголовков columns. Готово, объект создан, и теперь с ним можно работать.
Получившийся Data Frame группируем по часу, типу постов и длине текстов и вычисляем показатели вроде средней активности на пост, просмотров на пост и ER.
И записываем в Excel-файл.
Файл записывается туда же, где находится файл Jypter Notebook. Он содержит исходные необработанные данные, сгруппированные данные по часу, сгруппированные данные по количеству символов и группировку по вложениям.
Надеюсь, данный гайд поможет вам найти формулу вашего идеального поста.
я маркетолог, а не программист
И в то же время в этой статье вы офигенный программист, но никакой маркетолог. Собрали все популярные ошибки причинно-следственной связи в одном месте.
Все полученные факты будут верны тольк для группы Life News, но никак не помогут в других местах. Но и это не все
Лучшее время для постинга с 19:00 до 22:00
В любой группе, если выгрузить данные, будет интервал, где больше лайков и активности. Это не лучше время для постинга, а просто факт. Корни его растут из среднего возраста аудитории, их времяпровождения, и коррелирует с тематикой конкретного поста, общей тематикой постов сообщества.
Не учитывать это нельзя, нельзя только на время смотреть
Посты без встроенной ссылки собирают больше активностей на пост и ER в 2 раза выше.
Есть же базовая методика проверок гипотез, доверительные интервалы, вероятности ошибок. Я думал в маркетинге оно должно минимально использоваться, или хотя бы помнить, что бывают необходимые и достаточные условия, что надо в обе стороны смотреть факты.
И потом в статье все прямо красиво про обработку, душа радуется. Надеюсь, вам не будет обидно из-за написанного выше
Анализ дружеских связей VK с помощью Python
Совсем недавно на Хабре появилась статья о реализации дружеских связей в ВКонтакте с помощью Wolfram Mathematica. Идея мне понравилась, и, естественно, захотелось сделать такой же граф, используя Python и d3. Вот, что из этого получилось.
Внимание! В статье будут присутствовать части кода, описывая самые важные действия, но следует учесть, что проект претерпит еще не одно изменение в своей кодовой базе. Заинтересовавшиеся могут найти исходники на GitHub.
Создание и авторизация приложения
Чтобы получить доступ к API ВКонтакте, нам необходимо создать Standalone-приложение, после чего мы сможем использовать нужные нам методы API, которые будут описаны далее. Приложение создается здесь — выберем Standalone-приложение. Нас попросят ввести код-подтверждения, высланный на мобильный, после чего мы попадем на страницу управления приложением. На вкладке Настройки нам пригодится ID приложения для получения access_token.
Далее нам надо авторизовать наше приложение. Этот процесс состоит из 3х этапов.
Аутентификации пользователя на сайте ВКонтакте
Для этого сформируем url, как показано ниже:
APP_ID – идентификатор Вашего приложения;
PERMISSIONS – запрашиваемые права доступа приложения;
DISPLAY – внешний вид окна авторизации, поддерживаются: page, popup и mobile.
REDIRECT_URI – адрес, на который будет передан access_token.
API_VERSION – версия API, которую Вы используете.
В нашем случае PERMISSIONS — это доступ к друзьям и к API в любое время со стороннего сервера (бессрочный токен). Если адрес сформирован правильно, нам предложат ввести логин и пароль.
Разрешение доступа к своим данным
Получение access_token
После авторизации приложения клиент будет перенаправлен на REDIRECT_URI. Нужная нам информация будет заключена в ссылке.
Редактируем файл settings.py, вставляя туда полученные access_token и user_id. Теперь мы можем осуществлять запросы к API ВКонтакте.
Получение данных
Для начала разберем методы, которые будем использовать для данной цели.
Поскольку нужна хоть какая-то информация об id пользователя, по которому будет строиться граф, нам пригодиться users.get. Он принимает как один id, так и несколько, список полей, информация из которых нам необходима, а также падеж, в котором будет склоняться фамилия и имя. Мой метод base_info() получает список id и возвращает информацию о пользователе с фотографией.
Это может быть важно для тех, кто захочет отправлять в него id из friends.getMutual, таким образом произведя на свет огромное число запросов. Об этом позже.
Теперь нам надо получить информацию о друзьях пользователя, в чем нам и поможет метод friends.get. Из всех его параметров, перечисленных в документации, используем user_id, который находится в нашем setting.py и fields. Дополнительными полями будут id друзей, их имена, фамилии и фотографии. Ведь хочется, чтобы в узлах были миниатюры их фотографий.
Далее наступает самое интересное.
Список id общих друзей между двумя пользователями возвращает метод friends.getMutual. Это хорошо, потому что мы получаем только id, а более расширенная информация у нас уже есть, благодаря friends.get. Но никто не запрещает сделать вам лишнюю сотню-другую запросов, используя users.get. Схемы расположены чуть-чуть пониже.
Теперь определимся, как будем использовать friends.getMutual. Если у пользователя N-друзей, то надо сделать N-запросов, чтобы по каждому другу мы получили список общих друзей. К тому же нам надо будет делать задержки, чтобы у нас было допустимое количество запросов в секунду.
Предположим, что у сканируемого нами id есть 25 друзей.
И тут нам пригодится execute, который позволит запустить последовательность методов. У него есть единственный параметр code, он может содержать до 25 обращений к методам API.
То есть в итоге код в VKScript будет примерно таким:
Найдитесь те, кто напишет, как сократить данный код, не используя все время API.friends.getMutual.
Теперь нам надо всего лишь отправлять партиями id друзей по 25 в каждой. На нашем примере схема будет выглядеть так:
А ведь мы могли с помощью for отправлять каждого друга в friends.getMutual, а потом еще узнавать более детальную информацию через users.get.
Далее составим человеко понятную структуру, где уже вместо id друга и списка id ваших общих друзей, будет информация из friends.get. В итоге получим нечто вроде:
В словарях находится id, имя, фамилия, фото, в списках — словари общих друзей, если общих друзей нет, то None. Кортежами все это разделяется.
Итак, если хочется посмотреть свой список друзей и общих с ними друзей, запускаем:
Визуализация графа
Выбор пал на d3, а именно на Curved Links. Для этого надо сгенерировать json, который будет примерно такого содержания:
Немного видоизменяя index.html, узлами становятся фотографии друзей.
Если хочется сразу визуализировать граф:
Визуализация подтормаживает при большом количестве друзей, поэтому на будущее я думаю об использовании WebGL.
Так выглядит граф дружеских связей одного из моих друзей. Связи — это все.
Конечно, мне было интересно, у кого работает быстрее.
В статье, которая меня вдохновила, написано:
На моих 333 друзьях это заняло 119 секунд.
На момент написания этой статьи, у Himura в ВКонтакте был 321 друг. У меня это заняло 9 секунд (работа всей программы, а не одного friends.getMutual).
В заключение
Всю необходимую информацию об использованных методах можно найти в щедро написанной документации ВКонтакте, однако мной была обнаружена пара ошибок: не была описана ошибка с кодом 15 (‘error_msg’: ‘Access denied: user deactivated’, ‘error_code’: 15), догадаться можно, что она значит, и uid вместо user_id в документации к методу friends.get. Спустя 2 дня:
Как говорилось вначале, проект можно найти на GitHub, буду рад, если он понравится ещё кому-то и я получу много вкусных пулл реквестов…
Блог об аналитике, визуализации данных, data science и BI
Дашборд первых 8 месяцев жизни малыша
Анализ рынка вакансий аналитики и BI: дашборд в Tableau
Анализ альбомов Земфиры: дашборд в Tableau
Гайд по современным BI-системам
Парсинг целевой аудитории ВКонтакте
При размещении рекламы некоторые площадки в настройках аудитории позволяют загрузить список конкретных людей, которые увидят рекламу. Для парсинга id по конкретным пабликам существуют специальные инструменты, но куда интереснее (и дешевле) сделать это собственноручно при помощи Python и VK API. Сегодня расскажем, как для рекламной кампании LEFTJOIN мы спарсили целевую аудиторию и загрузили её в рекламный кабинет.
В материале «Собираем данные по рекламным кампаниям ВКонтакте» подробно описан процесс получения токена пользователя для VK API
Парсинг пользователей
Для отправки запросов потребуется токен пользователя и список пабликов, чьих участников мы хотим получить. Мы собрали около 30 сообществ, посвящённых аналитике, BI-инструментам и Data Science.
Запрос на получение участников сообщества к API ВКонтакте вернёт максимум 1000 строк — для получения последующих тысяч потребуется смещать параметр offset на единицу. Но нужно знать, до какого момента это делать — поэтому опишем функцию, которая принимает id сообщества, получает информацию о числе участников сообщества и возвращает максимальное значение для offset — отношение числа участников к 1000, ведь мы можем получить ровно тысячу человек за раз.
Следующим этапом опишем функцию, которая принимает id сообщества, собирает в один список id всех подписчиков и возвращает его. Для этого отправляем запросы на получение 1000 человек, пока не кончается offset, вносим данные в список и возвращаем его. Проходя по каждому человеку дополнительно проверяем дату его последнего посещения социальной сети — если он не заходил с середины ноября, добавлять его не будем. Время указывается в формате unixtime.
Теперь пройдём по всем сообществам из списка и для каждого соберём участников, а затем внесём их в общий список all_users. В конце переводим сначала список в множество, а затем опять в список, чтобы избавиться от возможных дубликатов: одни и те же люди могли быть участниками разных пабликов. Лишним не будет после каждого паблика приостановить работу программы на секунду, чтобы не столкнуться с ограничениями на число запросов.
Последним шагом записываем каждого пользователя в файл с новой строки.
Аудитория в рекламном кабинете из файла
Переходим в свой рекламный кабинет ВКонтакте и заходим во вкладку «Ретаргетинг». Там будем кнопка «Создать аудиторию»:
После нажатия на неё откроется новое окно, где можно будет выбрать в качестве источника файл и указать название для аудитории:
После загрузки пройдёт несколько секунд и аудитория будет доступна. Первые минут 10 будет указано, что аудитория слишком мала: это не так и панель вскоре обновится, если в вашей аудитории действительно более 100 человек.
Итоги
Сравним среднюю стоимость привлечённого в наше сообщество участника в объявлении с автоматической настройкой аудитории и в объявлении, аудиторию для которого мы спарсили. В первом случае получаем среднюю стоимость в 52,4 рубля, а во втором — в 33,2 рубля. Подбор качественной аудитории при помощи методов парсинга данных из ВКонтакте помог снизить среднюю стоимость на 37%.
Для рекламной кампании мы подготовили такой пост (нажмите на картинку, чтобы перейти к нему):
Парсинг сайтов через Python
Всем привет. Сегодня я расскажу о парсинге сайтов на Python.
Для начала установим модуль:
Далее создаем файл и добавляем модуль
from bs4 import BeautifulSoup
На этом подготовка окончена. Переходим к предисловию.
Я надеюсь все когда-нибудь заходили в инструменты разработчика и попадали на страницу «Elements», в которой видели какой-то большой текст, который при изменении меняет страницу. Это и есть HTML, его мы и будем парсить.
У каждого элемента есть свой childNode или parentNode. Это элементы в иерархии страницы.
Так же у элементов есть свой класс или айди.
Каждый элемент имеет свой тег
Сегодня мы будем парсить сайт vk.com, а именно мою группу, в которой будет эта статья. Будем парсить кол-во лайков на каждый записи
Имея ссылку (https://vk.com/p3rthython) можно получить html страницы
Имея html-страницу можно получить её распарсенный вид
Теперь можно получать элементы со страницы. Для этого есть метод find(для первого элемента с указанными аргументами) и find_all(для всех элементов с указанными аргументами).
Так как цель это пропарсить кол-во лайков на каждой записи, то нам нужно найти элемент, который хранит в себе кол-во лайков. Для этого есть прекрасная функция в инструментах разработчика, которая при клике показывает элемент, на который было совершенно нажатие, либо наведение
Я получил такой элемент с тегом div и классом like_button_count
Как нам его получить в коде?
Для этого нужно воспользоваться поиском через find_all, т.к цель распарсить кол-во лайков на каждой записи
Первый аргумент — тег, второй — словарь, с атрибутами. В них может быть любое значение и ключ, которое имеет этот элемент. Сначала указываем атрибут(это и будет ключ), после значение атрибута(значение ключа).
Занесем эти элементы в переменную likes_count и выведем её в консоль:
Мы ничего не получили, потому что вк автоматически переносит нас в мобильную версию, если мы им не скажем, что мы не с мобильного устройства. Для этого нужно указать доп. параметры(заголовки) для запроса, а именно user-agent(информация о браузере). Заголовки — словари, которые передаются в качестве аргумента в запрос.
2. Создаем ключ(User-Agent) со значением User-Agent обычного браузера(я буду использовать Chrome).
Можете скопировать Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36
3. Добавляем наш словарь, как аргумент
Ура! Мы получили список элементов,но кол-во постов 3, а кол-во элементов 11.
Перейдем в браузер и при помощи Ctrl + F во вкладке Elements ищем элементы с классом like_button_count. Как оказалось этот класс используется для лайков, репостов и кол-ва комментариев. Для получения именно для лайков мы будем использовать childNodes и parentNodes.
Мы будем искать все посты и дальше при помощи childNodes искать именно кол-во лайков.
Заметим, что у каждого поста есть одинаковые классы
Мы будем искать по классу _post. Перепишем код. Заменим переменную likes_count на posts. Так же заменим нужный класс на _post
Выведем переменную posts:
Мы получили нужный нам результат, но так как я из Республики Беларусь, то текст немного меняется на белорусский язык. Для исправления этого я поставлю прокси в запрос(не запуск с прокси, а прокси в запросах).
Для этого создадим еще 1 словарь(я назову его ru_proxy).
Теперь нужно добавить ключ https (если вы делаете запрос и на https, и на http, то добавляйте 2 ключа) в него вписываем наш прокси в формате ip:port
Так как мои прокси с паролем, то нужно немного изменить значения ключа https на
Если у вас запрос по протоколу http, то делаете аналогично, но теперь http.
Добавляем прокси в запрос
В аргумент proxies ставим значение ru_proxy
Теперь всё работает на русском языке)
Переходим к постам. Родитель класса с количеством лайков это тег A с классами like_btn like _like
Так как этот элемент находится в каждом посте, то нам нужно итерировать посты и искать этот элемент в каждом посте
Вот что нам выводится в консоль
А это уже ровно 3 поста, а не 11 как было раньше. Но появился пустой список, его мы будем пропускать через оператор if
Теперь всё еще легче, нам просто нужно достать кол-во лайков из каждого элемента:
Тут я использовал find, т.к получение списка нам не нужно.В консоли мы получили такой результат