2012-02-23 9 views
5

Hialxml - difficoltà parsing rss StackExchange nutrono

Ho problemi di parsing un feed RSS da StackExchange in python. Quando provo ad ottenere i nodi di riepilogo, viene restituita una lista vuota

Ho cercato di risolvere questo problema, ma non riesco a capirmi.

Qualcuno può dare una mano? grazie un

In [3o]: import lxml.etree, urllib2

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]: [] 

risposta

9

Date un'occhiata a queste due versioni

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') 

Come hai scoperto, la seconda versione non ha prodotto alcun nodi, ma la versione lxml.html funziona bene. La versione etree non funziona perché è in attesa di spazi dei nomi e la versione html funziona perché ignora gli spazi dei nomi. Scendendo verso il basso http://lxml.de/lxmlhtml.html, si dice "Il parser HTML ignora notevolmente spazi dei nomi e alcuni altri XMLisms."

Nota quando si stampa il nodo radice della versione di etree (print(data.getroot())), si ottiene qualcosa come <Element {http://www.w3.org/2005/Atom}feed at 0x22d1620>. Ciò significa che si tratta di un elemento feed con uno spazio dei nomi di http://www.w3.org/2005/Atom. Ecco una versione corretta del codice 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') 
+0

'data.xpath ('// ns: alimentazione/NS: entrata/NS: sintesi', i namespace = { 'ns': 'http: //www.w3.org/2005/Atom '}) ' – reclosedev

+0

gah, non c'è da stupirsi! Sembra che l'API abbia rinominato la parola chiave 'namespaces' a un certo punto. Aggiornamento del mio esempio con codice funzionante. – gfortune

+0

grazie mille gfortune. Inizierò a controllare la radice prima di andare ad analizzarla. – MrCastro

6

Il problema è spazio dei nomi.

Esegui questo:

cooking_parsed.getroot().tag 

e vedrete che l'elemento è namespace come

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

Allo stesso modo, se si passa a una delle voci di alimentazione.

Questo significa che il XPath nel lxml è:

print cooking_parsed.xpath(
    "//a:feed/a:entry", 
    namespaces={ 'a':'http://www.w3.org/2005/Atom' }) 
+0

In qualche modo sospetto che questa risposta ti sia stata più facile di quanto non fosse per me. ;) Urtando prepotentemente la tua risposta e sentiti libero di segnalare eventuali errori che ho commesso nella mia. – gfortune