Яндекс.XML Python

Суббота, Май 29, 2010 г.
Яндекс. Ну кто его не знает :)
Одни его обожают, другие ненавидят. Для одних он масса полезных и не очень сервисов и средство для поиска информации, для других рабочий инструмент.
Те кто относятся ко второй категории думаю знают что такое Яндекс.XML.


Яндекс.XML — это сервис, позволяющий делать автоматические поисковые запросы к Яндексу и публиковать его ответы у себя на сайте в собственном дизайне.


Для того чтобы пользоваться этим сервисом необходимо зарегистрировать IP адрес с которого будут отправляться запросы. Это необходимая мера, так как существует лимит запросов 1000 в сутки. На странице можно посмотреть типовые примеры использования. Примеры с исходным кодом на php и perl. При всём моём уважении к perl стало обидно за python. Этот язык благодаря фреймворкам Django, Pylons, TurboGears, Zope, тд... вполне успешно используется для создания вэб приложений.
В этой статье я хочу показать мой python вариант примера позволяющего узнать позицию занимающую сайтом в выдаче.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import urllib2
import re

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

def yxml (request, url):
    """мы должны получить место сервера в выдаче по некому запросу.
        делаем запрос по десять ссылок на страницу и запрашиваем 10
        страниц. при нахождении сервера останавливаемся и выдаем его
        место в выдаче"""
    j = 1
    doc_tpl = tpl.replace("{KEY}", request)
    for i in xrange(10):
        doc = doc_tpl.replace("{NUM}", str(i))
        conn = urllib2.Request("http://xmlsearch.yandex.ru/xmlsearch", doc)
        data = urllib2.urlopen(conn)

        groups = []
        result = data.read()

        if result.find('<error ') >= 0:
            m = re.search('<error code="(\d+)">', result, re.S)
            return [m.group(1), 'err']

        result = result.split('</results>')[0].split('<results>')[1]
        map(lambda x: groups.append(x.split('</group>')[0]), result.split('<group>')[1:])

        for group in groups:
            next_url = group.split('</url>')[0].split('<url>')[1]
            if next_url.find(url) >= 0:
                return [j, next_url]
            j += 1
    return [0, ""]

if __name__ == "__main__":
    result =  yxml ("зелёная лужа", "ru.wiktionary.org")
    print result[0]
    print result[1]


Если запрос пройдёт безошибочно, функция вернёт позицию сайта в выдаче, и соответствующий url или пустую строку если позиция не найдена. Если же Яндекс ругнётся в ответе, функция вернёт код ошибки.
Вышеописанный пример отработав вернул мне следующиё результат:
demoriz [~/Coding/Python]% python yxml.py
40
http://ru.wiktionary.org/wiki/%D0%B7%D0%B5%D0%BB%D1%91%D0%BD%D1%8B%D0%B9

Далее я попробовал намеренно испортить xml запрос и получил в ответ:
demoriz [~/Coding/Python]% python yxml.py
18
err

Ошибка №18 "Ошибка в XML-запросе — проверьте валидность отправляемого XML и корректность параметров" согласно расшифровке на странице.
Теги: Pythonweb
 
   
Комментарии (3)
Сергей
28.06.2010 в 9:36
Использовать регулярки для разбора ответа как то не очень красиво.
Есть же DOM и SAX парсеры. Они не такие уж и сложные.
Да и tpl.replace(«{KEY}», request) тоже правильнее было бы делать каким-нить DOM или etree. А то у вас так случайно вставленный < > или & в запрос поломает всю XMLку
demoriz
28.06.2010 в 9:53
Да вы правы. Но я практически не работал с xml и поэтому не приходилось сталкиваться с библиотеками разбора DOM. Если у вас есть опыт в подобной работе, предложите более правильное решение, мне и думаю другим будет интересно и полезно. Я исправлю пост и упомяну вас в качестве соавтора.
Serg
02.11.2011 в 20:37
http://docs.python.org/library/string.html#template-strings
Оставить комментарий   Нажмите, чтобы отменить ответ.
Доступен html впределах разумного. Для цитирования используйте <blockquote></blockquote>, для отрисовки программного кода [code][/code].
Для всяких хакеров и прочих: комментарии проходят санитизацию, всё лишнее будет вырезано. Так что не тратьте своё драгоценное время.
Имя (обязательно)
E-Mail (Не будет опубликован , обязательно)
Сайт (необязательно)