Взгляните на эти две версии
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')