26
И снова поиск: Яндекс.XML + ASP.NET
Программирование
Tagged Under : ASP.NET, yandex xml, поиск, Яндекс.XML
Итак, в продолжении темы использования различных поисковых движков я предпринял попытку воспользоваться сервисом Яндекс.XML и прочувствовать всю мощь российского сервиса.
В результате изучения Яндекс.XML я написал класс YandexSearch (+ парочку вспомогательных). Как видно из исходника я использовал GET-запрос: это на мой взгляд несколько проще чем составлять xml-тело для POST-запроса. Регулируется не всё, но того, что настраивается, вполне достаточно.
Итак, исходник ниже
{
private string ServiceUrl = "http://xmlsearch.yandex.ru/xmlsearch?user={0}&key={1}&query={2}&page={3}&sortby={4}.order%3D{5}&groupby=attr%3Dd.mode%3D{7}.groups-on-page%3D{6}.docs-in-group%3D1";
private string startSel = "<hlword>";
private string endSel = "</hlword>";
public string startTag
{
get;
set;
}
public string endTag
{
get;
set;
}
public string Key
{
get;
set;
}
public YandexSortType SortBy
{
set
{
_sortBy = value;
}
}
YandexSortType _sortBy = YandexSortType.rlv;
public YandexSortDirection SortDirection
{
set
{
_sortDirection = value;
}
}
YandexSortDirection _sortDirection = YandexSortDirection.descending;
public YandexSearchMode SearchMode
{
set
{
_searchMode = value;
}
}
YandexSearchMode _searchMode = YandexSearchMode.deep;
public string SearchTerm
{
get;
set;
}
public string User
{
get;
set;
}
public YandexSearchStatus Status
{
get
{
return _status;
}
}
public int Count
{
set
{
_Count = value;
}
}
int _Count = 10;
public int Offset
{
set
{
_Offset = value;
}
}
int _Offset = 0;
public int AllCount
{
get
{
return _AllCount;
}
}
int _AllCount = 0;
YandexSearchStatus _status = YandexSearchStatus.OK;
public YandexSearch()
{
}
public YandexSearch(string key, string searchTerm)
{
Key = key;
SearchTerm = searchTerm;
}
public List<YandexResult> GetResults()
{
string xml = SendRequest(GetQuery());
List<YandexResult> results = ParseResults(xml);
return results;
}
public List<YandexResult> GetResults(string key, string searchTerm)
{
Key = key;
SearchTerm = searchTerm;
string xml = SendRequest(GetQuery());
List<YandexResult> results = ParseResults(xml);
return results;
}
private string GetQuery()
{
string query = string.Format(ServiceUrl, User, Key, SearchTerm, _Offset, Enum.GetName(typeof(YandexSortType), _sortBy), Enum.GetName(typeof(YandexSortDirection), _sortDirection), _Count, Enum.GetName(typeof(YandexSearchMode), _searchMode));
return query;
}
private string SendRequest(string query)
{
string result = "";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(query);
request.Method = "GET";
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
result = sr.ReadToEnd();
}
_status = YandexSearchStatus.OK;
}
else
{
result = "";
_status = YandexSearchStatus.FAIL;
}
}
}
catch (Exception)
{
_status = YandexSearchStatus.FAIL;
}
return result;
}
private XmlNode GetNodeByName(XmlNode parentNode, string nodeName)
{
foreach (XmlNode child in parentNode.ChildNodes)
if (child.Name == nodeName)
return child;
return null;
}
private string GetNodeValue(XmlNode node)
{
return node != null ? node.InnerXml.Replace(startSel, startTag).Replace(endSel, endTag) : null;
}
private List<YandexResult> ParseResults(string xml)
{
List<YandexResult> list = new List<YandexResult>();
XmlDocument document = new XmlDocument();
document.LoadXml(xml);
XmlElement element = document.DocumentElement;
XmlNode response = null;
if (element.ChildNodes.Count > 1)
response = element.ChildNodes[1];
else
{
response = element.ChildNodes[0];
if (response.ChildNodes[0].Name == "error")
{
_status = YandexSearchStatus.FAIL;
return list;
}
}
_AllCount = int.Parse(GetNodeValue(GetNodeByName(response, "found")));
XmlNode grouping = GetNodeByName(GetNodeByName(response, "results"), "grouping");
if (grouping != null)
{
foreach(XmlNode group in grouping)
if (group.Name == "group")
{
YandexResult yr = new YandexResult();
XmlNode doc = GetNodeByName(group, "doc");
yr.Domain = GetNodeValue(GetNodeByName(doc, "domain"));
yr.Title = GetNodeValue(GetNodeByName(doc, "title"));
yr.Url = GetNodeValue(GetNodeByName(doc, "url"));
yr.Size = int.Parse(GetNodeValue(GetNodeByName(doc, "size")));
yr.SavedCopyUrl = GetNodeValue(GetNodeByName(doc, "saved-copy-url"));
yr.ModDate = GetNodeValue(GetNodeByName(doc, "modtime"));
XmlNode passsages = GetNodeByName(doc, "passages");
if (passsages!=null)
foreach (XmlNode passageItem in passsages.ChildNodes)
yr.Fragments.Add(GetNodeValue(passageItem));
list.Add(yr);
}
}
return list;
}
}
public class YandexResult
{
public string Title;
public List<string> Fragments = new List<string>();
public string ModDate;
public string Url;
public string SavedCopyUrl;
public string Domain;
public int Size;
}
public enum YandexSearchStatus
{
OK,
FAIL
}
public enum YandexSortType
{
rlv,
tm
}
public enum YandexSortDirection
{
ascending,
descending
}
public enum YandexSearchMode
{
deep,
flat
}
Ну, а теперь пример использования
search.User = "ваш ник на яндексе";
search.Key = "код сервиса - получаем на яндексе";
search.SearchTerm = "что ищем?";
search.startTag = "<b>"; //выделяем найденное слово жирным
search.endTag = "</b>";
search.Count = 40; //столько нам нужно результатов
search.SearchMode = YandexSearchMode.deep;
List<YandexResult> yrs = search.GetResults();
if (search.Status == YandexSearchStatus.OK)
{
foreach (YandexResult yr in yrs) //если все ок то выводим результаты
{
Console.WriteLine(yr.Title);
Console.WriteLine(yr.Url);
Console.WriteLine(yr.Domain);
foreach (string passage in yr.Fragments)
Console.WriteLine(passage);
Console.WriteLine("=====================");
}
}
else
{
Console.WriteLine("search is fail"); //что-то неправильно, возможно ip с которого был отправлен запрос: проверяется в настройках
}
Console.ReadLine();
Яндекс.XML также как и гугловый поиск ограничивает своё бесплатное использование 1000 запросами с одного ip. Да, и параметров нужно у него много получить: видимо кто-то обошел лимит, потому что паарметры user и key появились буквально в процессе изучения и написания данной заметки.
Замечания и советы принимаются сюда, в качестве комментариев.







Отличный пример, спасибо
Прекрасный пример! Подскажите пожалуйста, что нужно добавить в строку запроса, чтобы поиск осуществлялся по заданному сайту. Спасибо
Необходимо в строку запроса (searchTerm) добавить в конец host:адрес сайта и установить метод поиска плоским, т.е. SearchMode равным YandexSearchMode.flat.
Действительно прекрасно работает! Огромное спасибо!