2012-02-23 16 views
5

Hialxml - dificultad para analizar stackexchange rss feed

Tengo problemas para analizar rss feed de stackexchange en python. Cuando trato de obtener los nodos de resumen, devuelvo una lista vacía

He estado tratando de resolver esto, pero no entiendo bien.

¿Alguien puede ayudar? gracias 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]: [] 

Respuesta

9

Tome un vistazo a estas dos versiones

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

Como has descubierto, la segunda versión no devolvió los nodos, pero la versión lxml.html funciona bien. La versión etree no funciona porque está esperando espacios de nombres y la versión html está funcionando porque ignora los espacios de nombres. Parte abajo de http://lxml.de/lxmlhtml.html, dice "El analizador HTML ignora notablemente los espacios de nombres y algunos otros XMLisms".

Tenga en cuenta que cuando imprima el nodo raíz de la versión etree (print(data.getroot())), obtendrá algo como <Element {http://www.w3.org/2005/Atom}feed at 0x22d1620>. Eso significa que es un elemento de feed con un espacio de nombre de http://www.w3.org/2005/Atom. Aquí hay una versión corregida del código 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: alimentación/NS: entrada/NS: resumen', espacios de nombres = { 'ns': 'http: //www.w3.org/2005/Atom '}) ' – reclosedev

+0

gah, ¡no es de extrañar! Parece que la API renombró la palabra clave 'namespaces' en algún momento. Actualizando mi muestra con código de trabajo. – gfortune

+0

muchas gracias Gfortune. Comenzaré a verificar la raíz antes de dirigirme a analizarla. – MrCastro

6

El problema es el espacio de nombres.

Ejecutar este:

cooking_parsed.getroot().tag 

y verá que el elemento es el namespace por

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

Del mismo modo si se desplaza a una de las entradas de alimentación.

Esto significa que el XPath justo en lxml es:

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

De alguna manera, sospecho que esta respuesta fue más fácil para usted de lo que fue para mí. ;) Chocar tontamente con tu respuesta y no dudes en señalar cualquier error que haya cometido en el mío. – gfortune