И снова поиск: Яндекс.XML + ASP.NET

Программирование

Tagged Under : , , ,

Итак, в продолжении темы использования различных поисковых движков я предпринял попытку воспользоваться сервисом Яндекс.XML и прочувствовать всю мощь российского сервиса.
В результате изучения Яндекс.XML я написал класс YandexSearch (+ парочку вспомогательных). Как видно из исходника я использовал GET-запрос: это на мой взгляд несколько проще чем составлять xml-тело для POST-запроса. Регулируется не всё, но того, что настраивается, вполне достаточно.
Итак, исходник ниже

    public class YandexSearch
    {
        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
    }

Ну, а теперь пример использования

            YandexSearch search = new YandexSearch();
            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 появились буквально в процессе изучения и написания данной заметки.

Замечания и советы принимаются сюда, в качестве комментариев.




Комментарии:

Оставить комментарий