lxml - сложность разбора stackexchange rss feed - PullRequest
5 голосов
/ 23 февраля 2012

Ся

У меня проблемы с анализом RSS-канала из stackexchange в python. Когда я пытаюсь получить сводные узлы, возвращается пустой список

Я пытался решить эту проблему, но не могу разобраться.

Кто-нибудь может помочь? Спасибо а

In [3o]: import lxml.etree, urllib2</p> <pre><code>In [31]: url_cooking = 'http://cooking.stackexchange.com/feeds' In [32]: cooking_content = urllib2.urlopen(url_cooking) In [33]: cooking_parsed = lxml.etree.parse(cooking_content) In [34]: cooking_texts = cooking_parsed.xpath('.//feed/entry/summary') In [35]: cooking_texts Out[35]: []

Ответы [ 3 ]

9 голосов
/ 23 февраля 2012

Взгляните на эти две версии

import lxml.html, lxml.etree

url_cooking = 'http://cooking.stackexchange.com/feeds'

#lxml.etree version
data = lxml.etree.parse(url_cooking)
summary_nodes = data.xpath('.//feed/entry/summary')
print('Found ' + str(len(summary_nodes)) + ' summary nodes')

#lxml.html version
data = lxml.html.parse(url_cooking)
summary_nodes = data.xpath('.//feed/entry/summary')
print('Found ' + str(len(summary_nodes)) + ' summary nodes')

Как вы обнаружили, вторая версия не возвращает узлов, но версия lxml.html работает нормально. Версия etree не работает, потому что она ожидает пространства имен, а версия html работает, потому что она игнорирует пространства имен. Частично вниз http://lxml.de/lxmlhtml.html, он говорит: «HTML-парсер, в частности, игнорирует пространства имен и некоторые другие XMLism».

Обратите внимание, что при печати корневого узла версии etree (print(data.getroot())) вы получите что-то вроде <Element {http://www.w3.org/2005/Atom}feed at 0x22d1620>. Это означает, что это элемент канала с пространством имен http://www.w3.org/2005/Atom. Вот исправленная версия кода etree.

import lxml.html, lxml.etree

url_cooking = 'http://cooking.stackexchange.com/feeds'

ns = 'http://www.w3.org/2005/Atom'
ns_map = {'ns': ns}

data = lxml.etree.parse(url_cooking)
summary_nodes = data.xpath('//ns:feed/ns:entry/ns:summary', namespaces=ns_map)
print('Found ' + str(len(summary_nodes)) + ' summary nodes')
6 голосов
/ 23 февраля 2012

Проблема в пространствах имен.

Запустите это:

 cooking_parsed.getroot().tag

И вы увидите, что элемент имеет пространство имен как

{http://www.w3.org/2005/Atom}feed

Аналогично, если вы переходитек одной из записей фида.

Это означает, что правильный xpath в lxml:

print cooking_parsed.xpath(
  "//a:feed/a:entry",
  namespaces={ 'a':'http://www.w3.org/2005/Atom' })
1 голос
/ 23 февраля 2012

Попробуйте использовать BeautifulStoneSoup из beautifulsoup импорта.Это может помочь.

...