Пример использования VK API в Python

Хочу поделиться опытом, как я использовал Питона в одном из своих проектов по рекламе в VK. Для тех кто не в курсе, Питон — это такой язык программирования.

Данная статья может пригодиться тем, кто учится программировать на Питоне или занимается рекламой в VK.

Описание задачи и пути решения

Мне потребовалось найти VK-группы в заданном городе по нескольким ключевым словам, чтобы запустить на них рекламу. Эти группы нужно было где-то сохранить, чтобы не искать каждый раз по новой.

По каждой группе мне важна следующая информация:

  • id — чтобы использовать в рекламе;
  • name — чтобы оценить подходит группа или нет (Например, для ключевого слова «ремонт» может быть ремонт квартир или ремонт машин);
  • members_count — чтобы оценить размер группы;
  • contacts — чтобы получить список id пользователей, на которых не следует давать рекламу;
  • группы должны быть отсортированы по отношению дневной посещаемости к количеству пользователей — чтобы не использовать группы, которые никто не посещает.

Сначала, я начал искать группы используя стандартный поиск. Но это оказалось очень не быстро. На пятой группе я призадумался о более быстром способе.

Более быстрый способ оказался VK API через браузер. В документации VK https://vk.com/dev/manuals подробно написано, как это делать.

В конечном итоге, я решил использовать VK API в Python, чтобы решать подобные задачи за секунды.

Как использовать VK API через браузер

Для работы с VK API через браузер, прежде всего, необходимо получить так называемый access_token.

Делается это очень просто. Нужно просто указанный ниже код вставить в адресную строку браузера.

https://oauth.vk.com/authorize?client_id=6478436&display=page&redirect_uri=https://oauth.vk.com/blank.html&scope=friends&response_type=token&v=5.95

После успешной авторизации ваш браузер будет перенаправлен на другую страницу, а ключ доступа к VK API будет передан в качестве фрагмента URL-ссылки. Смотрите пример ниже. Ключ выделен жирным.

https://oauth.vk.com/blank.html#access_token=a8242171ff063622476fa7b3e0cc25690d698d8c92050e7918750e9083bcb0ed5c7ba2406eaee58ae73d6&expires_in=86400&user_id=133147577

Полученный ключ доступа следует сохранить в надёжном месте. Он будет использоваться при каждом запросе к методам API. Заменяйте ключ из примера своим ключом, чтобы всё работало.

Метод database.getCities

Этот метод я использовал, чтобы получить код (id) города, в котором искать нужные мне группы. Привожу для примера свой запрос. Вам нужно будет поменять ключ доступа access_token и город q на свой.

https://api.vk.com/method/database.getCities?v=5.55&access_token=a8242171ff063622476fa7b3e0cc25690d698d8c92050e7918750e9083bcb0ed5c7ba2406eaee58ae73d6&country_id=1&q=Балашиха

В случае успешного запроса будет выдан следующий ответ:

{«response»:{«count»:2,»items»:[{«id»:24,»title»:»Балашиха»,»area»:»Городской округ Балашиха район»,»region»:»Московская область»},{«id»:21613,»title»:»Железнодорожный (Балашиха)»,»area»:»Городской округ Балашиха район»,»region»:»Московская область»}]}}

Как видно из примера, id города равен 24. Будем использовать это номер в качестве параметра city_id при вызове следующего метода.

Метод groups.search

Этот метод я использовал, чтобы получить id групп соответствующих запросу по ключевому слову. В нижеприведённом примере нужно будет заменить аргументы access_token, city_id и q на соответствующие ваши.

https://api.vk.com/method/groups.search?v=5.95&access_token=a8242171ff063622476fa7b3e0cc25690d698d8c92050e7918750e9083bcb0ed5c7ba2406eaee58ae73d6&city_id=24&q=двери&sort=2&count=500

Успешный ответ может быть очень большим. Поэтому привожу его для примера в сокращенном виде.

