Работа с данными ВК / подсказка к 1 задачке

1

Доработать приложение. Добавить вывод на форму информации и количестве участников и описание сообщества

чтобы вывести толстый текст, создавая label указывайте шрифт

self.label1 = Label(text="Описание: ", font="Arial 8 bold")

чтобы вывести многострочный текст, создавая label указывайте длину строки в параметре wraplength:

self.label2 = Label(text=description, wraplength=200, justify="left")

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

В качестве данных для анализа будем использовать данные ВК.

В ВК есть раздел “разработчикам”

в нем имеется так называемся документация которая объясняет сторонним разработчикам какие данные есть в ВК, и как с ними работать

Зачем это может быть кому-то нужно? Ну, как правило, это всякая интеграция ВК с вашим приложением. Например, вы решили написать собственный мессенджер в котором можно будет отправлять сообщения прямо в свой профиль и читать какие-нибудь ответы. Или, например, реализовать синхронизацию изображений/сторисов с интсой. Или вы вдруг решили продавать товары в ВК, и хотите, чтобы данные в вашем сообществе совпадали с данными в магазине или пишите бот который должен эмулировать общение с человеком

В общем кейсов тьма

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

Но просто подтянуть и проанализировать данные – почему бы и нет. Для этого ВК предоставляет доступ через так называемые сервисные ключи, которые не дают сделать каких-нибудь опасных действий.

Но сначала давайте установим библиотечку для удобной работы с веб запросами. Как в прошлый раз открываем консоль из папки с питоном

и вводим туда следующие команды (если вы работает дома то ` –proxy=http://172.27.100.5:4444 ` писать не надо):

pip install --proxy=http://172.27.100.5:4444 requests

Разбираемся с тем как работает интернет

И так что за такие запросы и как их делать?

Главная фишка современного веба заключается в том, что весь интернет работает по принципу клиент-сервер. Клиент – это тот, кто отправляет запросы, а сервер этот тот кто отвечает на запросы. Самый распространённый пример запроса это проста ссылка на сайт.

То есть когда вы вводите в браузере, например, https://vk.com/golos_irnitu то браузер понимает, что ему надо найти адрес сервера (как правило IP адрес), который соответствует vk.com. Узнать IP адрес сайта можно на разных сайтах. Например, на https://2ip.ru/whois/:

Но это редко приходится делать вручную.

И так, на этот адрес отправляется запрос в виде текстовой строки /golos_irnitu. Сервер vk умеет реагировать на разные запросы, если сильно не усложнять, то там имеется аналог примерно такого кода:

if url == "/golos_irnitu":
    return "html код сообщества Голос ИРНИТУ"

и да, как правило, в качестве ответа приходит просто текст.

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

Резюмируем схему:

  1. Клиент (то бишь бразуер) делает текстовый запрос в виде адреса https://hostname/path
  2. По hostname определяется физический адрес сервера
  3. На физический адрес сервера отправляется запрос в виде строки /path
  4. Сервер по строке запроса формирует ответ и отправляет его клиенту
  5. Клиент получает текстовый ответ и показывает нам страничку в браузере

Пробуем делать запросы

Думаю идея понятна. Теперь попробуем сделать какой-нибудь запрос прямо из питона.

Открываем наш spyder и пишем код

import requests  # подключаем модуль для работы с запросами

# так как в политехе интернет работает через прокси,
# то и запросы надо делать через прокси
proxies = {
    "http": "http://172.27.100.5:4444",
    "https": "http://172.27.100.5:4444",
}

r = requests.get("https://vk.com/golos_irnitu", proxies=proxies)  # запрашиваем страницу сообщества
# если дома пробуете запросы то прокси указывать не надо, делайте запрос так:
# r = requests.get("https://vk.com/golos_irnitu")

print(r.text) # и выводим ответ

запускаем и видим вот такую абракадабру

то есть если о чем то попросить ВК, он вернет нам в ответ html код. Мы кстати всегда можем посмотреть его в браузере если откроем https://vk.com/golos_irnitu и тыкнем так:

увидим примерно похожий текст

конечно здорово, но на самом деле работать с этим не очень удобно. Поэтому мы будем использовать VK Api.

