Добрый день!
В процессе работы над одним .Net проектом появилась необходимость получать результаты поиска Яндекса по определённому запросу. В этой статье мне хотелось бы рассказать об опыте работы с API Яндекса из .Net среды.
Конечно, изначально мне не хотелось самому реализовывать обёртку API Яндекса (я надеялся на то, что кто-то уже сделал это до меня), поэтому где-то минут 20 я потратил на то, чтоб выяснить, что готовых решений, которые бы мне подходили, нет. В итоге мне ничего не оставалсоь, как писать её самому, благо документация API Яндекса в открытом доступе и довольно подробная.
Для моих нужд идеально подходил сервис Яндекс.XML, который принимает поисковый запрос и возвращает ответ в формате XML с результатами поиска. Для того, чтобы им пользоваться, необходимо иметь стандартную регистрацию на Яндексе и получить ключ доступа. Необходимо заметить, что ключ строго привязан к IP пользователя, на которого был получен. Ограничение количества запросов в сутки изначально 10, но после подтверждения телефонного номера возрастает до 1000.
После получения ключа, задача разделилась на 2 этапа: отправка запроса и получение ответа от Яндекс.XML, и парсинг этого ответа.
Чтобы составить запрос к Яндекс.XML необходимо понять из каких элементов этот запрос состоит.
Со структурой запроса разобрались, теперь самое время его отправлять. Делать это можно двумя способами: POST-методом и GET- методом. Расскажу о каждом в отдельности.
Суть пост метода в том, что запрос формируется в XML формате, записывается в поток и отсылается сервису. Чтоб не быть голословным, приведу код, в котором происходит вышеописанное:
Первая строка необходима, так как объект HttpWebRequest при отправке запроса POST-методом добавляет к нему HTTP заголовок «Expect: 100-Continue», что вводит в заблуждение некоторые сервисы (Яндекс.XML в том числе) и вызывает ошибку “(417) Expectation Failed”.
GET-метод отличается от POST-метода тем, что запрос представляет собой простую строку, а не строку XML-формата. Из текста запроса сервис при его получении сам формирует XML (преобразовывая каждый элемент строкового запроса в XML-аттрибут) и отсылает ответ (в XML формате). Пример кода:
Итак, ответ от сервиса получен. Теперь необходимо выудить из него всю необходимую информацию о результатах поиска. В среде .Net существует мощный механизм работы с XML-документами, так что с этим особых проблем не возникло. Для начала создадим объект, через который будем работать с XML-ответом на основе полученного HttpWebResponse ответа:
Осталось лишь распарсить полученный XML-ответ. Но прежде чем это сделать, необходимо знать структуру этого ответа. Она полностью описана в документации к Яндекс.XML. Скажу только, что мне в проекте не нужна была общая информация о результатах поиска, а с отдельными результатами поиска планировалось работать как с отдельными структурами. В каждом результате поиска меня интересовало следующее:
Сначала была заготовлена структура, в которую бы записывались результаты поиска:
В самом XML-документе каждый результат поиска называется group и имеет следующую структуру:
И, наконец, сам метод парсинга (+ в начале, вспомогательный метод выдирания значений их XML-я):
Лист с результатами поиска получен!
Если кому-то интересна тема работы с Яндекс АПИ из .Net, то в следующей статье могу написать, как работать с АПИ Яндексовского геокодинга/обратного геокодинга.
Напоследок хотелось бы сказать, что в планах написать красивую полную обёртку Яндекс АПИ для .Net, не только Яндекс.XML но и остальных сервисов
В процессе работы над одним .Net проектом появилась необходимость получать результаты поиска Яндекса по определённому запросу. В этой статье мне хотелось бы рассказать об опыте работы с API Яндекса из .Net среды.
Конечно, изначально мне не хотелось самому реализовывать обёртку API Яндекса (я надеялся на то, что кто-то уже сделал это до меня), поэтому где-то минут 20 я потратил на то, чтоб выяснить, что готовых решений, которые бы мне подходили, нет. В итоге мне ничего не оставалсоь, как писать её самому, благо документация API Яндекса в открытом доступе и довольно подробная.
Для моих нужд идеально подходил сервис Яндекс.XML, который принимает поисковый запрос и возвращает ответ в формате XML с результатами поиска. Для того, чтобы им пользоваться, необходимо иметь стандартную регистрацию на Яндексе и получить ключ доступа. Необходимо заметить, что ключ строго привязан к IP пользователя, на которого был получен. Ограничение количества запросов в сутки изначально 10, но после подтверждения телефонного номера возрастает до 1000.
После получения ключа, задача разделилась на 2 этапа: отправка запроса и получение ответа от Яндекс.XML, и парсинг этого ответа.
Структура запроса
Чтобы составить запрос к Яндекс.XML необходимо понять из каких элементов этот запрос состоит.
<query> - текст запроса.
<sortby> - тип сортировки результатов:
<rlv> - по релевантности,
<tm>- по времени последнего изменения документа.
<maxpassages> - число пассажей текста с найденными словами (максимум - 5, по умолчанию -2).
<groupings> - в этом элементе с помощью элемента <groupby> задаются необходимые группировки результатов поиска.
<groupby> - способ группировки, описывается следующими аттрибутами:
<attr=> - имя атрибута, по которыму происходит группировка:
<d> - группировка по сайтам.
<> - без группировки.
<mode=> - режим группировки:
<flat> - плоский.
<deep> - глубокий.
<groups-on-page=> - количество результатов на странице выдачи (не более 100).
<docs-in-group=> - число документов в группе.
* This source code was highlighted with Source Code Highlighter.
Со структурой запроса разобрались, теперь самое время его отправлять. Делать это можно двумя способами: POST-методом и GET- методом. Расскажу о каждом в отдельности.
POST-метод
Суть пост метода в том, что запрос формируется в XML формате, записывается в поток и отсылается сервису. Чтоб не быть голословным, приведу код, в котором происходит вышеописанное:
ServicePointManager.Expect100Continue = false;
/* Адрес для совершения запроса, полученный при регистрации IP,
в него уже забит логин и ключ API.*/
string url = @"http://xmlsearch.yandex.ru/xmlsearch?
user=**********&
key=**********************************";
// Текст запроса в формате XML
string command =
@"<?xml version=""1.0"" encoding=""UTF-8""?>
<request>
<query>какой-то запрос</query>
<groupings>
<groupby attr=""d""
mode=""deep""
groups-on-page=""10""
docs-in-group=""1"" />
</groupings>
</request>";
byte[] bytes = Encoding.UTF8.GetBytes(command);
// Объект, с помощью которого будем отсылать запрос и получать ответ.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentLength = bytes.Length;
request.ContentType = "text/xml";
// Пишем наш XML-запрос в поток
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
// Получаем ответ
HttpWebResponse response =(HttpWebResponse)request.GetResponse();
* This source code was highlighted with Source Code Highlighter.
Первая строка необходима, так как объект HttpWebRequest при отправке запроса POST-методом добавляет к нему HTTP заголовок «Expect: 100-Continue», что вводит в заблуждение некоторые сервисы (Яндекс.XML в том числе) и вызывает ошибку “(417) Expectation Failed”.
GET-метод
GET-метод отличается от POST-метода тем, что запрос представляет собой простую строку, а не строку XML-формата. Из текста запроса сервис при его получении сам формирует XML (преобразовывая каждый элемент строкового запроса в XML-аттрибут) и отсылает ответ (в XML формате). Пример кода:
//Ключ, полученный при регистрации IP.
string key = "***********************************";
//Логин на Яндексе.
string user = "*****************";
//Шаблон запроса.
string url = @"http://xmlsearch.yandex.ru/xmlsearch?
query={0}&
groupby=attr%3Dd.
mode%3Ddeep.
groups-on-page%3D10.
docs-in-group%3D1&
user={1}&
key={2}";
//Готовый текст запроса.
string completeUrl = String.Format(url, searchQuery, user, key);
//Объект, отсылающий запрос.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(completeUrl);
//Получение ответа.
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
* This source code was highlighted with Source Code Highlighter.
Итак, ответ от сервиса получен. Теперь необходимо выудить из него всю необходимую информацию о результатах поиска. В среде .Net существует мощный механизм работы с XML-документами, так что с этим особых проблем не возникло. Для начала создадим объект, через который будем работать с XML-ответом на основе полученного HttpWebResponse ответа:
XmlReader xmlReader = XmlReader.Create(response.GetResponseStream());
XDocument xmlResponse = XDocument.Load(xmlReader);
* This source code was highlighted with Source Code Highlighter.
Осталось лишь распарсить полученный XML-ответ. Но прежде чем это сделать, необходимо знать структуру этого ответа. Она полностью описана в документации к Яндекс.XML. Скажу только, что мне в проекте не нужна была общая информация о результатах поиска, а с отдельными результатами поиска планировалось работать как с отдельными структурами. В каждом результате поиска меня интересовало следующее:
• <url> - URL документа
• <title> - Заголовок документа
• <headline> -Краткое описание документа
• <modtime> - Время последнего обновление документа
• <saved-copy-url> - Ссылка на сохранённую копию документа
* This source code was highlighted with Source Code Highlighter.
Сначала была заготовлена структура, в которую бы записывались результаты поиска:
public struct YaSearchResult
{
//url
public string DisplayUrl,
//saved-copy-url
CacheUrl,
//title
Title,
//headline
Description,
//modtime
IndexedTime;
public YaSearchResult(string url,
string cacheUrl,
string title,
string description,
string indexedTime)
{
this.DisplayUrl = url;
this.CacheUrl = cacheUrl;
this.Title = title;
this.Description = description;
this.IndexedTime = indexedTime;
}
}
* This source code was highlighted with Source Code Highlighter.
В самом XML-документе каждый результат поиска называется group и имеет следующую структуру:
<group>
<categ attr="" name="" />
<doccount> </doccount>
<relevance priority="" />
-<doc id="">
<relevance priority="" />
<url> </url>
<domain> </domain>
<title> </title>
<modtime> </modtime>
<size> </size>
<charset> </charset>
+<passages>
+<properties>
<mime-type> </mime-type>
<saved-copy-url> </saved-copy-url>
</doc>
</group>
* This source code was highlighted with Source Code Highlighter.
И, наконец, сам метод парсинга (+ в начале, вспомогательный метод выдирания значений их XML-я):
//все нужные нам данные о результате поиска лежат в его элементе doc,
//метод GetValue по имени того, что нам нужно, возвращает строчку
public static string GetValue(XElement group, string name)
{
try
{
return group.Element(«doc»).Element(name).Value;
}
//это если в результате нету элемента с каким то именем,
//то будет вместо значащей строчки возвращаться пустая.
catch
{
return string.Empty;
}
}
* This source code was highlighted with Source Code Highlighter.
public static List<YaSearchResult> Search(string searchQuery)
{
//Лист структур YaSearchResult, который метод в итоге возвращает.
List<YaSearchResult> ret = new List<YaSearchResult>();
//из полученного XML'я выдираем все элементы с именем "group" - это результаты поиска
var groupQuery = from gr in response.Elements().
Elements("response").
Elements("results").
Elements("grouping").
Elements("group")
select gr;
//каждый элемент group преобразовывается в объект SearchResult
for (int i = 0; i < groupQuery.Count(); i++)
{
string urlQuery = GetValue(groupQuery.ElementAt(i), "url");
string titleQuery = GetValue(groupQuery.ElementAt(i), "title");
string descriptionQuery = GetValue(groupQuery.ElementAt(i), "headline");
string indexedTimeQuery = GetValue(groupQuery.ElementAt(i), "modtime");
string cacheUrlQuery = GetValue(groupQuery.ElementAt(i),
"saved-copy-url");
ret.Add(new YaSearchResult(urlQuery, cacheUrlQuery, titleQuery, descriptionQuery, indexedTimeQuery));
}
return ret;
}
* This source code was highlighted with Source Code Highlighter.
Лист с результатами поиска получен!
Заключение
Если кому-то интересна тема работы с Яндекс АПИ из .Net, то в следующей статье могу написать, как работать с АПИ Яндексовского геокодинга/обратного геокодинга.
Напоследок хотелось бы сказать, что в планах написать красивую полную обёртку Яндекс АПИ для .Net, не только Яндекс.XML но и остальных сервисов