<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://wiki.linuxformat.ru/wiki/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://wiki.linuxformat.ru/wiki/index.php?action=history&amp;feed=atom&amp;title=LXF123%3APython</id>
		<title>LXF123:Python - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.linuxformat.ru/wiki/index.php?action=history&amp;feed=atom&amp;title=LXF123%3APython"/>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF123:Python&amp;action=history"/>
		<updated>2026-05-13T03:02:46Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.19.20+dfsg-0+deb7u3</generator>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/index.php?title=LXF123:Python&amp;diff=12196&amp;oldid=prev</id>
		<title>Ewgen: добавил шаблон</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF123:Python&amp;diff=12196&amp;oldid=prev"/>
				<updated>2011-06-24T07:00:08Z</updated>
		
		<summary type="html">&lt;p&gt;добавил шаблон&lt;/p&gt;
&lt;table class='diff diff-contentalign-left'&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
			&lt;tr valign='top'&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Предыдущая&lt;/td&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Версия 07:00, 24 июня 2011&lt;/td&gt;
			&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;{{Цикл/Python}}&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;: '''''Python''''' Заставим Web доставлять нужное содержимое вам на блюдечке &amp;#160;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;: '''''Python''''' Заставим Web доставлять нужное содержимое вам на блюдечке &amp;#160;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Ewgen</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/index.php?title=LXF123:Python&amp;diff=10775&amp;oldid=prev</id>
		<title>Crazy Rebel: викификация, оформление</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF123:Python&amp;diff=10775&amp;oldid=prev"/>
				<updated>2010-09-19T08:25:22Z</updated>
		
		<summary type="html">&lt;p&gt;викификация, оформление&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;: '''''Python''''' Заставим Web доставлять нужное содержимое вам на блюдечке &lt;br /&gt;