{«response»:{«count»:8,»items»:[{«id»:147347745,»name»:»Установка дверей, ремонт балконов. Балашиха, ВАО»,»screen_name»:»club147347745″,»is_closed»:0,»type»:»group»,»photo_50″:»https:\/\/pp.userapi.com\/c837325\/v837325464\/47b4c\/GkASpGhOtM4.jpg?ava=1″,»photo_100″:»https:\/\/pp.userapi.com\/c837325\/v837325464\/47b4b\/SrZFgLWXXBU.jpg?ava=1″,»photo_200″:»https:\/\/pp.userapi.com\/c837325\/v837325464\/47b4a\/BrMPXrYAViI.jpg?ava=1″}, ]}

Это пример выводе первой группы, а всего их может быть до 500. Группы сортируются по отношению дневной посещаемости к количеству пользователей (sort=2).

Ответ получен в формате json. Этот формат не очень удобен в данном случае. Поэтому его нужно преобразовать в формат csv. Для этого копируем текст ответа (Ctrl+A, Ctrl+C), и используем какой-нибудь онлайн-конвертер. Например, этот http://www.convertcsv.com/json-to-csv.htm.

Ответ вставляем в верхнее поле (Ctrl+V), как на рисунке ниже, и нажимаем кнопку «Convert JSON To CSV». Результат можно скачать с помощью кнопки «Download Result».

Открыть полученный файл можно с помощью Excel.

На данном этапе нас интересует только первый столбик id. Нам нужно получить его в виде значений разделённых запятыми, чтобы использовать затем в качестве аргумента при вызове следующего метода VK API.

Я получаю его следующим способом. Копирую все значения столбика id. Затем вставляю его в новый файл используя Вставить Как… с опцией «Транспонировать». То есть преобразую столбец таблицы в строку. Теперь сохраняю этот файл формате csv.

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

96779849,147347745,84074989,77485430,95963951,139751651,130165257,88654849

Данный текст мы копируем, чтобы использовать в качестве аргумента group_ids при вызове следующего метода.

Метод groups.getById

Этот метод я использовал, чтобы получить список групп города соответствующих запросу со всеми необходимыми по условию данными. Пример запроса ниже.

https://api.vk.com/method/groups.getById?v=5.95&fields=members_count,contacts&access_token=a8242171ff063622476fa7b3e0cc25690d698d8c92050e7918750e9083bcb0ed5c7ba2406eaee58ae73d6&group_ids=96779849,147347745,84074989,77485430,95963951,139751651,130165257,88654849

Ответ будет получен, как обычно, в формате json. Его нужно будет преобразовать в формат csv, способом описанным выше.

Для сохранения порядка сортировки групп по отношению дневной посещаемости к количеству пользователей, я в полученный csv-файл добавил столбец ‘sort2’ , в котором последовательно пронумеровал все строки. Образец файла ниже.

Балашиха-двери.csv
sort2idtypeis_closedscreen_namenamemembers_countcontacts
1147347745group0club147347745Установка дверей, ремонт балконов. Балашиха, ВАО218[{'user_id': 308576095}]
296779849group0bastionsdoorsСтальные двери Бастион-C2653[{'user_id': 397896396, 'phone': '+74955057080', 'email': 'dveri@bastion-s.ru', 'desc': 'Менеджер-консультант '}, {'user_id': 237109628, 'desc': 'Дизайнер '}]
384074989group0timartdveryДвери Надмосковья782[{'phone': '8 925 555 40 30 ', 'email': 'mail@timartdoors.ru'}, {'phone': '8 916 562 99 25', 'email': 'mail@timartdoors.ru'}]
477485430page0dveriarmadaДвери Армада. Выбираем правильно!111[{'user_id': 16257595, 'phone': '+74951351374', 'email': 'Info@zavod-armada.ru', 'desc': 'Эксперт/Заявка на выезд мастера/Промо-код Юлин'}]
595963951group0club95963951Межкомнатные и металлические двери.СТРОЙВЕСТ.2588[{'user_id': 26986762}]
6139751651group0dveri_v_balashiheМежкомнатные двери в Балашихе71[{'user_id': 307843491}, {'user_id': 247429000}]
7130165257group0dverin1Мир дверей26[{'user_id': 205312602}]
888654849group0club88654849BARIER-HOUSE стальные двери в Москве15[{'user_id': 278636008}]


Использовать VK API для данной задачи, даже просто через браузер, гораздо быстрее, чем пользоваться стандартным поиском. Тем не менее, этот способ не самый быстрый. На поиск и анализ всех групп по всем запросам у меня ушло более двух часов.

Учитывая, что подобную задачу приходится решать практически в каждом проекте, было решено реализовать это с помощью программирования.

Как использовать VK API в Python

Реализация описанного выше алгоритма на Python-е оказалась проще, чем я ожидал. От начала программирования до рабочей версии программы прошло около 40 минут. Получается, если бы я сразу начал программировать, то всё получилось бы быстрее часа на два. Это даже несмотря на то, что пришлось тратить время на изучение самого языка.

Для реализации взял первую попавшуюся библиотеку для работы с VK в Python-е. Установил её следующей командой:

pip3 install vk --user

Ключ «—user» я использовал, чтобы избежать ошибок с разрешениями. У меня Linux, а ключ позволяет установить пакет только для текущего пользователя.

С самого начала была задача сделать как можно быстрее и проще, поэтому для реализации была выбрана консольная версия, где параметры задаются внутри кода. Таким образом, программа начинается с определения параметров.

# Параметры:
access_token = '3716eefa82841782e8d1093e01fb1eb89a00eaf089e849172a169d073b8e16565ab38edb43fe41d68dbad'
v = '5.95'
keyword_city = "Балашиха"
keywords_groups = ['ремонт', 'потолки', 'мебель', 'двери']

Следующим этапом было подключиться к VK API. Тут всего две строчки, но на них я застрял минут на 20. Сразу не понял как работает библиотека. Здесь соответственно мой access_token нужно поменять на ваш.

# Подключение к VK API
session = vk.Session(access_token=access_token)
api = vk.API(session, v=v)

Дальше просто идёт реализация алгоритма описанного выше. В конце я дам полный листинг программы. А по ходу просто буду пояснять отдельные моменты реализации.

Получение кода города:

# Запрос списка городов России (Cities) по ключевому слову
Cities = api.database.getCities(country_id=1, q=keyword_city)['items']

Метод database.getCities возвращает Словарь (dict), в котором под ключом ‘items’ хранится список городов, которые соответствуют ключевому слову запроса. Обратите внимания, что переменной Cities я присваиваю уже этот список, а не весь Словарь.

Вот ещё интересная реализация получения списка id групп методом
groups.search:

    # Получаем список IDs групп города удовлетворяющих ключевому слову
    group_ids = [g['id'] for g in api.groups.search(city_id=city_id, q=keyword, sort=2, count=500)['items']]

Эта конструкция называется «Генерация списка». Такое, по-моему есть только в Python-е. Схематично конструкция выглядит так:

>>> a = [i for i in range(1,15)]
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

Очень мне понравилась эта конструкция. При реализации через браузер на эту операцию уходило больше всего времени. А тут одной строчкой. Классно!!!

Ещё мне понравилась реализация работы с csv-файлами методом DictWriter. Сначала задаётся заголовок…

    # Задаём заголовок csv-файла
    fieldnames = ['sort2', 'id', 'type', 'is_closed', 'screen_name', 'name', 'members_count', 'contacts', 'photo_50', 'photo_100', 'photo_200']
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()

А затем целая группа сохраняется в файл одной строчкой:

        writer.writerow(group)

В целом, остальное должно быть понятно без слов. Просто привожу листинг.

Посмотреть код
import vk
import csv

# Как получить access_token:
# https://oauth.vk.com/authorize?client_id=6478436&display=page&redirect_uri=https://oauth.vk.com/blank.html&scope=friends&response_type=token&v=5.95

# Параметры:
access_token = '3716eefa82841782e8d1093e01fb1eb89a00eaf089e849172a169d073b8e16565ab38edb43fe41d68dbad'
v = '5.95'
keyword_city = "Балашиха"
keywords_groups = ['ремонт', 'потолки', 'мебель', 'двери']

# Подключение к VK API
session = vk.Session(access_token=access_token)
api = vk.API(session, v=v)

# Запрос списка городов России (Cities) по ключевому слову
Cities = api.database.getCities(country_id=1, q=keyword_city)['items']

# Выводим список городов по запросу на экран
for city in Cities:
    print(city['id'], "\t", city['region'], city['title'], city['area'])

# Поиск групп будет осуществляться только по первому городу из списка
city_id = Cities[0]['id']
city_name = Cities[0]['title']

# Начинаем поиск по каждому ключевому слову по очереди
for keyword in keywords_groups:

    # Получаем список IDs групп города удовлетворяющих ключевому слову
    group_ids = [g['id'] for g in api.groups.search(city_id=city_id, q=keyword, sort=2, count=500)['items']]

    # Получаем список групп города удовлетворяющих ключевому слову
    Groups = api.groups.getById(fields='members_count,contacts', group_ids=group_ids)

    # Создаём csv-файл с группами 'Город - ключевое_слово.csv'
    filename = city_name + " - " + keyword + ".csv"
    f = open(filename, 'w')

    # Задаём заголовок csv-файла
    fieldnames = ['sort2', 'id', 'type', 'is_closed', 'screen_name', 'name', 'members_count', 'contacts', 'photo_50', 'photo_100', 'photo_200']
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()

    # Сохраняем список групп в соответствующий запросу csv-файл
    i = 1
    for group in Groups:
        # Сохраняем порядок сортировки по отношению дневной посещаемости к количеству пользователей
        group['sort2'] = i
        writer.writerow(group)
        i+=1

Если что-то непонятно, то пишите в комментариях. Буду подробно отвечать

Пути развития программы

Программа полностью выполняет свою задачу. Но это не значить, что её нельзя сделать лучше. Я здесь вижу несколько направлений развития.

Классическое консольное приложение

Задавать параметры в коде программы вполне приемлемый способ для программиста. Однако, для простого пользователя — это слишком. Не мудрено ненароком испортить программу. Поэтому лучше реализовать передачу параметров через командную строку, как в классическом консольном приложении.

Контакты в отдельный файл

Контакты групп часто нужны, чтобы не показывать на них рекламу. Для этого нужно собрать id всех пользователей из контактов в отдельный файл. В текущей реализации это придётся делать вручную. Между тем добавить такой функционал совсем несложно и займёт минут 15.

Расширение функционала

По мере необходимости можно расширять функционал программы. Например, добавить возможность извлекать пользователей — членов групп и делать их пересечение. Строить списки пользователей, которые состоят в 2-х группах и тому подобное. Пока такой необходимости не было, но если понадобится, то дописать код будет гораздо быстрее, чем делать всё вручную.

Графический или WEB интерфейс

Если будет такой запрос, то можно добавить графический или веб интерфейс и обработку ошибок. Для своих внутренних нужд, я вряд ли буду это делать. Но, если будет такой запрос, то почему бы и нет.

***

Пишите в комментариях, какое ещё развитие программы вы хотели бы видеть.

Все исходники и описание размещены на GitHub https://github.com/deviur/vk_api_example