Записки Вредного программиста

enjoy, motherfuckers ;)

Yandex XML версии 2.0

Приветствую вас, многоуважаемые разработчики. Сегодня речь пойдет опять о Yandex и его сервисе XML, о котором я уже упоминал в заметке о Yandex XML, т.к. нашей веб студии для собственных нужд понадобился сей компонент, но немного расширенный, модернизированный и использующий Zend Framework. Сейчас он будет более объектно-ориентированный и удобный в использовании.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<?php

set_time_limit(0);

/**
 * YandexParser is class what helps getting position of your site by query string
 *
 * @author vredniy (dnd.pliz@gmail.com)
 */
class Model_YandexParser
{

    /**
     * @var string
     */
    protected $_query = '';
    /**
     * @var string
     */
    protected $_host = '';
    /**
     * @var int
     */
    protected $_pageLimit = 50;
    private $_username = '';
    private $_key = '';

    /**
     *
     * @param string $query query string
     * @param string $host host string
     * @param int $pageLimit page limit
     */
    public function __construct($query, $host, $pageLimit = null, $username = null, $key = null)
    {
        if (isset($query))
            $this->_query = htmlspecialchars($query);
        if (isset($host))
            $this->_host = preg_replace('[^http://|www\.]', '', htmlspecialchars($host));
        if (isset($pageLimit))
            $this->_pageLimit = is_int ($pageLimit) ? $pageLimit : (int) $pageLimit;

        if (isset($username))
            $this->_username = $username;
        if (isset($key))
            $this->_key = $key;
    }

    /**
     * send request
     *
     * @return int|string
     */
    public function request()
    {
        $page = 0;
        do {
            if ($result = $this->_doRoutine($this->_query, $this->_host, $page++))
                break;
        } while ($page * 10 < $this->_pageLimit);

        if (false == $result)
            return 'Nothing Found';
        return $result;
    }

    /**
     * does all dirty work
     *
     * @param string $query
     * @param string $host
     * @param int    $page
     * @throws       Zend_Http_Client_Exception
     * @return       false|int
     */
    protected function _doRoutine($query, $host, $page)
    {
        if (10 * $page >= $this->_pageLimit)
            return false;

        $doc = "<?xml version='1.0' encoding='utf-8'?>
            <request>
                <query>$query</query>
                <page>$page</page>
                <maxpassages>0</maxpassages>
                <groupings>
                <groupby attr='d' mode='deep' groups-on-page='10' docs-in-group='1' curcateg='-1'/>
                </groupings>
            </request>";

        $uri = 'http://xmlsearch.yandex.ru/xmlsearch';
        if ($this->_username)
            $uri .= '?user=' . $this->_username;

        if ($this->_key)
            $uri .= '&key=' . $this->_key;

        $httpClient = new Zend_Http_Client($uri);

        $response = $httpClient
                ->setRawData($doc, 'text/xml')
                ->request('POST');

        if ($response->isSuccessful()) {
            $zQ = new Zend_Dom_Query($response->getBody());
            $result = $zQ->queryXpath('/yandexsearch/response/results/grouping/group/doc/url');
            $innerHTML = '';
            $counter = 10 * $page;
            foreach($result as $r) {
                $children = $r->childNodes;
                $counter++;
                foreach($children as $child)
                    if (false !== strpos($child->ownerDocument->saveXml($child), $host))
                        return $counter;
            }
        } else {
            throw new Zend_Http_Client_Exception($response->getHeadersAsString(true, '<br>'));
        }
        return false;
    }

}
?>

Конструктор (строки 34-47) заполняет внутренние свойства класса, которые нам понадобятся для дальнейшей работы.

Метод Model_YandexParser::request() (54-65) запускает цикл по всей глубине поиска заданного сайта и возвращает значение.

Защищенный метод Model_YandexParser::_doRoutine(…) (76-120) выполняет всю грязную работу по отправлению запроса, получению ответа от Yandex’а и поиска подходящего нам сайта. Нужно будет, как будет больше времени, дописать проверка на ошибки и вывод соответствующих сообщений.

Дальше регистрируем свой IP (требования Yandex’а) тут и запускаем наш поиск в каком-нибудь из наших экшнов. К примеру так

1
2
3
4
5
6
7
8
9
10
11
12
13
public function indexAction()
    {

        $yandex = new Model_YandexParser(
                        'голая Викки Блоуз',
                        'wowboobs.ru',
                        1000,
                        'username',
                        'INSERT_HERE_YOUR_SECRET_KEY'
        );
        $result = $yandex->request();
        var_dump($result);
    }

И наслаждаемся результатом :)

Комментарии