lxml模块

Python有许多可以读写常见的HTML和XML格式数据的库,包括lxml、Beautiful Soup和html5lib。lxml的速度比较快,但其它的库处理有误的HTML或XML文件更好。

XML(Extensible Markup Language)是另一种常见的支持分层、嵌套数据以及元数据的结构化数据格式。本书所使用的这些文件实际上来自于一个很大的XML文档。

前面,我介绍了pandas.read_html函数,它可以使用lxml或Beautiful Soup从HTML解析数据。XML和HTML的结构很相似,但XML更为通用。这里,我会用一个例子演示如何利用lxml从XML格式解析数据。

纽约大都会运输署发布了一些有关其公交和列车服务的数据资料(http://www.mta.info/developers/download.html)。这里,我们将看看包含在一组XML文件中的运行情况数据。每项列车或公交服务都有各自的文件(如Metro-North Railroad的文件是Performance_MNR.xml),其中每条XML记录就是一条月度数据,如下所示:


  373889
  
  Metro-North Railroad
  Escalator Availability
  Percent of the time that escalators are operational
  systemwide. The availability rate is based on physical observations performed
  the morning of regular business days only. This is a new indicator the agency
  began reporting in 2009.
  2011
  12
  Service Indicators
  M
  U
  %
  1
  97.00
  
  97.00
  

我们先用lxml.objectify解析该文件,然后通过getroot得到该XML文件的根节点的引用:

from lxml import objectify

path = 'datasets/mta_perf/Performance_MNR.xml'
parsed = objectify.parse(open(path))
root = parsed.getroot()

所谓根节点就是XML最初始的标签,其子节点就是基于这个标签存在的。

root.INDICATOR返回一个用于产生各个XML元素的生成器。对于每条记录,我们可以用标记名(如YTD_ACTUAL)和数据值填充一个字典(排除几个标记):

data = []

skip_fields = ['PARENT_SEQ', 'INDICATOR_SEQ',
               'DESIRED_CHANGE', 'DECIMAL_PLACES']

for elt in root.INDICATOR:
    el_data = {}
    for child in elt.getchildren():
        if child.tag in skip_fields:
            continue
        el_data[child.tag] = child.pyval
    data.append(el_data)

最后,将这组字典转换为一个DataFrame:

In [81]: perf = pd.DataFrame(data)

In [82]: perf.head()
Out[82]:
Empty DataFrame
Columns: []
Index: []

XML数据可以比本例复杂得多。每个标记都可以有元数据。看看下面这个HTML的链接标签(它也算是一段有效的XML):

data = []

skip_fields = ['PARENT_SEQ', 'INDICATOR_SEQ',
               'DESIRED_CHANGE', 'DECIMAL_PLACES']

for elt in root.INDICATOR:
    el_data = {}
    for child in elt.getchildren():
        if child.tag in skip_fields:
            continue
        el_data[child.tag] = child.pyval
    data.append(el_data)

最后,将这组字典转换为一个DataFrame:

In [81]: perf = pd.DataFrame(data)

In [82]: perf.head()
Out[82]:
Empty DataFrame
Columns: []
Index: []

XML数据可以比本例复杂得多。每个标记都可以有元数据。看看下面这个HTML的链接标签(它也算是一段有效的XML):

from io import StringIO
tag = 'Google'
root = objectify.parse(StringIO(tag)).getroot()

现在就可以访问标签或链接文本中的任何字段了(如href):

In [84]: root
Out[84]: 

In [85]: root.get('href')
Out[85]: 'http://www.google.com'

In [86]: root.text
Out[86]: 'Google'

文章代码引用自:《利用Python进行数据分析·第2版》第6章 数据加载、存储与文件格式
作者:SeanCheney
感谢SeanCheney同意引用。

你可能感兴趣的:(lxml模块)