Не бойся JSON или твое первое приложение с использованием API

Я имею кое-какой 8ми летный опыт в ковырянии кода. За это время успел попробовать много разных языков и технологий в разных направлениях: от «разработки» всяких фишинговых приколов на PHP Devel Studio до полноценных веб приложений на современных фреймворках и софта на нейростеях. Кстати говоря, мое первое погружение в программирование осуществилось в 12 лет благодаря этому посту. Сейчас же я учусь на втором курсе бакалавра по специальности Computer Science. До недавнего времени, а именно до первого курса, я долгое время всегда пугался каждый раз, когда видел слово JSON. Разобрался и понял. Но заметил, что многие ребята из моей группы все еще не работали с каким-либо API. Я люблю статьи, где автор подробно объясняет свою тему, прилагая кусочки кода и разжевывая зачем и почему он так решил сделать, и не кидается сложными терминами и технологиями. В данной статье я опишу использование API (на примере PUBG API) простыми для новчика словами, как говорится, without bullshit. Поехали!

image

Google Colab


Для прохождения данной статьи, вам потребуется минимальные знания Python. Под «минимальными», я имею ввиду print, if, for, ну и всякие листы, словари. Работать мы будем в среде Google Colaboratory (дальше — просто «colab»). Colab — это бесплатная браузерная среда, где умные дядьки тренируют и тестируют свои программки с искусственным интеллектом и проводят всякие исследования. Но нам сейчас это не важно, нас интересует именно формат написания кода там: исполняющие файлы там называются «ноутбуки» (от англ. — тетрадь). В этом формате код можно писать и исполнять кусочками (кусочек кода в colab называется «code cell») прямо в браузере.

Давайте попробуем:

  1. Заходим на Google Colab и авторизовываемся со своим аккаунтом Google
  2. Нас поприветствует главная страница со справкой как пользоваться Colab'ом, а мы создаем свой первый ноутбук, нажав в левом верхнем углу на File > New Python 3 notebook

    Через несколько секунд мы должны увидеть нечто, похожее на это:

  3. Запоминаем следующие сочетания клавиш:
    Ctrl + Enter (Cmd + Enter для MacOS) — Запустить текущий code cell
    ALT + Enter (Option + Enter для MacOS) — Запустить текущий code cell, создать и перейти к новому code cell

В code cell можно сразу же писать обычный python код. Если же мы хотим выполнить какую-либо консольную команду, то перед строчкой вставляет восклицательный знак, например:

Python код

print('Hello, PUBG!')

Консольная команда

!mkdir hello_pubg
!cd hello_pubg

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

  1. В code cell вписываем:

    a = 10
    b = 8
    

  2. Нажимаем Alt + Enter (Option + Enter для MacOS) и в новом code cell пишем:

    while a != 0 and b != 0:
        if a > b:
            a %= b
        else:
            b %= a
    
    gcd = a + b
    

  3. Еще раз нажимаем Alt + Enter (Option + Enter для MacOS) и в новом code cell пишем:

    print(gcd)
    

    и нажимаем Ctrl + Enter (Cmd + Enter для MacOS). Получаем ответ: 2



Как видим, работать в Colab очень просто и тестировать некий функционал своего будущего приложения тут очень даже удобно. Кстати, если хотим выполнить алгоритм c другими числами, нам надо поменять значения переменных в первом code cell, запустить его, затем запустить второй и затем третий.

Ноутбук не закрываем, поехали дальше.

PUBG API


