本节书摘来自异步社区《Python Cookbook(第3版)中文版》一书中的第6章,第6.3节,作者[美]David Beazley , Brian K.Jones,陈舸 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。
我们想从一个简单的XML文档中提取出数据。
xml.etree.ElementTree模块可用来从简单的XML文档中提取出数据。为了说明,假设想对Planet Python(http://planet.python.org )上的RSS订阅做解析并生成一个总结报告。下面的脚本可以完成这个任务:
from urllib.request import urlopen from xml.etree.ElementTree import parse # Download the RSS feed and parse it u = urlopen('http://planet.python.org/rss20.xml') doc = parse(u) # Extract and output tags of interest for item in doc.iterfind('channel/item'): title = item.findtext('title') date = item.findtext('pubDate') link = item.findtext('link') print(title) print(date) print(link) print()如果运行上面的脚本,会得到类似这样的输出:
Steve Holden: Python for Data Analysis Mon, 19 Nov 2012 02:13:51 +0000 http://holdenweb.blogspot.com/2012/11/python-for-data-analysis.html Vasudev Ram: The Python Data model (for v2 and v3) Sun, 18 Nov 2012 22:06:47 +0000 http://jugad2.blogspot.com/2012/11/the-python-data-model.html Python Diary: Been playing around with Object Databases Sun, 18 Nov 2012 20:40:29 +0000 http://www.pythondiary.com/blog/Nov.18,2012/been-...-object-databases.html Vasudev Ram: Wakari, Scientific Python in the cloud Sun, 18 Nov 2012 20:19:41 +0000 http://jugad2.blogspot.com/2012/11/wakari-scientific-python-in-cloud.html Jesse Jiryu Davis: Toro: synchronization primitives for Tornado coroutines Sun, 18 Nov 2012 20:17:49 +0000 http://feedproxy.google.com/~r/EmptysquarePython/~3/_DOZT2Kd0hQ/显然,如果想做更多的处理,就需要将print()函数替换为其他更加有趣的处理函数。
在许多应用中,同XML编码的数据打交道是很常见的事情。这不仅是因为XML作为一种数据交换格式在互联网中使用广泛,而且XML还是用来保存应用程序数据(例如文字处理、音乐库等)的常用格式。本节后面的讨论假设读者已经熟悉XML的基本概念。
在许多情况下,XML如果只是简单地用来保存数据,那么文档结构就是紧凑而直接的。例如,上面示例中的RSS订阅源看起来类似于如下的XML文档:
<?xml version="1.0"?> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"> <channel> <title>Planet Python</title> <link>http://planet.python.org/</link> <language>en</language> <description>Planet Python - http://planet.python.org/</description> <item> <title>Steve Holden: Python for Data Analysis</title> <guid>http://holdenweb.blogspot.com/...-data-analysis.html</guid> <link>http://holdenweb.blogspot.com/...-data-analysis.html</link> <description>...</description> <pubDate>Mon, 19 Nov 2012 02:13:51 +0000</pubDate> </item> <item> <title>Vasudev Ram: The Python Data model (for v2 and v3)</title> <guid>http://jugad2.blogspot.com/...-data-model.html</guid> <link>http://jugad2.blogspot.com/...-data-model.html</link> <description>...</description> <pubDate>Sun, 18 Nov 2012 22:06:47 +0000</pubDate> </item> <item> <title>Python Diary: Been playing around with Object Databases</title> <guid>http://www.pythondiary.com/...-object-databases.html</guid> <link>http://www.pythondiary.com/...-object-databases.html</link> <description>...</description> <pubDate>Sun, 18 Nov 2012 20:40:29 +0000</pubDate> </item> ... </channel> </rss>xml.etree.ElementTree.parse()函数将整个XML文档解析为一个文档对象。之后,就可以利用find()、iterfind()以及findtext()方法查询特定的XML元素。这些函数的参数就是特定的标签名称,比如channel/item或者title。
当指定标签时,需要整体考虑文档的结构。每一个查找操作都是相对于一个起始元素来展开的。同样地,提供给每个操作的标签名也是相对于起始元素的。在示例代码中,对doc.iterfind('channel/item')的调用会查找所有在“channel”元素之下的“item”元素。doc代表着文档的顶层(顶层“rss”元素)。之后对item.findtext()的调用就相对于已找到的“item”元素来展开。
每个由ElementTree模块所表示的元素都有一些重要的属性和方法,它们对解析操作十分有用。tag属性中包含了标签的名称,text属性中包含有附着的文本,而get()方法可以用来提取出属性(如果有的话)。示例如下:
>>> doc <xml.etree.ElementTree.ElementTree object at 0x101339510> >>> e = doc.find('channel/title') >>> e <Element 'title' at 0x10135b310> >>> e.tag 'title' >>> e.text 'Planet Python' >>> e.get('some_attribute') >>>应该要指出的是xml.etree.ElementTree并不是解析XML的唯一选择。对于更加高级的应用,应该考虑使用lxml。lxml采用的编程接口和ElementTree一样,因此本节中展示的示例能够以同样的方式用lxml实现。只需要将第一个导入语句修改为from lxml.etree import parse即可。lxml完全兼容于XML标准,这为我们提供了极大的好处。此外,lxml运行起来非常快速,还提供验证、XSLT以及XPath这样的功能支持。
相关资源:python cookbook(第3版)高清中文完整版.pdf