Как стать автором
Обновить

API ВКонтакте и XDocument для самых маленьких

Время на прочтение5 мин
Количество просмотров12K
Доброе время суток.

Я хочу еще раз поговорить о простейших способах работы с API ВКонтакте и очень надеюсь, что эта статья может стать отправной точкой для начинающих разработчиков. Мы будем работать с довольно разнообразным методом messages.getHistory, а с помощью XDocument получать фотографию. Всех, кто научился проходить авторизацию и хочет опробовать работу с API, прошу под кат.

Начнем?

Итак, мы авторизовались, получили токен. Что дальше? Я хочу привести пример с довольно интересным методом, который поможет начинающим освоиться в мире API ВКонтакте. Если вы не нашли упомянутый выше метод в списке основных методов, то переходим сюда и видим большой список различных возможностей. С одной из них мы и начнем работу.

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


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

Результат:
Возвращает массив объектов message – личных сообщений в указанном диалоге с пользователем или групповой беседе. Каждый объект message содержит набор полей, описание которых доступно здесь.


В нашем распоряжении целых 6 параметров, 2 из которых обязательные. Подробнее о каждом:

uid – наверное, самый важный параметр. Сервер должен знать, с каким пользователем мы хотим получить историю сообщений.
chat_id – необязательный параметр в случае, если мы указали uid.
offsetсмещение для выборки. Проще говоря, тот параметр, без которого мы не сможем получить большую переписку из-за ограничения в 200 сообщений в одном ответе.
count – то самое количество сообщений, которое мы хотим получить от сервера. Помните об ограничении в 200 сообщений за один запрос.
start_midидентификатор сообщения, начиная с которого необходимо получить последующие сообщения. Прошу не путать с count. В этот аргумент мы заносим id сообщения, а не его порядковый номер.
rev – с какого сообщения нам нужна переписка. Последнее или первое. 0 по умолчанию, что означает обратный хронологический порядок.

Самое необходимое

Неплохо, да? Давайте опробуем.
Напоминаю, что работать мы будем с LINQ to XML. Подключаем необходимое пространство имен

using System.Xml.Linq;


Теперь у нас есть доступ к очень мощному, на мой взгляд, парсеру XML. Так давайте объявим его

XDocument doc;


Все получилось? Тогда продолжаем. Мы помним, что если у нас очень большая переписка, то нам надо использовать смещение и указывать параметр offset. Тогда создадим счетчик, который будет увеличиваться на 200 каждую итерацию. А также, создадим счетчик для динамических имен фотографий при сохранении

int m=0;
int k=0;


Конечно не забудем про WebClient, который поможет нам скачать фотографию

WebClient src_client = new WebClient();


Думаю, что стоит создать отдельную папку, чтобы не засорить ностальгическими фотографиями все остальные файлы с программой
Directory.CreateDirectory("img/");


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

doc = XDocument.Load("https://api.vk.com/method/messages.getHistory.xml?uid=123456&offset=" + m + "&count=200&access_token=" + token);


Во-первых обратите внимание, что мы указали формат получаемых данных .xml для метода messages.getHistory. Обычно он возвращает JSON, с которым LINQ to XML не справится. Также мы указали uid пользователя, с которым хотим историю. Ну и конечно offset, который мы будем изменять каждый раз, пока не дойдем до конца. count ставим тот, который вам нужен. Но помните, что не больше 200, а то сервер устанет и пойдет отдыхать вернет нам ошибку. Ну и конечно укажем токен.

Работа с XML

А теперь рассмотрим сам цикл. Я не претендую на оптимизированный код и понимаю, что его можно сократить, но хочу показать подробную работу парсера с подобными XML.

while (true)
            {
                doc = XDocument.Load("https://api.vk.com/method/messages.getHistory.xml?uid=12345&offset=" + m + "&count=200&access_token=" + token);// Загружаем наш xml с сервера и начнем обработку

                foreach (XElement el in doc.Root.Elements())// Раскрываем корневой узел
                {
                    // И ищем в нем узел с говорящим названием
                    if (el.Name.ToString() == "message")
                    {
                        foreach (XElement el_msg in el.Elements())// Теперь в узле message
                        {
                            // ищем узел с приложениями
                            if (el_msg.Name == "attachment")
                            {
                                foreach (XElement el_attch in el_msg.Elements())
                                {
                                    // Аналогично ищем в нем узел, который укажет нам, что тут фото
                                    if (el_attch.Name == "photo")
                                    {
                                        foreach (XElement el_photo in el_attch.Elements())
                                        {
                                            // Получаем элемент большой фотографии
                                            if (el_photo.Name == "src_xbig")
                                            {
                                                // Скачиваем фотографию в img/
                                                src_client.DownloadFile(el_photo.Value, "img/img" + k + ".jpg");
                                                k++;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                 // Ну и конечно увеличение параметра count
                m += 200;
            }


LINQ

Спасибо Atreides07 за LINQ версию. К сожалению, я не додумался написать её сразу.
while (true)
{
    var doc = XDocument.Load("https://api.vk.com/method/messages.getHistory.xml?uid=12345&offset=" + m + "&count=" + n + "&access_token=" + token);// Загружаем наш xml с сервера и начнем обработку
    var photoElements=
    doc.Root.Elements("message")
        .SelectMany(el => el.Elements("attachment")
        .SelectMany(el_msg => el_msg.Elements("photo")
        .SelectMany(elAttch => elAttch.Elements("src_xbig"))));

    foreach (var el_photo in photoElements)
    {
        // Скачиваем фотографию в img/
        src_client.DownloadFile(el_photo.Value, "img/img" + k + ".jpg");
        k++;
    }
    // Ну и конечно увеличение параметра count
    m += n;
}


XPath

using System.Xml.XPath;

Также думаю, что стоит показать вариант с XPath.
                // Создаем запрос
                XPathDocument document_x = new XPathDocument("https://api.vk.com/method/messages.getHistory.xml?uid=12345&offset=" + m + "&count=200&access_token=" + token);
                XPathNavigator navigator = document_x.CreateNavigator();

                 // Выражение
                string str_exp = "//message//attachment//photo//src_big";

                XPathExpression expres = XPathExpression.Compile(str_exp);
                XmlNamespaceManager manager = new XmlNamespaceManager(navigator.NameTable);
                expres.SetContext(manager);

                XPathNodeIterator nodes = navigator.Select(expres);
                while (nodes.MoveNext())// Пробегаемся по найденному
                    src_client.DownloadFile(nodes.Current.ToString(), "img/imj" + k + ".jpg");// Скачиваем

Конечно не забываем про цикл и увеличение m.

Вот собственно и все. Открываем папку, откуда запускали нашу программу, находим папку img и наслаждаемся результатом.

Вывод

Как мы видим, работа с API ВКонтакте довольно проста, а с удобными возможностями LINQ to XML она становится подробной и более понятной. Надеюсь, что вам понравилось. Спасибо за прочтение.

Пожалуйста, указывайте на любые недочеты в статье. Буду учиться.
Теги:
Хабы:
+17
Комментарии31

Публикации