1. Вступайте в наш Telegram чат: https://t.me/a_parser Нас уже 550+ и мы растем!
    Скрыть объявление

Парсинг JSON ответов и работа с их содержимым

Решение задач по обработке содержимого JSON объектов "на лету"

Метки:
  1. Support
    При парсинге различных сервисов через их API, ответы часто приходят в виде JSON. В А-Парсере есть инструмент для работы с ним: tools.parseJSON. Но, если возникает задача сделать дополнительные действия с данными внутри объекта (например отфильтровать, извлечь регулярным выражением часть данных или уникализировать по какой-то переменной), то использование данного инструмента может вызывать трудности из-за необходимости писать шаблоны (порой довольно сложные) с помощью Template Toolkit в Формате результата или других полях. Поэтому, ниже будет рассказано, как написать универсальный парсер JSON, используя JavaScript парсеры.

    Разберем следующую задачу.
    Есть список пользователей на GitHub. Нужно отфильтровать и оставить только тех пользователей, у которых кол-во подписчиков >100. При этом, местоположение каждого пользователя должно быть уникально.
    Узнать кол-во подписчиков пользователя GitHub можно с помощью простого API запроса:
    Код:
    https://api.github.com/users/{username}
    В ответе будет JSON, внутри которого в переменной followers указано количество подписчиков, а в location - местоположение.

    Стандартными средствами А-Парсера данную задачу можно решить так:
    • Используется Net::HTTP Net::HTTP
    • В указанный выше урл подставляется имя пользователя
    • В формате результата пишется шаблон, который
      • десериализует полученный JSON
      • извлекает нужную переменную
      • проверяет ее значение и фильтрует
    При этом уникализировать по location еще сложнее: нужно создавать глобальный хэш, заносить туда ранее выведенные местоположения и каждый раз проверять его содержимое.

    Но, используя JS парсеры, эту задачу можно решить значительно проще. Напишем небольшой парсер, который:
    • сделает запрос по указанной ссылке;
    • проверит валидность ответа;
    • вернет json-объект, к переменным которого можно обращаться напрямую в пресете.
    Код:
        *parse(set, results) {
            let resp = yield this.parser.request('Net::HTTP', this.conf.Net_HTTP_preset, set.query);
            if(!resp.info.success) {
                this.logger.put('Error open page');
                results.success = 0;
            } else {
                this.utils.updateResultsData(results, resp.data);
                try {
                    results.json = JSON.parse(resp.data);
                    results.success = 1;
                } catch(e) {
                    this.logger.put('Error parsing JSON response: ' + e.message);
                    results.success = 0;
                }
            }
    
            return results;
        }
    Для удобства и возможности задавать различные параметры (юзер-агент, заголовки и т.д.) используется Net::HTTP Net::HTTP.
    Готовый парсер доступен в каталоге: https://a-parser.com/resources/288/

    Используем этот парсер для решения нашей задачи:
    [​IMG]
    Теперь полученный JSON десериализуется не в формате результата, после того, как отработали все составные части пресета (Порядок обработки запросов), а непосредственно на этапе работы используемого парсера. И это позволяет использовать переменные из полученного обьекта, как стандартные.
    Как видно на скриншоте, теперь можно легко применить фильтр, выбрав в нем Custom template и указав нужную переменную.
    Уникализацию так же можно использовать, но тут немного сложнее, т.к. в уникализации нет возможности задать Custom template. Поэтому сначала используется Конструктор результатов, который по сути просто копирует в новую переменную содержимое $json.location. И уже эта переменная доступна для уникализации.
    Таким образом поставленная задача решается в полном обьеме.
    Пример результата:
    Получившийся пресет доступен под спойлером:
    Код:
    eJyNVm1T4zYQ/iuuhhuHnjHJh36ob9oZelfaMgxQ4D7FGUaxN45AkVxJJqQZ//fu
    +j0md1N/AGv30e6zr86eOW5f7J0BC86yaL5nefXOInYDLor+fHy8864ebm88eOOb
    XAILWM6NBUPoObt6iKIOGEWEREQKK15Ix4I9c7sc0NhKSAcGVWidNBGbf/CerVbh
    Skupt2jP+7BAfQ18rG/9ioJXLgt6n02neNK5E1rh0YKyrOwdFEr8U8DQgdQJr8BB
    o2yMWmeEyjrpH1IvuWSRMwWUi0VrwF5qs+Fk51pnQkXeST4LK8KSzoF3wzcwkCo8
    Bt5lG8xA0wUYeNcNpQNrtSiOVUfePvBXeNR12vqY7CWeyC0qTlLugLRonnhOTkP3
    hglnPE0F2eOyDoDK1Af1tc5SxJRGLL4aAfbS6A2KHFQGSLhrg5+ztXO5jc7PeS7C
    TLh1sQwTvTkvqAPOTyowW7S5/Ls2yKIVlxYCZjGOS44s07FGYJG50+a2qifK90yr
    Cymv4RVkD6vs/1YImaK7ixVe+qu5eBxy+85G2cU+dPUKZmuQQw9KNda5TcwLQN6l
    6oYkG22gM9B4buzi8OSgUkT2lbrIe9EBwYNqDIR7ZnVhEvQ3nwZns6Abj7Y/aDrw
    ZtPtBjJ4q9zR/4hNwo+n7bFuc1VIiXBNNewmYVGiiUSrlchuMQVGpNAyKtQjboJb
    9VnTlLvOAhb6vu++C9sUkg59IsaXP1cukFe3CJCJlvbqoU5JbgQS+4kIb7AWQ6+N
    yYRL+fX+eqhhfcfiIdNprC42IllzEatnvVOg8xjhmNAvW66yWElRbLFeseKFdUK9
    gJSwBoPX5Jav7TpWwEWmSLIWihvBEbrR6gWvrM3y5ymaKIQVS67gX1Sd2RdGzBxk
    GrueilbNDI2OpRjhLecqhbRdJpTtZll2G3Z/dGVG+xJ78Nne1WjK7newtJrPSHJG
    AtwjSCGR3Fqvvu/tY+Xhg5XGZVckOC6T01ZIj1sLGza1oVp5vwy19GB32GpR+bNw
    Gs784FDdNHA0vkbPSnIXefP3CnrmPnW1H3h+9VHRy2dInL8IvoXGNccJfc+3XvW+
    eI8cicrjXJ/qRYkRnVSDVfM4hGJenyivT/VHELFNkvweV37q30cZBVy9fCmhSeko
    BXN/ZB7jmvu4TJd6qd8oyP6L2wAWg9AWjd8yVvXLj1VrTRAXtDEeFBmnhuQ5MtkJ
    kGnNse7H0ACOknWT3icSqAC0HsIR08DDP2G1yE6RRuxiJ1aTH8h6KNRKh7ZIErCH
    /ru04AczQ5d5ge5+N0YbT+N29HKegX/66WixWoPIfTpAlB4udjjqpHBC4t+cvovN
    wvqC/TJpDFYpykNqobFLZ3ZDixRcy4J6BClUU1Zn+5tWjpOfjVClh+sjWU/gXaa+
    ky3yjL9Y6p9hRADHGn96+N5HD8INOsJE/j860zGdQWrbtqpvusKo1kDfeCWjNdXs
    BhbNyv8A5BBIvA==

    Рассматриваемая задача является довольно простой и выбрана для демонстрации возможностей. Получившийся парсер является универсальным, его можно использовать и для более сложных сценариев, в которых ключевой является необходимость "на лету" обрабатывать данные из получаемых JSON-объектов.