Теперь что такое API простыми словами. Каждый раз, когда мы заходим на какой либо сайт, нам сервер этого сайта отвечает HTML кодом, то есть заходя, например, на google.com, сервер гугла присылает нашему браузеру HTML код, который обрабатывается уже самим браузером, а браузер показывает нам уже красивую картинку, обработав все стили и тд. Но так происходит не всегда, например перейдя по этой ссылке, мы увидим нечто похожее на вывод какого-то словаря в python командой print(). Так и есть. Это словарь с информацией о текущей погоде, который мы получили с сайта openweathermap. И человек никогда не будет своими силами обрабатывать такие ответы от сервера. Разработчики этого сайта предоставили нам такие ссылки, чтобы мы могли использовать их своих программах. В общем говоря, если нам понадобилось сделать блок с погодой на своем сайте или приложении, то мы заходим на openweathermap (или любой другой аналог, предоставляющий API), открываем их документацию и пользуемся. API в расшифровке и переводе на русский звучит как «интерфейс программирования приложений», то есть сборник запросов вида site.com/request, которые возвращают нам словарь с нужной нам информацией. А формат этих словарей называется JSON. Есть еще формат XML, но разбирать в данной статье его не будем.

Вначале я писал о том, что мы будем использовать официальный API от разработчиков игры PUBG. Давайте приступим. Вот ресурс, с которым мы будем сверять полученную формацию, открываем его в новой вкладке и вводим в поиске игроков никнейм любого игрока, например, «Twitch_todol». Открывается статистика этого игрока:



Открываем его последний матч (первый в списке) и видим всю нужную нам информацию:



Чтобы получить из PUBG API информацию об этом матче:

  1. Заходим на официальную страницу разработчика PUBG.
  2. Авторизовываемся или регистрируемся на странице, нажав на кнопку GET YOUR OWN API KEY. Причем не важно, играли ли мы в эту игру или нет. Нам от этого сайта всего лишь нужно получить наш token, то есть api key.

    Каждый раз, обращаясь к серверу PUBG за какой либо информацией, нам нужно предоставлять ему наш уникальный token. Сделано это по разным причинам, наиболее очевидная — чтоб разработчики игры могли знать, кто именно получает информацию с их сервера, и сделать ограничения для каждого программиста. В данном случае, у нас есть одно ограничение — не более 10 запросов в минуту. Нам этого более чем достаточно.
  3. Создаем приложение и получаем наш токен



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

    eyJ0eXAiOiJKV1QiLWFeCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI5ZjIwYTJkMC0xMzYwLTAxMzgtZTFhYS03ZDVjOWM4YTdjZWUiLCJpc3MiOiJnYW1lbG9ja2VyIiwiaWF04IjoxNTc4MzkwNDQwLCJwdWIiOiJibHVlaG9sZSIsInRpdGxlIjoicHViZyIsImFwcCI6ImxlYW5jb3JlZ2ctZ21hIn0.fwFwEeEw3OghE8sACAHbpKWlJFBVo6F_DbB7dbanybLIIToJc4
    

  4. Копируем свой токен и открываем свою вкладку с colab'ом. Вы ведь не закрывали его?
  5. В первый code cell вписываем данный код:

    import requests
    
    url = "endpoint-url"
    
    API_KEY = '<НАШ ТОКЕН>'
    
    header = {
      "Authorization": "Bearer " + API_KEY,
      "Accept": "application/vnd.api+json"
    }
    

    И запускаем. В данном куске кода мы создали словарь (header), который содержит в себе базовые параметры для обращения к PUBG API. Мы будем отправлять этот словарь серверу каждый раз, когда захотим от него что-либо получить. Условно, мы говорим серверу «Привет, меня зовут Петя,» — где Петя — наш токен — «я хочу получить от тебя информацию в формате JSON!». Кусок кода, который я вам только что дал, я получил с документации PUBG API на этой странице.
  6. Теперь нам надо сообщить, что именно нам надо получить от сервера. В нашем случае, мы хотим получить от него последнюю игру игрока Twitch_todol. Для получения информации об игроке, мы делаем запрос по адресу
    api.pubg.com/shards/steam/players?filter[playerNames]=Twitch_todol

    То есть (в новом code cell):

    player_name = 'Twitch_todol'
    r = requests.get('https://api.pubg.com/shards/steam/players?filter[playerNames]=' + player_name, headers=header)
    player = r.json()
    

    где во второй строчке мы используем функцию из библиотеки requests, где первым параметром задаем что именно нам надо от сервера, а вторым параметром передаем наш словарь header. Иными словами, говорим серверу «Привет, я Петя! Я хочу получить от тебя информацию об игроке Twitch_todol в формате JSON».

    А в третьей строчке мы переводим ответ от сервера в этот самый JSON. Зачем мы это делаем? Дело в том, что сервер нам возвращает не совсем json ответ, а json переведенный в строку (string). А методом .json() мы как бы конвертируем эту строку в понятный пайтону словарь.

    Давайте убедимся в этом, написав в новом code cell:

    type(player)
    

    ответом будет dict. То есть, теперь мы точно знаем, что переменная player содержит в себе понятный пайтону словарь с информацией об игроке.
  7. Что же именно содержит в себе этот словарь? Давайте посмотрим, выполнив

    player.keys()

    Видим ответ:

    dict_keys(['data', 'links', 'meta'])

    Это ключи полученного нами словаря. Что содержит каждый из них, написано на этой странице.

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

    player['data'][0]['attributes']

    Здесь мы видим базовую информацию об игроке: когда он зарегистрировался, его никнейм, на какой платформе он играет и так далее.
  8. Нам нужно получить id его последнего матча, который мы можем сверить с сайтом pubg.op.gg, который уже открыт у нас в одной из вкладок браузера. Для этого пишем:

    player['data'][0]['relationships']['matches']['data'][0]['id']

    Мы получили нечто похожее на 'ca2c453b-649a-4556-b768-66b9e01aae63' (у вас может отличаться, потому что игрок на момент прочтения вами данной статьи мог уже сыграть несколько матчей). Используйте то, что вы получили сами. Я же вам даю пример, чтобы вы не запутались.

    Итак, мы знаем id матча, теперь давайте получим информацию об этом матче, для этого мы создаем переменную match_id, которую приравниваем к полученному нами id. И делаем запрос немного по другому адресу, но по привычной нам схеме, то есть так:

    match_id = player['data'][0]['relationships']['matches']['data'][0]['id'] # id матча
    r = requests.get('https://api.pubg.com/shards/steam/matches/' + match_id, headers=header)
    match = r.json()
    

  9. Переменная match, которая является словарем, содержит всю информацию об этом матче. Для начала, мы получим показатели всех игроков данного матча:

    match_players = [item for item in match['included'] if item['type'] == 'participant']
    match_players
    

    В данном случае, мы заполняем лист игроков (match_players), проходясь по словарю match['included'] ('included' — это ключ словаря match, который содержит показатели всех игроков матча), попутно делая проверку значения ключа 'type'. Зачем мы делаем проверку, если
    match['included'] содежрит информацию об игроках? Дело в том, что это не совсем так, match['included'] содержит еще и информацию о командах, в которых играли эти игроки (то есть, item['type'] может равнятся 'roster'). То есть, match['included'] выглядит примерно так:

    [игрок, команда, команда, игрок, игрок, игрок, команда, ...]

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

    Итак, мы получили показатели игроков, но нам не особо интересно, как в этом матче сыграли другие игроки, мы посмотрим на показатели нашего игрока Twitch_todol в этом матче. Для этого выполняем:

    my_player_stats = [item for item in match_players if item['attributes']['stats']['name'] == player_name][0]
    my_player_stats
    


Сравниваем полученную статистику:



со статистикой на сайте pubg.op.gg



Видим что все совпадает. Радуемся! Кстати, пока я писал данную статью, наш герой уже успел сыграть несколько матчей, поэтому некоторые скрины, приведенные мной выше, могут не совпадать.

Завершение


В этой статье я хотел рассказать нашим самым маленьким программистам, что не стоит бояться слов JSON и API, что они удобно и понятно реализованы и к каждому прилагается документация. Я попытался объяснить это самым доступным языком, не используя сложные термины.

А еще, хочу сказать спасибо Хабру и автору (ArhMax) за то, что помогли мне 8 лет назад впервые написать код.
Источник: habr.ru