API – это application programming interface или программный интерфейс приложения. Проще говоря это набор юрлов, которые позволяют сторонним разработчикам (то бишь нам) в удобном виде взаимодействовать с чужим приложением/сервером (в нашем случае с ВК)

Кстати если вы хотите работать с какой-нибудь другой группой просто узнайте ее название, оно присутствует в адресной строке:

Получение сервисного ключа

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

Отсюда и далее, если вы работаете не на своем компьютере, рекомендую запустить браузер в режиме Инкогнито, чтобы после того как вы войдете под своим ВК пользователем и закроете браузер данные о вашем посещении стерлись из памяти браузера

И так, заходите в раздел разработчикам, попасть в него можно так:

вверху тыкаете

далее тыкаете создать:

пишите имя, выбираете Standalone

открывается окошко, где вам обещают позвонить

тыкаете позвонить, к вам приходит звонок со странного номера

из номер берете последние четыре цифры и загоняете в форму:

поздравляю теперь у вас есть свое вк-приложение

теперь идем в настройки и копируем куда-нибудь вот этот сервисный ключ

именно его мы будем использовать для доступа к данным ВК

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

Я буду использовать такой ключ

203a983a203a983a203a983a58204daa522203a203a983a405dff18fea57bccc1c68d62

Запрашиваем информацию о группе

Попробуем получить информацию о группе в более удобно для обработки виде. То есть в json.

Для этого мы воспользуемся следующим запросом:

import requests 
from pprint import pprint # подключаем улучшенный print, который умеет выводить даже кривой json красиво

proxies = {
    "http": "http://172.27.100.5:4444",
    "https": "http://172.27.100.5:4444",
}

# делаем запрос, тут пока не понятно, но сейчас объясню
r = requests.get("https://api.vk.com/method/groups.getById?access_token=203a983a203a983a203a983a58204daa522203a203a983a405dff18fea57bccc1c68d62&v=5.130&group_id=golos_irnitu", proxies=proxies)

# выводим полученный ответ красиво
pprint(r.json())

то есть как мы видим нам vk что-то вернул в ответ и там даже есть поле name в словарике со значением “Голос ИРНИТУ”

плюс видим тут есть какие-то ссылки – это адреса аватарок сообщества, можно их открыть в браузере например вот я вам выковырял https://sun9-69.userapi.com/s/v1/ig2/ViVC1SkSwVHnQt3VN4eLhhlgiz07_hInH-NBSGqQntyCKLN6Qgso4_5SRe58XCWg8e0qN9ZJAU7NcHXpqdhZOcx8.jpg?size=100x0&quality=96&crop=272,272,1614,1614&ava=1 можно тыкнуть и увидеть картинку

Давайте теперь разберемся с запросом. Он выглядит страшно и непонятно

https://api.vk.com/method/groups.getById?access_token=203a983a203a983a203a983a58204daa522203a203a983a405dff18fea57bccc1c68d62&v=5.130&group_id=golos_irnitu

Первая часть https://api.vk.com/method/ – это обязательный кусок, по которому вк понимает, что мы хотим от него получить данные

Далее идет groups.getById – это метод, по нему ВК понимает какие именно данные мы хотим от него получить. В нашем случае мы хотим получить информацию о группе по идентификатору. Полная документация на метод есть тут https://vk.com/dev/groups.getById?params%5Bgroup_ids%5D=apiclub&params%5Bfields%5D=description&params%5Bv%5D=5.130

Далее идет знак вопроса, с помощью которого принято отделять параметры запроса от непосредственно адреса. То есть https://vk.com/dev/groups.getById – это адрес запроса, а следующие за ним access_token=203a983a203a983a203a983a58204daa522203a203a983a405dff18fea57bccc1c68d62&v=5.130&group_id=golos_irnitu – это параметры

Тут у нас несколько параметров, каждый параметр отделяется от другого знаком амперсанда &. В нашем случае имеем следующие параметры

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

import requests 
from pprint import pprint

proxies = {
    "http": "http://172.27.100.5:4444",
    "https": "http://172.27.100.5:4444",
}

r = requests.get("https://api.vk.com/method/groups.getById", {
    "access_token": "203a983a203a983a203a983a58204daa522203a203a983a405dff18fea57bccc1c68d62",
    "v": "5.130",
    "group_id": "golos_irnitu"
}, proxies=proxies)

