Читать нас в Telegram
© pixabay.com

Введение

Практически всем, кто занимается количественными исследованиями, знакома следующая проблема: идея есть, а данных для её реализации нет. И хотя сейчас существует немало сайтов с данными (например, Kaggle.com (https://www.kaggle.com/), где можно найти как корпус обзоров на вино, так и классификатор древнеяпонских иероглифов или метаданные по коллекциям Metropolitan Museum of Art), все равно найти что-то готовое, что соответствовало бы индивидуальным нуждам конкретного исследования, довольно сложно. В таких случаях остается одно: выкачивать данные самостоятельно.
ВКонтакте — ценный источник данных, который может помочь в лингвистических, социологических и других исследованиях. Хочется исследовать корпус авторских стихотворных сочинений подростков? Пожалуйста, практически готовый корпус уже ожидает тебя в группе, посвященной поэзии! Хочется понять, как в реальности работает теория шести рукопожатий? Выкачай случайных пользователей и построй граф!
На самом деле, это совсем не сложно, и сегодня мы покажем, как скачать заветные данные.

Что понадобится?

  1. Аккаунт ВКонтакте
  2. Среда для работы с Python* (уметь программировать почти не надо)
  3. Желание и немного времени

*Например, любые IDE: PyCharm, Sublime Text или любой другой, какой душе угодно. Мы в данном руководстве будем использовать оболочку Jupyter, функционал которой удобен для аналитики: можно писать и редактировать код на каждом этапе, не прогоняя всю программу целиком, строить красивые визуализации и делать ещё кучу всего интересного. Подробнее об установке и возможностях Jupyter можно посмотреть тут.

Примите во внимание, что код для туториала написан с целью помочь понять, что происходит и как все работает, поэтому не является образцом великолепия.

Этап 1. Получение ключа к ВК API

Первый шаг на пути к данным состоит в том, чтобы получить доступ к ВKонтакте API (Application Programming Interface), с помощью которого мы и будем дальше взаимодействовать с ВКонтакте. API содержит в себе множество методов, которые позволяют быстро доставать из базы ВК нужную информацию, например, со страниц пользователей, групп и т.д. (вернее, только ту информацию, которая не скрыта).
Чтобы иметь возможность их использовать, надо авторизоваться в ВК и создать Standalone приложение на странице API. Для этого надо во вкладке Мои приложения нажать Создать приложение.
Дальше надо выбрать Standalone-приложение, назвать его и подключить.
Как только вы его подключите, вы окажетесь во вкладке Информация, где находятся описание, название и т.д. Здесь трогать ничего не нужно, и можно сразу перейти на вкладку Настройки слева. Здесь мы смотрим на Сервисный ключ доступа, который надо скопировать или запомнить, потому что он нам понадобится дальше.
Страничку API пока оставляем открытой, мы к ней ещё вернемся чуть позже.

Этап 2. Пишем код

Часть 1. Пользователи

Шаг 1

Теперь, когда у нас есть ключ доступа к API, можно смело переходить к самой интересной части — написанию кода. Для начала устанавливаем библиотеки и подгружаем нужные модули оттуда. В туториале мы будем использовать библиотеку requests — пакет, который позволяет посылать http-запросы на сервер и отдавать ответы на эти запросы в различных форматах*.

 import requests

** Если не знаете как устанавливать библиотеки в Python, не пугайтесь, Интернет полон различных гайдов о том, как это делать. Например, вот.
***На самом деле, это только один из способов добычи данных ВКонтакте через Python. Существует ещё некоторое количество библиотек, которые позволяют получать ответы от ВКонтакте API другими способами. Они очень хорошо гуглятся, так что при желании можно освоить и альтернативные техники. Или если кто-то уже знаком с другими методами, будет здорово услышать о них в комментариях).

Шаг 2

Теперь разберемся в том, как, собственно, делать запросы к ВКонтакте API. По сути, все это нам уже рассказали разработчики: мы формируем http-запрос о нужной нам информации, который мы отправляем в базу ВК. При этом разработчики ВК даже предлагают шаблон запроса:
Часть, которая нам интересна, выделена жирным шрифтом:
METHOD_NAME — обязательный параметр — метод, который мы хотим применить. Выбирается в зависимости от того, какую информацию мы хотим достать из базы. Полный список методов ВКонтакте API доступен по ссылке. Метод отделяется от последующих частей запроса символом ?.
PARAMETERS — это уже опциональный параметр, для каждого метода свой набор. Каждый метод по умолчанию отдает некоторую изначальную информацию, которую можно расширить с помощью этого параметра. Если параметров несколько, то они разделяются между собой символом &.
ACCESS_TOKEN — помните тот сервисный ключ доступа со странички разработчиков, который мы запомнили ранее? Это он и есть. Ключ обязателен при составлении запроса.
V — версия ВК API, без которой также нельзя сформировать запрос. На момент написания статьи версия API — 5.92.

Шаг 3

Рассмотрим процесс формирования и отправления запроса. Для начала определимся, что именно мы хотим достать. Допустим, что-то связанное с данными пользователей. Посмотрим список доступных методов и что они могут нам предложить. Для этого в списке методов выберем вкладку Users.

Появился список методов для работы с данными пользователей.

Шаг 4

Итак, попробуем вытащить расширенную информацию о пользователе. Откроем страницу метода get и внимательно читаем параметры. Допустим, мы хотим получить информацию о пользователе с идентификатором 1 (user_ids=1).
Для начала запишем ключ доступа и версию ВК API в отдельные переменные формата «строка», чтобы мы могли их использовать потом****.

access_token = 'your token'
api_version = '5.89'

* Заметьте, что так как мы используем Jupyter Notebook, нам не требуется создавать отдельный файлик на компьютере, хотя такой вариант и возможен. Но мы просто зададим ключи как переменные в отдельной ячейке скрипта. Теперь сформируем запрос к API. Для обращения к методу надо перед его названием написать, к какой группе он относится (так как названия методов пересекаются в различных группах). Мы записываем запрос как форматируемую строку, где значения в {} будут принимать значения переменных, которые там записаны**.

res_users = requests.get(f'https://api.vk.com/method/users.get?user_ids=1&access_token={access_token}&v={api_version}')

И посмотрим на результат

res_users.json()

По умолчанию (без заданных параметров) мы получили просто имя, фамилию и статус страницы.

***** Если вы хотите получить информацию больше, чем об одном человеке, вы можете записать их идентификаторы через запятую. Если пользователей много, то можно задать их id в отдельной переменной (допустим, загрузить из файла), и записать её также в {}. Важно, чтобы они были разделены через запятую. Подробнее о форматировании строк в Python.

Шаг 5.

Теперь добавим конкретики. Допустим, мы хотим получить ещё даты рождения, страну и город. Эти поля находятся в параметре fields, как говорит нам документация.

res_users = requests.get(f'https://api.vk.com/method/users.get?user_ids=1&fields=bdate, city&access_token={access_token}&v={api_version}')

Шаг 6.

Пойдем дальше: скачаем 200 друзей Павла Дурова и запишем их в отдельный список. Для этого нам потребуется функция из той же вкладки Users — getFollowers.
Сначала оформим запрос в виде строки, в которой мы будем потом форматировать части, находящиеся в {}.

url = ’https://api.vk.com/method/users.getFollowers?user_id=1&fields=city,country&count=100&offset={offset}&access_token={access_token}&v={api_version}’

Тут у нас появляется новые параметры — count и offset. Сount показывает, сколько друзей за один запрос мы будем выкачивать, а offset — на сколько значений мы будем сдвигаться каждый раз, когда отправляем новый запрос. То есть если бы параметра offset не было, мы бы каждый раз скачивали только 100 первых друзей, а с ним мы по очереди (итеративно) выбираем каждую следующую сотню.
Итак, сначала мы создаем пустой список friends, в который мы потом запишем выгруженных пользователей. Потом мы определяем, какие отступы (offset) у нас будут каждый раз и с каким шагом. За это отвечает функция range: условно говоря, у нас будет 3 шага от 0 до 300, каждый из которых будет равен 100. После чего мы циклом выкачиваем по 100 подписчиков за каждую итерацию. И в конечном итоге записываем фамилии пользователей в список.

friends = []
for i in range(0, 201, 100):
	url_formatted = url.format(access_token = access_token, api_version = api_version, offset = i)
	print(i)
	res_friends = requests.get(url_formatted)
	for friend in res_friends.json()["response"]['items']:
        friends.append(friend["last_name"])

И вуаля! Список подписчиков готов!

Часть 2. Сообщества

А теперь предположим, что для наших исследовательских целей мы хотим получить корпус каких-нибудь текстов. Для этого мы можем, например, скачать стену какого-то сообщества или пользователя.
Принцип тут тот же, что и при работе с юзерами: выбираем метод, формируем запрос, наслаждаемся.
Список методов для работы со стенами находится в соответствующей вкладке Wall в документации. Если мы хотим выкачать посты на стене, то нам нужен метод wall.get.
Давайте попробуем скачать посты сообщества Вышкинские хокку. Для начала попробуем выкачать первые 100 публикаций.

res_wall = requests.get(f'https://api.vk.com/method/wall.get?domain=hsehokku&count=100&access_token={access_token}&v={api_version}')

По сути, ничего особо не изменилось, кроме метода и его параметра: domain содержит короткий адрес сообщества, с которого мы выкачиваем данные.
Посмотрим на выдачу по первому посту: мы получили не только сам текст публикации, но и метаинформацию к нему, которую также при желании можно вытащить из списка и использовать.

Но мы в учебных целях сосредоточимся только на текстах публикаций. Теперь давайте соберем первые 400 постов со стены и запишем их в файлик на компьютере, чтобы можно было использовать потом.

Шаг 1

Пишем строку запроса, в который добавляем параметр offset, который отвечает за отступы.

url = 'https://api.vk.com/method/wall.get?domain=hsehokku&count=100&offset = {offset}&access_token={access_token}&v={api_version}'

Шаг 2

Создаем пустой список texts, в который будем записывать тексты. Потом пишем цикл, который будет выкачивать по 100 постов за каждую из 4-ех итераций, и записывать каждый пост в созданный список.

texts = []
for i in range(0, 301, 100):
	url_formatted = url.format(access_token = access_token, api_version = api_version, offset = i)
	print(i)
	res_wall = requests.get(url_formatted)
	for post in res_wall.json()["response"]['items']:
    	texts.append(post["text"])

Посмотрим на то, как это выглядит в списке:
Ага, в тексте есть лишние символы, а точнее \n. Это всего лишь разделитель: он показывает, что текст в данном месте в оригинале начинается с новой строки.

Шаг 3

Создаем в корневой папке на компьютере файл texts.txt, в который мы и запишем итоговый результат.

Шаг 4

Записываем посты из списка texts в файл texts.txt. И заменим символы \n в тексте на нормальные разделители строки.

with open("vk.texts.txt", "wt", encoding = "utf8") as f:
	for text in texts:
    	f.write(text.replace("\n", " ") + "\n")

Поздравляем, вы стали счастливым обладателем сборника страдальческих студенческих хокку!
В туториале показаны основы работы в ВКонтакте API с помощью Python. На деле ВК может предоставить намного больше: можно искать пользователей по заданным критериям, скачивать фотографии и ещё кучу всего интересного. Главное теперь — не бояться обилия методов в документации и искать то самое, что нужно именно вам.

Полный код на Github