&lt;br /&gt;
==''Python'': Роемся в XML==&lt;br /&gt;
&lt;br /&gt;
: '''Часть 4''': Мы вскроем API Сети посредством XML. Ваш отважный проводник по глубинам ''Python'', '''Ник Вейч''', не успокоился, пока не откопал ''Digg''.&lt;br /&gt;
&lt;br /&gt;
Ранее в этом цикле статей в качестве интерфейса для наших web-объектов и работы с ними мы использовали существующий API-код. Это экономит кучу времени, но иногда и ограничивает, делая нас зависимыми от других. И вообще, зачем беспокоиться о импорте целого модуля API, если требуется всего несколько методов?&lt;br /&gt;
&lt;br /&gt;
Итак, на сей раз, невзирая на то, что есть весьма удачные API для ''Digg'' – хотя и слегка несвежие – мы создадим вместо них свой собственный. Ну, типа того. Мы не собираемся охватывать всю функциональность Digg, но освоим достаточно, чтобы при желании вы смогли создать полноценный API.&lt;br /&gt;
&lt;br /&gt;
Многие сайты используют конкретный способ взаимодействия со своими API, а некоторые – даже несколько способов. Самые популярные – JSON и XML. JSON проще и легко интегрируется с ''JavaScript'', поэтому встречается часто. XML больше, массивнее и приятнее на вид. К тому же его чуть легче сопровождать; правда, в итоге вы получаете копну ответов даже на простой запрос. Но все равно, его-то мы здесь и используем.&lt;br /&gt;
&lt;br /&gt;
Если честно, большой разницы между ними нет, но XML – практически универсальный язык для web, и если вы научитесь работать с вызовами API через XML, это сослужит вам хорошую службу.&lt;br /&gt;
&lt;br /&gt;
''Python'' хорошо справляется с XML и имеет готовые модули для работы с ним... но мы забегаем вперед. Первым делом определим, как мы будем взаимодействовать с API ''Digg''. И, подобно многим запасливым социальным web-сайтам, ''Digg'' располагает массой документации для программистов о том как использовать API. Ура!&lt;br /&gt;
&lt;br /&gt;
===Большая кнопка «Digg it»===&lt;br /&gt;
&lt;br /&gt;
Зайдем на сайт ''Digg'' API (http://apidoc.digg.com) и посмотрим, что там предлагается. Доступ к API осуществляется посредством запросов к главному web-сайту. Возможно, вы уже знакомы с этим – имеется набор значений, передаваемых на web-сервер для обработки; начинаются они с '''?''' и разделяются '''&amp;amp;'''. Чтобы это опробовать, не нужно даже писать ни строчки кода самостоятельно: достаточно набрать URL и ввести его в браузере. Поскольку мы собираемся использовать стандартный XML-отклик, то браузер типа ''Firefox'' отобразит полученный XML-код прямо в своем окне, не требуя предварительно сохранить его в файл, что есть великое благо. В конце концов, нуднее, чем ввод сложного запроса и получение ошибки в ответ, может быть только необходимость загрузки файла в текстовый редактор ради выяснения, что он не работает.&lt;br /&gt;
&lt;br /&gt;
Для активации конкретных функций API ''Digg'' использует специальные конечные точки ('''endpoints'''), или URL-пути. Например, если необходимо найти список последний горячих новостей ['''hot list'''], перейдите по адресу http://services.digg.com/stories/hot.&lt;br /&gt;
&lt;br /&gt;
Опробуйте это в вашем браузере – и, однако, получите сообщение об ошибке. Единственной оговоркой ''Digg'' при предоставлении данного сервиса является то, что приложение, делающее запрос, должно иметь свой ключ (или API-ключ). Это распространено среди web-служб – они хотят иметь способ определить конкретного&lt;br /&gt;
клиента, и вовсе не из подлости: если что-то пойдет не так и некто будет опрашивать сервер каждые 10 миллисекунд, должна быть возможность блокировать&lt;br /&gt;
его, не останавливая API-сервис как целое. &lt;br /&gt;
&lt;br /&gt;
{{Врезка|Заголовок=Скорая помощь|Содержание=Начинающие часто впадают в ступор в оболочке ''Python'', поскольку стандартная комбинация '''Ctrl+C''' не работает. Вместо этого для выхода из оболочки ''Python'' нажмите '''Ctrl+D'''.|Ширина=200px}}&lt;br /&gt;
&lt;br /&gt;
В этом отношении ''Digg'' немного необычен – он не требует полной регистрации ключа API: просто введите URL вашего web-проекта или сайта с исходным текстом клиентского приложения. И если мы вновь обратимся к ''Digg'', уже с ключом http://services.digg.com/stories/hot/?appkey=http://www.linuxformat.ru,&lt;br /&gt;
экран заполнится структурированным текстом. Символ '''?''' в URL означает запрос, а нам надо передать несколько значений. Стандартный формат&lt;br /&gt;
для этого – список пар «ключ–значение», разделенных амперсандом, '''&amp;amp;'''. Если мы теперь поменяем наш URL на http://services.digg.com/stories/hot/?appkey=http://www.linuxformat.ru&amp;amp;count=1, то увидим только первую статью. Естественно, можно указать другое число или любые другие переменные,&lt;br /&gt;
принимаемые этим запросом. Как узнать, что это за переменные? Ну, придется попросить ''Digg'' опубликовать их. В данном случае вы найдете аргументы&lt;br /&gt;
для конечных точек внизу страницы http://apidoc.digg.com/ListStories.&lt;br /&gt;
&lt;br /&gt;
===''Digg'' и ''Python''===&lt;br /&gt;
&lt;br /&gt;
Итак, мы ознакомились с основами ''Digg'' API. Можно вводить URL  и получатьв замен XML-код. Здорово; но как бы провернуть это программно? Что же, для  начала необходим способ открытия URL. Стандартный модуль ''Python, urllib'', может сделать это для нас, поэтому запустим оболочку ''Python'' (откройте&lt;br /&gt;
окно терминала и просто введите ''python'') и посмотрим, что можно сделать.&lt;br /&gt;
&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; url=’http://services.digg.com/stories/hot/?’&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; appkey=’http://www.linuxformat.ru’&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; import urllib&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; diggargs ={ ‘count’: 1, ‘appkey’: appkey}&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; foo=urllib.urlencode(diggargs)&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; request = url+foo&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; request&lt;br /&gt;
 ‘http://services.digg.com/stories/hot/?count=1&amp;amp;appkey=http%3A%2F%2Fwww.linuxformat.ru’&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тут требуется небольшое пояснение. Сперва мы сохраняем базовый URL и ключ приложения в виде строк, потому что далее они будут часто использоваться. После&lt;br /&gt;
импорта модуля ''urllib'' нам надо определить некоторые переменные для передачи ''Digg''. Здесь мы воспользовались словарем ''Python''. Это простая конструкция, заключенная в фигурные скобки – она хранит пары «ключ–значение» и ведет себя схоже со списками. Сперва указывается ключ, затем следует двоеточие, а далее значение. Тип значения может быть любым из распознаваемых ''Python'', но чаще всего это строки или целые числа.&lt;br /&gt;
&lt;br /&gt;
===Зачем нужен словарь?===&lt;br /&gt;
&lt;br /&gt;
Но зачем, собственно, создавать из аргументов словарь? Во-первых, ради стройности кода, а во-вторых, в библиотеке ''urllib'' имеются полезные функции, которые преобразуют его в строку-запрос вместо нас. Это не так просто, как конкатенация (объединение) всех строк, потому что в HTTP есть соглашения о символах, допустимых в запросах. Поэтому в следующей строке вызывается функция '''urllib.urlencode''' для преобразования нашего словаря в строку-запрос. Еще одно преимущество использования словарей – простота добавления или изменения значений, а строку-запрос можно сгенерировать заново. А если бы мы напрямую конвертировали аргументы в строку-запрос, внесение изменений было бы более хитрым (или муторным) делом.&lt;br /&gt;
&lt;br /&gt;
===Массивный отклик===&lt;br /&gt;
&lt;br /&gt;
Запрос ['''request'''] строится простым объединением базового URL и строки-запроса. Любопытства ради, можете просто ввести имя этой переменной, и ''Python'' напечатает ее значение: в данном случае – с трудом читаемый URL, результат использования верной кодировки. Итак, что же мы получим, подключившись к серверу с этим запросом? Ответ должен выглядеть примерно так:&lt;br /&gt;
&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; response = urllib.urlopen(request)&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; response.read()&lt;br /&gt;
 ‘&amp;lt;?xml version=”1.0” encoding=”utf-8” ?&amp;gt;\n&amp;lt;stories timestamp=”1251657872” total=”13711” offset=”0”&lt;br /&gt;
 count=”1”&amp;gt;\n &amp;lt;story link=”http://myfirstfail.com/2009/08/24/funny-baby-photos-im-really-excited-to-be-here/” submit_&lt;br /&gt;
 date=”1251584276” diggs=”125” id=”15364594” comments=”18” href=”http://digg.com/people/I_m_REALLY_Excited_to_be_&lt;br /&gt;
 Here” status=”upcoming” media=”images”&amp;gt;\n &amp;lt;description&amp;gt;&amp;lt;/description&amp;gt;\n &amp;lt;title&amp;gt;I\'m REALLY Excited to be Here!&amp;lt;/title&amp;gt;\n&lt;br /&gt;
 &amp;lt;user name=”sungoddess808” registered=”1201436227” profileviews=”40965” fullname=”Sunshine ” icon=”http://digg.&lt;br /&gt;
 com/users/sungoddess808/l.png” /&amp;gt;\n &amp;lt;topic name=”People” short_name=”people” /&amp;gt;\n &amp;lt;container name=”Offbeat”&lt;br /&gt;
 short_name=”offbeat” /&amp;gt;\n &amp;lt;thumbnail originalwidth=”500” originalheight=”426” contentType=”image/jpeg” &lt;br /&gt;
 src=”http://digg.com/people/I_m_REALLY_Excited_to_be_Here/t.jpg” width=”80”&lt;br /&gt;
 height=”80” /&amp;gt;\n &amp;lt;shorturl short_url=”http://digg.com/d312T22” view_count=”582” /&amp;gt;\n &amp;lt;/story&amp;gt;\n&amp;lt;/stories&amp;gt;‘&lt;br /&gt;
&lt;br /&gt;
Функция '''urlopen''' возвращает файлоподобный объект, с которым можно обращаться как с любым другим файл-объектом. Это полезно, если вы ожидаете в ответ огромный объем данных, но я сомневаюсь, что из-за экспериментов нашего урока ''Digg'' заполнит всю вашу память. Далее, '''response.read()''' просто выводит «файл», и можно совместить эти две команды:&lt;br /&gt;
&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; response = urllib.urlopen(request).read()&lt;br /&gt;
&lt;br /&gt;
Такой трюк применим к большинству объектов ''Python'', хотя затрудняет понимание кода.&lt;br /&gt;
&lt;br /&gt;
Наша уловка сработала, и мы получили ответ – кучу XML-кода для обработки. Чтобы получить из нее XML-объект, необходимо задействовать кое-какие методы из XML-модуля ''Python'', а именно&lt;br /&gt;
&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; from xml.dom import xml.minidom&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; x = minidom.parseString(response)&lt;br /&gt;
&lt;br /&gt;
Выуживание данных из объектов и построение из этой информации правильно структурированного XML-файла известно в мире XML как маршалинг [marshalling, упорядочивание]. Но нам-то нужна обратная операция – создать объект ''Python'' из данных. Нижеследующий кусок кода, вероятно, один из наиболее часто копируемых, по крайней мере для ''Python'' и XML. По-моему, он восходит к коду, написанному Марком Пилгримом [Mark Pilgrim] (автор книги '''В глубь языка Python''', http://ru.diveintopython.org), а кто несогласен – пишите на известный адрес...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=Python&amp;gt;&lt;br /&gt;
 class Bag: pass&lt;br /&gt;
 def unmarshal(element):&lt;br /&gt;
   rc = Bag()&lt;br /&gt;
   if isinstance(element, minidom.Element):&lt;br /&gt;
    for key in element.attributes.keys():&lt;br /&gt;
      setattr(rc, key, element.attributes[key].value)&lt;br /&gt;
&lt;br /&gt;
 childElements = [e for e in element.childNodes \&lt;br /&gt;
     if isinstance(e, minidom.Element)]&lt;br /&gt;
 if childElements:&lt;br /&gt;
   for child in childElements:&lt;br /&gt;
     key = child.tagName&lt;br /&gt;
     if hasattr(rc, key):&lt;br /&gt;
      if type(getattr(rc, key)) &amp;lt;&amp;gt; type([]):&lt;br /&gt;
        setattr(rc, key, [getattr(rc, key)])&lt;br /&gt;
      setattr(rc, key, getattr(rc, key) + [unmarshal(child)])&lt;br /&gt;
     elif isinstance(child, minidom.Element) and \&lt;br /&gt;
        (child.tagName == ‘Details’):&lt;br /&gt;
      # Делаем первый элемент Details ключом&lt;br /&gt;
      setattr(rc,key,[unmarshal(child)])&lt;br /&gt;
     else:&lt;br /&gt;
      setattr(rc, key, unmarshal(child))&lt;br /&gt;
  else:&lt;br /&gt;
    text = “”.join([e.data for e in element.childNodes \&lt;br /&gt;
       if isinstance(e, minidom.Text)])&lt;br /&gt;
    setattr(rc, ‘text’, text)&lt;br /&gt;
 return rc&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Опять немного поясним. Первая странность – класс '''Bag''', который вроде и описан, но пуст. В ''Python'' такое допустимо – и правда, как узнать, что будет в классе, пока не распакованы данные? Это прекрасно демонстрирует гибкость ''Python''; он допускает классы объектов, которые можно создавать в процессе выполнения.&lt;br /&gt;
&lt;br /&gt;
{{Врезка|Заголовок=Порезвимся с XML|Содержание=В приведенном примере XML-код короткий и без причуд, не уводящий в сложности. Для больших документов, или если вы захотите генерировать XML для себя, понадобится установить хороший редактор.&lt;br /&gt;
&lt;br /&gt;
Есть несколько редакторов специально для XML – например, ''XMLCopyEditor'': он отслеживает корректность структуры, а кроме того, упрощает поиск и сканирование текста.|Ширина=200px}}&lt;br /&gt;
&lt;br /&gt;
===Анархия кода?===&lt;br /&gt;
&lt;br /&gt;
Функция '''unmarshal''' – просто рекурсивная процедура, которая пошагово проходит каждый узел дерева XML DOM и собирает из него объект ''Python''. Желая создать модуль API для ''Python'', выполняющий интерпретацию вывода ''Digg'', вы можете делать это более структурировано и осмысленно, потому что структура XML известна заранее. А приведенный метод – из разряда всеобъемлющих, с тем недостатком, что получающийся объект все еще неуклюж. Однако небольшая пост-обработка расставит все по местам.&lt;br /&gt;
&lt;br /&gt;
Мы получили список контейнеров '''story''', заключенных в контейнер с именем '''stories'''. Каждый из них имеет свои собственные подузлы для комментариев, ID, URL и так далее. Если мы хотим взглянуть на объекты '''story''', следует просто в цикле пройтись по контейнеру '''stories''', вот так:&lt;br /&gt;
&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; for item in bar.stories.story:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; print item.id, item.link, item.title.text&lt;br /&gt;
&lt;br /&gt;
Ничто не мешает добавлять данные в эту структуру программно. Что если, например, полюбопытствовать, где опубликованы все эти истории? На это имеется полезная свободная библиотека с именем ''GeoIP'', выставляющая соответствие между IP-адресами и странами.&lt;br /&gt;
&lt;br /&gt;
===Добавляем данные===&lt;br /&gt;
&lt;br /&gt;
Модуль ''GeoIP'' имеется в основных дистрибутивах, или можно загрузить его с MaxMind (http://www.maxmind.com/app/python). Все очень просто: вы создаете объект '''GeoIP''', затем используете его методы для определения кода или названия страны по имени домена web-сервера. Вот простой пример:&lt;br /&gt;
&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; import GeoIP&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; geo=GeoIP.new(GeoIP.GEOIP_STANDARD)&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; geo.country_name_by_name(‘google.com’) ‘United States’&lt;br /&gt;
&lt;br /&gt;
Проще некуда. К сожалению, ему необходим только домен, а не весь URL. Но мы можем импортировать еще один стандартный модуль ''Python'', под названием ''urlparse'' (http://www.python.org/doc/2.5.2/lib/moduleurlparse.html), который разбивает URL на части.&lt;br /&gt;
&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; import urlparse&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; for item in bar.stories.story:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; item.country=geo.country_name_by_name(urlparse.urlparse(item.link).netloc)&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; print item.country&lt;br /&gt;
&lt;br /&gt;
Мы переписали наш цикл и создали внутри него новое свойство объекта '''item''' с именем '''country'''. Передача вырезанного имени домена от функции ''urlparse'' к функции '''GeoIP''' выдает название страны в виде строки.&lt;br /&gt;
&lt;br /&gt;
Можно зайти дальше и на основании значений '''country''' проследить частоту появления различных стран, скажем, в первой сотне самых посещаемых сайтов. Это весьма легко сделать: объявим пустой словарь, затем будем добавлять единицу к величине ключа данной страны по ходу цикла обработки. Если ключа не существует, то используем значение по умолчанию – ноль. Словарь потом можно преобразовать в упорядоченный список и построить гистограмму частоты появления стран.&lt;br /&gt;
&lt;br /&gt;
{{Врезка|Заголовок=Скорая помощь|Содержание=Экспериментируя с ''Python 3'', вы обнаружите, что ''urllib'' больше не работает. Все потому, что в ''Python 3'' она разбита на части: ''urllib.request, urllib.parse'' и ''urllib.error''. Дополнительную информацию можно получить на сайте с документацией по ''Python'', http://docs.python.org/library/urllib.htm.|Ширина=200px}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
 #!/usr/bin/python&lt;br /&gt;
&lt;br /&gt;
 import urllib&lt;br /&gt;
 from xml.dom import minidom&lt;br /&gt;
 import urlparse, GeoIP, operator&lt;br /&gt;
&lt;br /&gt;
 url=’http://services.digg.com/stories/hot/?’&lt;br /&gt;
 appkey=’http://linuxformat.co.uk’&lt;br /&gt;
 geo=GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE)&lt;br /&gt;
&lt;br /&gt;
 class Bag: pass&lt;br /&gt;
 def unmarshal(element):&lt;br /&gt;
   rc = Bag()&lt;br /&gt;
   if isinstance(element, minidom.Element):&lt;br /&gt;
     for key in element.attributes.keys():&lt;br /&gt;
       setattr(rc, key, element.attributes[key].value)&lt;br /&gt;
&lt;br /&gt;
   childElements = [e for e in element.childNodes \&lt;br /&gt;
         if isinstance(e, minidom.Element)]&lt;br /&gt;
   if childElements:&lt;br /&gt;
     for child in childElements:&lt;br /&gt;
       key = child.tagName&lt;br /&gt;
       if hasattr(rc, key):&lt;br /&gt;
         if type(getattr(rc, key)) &amp;lt;&amp;gt; type([]):&lt;br /&gt;
           setattr(rc, key, [getattr(rc, key)])&lt;br /&gt;
         setattr(rc, key, getattr(rc, key) + [unmarshal(child)])&lt;br /&gt;
       elif isinstance(child, minidom.Element) and \&lt;br /&gt;
            (child.tagName == ‘Details’):&lt;br /&gt;
         # делаем первый элемент Details ключом&lt;br /&gt;
         setattr(rc,key,[unmarshal(child)])&lt;br /&gt;
       else:&lt;br /&gt;
         setattr(rc, key, unmarshal(child))&lt;br /&gt;
    else:&lt;br /&gt;
      text = “”.join([e.data for e in element.childNodes \&lt;br /&gt;
        if isinstance(e, minidom.Text)])&lt;br /&gt;
      setattr(rc, ‘text’, text)&lt;br /&gt;
    return rc&lt;br /&gt;
&lt;br /&gt;
 diggargs ={ ‘count’: 100, ‘appkey’: appkey}&lt;br /&gt;
 foo=urllib.urlencode(diggargs)&lt;br /&gt;
 request = url+foo&lt;br /&gt;
 response = urllib.urlopen(request).read()&lt;br /&gt;
&lt;br /&gt;
 x = minidom.parseString(response)&lt;br /&gt;
 bar = unmarshal(x)&lt;br /&gt;
&lt;br /&gt;
 hist = {}&lt;br /&gt;
 for item in bar.stories.story:&lt;br /&gt;
&lt;br /&gt;
   item.country=geo.country_name_by_name(urlparse.urlparse(item.link).netloc)&lt;br /&gt;
   hist[item.country]=hist.get(item.country, 0) +1&lt;br /&gt;
&lt;br /&gt;
 sorted = sorted(hist.items(), key=operator.itemgetter(1),reverse=True)&lt;br /&gt;
 print sorted&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сегодня мы освоили солидный кусок, хотя занимались всего одной точкой входа для ''Digg''. Для более полезного API вы, возможно, захотите создать класс и несколько объектов, чтобы описать пользователей, заметки и тому подобное, и примените описанные здесь советы, чтобы заполнить их. ''Digg'' – это, в основном, трафик в одну сторону, но в следующий раз мы рассмотрим также и запись данных, создав графический клиент Flickr.&lt;/div&gt;</summary>
		<author><name>Crazy Rebel</name></author>	</entry>

	</feed>