pprint(r.json())

так и читабельнее, и проще править

Делаем интерфейс

Давайте теперь сделаем интерфейс:

from tkinter import *


class UI():
    def __init__(self, gui):    
        gui.geometry("600x200")

gui = Tk()
UI(gui)
gui.mainloop()

запихаем в него теперь наш запрос:

from tkinter import *
import requests  # не забываем подключать библиотечки
from pprint import pprint

class UI():
    def __init__(self, gui):    
        gui.geometry("600x200")
        
        proxies = {
            "http": "http://172.27.100.5:4444",
            "https": "http://172.27.100.5:4444",
        }

        # просто делаем запрос
        r = requests.get("https://api.vk.com/method/groups.getById", {
            "access_token": "203a983a203a983a203a983a58204daa522203a203a983a405dff18fea57bccc1c68d62",
            "v": "5.130",
            "group_id": "golos_irnitu"
        }, proxies=proxies)
        
        pprint(r.json())

gui = Tk()
UI(gui)
gui.mainloop()

добавим теперь поле label в который запихаем имя

class UI():
    def __init__(self, gui):    
        # ЭТО НЕ ТРОГАЕМ
        gui.geometry("400x200")

        proxies = {
            "http": "http://172.27.100.5:4444",
            "https": "http://172.27.100.5:4444",
        }

        r = requests.get("https://api.vk.com/method/groups.getById", {
            "access_token": "203a983a203a983a203a983a58204daa522203a203a983a405dff18fea57bccc1c68d62",
            "v": "5.130",
            "group_id": "golos_irnitu"
        }, proxies=proxies)
        
        pprint(r.json())
         # конец ЭТО НЕ ТРОГАЕМ
        
        data = r.json() # вытаскиваем запрос в виде словарика
        group_name = data['response'][0]['name'] # вытаскиваем имя группы
        
        self.label_name = Label(text=group_name)
        self.label_name.place(x=10, y=10)

запускаем, о как получается

давайте теперь картинку выведем, тут немного похитрее

# ...
from PIL import Image, ImageTk # добавляем импорт для работы с картинками


class UI():
    def __init__(self, gui):    
        # ЭТО НЕ ТРОГАЕМ
        gui.geometry("400x200")
        
        # ...
        
        self.label_name = Label(text=group_name)
        self.label_name.place(x=10, y=10)
         # конец ЭТО НЕ ТРОГАЕМ
        
        # вытаскиваем url картинки
        avatar_url = data['response'][0]['photo_100']
        
        # создаем лейбл под картинку, с границей
        self.lblImage = Label(borderwidth=1, relief="solid")
        self.lblImage.place(x=10, y=30, width=150, height=150)
        
        image_data = requests.get(avatar_url, stream=True).raw # стягиваем картинку из интернета
        
        # собираем данные в картинку
        image = Image.open(image_data)
        image.thumbnail([150, 150], Image.ANTIALIAS) # уменьшаем чтобы влезло в лейбл
        
        # привязываем к лейблу
        self.lblImage.image = ImageTk.PhotoImage(image)
        self.lblImage.configure(image=self.lblImage.image)

# ...

проверяем:

Давайте теперь посмотрим какие еще данные есть по группе. Если зайти сюда https://vk.com/dev/groups.getById, то увидим тут что можно передать параметр feilds в котором можно указать какие дополнительные данные можно получить в ответ

если проскроллить чуть вниз, то там можно потестировать запросы. Загоню такие данные и тыкну выполнить

чтобы сделать такой запрос из питона, надо добавить поле в параметры, вот так:

class UI():
    def __init__(self, gui):  
        gui.geometry("400x200")

        proxies = {
            "http": "http://172.27.100.5:4444",
            "https": "http://172.27.100.5:4444",
        }

        r = requests.get("https://api.vk.com/method/groups.getById", {
            "access_token": "203a983a203a983a203a983a58204daa522203a203a983a405dff18fea57bccc1c68d62",
            "v": "5.130",
            "group_id": "golos_irnitu",
            "fields": "members_count,description",  # добавил fields и передал список дополнительных параметров
        }, proxies=proxies)
        
        #...

запускаем и видим, что данные теперь появились в ответе

ну все, теперь можно задание пилить =)